From cef9cc22bcbe0ad1fdeb8d071f2fb14fa24c552e Mon Sep 17 00:00:00 2001 From: cbnolok Date: Sat, 10 Aug 2024 18:59:54 +0200 Subject: [PATCH 01/86] Merged DavideRei PR: Read mobtypes.txt and handle standard and custom creatures animations #1266 --- Changelog.txt | 50 + src/CMakeSources.cmake | 2 + src/common/CUOInstall.cpp | 5 + src/common/CUOInstall.h | 3 + src/game/CServerConfig.cpp | 3 + src/game/CServerConfig.h | 1 + src/game/chars/CCharAct.cpp | 1463 ++++++++++++++++++++--- src/game/chars/CCharAttacker.cpp | 5 + src/game/chars/CCharBase.cpp | 2 +- src/game/chars/CCharNPCAct.cpp | 2 + src/game/chars/CCharSpell.cpp | 3 +- src/game/clients/CClientTarg.cpp | 3 +- src/game/uo_files/CUOMobtypes.cpp | 98 ++ src/game/uo_files/CUOMobtypes.h | 45 + src/game/uo_files/uofiles_enums.h | 102 +- src/game/uo_files/uofiles_enums_creid.h | 25 +- src/sphere.ini | 3 + 17 files changed, 1662 insertions(+), 153 deletions(-) create mode 100644 src/game/uo_files/CUOMobtypes.cpp create mode 100644 src/game/uo_files/CUOMobtypes.h diff --git a/Changelog.txt b/Changelog.txt index 011002d12..56d6c719a 100644 --- a/Changelog.txt +++ b/Changelog.txt @@ -3808,3 +3808,53 @@ Added: 'H' shortcut for variables to get the value as hexadecimal. New values: SPELLFLAG_FIELD_RANDOMDECAY 02000 SPELLFLAG_NO_ELEMENTALENGINE 04000 + +10-08-2024, DavideRei +- Added: read mobtypes.txt (if available among mul files) and cache it to check animations type when using creatures animations +- Added: alert anim on NPCs when they start combat, pillage anim when they loot something (items on ground or in bodies) and "summon" anim when they are summoned or added +- Modified: now standard anims (SEA_MONSTER, ANIMAL, MONSTER) and UOP anims are handled correctly depending on which actions anim they have on anim files (checked on last client version). + Please note that some actions are handled by the client (for example walk, run, fly, getHit while flying, die) and they could not work depending on which client you are using. +- Added: missing/new actions to be used with .ANIM command. + ANIM_ALERT = 35, + ANIM_THROW = 36, + ANIM_PILLAGE = 37, + ANIM_STOMP = 38, + ANIM_FLY = 39, + ANIM_LAND = 40, + ANIM_GETHIT_AIR = 41, + ANIM_SUMMON = 42, + ANIM_SPECIAL = 43, //UOP anims + ANIM_BOSS_SPECIAL_1 = 44, //Only few UOP anims: Order Variant, Chaos Variant, Stygian Dragon, Scalis + ANIM_BOSS_SPECIAL_2 = 45, //Only few UOP anims: Order Variant, Chaos Variant, Stygian Dragon, Scalis + +- Modified: now custom anims can be handled by scripts using ANIM command under CHARDEF, to set which anim actions they have/don't have, using the following flags. + MONSTER (H slot) default configuration is with actions: 0 (Walk), 1 (Stand), 2 (Die1), 3 (Die2), 4 (Attack1), 5 (Attack2), 6 (Attack3), 10 (GetHit), 11 (Pillage), 15 (Block Right), 16 (Block Left), 17 (Idle), 18 (Fidget) + No DIE2 action = 01, + No ATTACK1 action = 02, + No ATTACK2 action = 04, + No ATTACK3 action = 08, + No GETHIT action = 010, + No PILLAGE action = 020, + STOMP action = 040, + CAST2 action = 080, + CAST3 action = 0100, + No BLOCKR action = 0200, + No BLOCKL action = 0400, + No FIDGET1 action = 0800, + No FIDGET2 action = 01000, + FLY action = 02000, + Anims with Attacks 1-2-3 in actions 9,10,11 and with GetHit in action 20 (there are many custom WOW anims with this configuration) = 0x10000 + + ANIMAL (L slot) default configuration is with all actions: 1 - 12 + No EAT action = 01, + No ALERT action = 02, + No ATTACK2 action = 04, + No GETHIT action = 08, + No FIDGET1 action = 010, + No FIDGET2 action = 020, + No LIEDOWN action = 040, + No DIE2 action = 080 + + So for example if you have a MONSTER (H slot) flying custom anim, with Cast2 action but not Pillage action you can set ANIM=020A0 + If you have a custom anim with default configuration, you don't need to set ANIM= + diff --git a/src/CMakeSources.cmake b/src/CMakeSources.cmake index d6976347d..4c5feb64b 100644 --- a/src/CMakeSources.cmake +++ b/src/CMakeSources.cmake @@ -89,6 +89,8 @@ src/game/uo_files/CUOMapList.h src/game/uo_files/CUOMapList.cpp src/game/uo_files/CUOMapMeter.h src/game/uo_files/CUOMapMeter.cpp +src/game/uo_files/CUOMobtypes.h +src/game/uo_files/CUOMobtypes.cpp src/game/uo_files/CUOMultiItemRec.h src/game/uo_files/CUOMultiItemRec.cpp src/game/uo_files/CUOStaticItemRec.h diff --git a/src/common/CUOInstall.cpp b/src/common/CUOInstall.cpp index ff252ec86..d22146431 100644 --- a/src/common/CUOInstall.cpp +++ b/src/common/CUOInstall.cpp @@ -486,6 +486,11 @@ VERFILE_TYPE CUOInstall::OpenFiles( ullong ullMask ) m_tiledata.Load(); + if (g_Cfg.m_fUseMobTypes) + { + m_mobtypes.Load(); + } + return (VERFILE_TYPE)i; } diff --git a/src/common/CUOInstall.h b/src/common/CUOInstall.h index b62151b31..f4417d531 100644 --- a/src/common/CUOInstall.h +++ b/src/common/CUOInstall.h @@ -10,6 +10,7 @@ #include "../game/uo_files/CUOTiledata.h" #include "../game/uo_files/CUOIndexRec.h" #include "../game/uo_files/CUOMapList.h" +#include "../game/uo_files/CUOMobtypes.h" #include "sphere_library/CSFile.h" #include "CSVFile.h" @@ -52,6 +53,8 @@ extern struct CUOInstall CSVFile m_CsvFiles[8]; // doors.txt, stairs.txt (x2), roof.txt, misc.txt, teleprts.txt, floors.txt, walls.txt + CUOMobTypes m_mobtypes; + public: CSString GetFullExePath( lpctstr pszName = nullptr ) const; CSString GetFullCDPath( lpctstr pszName = nullptr ) const; diff --git a/src/game/CServerConfig.cpp b/src/game/CServerConfig.cpp index 56c6df51d..87f9f526f 100644 --- a/src/game/CServerConfig.cpp +++ b/src/game/CServerConfig.cpp @@ -45,6 +45,7 @@ CServerConfig::CServerConfig() _iMapCacheTime = 2ll * 60 * MSECS_PER_SEC; _iSectorSleepDelay = 10ll * 60 * MSECS_PER_SEC; m_fUseMapDiffs = false; + m_fUseMobTypes = false; m_iDebugFlags = 0; //DEBUGF_NPC_EMOTE m_fSecure = true; @@ -707,6 +708,7 @@ enum RC_TYPE RC_USEEXTRABUFFER, // m_fUseExtraBuffer RC_USEHTTP, // m_fUseHTTP RC_USEMAPDIFFS, // m_fUseMapDiffs + RC_USEMOBTYPES, // m_fUseMobTypes RC_USENOCRYPT, // m_Usenocrypt RC_USEPACKETPRIORITY, // m_fUsePacketPriorities RC_VENDORMARKUP, // m_iVendorMarkup @@ -992,6 +994,7 @@ const CAssocReg CServerConfig::sm_szLoadKeys[RC_QTY + 1] { "USEEXTRABUFFER", { ELEM_BOOL, static_castOFFSETOF(CServerConfig,m_fUseExtraBuffer) }}, { "USEHTTP", { ELEM_INT, static_castOFFSETOF(CServerConfig,m_fUseHTTP) }}, { "USEMAPDIFFS", { ELEM_BOOL, static_castOFFSETOF(CServerConfig,m_fUseMapDiffs) }}, + { "USEMOBTYPES", { ELEM_BOOL, static_castOFFSETOF(CServerConfig,m_fUseMobTypes) } }, { "USENOCRYPT", { ELEM_BOOL, static_castOFFSETOF(CServerConfig,m_fUsenocrypt) }}, // we don't want no-crypt clients { "USEPACKETPRIORITY", { ELEM_BOOL, static_castOFFSETOF(CServerConfig,m_fUsePacketPriorities) }}, { "VENDORMARKUP", { ELEM_INT, static_castOFFSETOF(CServerConfig,m_iVendorMarkup) }}, diff --git a/src/game/CServerConfig.h b/src/game/CServerConfig.h index 0f19cf212..8e3d8e0a2 100644 --- a/src/game/CServerConfig.h +++ b/src/game/CServerConfig.h @@ -240,6 +240,7 @@ extern class CServerConfig : public CResourceHolder int64 _iMapCacheTime; // Time in sec to keep unused map data.. int64 _iSectorSleepDelay; // The mask for how long sectors will sleep. bool m_fUseMapDiffs; // Whether or not to use map diff files. + bool m_fUseMobTypes; // Whether or not to use mobtypes.txt file. CSString m_sWorldBaseDir; // save\" = world files go here. CSString m_sAcctBaseDir; // Where do the account files go/come from ? diff --git a/src/game/chars/CCharAct.cpp b/src/game/chars/CCharAct.cpp index 71ae37737..481093daa 100644 --- a/src/game/chars/CCharAct.cpp +++ b/src/game/chars/CCharAct.cpp @@ -23,6 +23,7 @@ #include "../triggers.h" #include "CChar.h" #include "CCharNPC.h" +#include "../../common/CUOInstall.h" // "GONAME", "GOTYPE", "GOCHAR" // 0 = object name @@ -900,169 +901,1337 @@ ANIM_TYPE CChar::GenerateAnimate( ANIM_TYPE action, bool fTranslate, bool fBackw case ANIM_SALUTE: case ANIM_EAT: return ANIM_HORSE_ATTACK_XBOW; + case ANIM_ALERT: + case ANIM_SUMMON: + return ANIM_HORSE_STAND; + case ANIM_PILLAGE: + return ANIM_HORSE_SLAP; default: return ANIM_HORSE_STAND; } } - else if (!IsPlayableCharacter()) //( GetDispID() < CREID_MAN ) Possible fix for anims not being displayed above 400 + else if (!IsPlayableCharacter()) { // Animals have certain anims. Monsters have others. - if (GetDispID() >= CREID_HORSE_TAN) + CUOMobTypesType mobTypesRow = { 0, 0 }; + + CREID_TYPE dispID = GetDispID(); + + //Check mobtypes.txt to get the anim type + if (g_Cfg.m_fUseMobTypes && g_Install.m_mobtypes.IsLoaded()) + { + mobTypesRow.m_type = g_Install.m_mobtypes.GetEntry((ushort)dispID)->m_type; + mobTypesRow.m_flags = g_Install.m_mobtypes.GetEntry((ushort)dispID)->m_flags; + } + else + { + //Old Method + if (GetDispID() >= CREID_HORSE_TAN) + { + mobTypesRow.m_type = 2; + } + } + + //Standard UOP Animations + if (mobTypesRow.m_flags & ATFLAG_UseUopAnimation) + { + + //Only mount animations, 3 actions + if (dispID == CREID_BOURA_AR || dispID == CREID_TARANTULA || dispID == CREID_DRAGON_SERPENTINE_ETH) + { + switch (action) + { + case ANIM_WALK_UNARM: + case ANIM_WALK_ARM: + case ANIM_WALK_WAR: + case ANIM_CAST_DIR: + case ANIM_CAST_AREA: + case ANIM_GET_HIT: + case ANIM_ATTACK_1H_SLASH: + case ANIM_ATTACK_1H_PIERCE: + case ANIM_ATTACK_1H_BASH: + case ANIM_ATTACK_2H_BASH: + case ANIM_ATTACK_2H_SLASH: + case ANIM_ATTACK_2H_PIERCE: + case ANIM_ATTACK_WRESTLE: + case ANIM_ATTACK_BOW: + case ANIM_ATTACK_XBOW: + case ANIM_HORSE_RIDE_SLOW: + return ANIM_UOP_WALK_MOUNTED; + + case ANIM_RUN_UNARM: + case ANIM_RUN_ARMED: + case ANIM_HORSE_RIDE_FAST: + return ANIM_UOP_RUN_MOUNTED; + + default: + return ANIM_UOP_STAND_MOUNTED; + } + } + //Only 3 actions + else if (dispID == CREID_HOMUNCULUS) + { + switch (action) + { + case ANIM_DIE_BACK: + case ANIM_DIE_FORWARD: + return ANIM_UOP_DIE_BACKWARD; + + case ANIM_SPECIAL: + case ANIM_SUMMON: + return ANIM_UOP_SPECIAL; + + default: + return ANIM_UOP_STAND; + } + } + + switch (action) + { + case ANIM_WALK_UNARM: + case ANIM_WALK_ARM: + //Creatures without walk animation + if (dispID == CREID_TUNNEL_SPIRIT_BODY || dispID == CREID_CHARYBDIS || (dispID >= CREID_PUMPKIN_DEMON && dispID <= CREID_CLOCKWORK_EXODUS) || dispID == CREID_JACK_IN_THE_BOX) + { + return ANIM_UOP_WALK_COMBAT; + } + else if (dispID == CREID_ANIMATED_WEAPON || dispID == CREID_LITHOS) + { + return ANIM_UOP_STAND; + } + else if (dispID == CREID_TS_TENTACLE || dispID == CREID_CHARYBDIS_TENTACLE) + { + return ANIM_UOP_STAND_COMBAT; + } + else + { + return ANIM_UOP_WALK; + } + + case ANIM_WALK_WAR: + //Creatures without walk combat animation + if (dispID == CREID_PARROT_BIRD || dispID == CREID_TURKEY_GIANT || dispID == CREID_HELLHOUND_ANCIENT || dispID == CREID_GIANT_GORILLA || dispID == CREID_HORSE_PALOMINO) + { + return ANIM_UOP_WALK; + } + else if (dispID == CREID_PHOENIX) + { + return ANIM_UOP_FLY; + } + else if (dispID == CREID_ANIMATED_WEAPON || dispID == CREID_TS_TENTACLE || dispID == CREID_CHARYBDIS_TENTACLE || dispID == CREID_LITHOS) + { + return ANIM_UOP_STAND_COMBAT; + } + else + { + return ANIM_UOP_WALK_COMBAT; + } + + case ANIM_RUN_UNARM: + case ANIM_RUN_ARMED: + //If the creature can fly we can use flying action for running + if (mobTypesRow.m_flags & ATFLAG_CanFlying) + { + //Phoenix and Parrot Bird don't have run anims + if (IsStatFlag(STATF_FLY | STATF_HOVERING) || (dispID == CREID_PARROT_BIRD || dispID == CREID_PHOENIX) ) + return ANIM_UOP_FLY; + else + return ANIM_UOP_RUN; + } + else + { + //Creatures without run anim + if (dispID == CREID_TUNNEL_SPIRIT_BODY || dispID == CREID_CHARYBDIS || (dispID >= CREID_PUMPKIN_DEMON && dispID <= CREID_CLOCKWORK_EXODUS)) + { + return ANIM_UOP_WALK_COMBAT; + } + else if (dispID == CREID_ANIMATED_WEAPON) + { + return ANIM_UOP_STAND; + } + else if (dispID == CREID_TS_TENTACLE || dispID == CREID_CHARYBDIS_TENTACLE) + { + return ANIM_UOP_STAND_COMBAT; + } + else + { + return ANIM_UOP_RUN; + } + } + + case ANIM_STAND: + //Creatures without stand anim + if (dispID == CREID_TUNNEL_SPIRIT_BODY || dispID == CREID_TS_TENTACLE || dispID == CREID_CHARYBDIS || dispID == CREID_CHARYBDIS_TENTACLE || dispID == CREID_CLOCKWORK_EXODUS || dispID == CREID_JACK_IN_THE_BOX) + { + return ANIM_UOP_STAND_COMBAT; + } + else + { + return ANIM_UOP_STAND; + } + + case ANIM_STAND_WAR_1H: + case ANIM_STAND_WAR_2H: + if (dispID == CREID_PARROT_BIRD) + { + return ANIM_UOP_STAND; + } + else + { + return ANIM_UOP_STAND_COMBAT; + } + + case ANIM_FIDGET1: + case ANIM_BOW: + case ANIM_EAT: + if (dispID == CREID_PUMPKIN_FRIGHT) + { + return ANIM_UOP_PEACE_TO_COMBAT; + } + else if (dispID == CREID_ANIMATED_WEAPON || dispID == CREID_TUNNEL_SPIRIT_BODY || dispID == CREID_TS_TENTACLE || (dispID >= CREID_CHARYBDIS && dispID <= CREID_CLOCKWORK_EXODUS) || dispID == CREID_JACK_IN_THE_BOX) + { + return ANIM_UOP_SPECIAL; + } + else + { + return ANIM_UOP_FIDGET; + } + + case ANIM_FIDGET_YAWN: + case ANIM_SALUTE: + if (dispID == CREID_PARROT_BIRD || dispID == CREID_PHOENIX || dispID == CREID_TURKEY_GIANT || dispID == CREID_PUMPKIN_DEMON) + { + return ANIM_UOP_FIDGET; + } + else if(dispID == CREID_PUMPKIN_FRIGHT) + { + return ANIM_UOP_PEACE_TO_COMBAT; + } + else if (dispID == CREID_ANIMATED_WEAPON || dispID == CREID_TS_TENTACLE || (dispID >= CREID_CHARYBDIS && dispID <= CREID_CLOCKWORK_EXODUS)) + { + return ANIM_UOP_SPECIAL; + } + else + { + return ANIM_UOP_ROAR; + } + + case ANIM_CAST_DIR: + case ANIM_CAST_AREA: + case ANIM_ATTACK_BOW: + case ANIM_ATTACK_XBOW: + case ANIM_THROW: + + // 2 actions for cast + if (dispID == CREID_CLOCKWORK_EXODUS) + { + switch (g_Rand.GetVal(2)) + { + case 0: return ANIM_UOP_CAST_1; break; + case 1: return ANIM_UOP_CAST_2; break; + } + } + //Creatures with cast action + else if (dispID == CREID_DRAGON_CRIMSON || dispID == CREID_DRAGON_PLATINUM || dispID == CREID_GRUBBER || dispID == CREID_STONE_FORM || dispID == CREID_ABYSSAL_INFERNAL + || (dispID >= CREID_ELEM_LAVA && dispID <= CREID_GARG_UNDEAD) || dispID == CREID_GOBLIN_GREEN_MAGE || dispID == CREID_MEDUSA || dispID == CREID_SLASHER_VEILS + || dispID == CREID_DRAGON_STYGIAN || dispID == CREID_LICH_PRIMEVAL || dispID == CREID_SCALIS || dispID == CREID_HELLHOUND_ANCIENT || dispID == CREID_MINOTAUR_LORD + || dispID == CREID_PUMPKIN_FRIGHT || dispID == CREID_CLOCKWORK_EXODUS || dispID == CREID_MYRMIDEX_DRONE || dispID == CREID_MYRMIDEX_WARRIOR || dispID == CREID_ZIPACTRIOTL + || dispID == CREID_LASHER || dispID == CREID_WINDRUNNER || dispID == CREID_HYDROS || dispID == CREID_JACK_IN_THE_BOX || (dispID >= CREID_LITHOS && dispID <= CREID_PYROS) + || dispID == CREID_KHAL_ANKUR || dispID == CREID_WAR_BOAR_MOUNT) + { + return ANIM_UOP_CAST_1; + } + else if (dispID == CREID_PARROT_BIRD || dispID == CREID_PHOENIX || dispID == CREID_TURKEY_GIANT) + { + return ANIM_UOP_FIDGET; + } + else if (dispID == CREID_ANIMATED_WEAPON) + { + return ANIM_UOP_SPECIAL; + } + else if (dispID == CREID_TS_TENTACLE || dispID == CREID_CHARYBDIS_TENTACLE) + { + return ANIM_UOP_ATTACK_1; + } + else if (dispID == CREID_CHARYBDIS) + { + return ANIM_UOP_GETHIT; + } + else if (dispID == CREID_PUMPKIN_DEMON) + { + return ANIM_UOP_PEACE_TO_COMBAT; + } + else + { + return ANIM_UOP_ROAR; + } + break; + + case ANIM_GET_HIT: + //No GetHit + if (dispID == CREID_TURKEY_GIANT || dispID == CREID_CLOCKWORK_EXODUS) + { + return ANIM_UOP_STAND_COMBAT; + } + else + { + return ANIM_UOP_GETHIT; + } + break; + + case ANIM_ATTACK_1H_SLASH: + case ANIM_ATTACK_1H_PIERCE: + case ANIM_ATTACK_1H_BASH: + case ANIM_ATTACK_2H_BASH: + case ANIM_ATTACK_2H_SLASH: + case ANIM_ATTACK_2H_PIERCE: + case ANIM_ATTACK_WRESTLE: + //No attack + if (dispID == CREID_TUNNEL_SPIRIT_BODY || dispID == CREID_CHARYBDIS) + { + return ANIM_UOP_BLOCK; + } + else if (dispID == CREID_PARROT_BIRD) + { + return ANIM_UOP_FIDGET; + } + //No attack 2 + else if (dispID == CREID_ANIMATED_WEAPON || dispID == CREID_TS_TENTACLE || dispID == CREID_TURKEY_GIANT || dispID == CREID_HORSE_PALOMINO || dispID == CREID_BLOOD_FOX || dispID == CREID_KRUMPUS_IMP || (dispID >= CREID_CHARYBDIS_TENTACLE && dispID <= CREID_PUMPKIN_FRIGHT) || (dispID >= CREID_DOG_NEWFOUNDLAND && dispID <= CREID_DOG_ROTTWEILER)) + { + return ANIM_UOP_ATTACK_1; + } + else + { + switch (g_Rand.GetVal(2)) + { + case 0: return ANIM_UOP_ATTACK_1; break; + case 1: return ANIM_UOP_ATTACK_2; break; + } + break; + } + + case ANIM_DIE_BACK: + return ANIM_UOP_DIE_BACKWARD; + + case ANIM_DIE_FORWARD: + //No die forward + if (dispID == CREID_ANIMATED_WEAPON || dispID == CREID_TUNNEL_SPIRIT_BODY || dispID == CREID_TS_TENTACLE || dispID == CREID_PARROT_BIRD || dispID == CREID_PHOENIX || dispID == CREID_TURKEY_GIANT + || dispID == CREID_HELLHOUND_ANCIENT || (dispID >= CREID_CHARYBDIS && dispID <= CREID_PUMPKIN_FRIGHT) || dispID == CREID_GIANT_GORILLA || dispID == CREID_BLOOD_FOX || dispID == CREID_FROST_MITE + || dispID == CREID_STRATOS || dispID == CREID_KRUMPUS_IMP || (dispID >= CREID_WAR_BOAR_MOUNT && dispID <= CREID_WAR_CAPYBARA_BABY) || (dispID >= CREID_RABBIT_DOOM_BABY && dispID <= CREID_DOG_ROTTWEILER)) + { + return ANIM_UOP_DIE_BACKWARD; + } + else + { + return ANIM_UOP_DIE_FORWARD; + } + + case ANIM_BLOCK: + //No Block + if (dispID == CREID_TURKEY_GIANT || dispID == CREID_CLOCKWORK_EXODUS) + { + return ANIM_UOP_STAND_COMBAT; + } + else if (dispID == CREID_ANIMATED_WEAPON || dispID == CREID_TS_TENTACLE || dispID == CREID_PARROT_BIRD || dispID == CREID_PHOENIX || dispID == CREID_CHARYBDIS_TENTACLE || dispID == CREID_PUMPKIN_FRIGHT || dispID == CREID_FROST_MITE) + { + return ANIM_UOP_GETHIT; + } + else + { + return ANIM_UOP_BLOCK; + } + + case ANIM_PILLAGE: + //Creatures with Pillage + if (dispID == CREID_GARG_FIRE || dispID == CREID_DRAGON_CRIMSON || dispID == CREID_DRAGON_PLATINUM || dispID == CREID_TROGLODYTE || dispID == CREID_GRUBBER || dispID == CREID_BLOODWORM || dispID == CREID_VOLLEM || dispID == CREID_GOBLIN_GRAY + || dispID == CREID_STONE_FORM || (dispID >= CREID_MADDENING_HORROR && dispID <= CREID_GOBLIN_GREEN_MAGE) || dispID == CREID_MEDUSA || dispID == CREID_SKREE || dispID == CREID_SPIDER_TRAPDOOR || dispID == CREID_FIRE_ANT || dispID == CREID_DREAM_WRAITH + || dispID == CREID_SLASHER_VEILS || dispID == CREID_GARG_ENSLAVED || dispID == CREID_DRAGON_STYGIAN || dispID == CREID_RISING_COLOSSUS || dispID == CREID_LICH_PRIMEVAL || dispID == CREID_SCALIS || dispID == CREID_MINOTAUR_LORD + || dispID == CREID_DRAGON_TURTLE || dispID == CREID_SAUROSAURUS || dispID == CREID_MYRMIDEX_LARVAE || dispID == CREID_DRAGON_TURTLE_HATCHL || dispID == CREID_MYRMIDEX_DRONE || dispID == CREID_MYRMIDEX_WARRIOR || dispID == CREID_ZIPACTRIOTL || dispID == CREID_KHAL_ANKUR) + { + return ANIM_UOP_PILLAGE; + } + else + { + return ANIM_UOP_FIDGET; + } + + case ANIM_STOMP: + return ANIM_UOP_ROAR; + + case ANIM_FLY: + return ANIM_UOP_FLY; + + case ANIM_ALERT: + return ANIM_UOP_PEACE_TO_COMBAT; + + case ANIM_SPECIAL: + return ANIM_UOP_SPECIAL; + + case ANIM_BOSS_SPECIAL_1: + case ANIM_HORSE_RIDE_SLOW: + return ANIM_UOP_WALK_MOUNTED; + + case ANIM_BOSS_SPECIAL_2: + case ANIM_HORSE_RIDE_FAST: + return ANIM_UOP_RUN_MOUNTED; + + case ANIM_HORSE_STAND: + return ANIM_UOP_STAND_MOUNTED; + + case ANIM_SUMMON: + if (dispID == CREID_WILD_TIGER || dispID == CREID_TIGER_ETHEREAL || (dispID >= CREID_GIANT_GORILLA && dispID <= CREID_TYRANNOSAURUS_REX) || dispID == CREID_LASHER || dispID == CREID_HORSE_PALOMINO + || (dispID >= CREID_TRICERATOPS && dispID <= CREID_FROST_MITE) || dispID == CREID_LION || dispID == CREID_HYDROS || (dispID >= CREID_LITHOS && dispID <= CREID_PYROS) || dispID == CREID_TIGER_UNDEAD + || (dispID >= CREID_CRAB_COCONUT_MOUNT && dispID <= CREID_CRAB_COCONUT_LARGE) || (dispID >= CREID_WAR_BOAR_MOUNT && dispID <= CREID_WAR_CAPYBARA_BABY) || (dispID >= CREID_RABBIT_DOOM_BABY && dispID <= CREID_DOG_ROTTWEILER)) + { + return ANIM_UOP_ROAR; + } + else if (dispID == CREID_PARROT_BIRD) + { + return ANIM_UOP_GETHIT; + } + else if (dispID == CREID_PHOENIX || dispID == CREID_TURKEY_GIANT || dispID == CREID_PUMPKIN_DEMON || dispID == CREID_PUMPKIN_FRIGHT) + { + return ANIM_UOP_PEACE_TO_COMBAT; + } + else + { + return ANIM_UOP_SPECIAL; + } + + default: + return ANIM_WALK_UNARM; + } + } + //Sea Monster: H slot with only 9 actions in L slot order + //Only Sea Serpent and Dolphin + else if (mobTypesRow.m_type == 1) + { + switch (action) + { + case ANIM_WALK_UNARM: + case ANIM_WALK_ARM: + case ANIM_WALK_WAR: + return ANIM_MON_WALK; + + case ANIM_RUN_UNARM: + case ANIM_RUN_ARMED: + return ANIM_MON_STAND; + + case ANIM_STAND: + case ANIM_STAND_WAR_1H: + case ANIM_STAND_WAR_2H: + return ANIM_MON_DIE1; + + case ANIM_FIDGET1: + return ANIM_MON_DIE2; + + case ANIM_FIDGET_YAWN: + return ANIM_MON_ATTACK1; + + case ANIM_CAST_DIR: + if (dispID == CREID_DOLPHIN) //Dolphin doesn't have ANIM_MON_ATTACK2 and ANIM_MON_ATTACK3 + return ANIM_MON_AttackBow; + else + return ANIM_MON_ATTACK2; + + case ANIM_CAST_AREA: + if (dispID == CREID_DOLPHIN) //Dolphin doesn't have ANIM_MON_ATTACK2 and ANIM_MON_ATTACK3 + return ANIM_MON_DIE2; + else + return ANIM_MON_ATTACK3; + + case ANIM_GET_HIT: + return ANIM_MON_AttackBow; + + case ANIM_ATTACK_1H_SLASH: + case ANIM_ATTACK_1H_PIERCE: + case ANIM_ATTACK_1H_BASH: + case ANIM_ATTACK_2H_BASH: + case ANIM_ATTACK_2H_SLASH: + case ANIM_ATTACK_2H_PIERCE: + case ANIM_ATTACK_BOW: + case ANIM_ATTACK_XBOW: + case ANIM_ATTACK_WRESTLE: + if (dispID == CREID_DOLPHIN) //Dolphin doesn't have ANIM_MON_ATTACK2 and ANIM_MON_ATTACK3 + { + switch (g_Rand.GetVal(2)) + { + case 0: return ANIM_MON_AttackBow; break; + case 1: return ANIM_MON_DIE2; break; + } + } + else + { + switch (g_Rand.GetVal(3)) + { + case 0: return ANIM_MON_ATTACK2; break; + case 1: return ANIM_MON_ATTACK2; break; + case 2: return ANIM_MON_ATTACK3; break; + } + } + break; + case ANIM_DIE_BACK: + case ANIM_DIE_FORWARD: + return ANIM_MON_AttackXBow; + + case ANIM_BLOCK: + return ANIM_MON_AttackBow; + + case ANIM_BOW: + case ANIM_SALUTE: + return ANIM_MON_ATTACK1; + + case ANIM_EAT: + case ANIM_PILLAGE: + case ANIM_ALERT: + return ANIM_MON_DIE2; + + case ANIM_THROW: + if (dispID == CREID_DOLPHIN) //Dolphin doesn't have ANIM_MON_ATTACK2 and ANIM_MON_ATTACK3 + { + return ANIM_MON_AttackBow; + } + else + { + return ANIM_MON_ATTACK2; + } + + case ANIM_SUMMON: + return ANIM_MON_ATTACK1; + + default: + return ANIM_MON_WALK; + } + } + //Animal + else if ((mobTypesRow.m_type == 2 && !(mobTypesRow.m_flags & ATFLAG_CalculateOffsetLowGroupExtended)) + || (mobTypesRow.m_type == 0 && (mobTypesRow.m_flags & ATFLAG_CalculateOffsetByLowGroup))) { - // All animals have all these anims thankfully - switch (action) - { - case ANIM_WALK_UNARM: - case ANIM_WALK_ARM: - case ANIM_WALK_WAR: - return ANIM_ANI_WALK; - case ANIM_RUN_UNARM: - case ANIM_RUN_ARMED: - return ANIM_ANI_RUN; - case ANIM_STAND: - case ANIM_STAND_WAR_1H: - case ANIM_STAND_WAR_2H: - - case ANIM_FIDGET1: - return ANIM_ANI_FIDGET1; - case ANIM_FIDGET_YAWN: - return ANIM_ANI_FIDGET2; - case ANIM_CAST_DIR: - return ANIM_ANI_ATTACK1; - case ANIM_CAST_AREA: - return ANIM_ANI_EAT; - case ANIM_GET_HIT: - return ANIM_ANI_GETHIT; - - case ANIM_ATTACK_1H_SLASH: - case ANIM_ATTACK_1H_PIERCE: - case ANIM_ATTACK_1H_BASH: - case ANIM_ATTACK_2H_BASH: - case ANIM_ATTACK_2H_SLASH: - case ANIM_ATTACK_2H_PIERCE: - case ANIM_ATTACK_BOW: - case ANIM_ATTACK_XBOW: - case ANIM_ATTACK_WRESTLE: - switch (g_Rand.GetVal(2)) - { - case 0: return ANIM_ANI_ATTACK1; - case 1: return ANIM_ANI_ATTACK2; - } + //Partial actions + if (dispID == CREID_PARROT || dispID == CREID_BIRD_CROW) + { + switch (action) + { + case ANIM_WALK_UNARM: + case ANIM_WALK_ARM: + case ANIM_WALK_WAR: + case ANIM_RUN_UNARM: + case ANIM_RUN_ARMED: + return ANIM_ANI_WALK; + + case ANIM_STAND: + case ANIM_STAND_WAR_1H: + case ANIM_STAND_WAR_2H: + return ANIM_ANI_STAND; + + case ANIM_FIDGET1: + case ANIM_CAST_DIR: + case ANIM_CAST_AREA: + case ANIM_GET_HIT: + case ANIM_BLOCK: + case ANIM_DIE_BACK: + case ANIM_DIE_FORWARD: + case ANIM_ALERT: + case ANIM_SUMMON: + return ANIM_ANI_FIDGET1; + + case ANIM_FIDGET_YAWN: + case ANIM_ATTACK_1H_SLASH: + case ANIM_ATTACK_1H_PIERCE: + case ANIM_ATTACK_1H_BASH: + case ANIM_ATTACK_2H_BASH: + case ANIM_ATTACK_2H_SLASH: + case ANIM_ATTACK_2H_PIERCE: + case ANIM_ATTACK_BOW: + case ANIM_ATTACK_XBOW: + case ANIM_ATTACK_WRESTLE: + case ANIM_BOW: + case ANIM_SALUTE: + case ANIM_EAT: + case ANIM_PILLAGE: + case ANIM_THROW: + return ANIM_ANI_FIDGET2; + + default: + return ANIM_ANI_STAND; + } + } + + ushort attackActions = 2; + + // Standard and Custom Anims + switch (action) + { + case ANIM_WALK_UNARM: + case ANIM_WALK_ARM: + case ANIM_WALK_WAR: + return ANIM_ANI_WALK; + + case ANIM_RUN_UNARM: + case ANIM_RUN_ARMED: + return ANIM_ANI_RUN; + + case ANIM_STAND: + case ANIM_STAND_WAR_1H: + case ANIM_STAND_WAR_2H: + return ANIM_ANI_STAND; + + case ANIM_FIDGET1: + if (pCharDef->m_Anims & AFLAG_CUST_ANI_NO_FIDGET1) + { + if (!(pCharDef->m_Anims & AFLAG_CUST_ANI_NO_FIDGET2)) + { + return ANIM_ANI_FIDGET2; + } + else + { + return ANIM_ANI_STAND; + } + } + else + { + return ANIM_ANI_FIDGET1; + } + + case ANIM_FIDGET_YAWN: + if (pCharDef->m_Anims & AFLAG_CUST_ANI_NO_FIDGET2) + { + if (!(pCharDef->m_Anims & AFLAG_CUST_ANI_NO_FIDGET1)) + { + return ANIM_ANI_FIDGET1; + } + else + { + return ANIM_ANI_STAND; + } + } + else + { + return ANIM_ANI_FIDGET2; + } + + case ANIM_CAST_DIR: + return ANIM_ANI_ATTACK1; + + case ANIM_CAST_AREA: + if (pCharDef->m_Anims & AFLAG_CUST_ANI_NO_EAT) + { + return ANIM_ANI_ATTACK1; + } + else + { + return ANIM_ANI_EAT; + } + + case ANIM_GET_HIT: + if (pCharDef->m_Anims & AFLAG_CUST_ANI_NO_GETHIT) + { + if (pCharDef->m_Anims & AFLAG_CUST_ANI_NO_FIDGET1) + { + if (!(pCharDef->m_Anims & AFLAG_CUST_ANI_NO_FIDGET2)) + { + return ANIM_ANI_FIDGET2; + } + else + { + return ANIM_ANI_STAND; + } + } + else + { + return ANIM_ANI_FIDGET1; + } + } + else + { + return ANIM_ANI_GETHIT; + } + + case ANIM_ATTACK_1H_SLASH: + case ANIM_ATTACK_1H_PIERCE: + case ANIM_ATTACK_1H_BASH: + case ANIM_ATTACK_2H_BASH: + case ANIM_ATTACK_2H_SLASH: + case ANIM_ATTACK_2H_PIERCE: + case ANIM_ATTACK_BOW: + case ANIM_ATTACK_XBOW: + case ANIM_ATTACK_WRESTLE: + case ANIM_THROW: + if (pCharDef->m_Anims & AFLAG_CUST_ANI_NO_ATTACK2) + { + attackActions--; + } + + switch (g_Rand.GetVal(attackActions)) + { + case 0: return ANIM_ANI_ATTACK1; break; + case 1: return ANIM_ANI_ATTACK2; break; + } break; - case ANIM_DIE_BACK: - return ANIM_ANI_DIE1; - case ANIM_DIE_FORWARD: - return ANIM_ANI_DIE2; - case ANIM_BLOCK: - case ANIM_BOW: - case ANIM_SALUTE: - return ANIM_ANI_SLEEP; - case ANIM_EAT: - return ANIM_ANI_EAT; - default: - break; - } - ASSERT(action < ANIM_MASK_MAX); - while (action != ANIM_WALK_UNARM && !(pCharDef->m_Anims & (1ULL << action))) - { - // This anim is not supported. Try to use one that is. - switch (action) - { - case ANIM_ANI_SLEEP: // All have this. - return ANIM_ANI_EAT; - default: - return ANIM_WALK_UNARM; - } - } + case ANIM_DIE_BACK: + return ANIM_ANI_DIE1; + + case ANIM_DIE_FORWARD: + if (pCharDef->m_Anims & AFLAG_CUST_ANI_NO_DIE2) + { + return ANIM_ANI_DIE1; + } + else + { + return ANIM_ANI_DIE2; + } + + case ANIM_BLOCK: + return ANIM_ANI_GETHIT; + + case ANIM_BOW: + case ANIM_SALUTE: + if (pCharDef->m_Anims & AFLAG_CUST_ANI_NO_LIEDOWN) + { + if (pCharDef->m_Anims & AFLAG_CUST_ANI_NO_FIDGET1) + { + if (!(pCharDef->m_Anims & AFLAG_CUST_ANI_NO_FIDGET2)) + { + return ANIM_ANI_FIDGET2; + } + else + { + return ANIM_ANI_STAND; + } + } + else + { + return ANIM_ANI_FIDGET1; + } + } + //No Lie Down + else if (dispID == CREID_CAT || dispID == CREID_PANTHER || dispID == CREID_COW_BW || dispID == CREID_DOG || dispID == CREID_WOLF_TIMBER || (dispID >= CREID_COW_BROWN && dispID <= CREID_BULL_BROWN_DK)) + { + return ANIM_ANI_FIDGET1; + } + else if (dispID == CREID_SQUIRREL) + { + return ANIM_ANI_FIDGET2; + } + else + { + return ANIM_ANI_SLEEP; + } + + case ANIM_EAT: + case ANIM_PILLAGE: + if (pCharDef->m_Anims & AFLAG_CUST_ANI_NO_EAT) + { + if (pCharDef->m_Anims & AFLAG_CUST_ANI_NO_FIDGET1) + { + if (!(pCharDef->m_Anims & AFLAG_CUST_ANI_NO_FIDGET2)) + { + return ANIM_ANI_FIDGET2; + } + else + { + return ANIM_ANI_STAND; + } + } + else + { + return ANIM_ANI_FIDGET1; + } + } + else + { + return ANIM_ANI_EAT; + } + + case ANIM_ALERT: + if (pCharDef->m_Anims & AFLAG_CUST_ANI_NO_ALERT) + { + if (pCharDef->m_Anims & AFLAG_CUST_ANI_NO_FIDGET1) + { + if (!(pCharDef->m_Anims & AFLAG_CUST_ANI_NO_FIDGET2)) + { + return ANIM_ANI_FIDGET2; + } + else + { + return ANIM_ANI_STAND; + } + } + else + { + return ANIM_ANI_FIDGET1; + } + } + //No Alert + else if (dispID == CREID_SQUIRREL) + { + return ANIM_ANI_FIDGET2; + } + //Bugged Alert + else if (dispID == CREID_CAT || dispID == CREID_PANTHER || dispID == CREID_COW_BW || dispID == CREID_DOG || dispID == CREID_WOLF_TIMBER || (dispID >= CREID_COW_BROWN && dispID <= CREID_BULL_BROWN_DK)) + { + return ANIM_ANI_FIDGET2; + } + else + { + return ANIM_ANI_ALERT; + } + + case ANIM_SUMMON: + return ANIM_ANI_ATTACK1; + + default: + return ANIM_ANI_STAND; + } } - else - { - // Monsters don't have all the anims. + else + { + // Monsters don't have all the anims. + + ANIM_TYPE attack1 = ANIM_MON_ATTACK1; + ANIM_TYPE cast1 = ANIM_MON_WALK, cast2 = ANIM_MON_WALK, cast3 = ANIM_MON_WALK; + ushort castActions = 0, attackActions = 3, blockActions = 2; + + //Standard and Custom Anims + switch (action) + { + case ANIM_WALK_UNARM: + case ANIM_WALK_ARM: + case ANIM_WALK_WAR: + return ANIM_MON_WALK; + + case ANIM_RUN_UNARM: + case ANIM_RUN_ARMED: + //If the creature can fly we can use flying action for running + if ((mobTypesRow.m_flags & ATFLAG_CanFlying) + || (pCharDef->m_Anims & AFLAG_CUST_MON_FLY)) //Custom anims with Fly action + { + return ANIM_MON_FLY; + } + else + { + return ANIM_MON_WALK; + } + + case ANIM_STAND: + case ANIM_STAND_WAR_1H: + case ANIM_STAND_WAR_2H: + //Stand action in crossbow + if (mobTypesRow.m_flags & ATFLAG_IdleAt8Frame) + { + return ANIM_MON_AttackXBow; + } + else + { + return ANIM_MON_STAND; + } + + case ANIM_FIDGET1: + case ANIM_BOW: + if (pCharDef->m_Anims & AFLAG_CUST_MON_NO_FIDGET1) //Custom Anims without Fidget1 + { + if (!(pCharDef->m_Anims & AFLAG_CUST_MON_NO_FIDGET2)) //Custom Anims with Fidget2 + { + return ANIM_MON_FIDGET2; + } + else + { + return ANIM_MON_STAND; + } + } + else + { + return ANIM_MON_FIDGET1; + } + + case ANIM_FIDGET_YAWN: + case ANIM_SALUTE: + case ANIM_EAT: + if (pCharDef->m_Anims & AFLAG_CUST_MON_NO_FIDGET2) //Custom Anims without Fidget2 + { + if (!(pCharDef->m_Anims & AFLAG_CUST_MON_NO_FIDGET1)) //Custom Anims with Fidget1 + { + return ANIM_MON_FIDGET1; + } + else + { + return ANIM_MON_STAND; + } + } + else if (dispID == CREID_EAGLE || dispID == CREID_DRAGON_CRIMSON || dispID == CREID_DRAGON_PLATINUM) //No Fidget + { + return ANIM_MON_FIDGET1; + } + else + { + return ANIM_MON_FIDGET2; + } + + case ANIM_CAST_DIR: + case ANIM_CAST_AREA: + case ANIM_ATTACK_BOW: //return ANIM_MON_AttackBow; //Always Empty except for standard ID 13, 15 and 16 + case ANIM_ATTACK_XBOW: //return ANIM_MON_AttackXBow; //Always Empty except for standard ID 13, 15 and 16 + + //Check how many cast actions are present + //Stomp action is not a cast for Corpser, Earth Elemental and Gorilla + if (((mobTypesRow.m_flags & ATFLAG_StompAction) + && (dispID != CREID_CORPSER && dispID != CREID_EARTH_ELEM && dispID != CREID_GORILLA)) + || (pCharDef->m_Anims & AFLAG_CUST_MON_STOMP)) //Custom Anim with Stomp action + { + cast1 = ANIM_MON_Stomp; + castActions++; + } + //Cast 2 + if (dispID == CREID_TERA_MATRIARCH || dispID == CREID_OPHID_SHAMAN || dispID == CREID_GARGOYLE || dispID == CREID_DEMON || dispID == CREID_DEMON_SWORD || dispID == CREID_LICH + || (pCharDef->m_Anims & AFLAG_CUST_MON_CAST2)) //Custom Anim with Cast2 action + { + if (castActions == 0) + { + cast1 = ANIM_MON_Cast2; + } + else + { + cast2 = ANIM_MON_Cast2; + } + castActions++; + } + //Cast 3 + if (dispID == CREID_TERA_MATRIARCH || dispID == CREID_OPHID_SHAMAN + || (pCharDef->m_Anims & AFLAG_CUST_MON_CAST3)) //Custom Anim with Cast3 action + { + if (castActions == 0) + { + cast1 = ANIM_MON_Cast3; + } + else if (castActions == 1) + { + cast2 = ANIM_MON_Cast3; + } + else + { + cast3 = ANIM_MON_Cast3; + } + castActions++; + } + + if (castActions > 0) + { + switch (g_Rand.GetVal(castActions)) + { + case 0: return cast1; break; + case 1: return cast2; break; + case 2: return cast3; break; + } + } + else //No cast Actions + { + if (mobTypesRow.m_flags & ATFLAG_ReplaceAttack1With2) + { + attack1 = ANIM_MON_ATTACK2; + } + + //Special handling for custom anims (some WOW anims) with attacks 4-6 in 9-11 + if (pCharDef->m_Anims & AFLAG_CUST_MON_ATTACKSFROM9) + { + switch (g_Rand.GetVal(3)) + { + case 0: return ANIM_MON_AttackThrow; break; + case 1: return ANIM_MON_GETHIT; break; + case 2: return ANIM_MON_PILLAGE; break; + } + } + + if (dispID == CREID_SHADOW_LORD + || (pCharDef->m_Anims & AFLAG_CUST_MON_NO_ATTACK1)) //Custom Anim without Attack1 + { + attackActions--; + } + if (dispID == CREID_EAGLE || dispID == CREID_SHADOW_LORD + || (pCharDef->m_Anims & AFLAG_CUST_MON_NO_ATTACK2)) //Custom Anim without Attack2 + { + attackActions--; + } + if (dispID == CREID_EAGLE || dispID == CREID_DRAGON_CRIMSON || dispID == CREID_DRAGON_PLATINUM || dispID == CREID_SHADOW_LORD + || (pCharDef->m_Anims & AFLAG_CUST_MON_NO_ATTACK3)) //Custom Anim without Attack3 + { + attackActions--; + } + + if (attackActions > 0) + { + switch (g_Rand.GetVal(attackActions)) + { + case 0: return attack1; break; + case 1: return ANIM_MON_ATTACK2; break; + case 2: return ANIM_MON_ATTACK3; break; + } + } + else if (dispID == CREID_SHADOW_LORD) //No Attacks + { + switch (g_Rand.GetVal(2)) + { + case 0: return ANIM_MON_FIDGET1; break; + case 1: return ANIM_MON_FIDGET2; break; + } + } + else + { + return ANIM_MON_STAND; + } + } + break; - switch (action) - { - case ANIM_CAST_DIR: - return ANIM_MON_Stomp; - case ANIM_CAST_AREA: - return ANIM_MON_PILLAGE; - case ANIM_DIE_BACK: - return ANIM_MON_DIE1; - case ANIM_DIE_FORWARD: - return ANIM_MON_DIE2; - case ANIM_GET_HIT: - switch (g_Rand.GetValFast(3)) - { - case 0: return ANIM_MON_GETHIT; break; - case 1: return ANIM_MON_BlockRight; break; - case 2: return ANIM_MON_BlockLeft; break; - } - break; - case ANIM_ATTACK_1H_SLASH: - case ANIM_ATTACK_1H_PIERCE: - case ANIM_ATTACK_1H_BASH: - case ANIM_ATTACK_2H_BASH: - case ANIM_ATTACK_2H_PIERCE: - case ANIM_ATTACK_2H_SLASH: - case ANIM_ATTACK_BOW: - case ANIM_ATTACK_XBOW: - case ANIM_ATTACK_WRESTLE: - switch (g_Rand.GetValFast(3)) - { - case 0: return ANIM_MON_ATTACK1; - case 1: return ANIM_MON_ATTACK2; - case 2: return ANIM_MON_ATTACK3; - } + case ANIM_GET_HIT: + if (IsStatFlag(STATF_FLY | STATF_HOVERING)) //Running or Flying + { + if (mobTypesRow.m_flags & ATFLAG_Use2IfHittedWhileRunning) + { + return ANIM_MON_DIE1; + } + //GetHit while flying + else if ((mobTypesRow.m_flags & ATFLAG_CanFlying) && !(mobTypesRow.m_flags & ATFLAG_Use10IfHittedWhileFlying)) + { + return ANIM_MON_DIE_FLIGHT; + } + } + if (mobTypesRow.m_flags & ATFLAG_ReplaceGetHitBlockPillage) + { + return ANIM_MON_STAND; + } + else if (pCharDef->m_Anims & AFLAG_CUST_MON_ATTACKSFROM9) //Custom Anims with GetHit in Land/TakeOff action + { + return ANIM_MON_LAND; + } + else if (pCharDef->m_Anims & AFLAG_CUST_MON_NO_GETHIT) //Cutsom Anims without GetHit + { + if (pCharDef->m_Anims & AFLAG_CUST_MON_NO_BLOCKR) + { + blockActions--; + } + if (pCharDef->m_Anims & AFLAG_CUST_MON_NO_BLOCKL) + { + blockActions--; + } + if (blockActions > 0) + { + switch (g_Rand.GetVal(blockActions)) + { + case 0: return ANIM_MON_BlockRight; break; + case 1: return ANIM_MON_BlockLeft; break; + } + } + else + { + return ANIM_MON_STAND; + } + } + else if (dispID == CREID_BIRD || dispID == CREID_GAZER || dispID == CREID_SHADOW_LORD) //No GetHit + { + return ANIM_MON_FIDGET1; + } + else + { + return ANIM_MON_GETHIT; + } break; - default: - return ANIM_WALK_UNARM; - } - // NOTE: Available actions depend HEAVILY on creature type ! - // ??? Monsters don't have all anims in common ! - // translate these ! - ASSERT(action < ANIM_MASK_MAX); - while (action != ANIM_WALK_UNARM && !(pCharDef->m_Anims & (1ULL << action))) - { - // This anim is not supported. Try to use one that is. - switch (action) - { - case ANIM_MON_ATTACK1: // All have this. - DEBUG_ERR(("Anim 0%x This is wrong! Invalid SCP file data.\n", GetDispID())); - return ANIM_WALK_UNARM; - - case ANIM_MON_ATTACK2: // Dolphins, Eagles don't have this. - case ANIM_MON_ATTACK3: - return ANIM_MON_ATTACK1; // ALL creatures have at least this attack. - case ANIM_MON_Cast2: // Trolls, Spiders, many others don't have this. - return ANIM_MON_BlockRight; // Birds don't have this ! - case ANIM_MON_BlockRight: - return ANIM_MON_BlockLeft; - case ANIM_MON_BlockLeft: - return ANIM_MON_GETHIT; - case ANIM_MON_GETHIT: - if (pCharDef->m_Anims & (1 << ANIM_MON_Cast2)) - return ANIM_MON_Cast2; - else - return ANIM_WALK_UNARM; - - case ANIM_MON_Stomp: - return ANIM_MON_PILLAGE; - case ANIM_MON_PILLAGE: - return ANIM_MON_ATTACK3; - case ANIM_MON_AttackBow: - case ANIM_MON_AttackXBow: - return ANIM_MON_ATTACK3; - case ANIM_MON_AttackThrow: - return ANIM_MON_AttackXBow; - default: - DEBUG_ERR(("Anim Unsupported 0%x for 0%x\n", action, GetDispID())); - return ANIM_WALK_UNARM; - } - } + case ANIM_ATTACK_1H_SLASH: + case ANIM_ATTACK_1H_PIERCE: + case ANIM_ATTACK_1H_BASH: + case ANIM_ATTACK_2H_BASH: + case ANIM_ATTACK_2H_SLASH: + case ANIM_ATTACK_2H_PIERCE: + case ANIM_ATTACK_WRESTLE: + + if (mobTypesRow.m_flags & ATFLAG_ReplaceAttack1With2) + { + attack1 = ANIM_MON_ATTACK2; + } + + //Special handling for custom anims (some WOW anims) with attacks 4-6 in 9-11 + if (pCharDef->m_Anims & AFLAG_CUST_MON_ATTACKSFROM9) + { + switch (g_Rand.GetVal(3)) + { + case 0: return ANIM_MON_AttackThrow; break; + case 1: return ANIM_MON_GETHIT; break; + case 2: return ANIM_MON_PILLAGE; break; + } + } + + if (dispID == CREID_SHADOW_LORD + || (pCharDef->m_Anims & AFLAG_CUST_MON_NO_ATTACK1)) //Custom Anim without Attack1 + { + attackActions--; + } + if (dispID == CREID_EAGLE || dispID == CREID_SHADOW_LORD + || (pCharDef->m_Anims & AFLAG_CUST_MON_NO_ATTACK2)) //Custom Anim without Attack2 + { + attackActions--; + } + if (dispID == CREID_EAGLE || dispID == CREID_DRAGON_CRIMSON || dispID == CREID_DRAGON_PLATINUM || dispID == CREID_SHADOW_LORD + || (pCharDef->m_Anims & AFLAG_CUST_MON_NO_ATTACK3)) //Custom Anim without Attack3 + { + attackActions--; + } + + if (attackActions > 0) + { + switch (g_Rand.GetVal(attackActions)) + { + case 0: return attack1; break; + case 1: return ANIM_MON_ATTACK2; break; + case 2: return ANIM_MON_ATTACK3; break; + } + } + else if (dispID == CREID_SHADOW_LORD) //No Attacks + { + switch (g_Rand.GetVal(2)) + { + case 0: return ANIM_MON_FIDGET1; break; + case 1: return ANIM_MON_FIDGET2; break; + } + } + else + { + return ANIM_MON_STAND; + } + break; + + case ANIM_DIE_BACK: + //Die while flying animation + if ((mobTypesRow.m_flags & ATFLAG_StompAction) && (mobTypesRow.m_flags & ATFLAG_CanFlying) && (mobTypesRow.m_flags & ATFLAG_Use10IfHittedWhileFlying) + && IsStatFlag(STATF_FLY | STATF_HOVERING)) + { + return ANIM_MON_DIE_FLIGHT; + } + else + { + return ANIM_MON_DIE1; + } + + case ANIM_DIE_FORWARD: + //Die while flying animation + if ((mobTypesRow.m_flags & ATFLAG_StompAction) && (mobTypesRow.m_flags & ATFLAG_CanFlying) && (mobTypesRow.m_flags & ATFLAG_Use10IfHittedWhileFlying) + && IsStatFlag(STATF_FLY | STATF_HOVERING)) + { + return ANIM_MON_DIE_FLIGHT; + } + else if (pCharDef->m_Anims & AFLAG_CUST_MON_NO_DIE2) //Custom Anims without Die2 + { + return ANIM_MON_DIE1; + } + else if (dispID == CREID_SHADOW_LORD) //No Die2 + { + return ANIM_MON_DIE1; + } + else + { + return ANIM_MON_DIE2; + } + + case ANIM_BLOCK: + if (mobTypesRow.m_flags & ATFLAG_ReplaceGetHitBlockPillage) + { + return ANIM_MON_STAND; + } + else if (pCharDef->m_Anims & AFLAG_CUST_MON_ATTACKSFROM9) //Custom Anims with only Block Left + { + return ANIM_MON_BlockLeft; + } + else if (dispID == CREID_BIRD || dispID == CREID_GAZER || dispID == CREID_SLIME || dispID == CREID_SHADOW_LORD) //No block + { + return ANIM_MON_FIDGET2; + } + + if (dispID == CREID_EAGLE || dispID == CREID_CORPSER + || (pCharDef->m_Anims & AFLAG_CUST_MON_NO_BLOCKR)) //Custom anims without BlockRight + { + blockActions--; + } + if (dispID == CREID_EAGLE || dispID == CREID_CORPSER || dispID == CREID_DRAGON_CRIMSON || dispID == CREID_DRAGON_PLATINUM + || (pCharDef->m_Anims & AFLAG_CUST_MON_NO_BLOCKL)) //Custom anims without BlockLeft + { + blockActions--; + } + if (blockActions > 0) + { + switch (g_Rand.GetVal(blockActions)) + { + case 0: return ANIM_MON_BlockRight; break; + case 1: return ANIM_MON_BlockLeft; break; + } + } + else if (pCharDef->m_Anims & AFLAG_CUST_MON_NO_GETHIT) //Custom anims without GetHit + { + return ANIM_MON_STAND; + } + else + { + return ANIM_MON_GETHIT; + } + break; + + case ANIM_THROW: + if (mobTypesRow.m_flags & ATFLAG_IdleAt8Frame) //Action Throw in Bow action + { + return ANIM_MON_AttackBow; + } + else if (((mobTypesRow.m_flags & ATFLAG_StompAction) + && (dispID != CREID_CORPSER && dispID != CREID_EARTH_ELEM && dispID != CREID_GORILLA)) + || (pCharDef->m_Anims & AFLAG_CUST_MON_STOMP)) //Custom anims with Stomp action + { + return ANIM_MON_Stomp; + } + else + { + if (pCharDef->m_Anims & AFLAG_CUST_MON_ATTACKSFROM9) //Custom anims with first attack in AttackThrow + { + return ANIM_MON_AttackThrow; + } + else if (pCharDef->m_Anims & AFLAG_CUST_MON_NO_ATTACK1) //Custom anims without Attack1 + { + return ANIM_MON_STAND; + } + else + { + return ANIM_MON_ATTACK1; + //return ANIM_MON_AttackThrow; //Always Empty except for Custom Anims with AFLAG_CUST_MON_ATTACKSFROM9 flag + } + } + + case ANIM_PILLAGE: + if (mobTypesRow.m_flags & ATFLAG_ReplaceGetHitBlockPillage) + { + return ANIM_MON_FIDGET1; + } + else if (pCharDef->m_Anims & AFLAG_CUST_MON_ATTACKSFROM9) + { + return ANIM_MON_FIDGET1; + } + else if ((pCharDef->m_Anims & AFLAG_CUST_MON_NO_PILLAGE) && (!(pCharDef->m_Anims & AFLAG_CUST_MON_NO_FIDGET1))) //Custom Anims with No Pillage but Fidget1 + { + return ANIM_MON_FIDGET1; + } + else if ((pCharDef->m_Anims & AFLAG_CUST_MON_NO_PILLAGE) && (!(pCharDef->m_Anims & AFLAG_CUST_MON_NO_FIDGET2))) //Custom Anims with No Pillage but Fidget2 + { + return ANIM_MON_FIDGET2; + } + else if (dispID == CREID_BIRD || dispID == CREID_EAGLE || dispID == CREID_GAZER || dispID == CREID_SHADOW_LORD) //No Pillage + { + return ANIM_MON_FIDGET1; + } + else if (dispID == CREID_CORPSER) //No Pillage + { + return ANIM_MON_FIDGET2; + } + else + { + return ANIM_MON_PILLAGE; + } + + case ANIM_STOMP: + case ANIM_SPECIAL: + case ANIM_SUMMON: + if ((mobTypesRow.m_flags & ATFLAG_StompAction) || (pCharDef->m_Anims & AFLAG_CUST_MON_STOMP)) + { + return ANIM_MON_Stomp; + } + else if ((mobTypesRow.m_flags & ATFLAG_CanFlying) && !(pCharDef->m_Anims & AFLAG_CUST_MON_FLY)) //Standard flying anims with Land/TakeOff action + { + return ANIM_MON_LAND; + } + else + { + if (dispID == CREID_SHADOW_LORD) //No Attack + { + return ANIM_MON_FIDGET1; + } + else if (pCharDef->m_Anims & AFLAG_CUST_MON_ATTACKSFROM9) //Custom anims with first attack in AttackThrow + { + return ANIM_MON_AttackThrow; + } + else if (pCharDef->m_Anims & AFLAG_CUST_MON_NO_ATTACK1) //Custom anims without Attack1 + { + return ANIM_MON_STAND; + } + else + { + return ANIM_MON_ATTACK1; + } + } + + case ANIM_ALERT: + if (((mobTypesRow.m_flags & ATFLAG_StompAction) && dispID != CREID_CORPSER && dispID != CREID_EARTH_ELEM) + || (pCharDef->m_Anims & AFLAG_CUST_MON_STOMP)) //Custom anims with Stomp action + { + return ANIM_MON_Stomp; + } + else if ((mobTypesRow.m_flags & ATFLAG_CanFlying) && !(pCharDef->m_Anims & AFLAG_CUST_MON_FLY)) //Standard flying anims with Land/TakeOff action + { + return ANIM_MON_LAND; + } + else + { + return ANIM_MON_STAND; + } + + case ANIM_FLY: + if (mobTypesRow.m_flags & ATFLAG_ReplaceFlyAction) + { + return ANIM_MON_WALK; + } + else + { + return ANIM_MON_FLY; + } + + case ANIM_LAND: + if (mobTypesRow.m_flags & ATFLAG_ReplaceFlyAction) + { + return ANIM_MON_STAND; + } + else + { + return ANIM_MON_LAND; + } + + case ANIM_GETHIT_AIR: + if (mobTypesRow.m_flags & ATFLAG_ReplaceFlyAction) + { + return ANIM_MON_STAND; + } + else if (mobTypesRow.m_flags & ATFLAG_Use10IfHittedWhileFlying) + { + return ANIM_MON_GETHIT; + } + else + { + return ANIM_MON_DIE_FLIGHT; + } + + default: + return ANIM_MON_STAND; + } } } + else + { + //Not mounted human + switch (action) + { + case ANIM_ALERT: + return ANIM_FIDGET1; + case ANIM_SUMMON: + return ANIM_SALUTE; + case ANIM_PILLAGE: + return ANIM_BOW; + case ANIM_THROW: + return ANIM_ATTACK_1H_BASH; + } + } } return action; diff --git a/src/game/chars/CCharAttacker.cpp b/src/game/chars/CCharAttacker.cpp index c43e8ecbd..7b449d1e2 100644 --- a/src/game/chars/CCharAttacker.cpp +++ b/src/game/chars/CCharAttacker.cpp @@ -23,6 +23,11 @@ bool CChar::Attacker_Add(CChar * pChar, int threat) TRIGRET_TYPE tRet = OnTrigger(CTRIG_CombatStart, pChar, 0); if (tRet == TRIGRET_RET_TRUE) return false; + else + { + if (pChar->IsNPC()) + UpdateAnimate(ANIM_ALERT); + } } CScriptTriggerArgs Args; diff --git a/src/game/chars/CCharBase.cpp b/src/game/chars/CCharBase.cpp index a4483eafb..4914a6063 100644 --- a/src/game/chars/CCharBase.cpp +++ b/src/game/chars/CCharBase.cpp @@ -20,7 +20,7 @@ CCharBase::CCharBase( CREID_TYPE id ) : m_defense = 0; m_defenseBase = 0; m_defenseRange = 0; - m_Anims = 0xFFFFFF; + m_Anims = 0; m_MaxFood = 0; // Default value _wBloodHue = 0; m_wColor = 0; diff --git a/src/game/chars/CCharNPCAct.cpp b/src/game/chars/CCharNPCAct.cpp index eb79497c2..f9c28d38b 100644 --- a/src/game/chars/CCharNPCAct.cpp +++ b/src/game/chars/CCharNPCAct.cpp @@ -1573,6 +1573,8 @@ void CChar::NPC_Act_Looting() Speak(g_Cfg.GetDefaultMsg(DEFMSG_LOOT_RUMMAGE), HUE_TEXT_DEF, TALKMODE_EMOTE); ItemBounce(pItem, false); + UpdateAnimate(ANIM_PILLAGE); + SetTimeout(1000); } bool CChar::NPC_Act_Flee() diff --git a/src/game/chars/CCharSpell.cpp b/src/game/chars/CCharSpell.cpp index c97448fc3..922a9f068 100644 --- a/src/game/chars/CCharSpell.cpp +++ b/src/game/chars/CCharSpell.cpp @@ -354,7 +354,8 @@ CChar * CChar::Spell_Summon_Place( CChar * pChar, CPointMap ptTarg, int64 iDurat //pChar->NPC_PetSetOwner(this); pChar->OnSpellEffect(SPELL_Summon, this, Skill_GetAdjusted((SKILL_TYPE)iSkill), nullptr, false, iDuration); pChar->Update(); - pChar->UpdateAnimate(ANIM_CAST_DIR); + pChar->UpdateAnimate(ANIM_SUMMON); + pChar->SetTimeout(2000); pChar->SoundChar(CRESND_GETHIT); m_Act_UID = pChar->GetUID(); // for last target stuff return pChar; diff --git a/src/game/clients/CClientTarg.cpp b/src/game/clients/CClientTarg.cpp index 3ea9bb43e..85d379fcf 100644 --- a/src/game/clients/CClientTarg.cpp +++ b/src/game/clients/CClientTarg.cpp @@ -333,7 +333,8 @@ bool CClient::OnTarg_Char_Add( CObjBase * pObj, const CPointMap & pt ) pChar->MoveToChar(pt); pChar->NPC_CreateTrigger(); // removed from NPC_LoadScript() and triggered after char placement pChar->Update(); - pChar->UpdateAnimate(ANIM_CAST_DIR); + pChar->UpdateAnimate(ANIM_SUMMON); + pChar->SetTimeout(2000); pChar->SoundChar(CRESND_GETHIT); m_pChar->m_Act_UID = pChar->GetUID(); // for last target stuff. (trigger stuff) return true; diff --git a/src/game/uo_files/CUOMobtypes.cpp b/src/game/uo_files/CUOMobtypes.cpp new file mode 100644 index 000000000..2cf64a7ee --- /dev/null +++ b/src/game/uo_files/CUOMobtypes.cpp @@ -0,0 +1,98 @@ +/** +* @file CUOMobtypes.cpp +* +*/ + +#include "../../sphere/threads.h" +#include "../../common/CException.h" +#include "../../common/CExpression.h" +#include "../../common/CLog.h" +#include "../../common/CUOInstall.h" +#include "../../game/uo_files/uofiles_enums_creid.h" +#include "CUOMobtypes.h" + +void CUOMobTypes::Load() +{ + ADDTOCALLSTACK("CUOMobTypes::Load"); + g_Log.Event(LOGM_INIT, "Caching mobtypes.txt...\n"); + + CUOMobTypesType mobTypesRow = {0,0}; + + _mobTypesEntries.clear(); + + CSFileText csvMobTypes; + + if (g_Install.OpenFile(csvMobTypes, "mobtypes.txt", (word)(OF_READ | OF_TEXT | OF_DEFAULTMODE))) + { + _mobTypesEntries.resize(CREID_QTY); + for (int i = 0; i < _mobTypesEntries.size(); i++) + { + mobTypesRow.m_type = 4; + mobTypesRow.m_flags = 0; + _mobTypesEntries[i] = mobTypesRow; + } + + tchar* pszTemp = Str_GetTemp(); + size_t count = 0; + while (!csvMobTypes.IsEOF()) + { + csvMobTypes.ReadString(pszTemp, 200); + if (*pszTemp) + { + count++; + + std::string tmpString = pszTemp; + + int len = (int)tmpString.length(); + len = Str_TrimEndWhitespace(tmpString.data(), len); + + if (len == 0 || tmpString[0] == '#') //Empty line or commented + continue; + + //Split the string + std::vector splitArray; + splitArray.resize(3); + size_t iQty = Str_ParseCmds(tmpString.data(), splitArray.data(), 3, " \t#"); + + if (splitArray.size() < 3) + { + g_Log.EventError("Mobtypes.txt: not enough parameters on line %" PRIuSIZE_T " \n", count); + continue; + } + + if (!IsStrNumeric(splitArray[0])) + { + g_Log.EventError("Mobtypes.txt: non numeric ID on line %" PRIuSIZE_T " \n", count); + continue; + } + + int animIndex = std::stoi(splitArray[0]); + std::string sType = splitArray[1]; + if (sType == "MONSTER") + mobTypesRow.m_type = 0; + else if (sType == "SEA_MONSTER") + mobTypesRow.m_type = 1; + else if (sType == "ANIMAL") + mobTypesRow.m_type = 2; + else if (sType == "HUMAN") + mobTypesRow.m_type = 3; + else if (sType == "EQUIPMENT") + mobTypesRow.m_type = 4; + else + { + mobTypesRow.m_type = 0; + g_Log.EventError("Mobtypes.txt: wrong type found on line %" PRIuSIZE_T " \n", count); + } + + mobTypesRow.m_flags = std::strtol(splitArray[2], NULL, 16); + + if (animIndex <= _mobTypesEntries.size()) //Safety check + { + _mobTypesEntries[animIndex] = mobTypesRow; + } + } + } + csvMobTypes.Close(); + } +} + diff --git a/src/game/uo_files/CUOMobtypes.h b/src/game/uo_files/CUOMobtypes.h new file mode 100644 index 000000000..7b7c2bbb7 --- /dev/null +++ b/src/game/uo_files/CUOMobtypes.h @@ -0,0 +1,45 @@ +/** +* @file CUOMobtypes.h +* +*/ + +#ifndef _INC_CUOMOBTYPES_H +#define _INC_CUOMOBTYPES_H + +#include +#include "../../common/common.h" + +/** +* mobtypes.txt +*/ +struct CUOMobTypesType +{ + ushort m_type; // 0 = MONSTER, 1 = SEA_MONSTER, 2 = ANIMAL, 3 = HUMAN, 4 = EQUIPMENT + dword m_flags; + +}; + +class CUOMobTypes +{ + std::vector _mobTypesEntries; + +public: + void Load(); + + inline const bool IsLoaded() { + if (_mobTypesEntries.size() > 0) + return true; + else + return false; + } + + inline const CUOMobTypesType* GetEntry(ushort id) { + return &(_mobTypesEntries[id]); + } +}; + + + + + +#endif // _INC_CUOMOBTYPES_H diff --git a/src/game/uo_files/uofiles_enums.h b/src/game/uo_files/uofiles_enums.h index 72f73988e..3f30306ca 100644 --- a/src/game/uo_files/uofiles_enums.h +++ b/src/game/uo_files/uofiles_enums.h @@ -227,7 +227,48 @@ enum ANIM_TYPE // not all creatures animate the same for some reason. ANIM_ANI_SLEEP = 0x0b, // lie down (not all have this) ANIM_ANI_DIE2 = 0x0c, - ANIM_QTY_ANI = 13, + ANIM_QTY_ANI = 13, + + //UOP anims + ANIM_UOP_WALK_COMBAT = 0, + ANIM_UOP_STAND_COMBAT = 1, + ANIM_UOP_DIE_BACKWARD = 2, + ANIM_UOP_DIE_FORWARD = 3, + ANIM_UOP_ATTACK_1 = 4, + ANIM_UOP_ATTACK_2 = 5, + + ANIM_UOP_GETHIT = 10, + ANIM_UOP_PILLAGE = 11, + ANIM_UOP_CAST_1 = 12, + ANIM_UOP_CAST_2 = 13, + + ANIM_UOP_BLOCK = 15, + + ANIM_UOP_FLY = 19, + + ANIM_UOP_WALK = 22, + ANIM_UOP_SPECIAL = 23, + ANIM_UOP_RUN = 24, + ANIM_UOP_STAND = 25, + ANIM_UOP_FIDGET = 26, + ANIM_UOP_ROAR = 27, + ANIM_UOP_PEACE_TO_COMBAT = 28, + ANIM_UOP_WALK_MOUNTED = 29, //Or Boss Special 1 + ANIM_UOP_RUN_MOUNTED = 30, //Or Boss Special 2 + ANIM_UOP_STAND_MOUNTED = 31, + + //Missing actions + ANIM_ALERT = 35, + ANIM_THROW = 36, + ANIM_PILLAGE = 37, + ANIM_STOMP = 38, + ANIM_FLY = 39, + ANIM_LAND = 40, + ANIM_GETHIT_AIR = 41, + ANIM_SUMMON = 42, + ANIM_SPECIAL = 43, //UOP anims + ANIM_BOSS_SPECIAL_1 = 44, //Only few UOP anims: Order Variant, Chaos Variant, Stygian Dragon, Scalis + ANIM_BOSS_SPECIAL_2 = 45, //Only few UOP anims: Order Variant, Chaos Variant, Stygian Dragon, Scalis ANIM_QTY = 0x32, ANIM_MASK_MAX = 64 // CCharBase::m_Anims bitmask can hold a maximum of 64 values (1 << 63) @@ -280,6 +321,65 @@ enum ANIM_TYPE_NEW // not all creatures animate the same for some reason. http:/ }; +enum ANIM_TYPE_FLAGS +{ + //Mobtypes.txt + ATFLAG_None = 0x00000, + ATFLAG_Use10IfHittedWhileFlying = 0x00001, + ATFLAG_Use2IfHittedWhileRunning = 0x00002, + ATFLAG_IdleAt8Frame = 0x00004, + ATFLAG_CanFlying = 0x00008, + ATFLAG_Unknown10 = 0x00010, //HUMAN 10, Unknown + ATFLAG_CalculateOffsetLowGroupExtended = 0x00020, //Animal in Monster Slot + ATFLAG_CalculateOffsetByLowGroup = 0x00040, //Monster in Animal slot + ATFLAG_ReplaceAttack1With2 = 0x00080, + ATFLAG_ReplaceGetHitBlockPillage = 0x00100, + ATFLAG_ReplaceFlyAction = 0x00200, + ATFLAG_CalculateOffsetByPeopleGroup = 0x00400, //Animal or Monster in People slot: doesn't seems to be used + ATFLAG_Unknown800 = 0x00800, //MONSTER 800, unknown: Corpser, Gazer, Reaper + ATFLAG_StompAction = 0x01000, + ATFLAG_Unknown2000 = 0x02000, //Used for UOP but unknown + ATFLAG_Unknown4000 = 0x04000, //ANIMAL 4000, Unknown (Open Animal Backpack?) Polar Bear, HIRYU, Ridgeback, Savage Ridgeback, Giant Beetle + ATFLAG_Unknown8000 = 0x08000, //HUMAN 8000, Unknown + ATFLAG_UseUopAnimation = 0x10000, + ATFLAG_HumanPaperdoll = 0x20000, //Let Open Paperdoll in Standard Client + ATFLAG_Unknown40000 = 0x40000, //Unused + ATFLAG_Unknown80000 = 0x80000, //Unused + + //Custom in monster script ANIM= + //The default configuration is with this actions: + // 0 (Walk), 1 (Stand), 2 (Die1), 3 (Die2), + // 4 (Attack1), 5 (Attack2), 6 (Attack3), + // 10 (GetHit), 11 (Pillage), 15 (Block Right), 16 (Block Left), + // 17 (Idle), 18 (Fidget) + AFLAG_CUST_MON_NO_DIE2 = 0x01, + AFLAG_CUST_MON_NO_ATTACK1 = 0x02, + AFLAG_CUST_MON_NO_ATTACK2 = 0x04, + AFLAG_CUST_MON_NO_ATTACK3 = 0x08, + AFLAG_CUST_MON_NO_GETHIT = 0x10, + AFLAG_CUST_MON_NO_PILLAGE = 0x20, + AFLAG_CUST_MON_STOMP = 0x40, + AFLAG_CUST_MON_CAST2 = 0x80, + AFLAG_CUST_MON_CAST3 = 0x100, + AFLAG_CUST_MON_NO_BLOCKR = 0x200, + AFLAG_CUST_MON_NO_BLOCKL = 0x400, + AFLAG_CUST_MON_NO_FIDGET1 = 0x800, + AFLAG_CUST_MON_NO_FIDGET2 = 0x1000, + AFLAG_CUST_MON_FLY = 0x2000, + AFLAG_CUST_MON_ATTACKSFROM9 = 0x10000, + + //Custom in animal script ANIM= + //The default configuration is with all actions: 1 - 12 + AFLAG_CUST_ANI_NO_EAT = 0x01, + AFLAG_CUST_ANI_NO_ALERT = 0x02, + AFLAG_CUST_ANI_NO_ATTACK2 = 0x04, + AFLAG_CUST_ANI_NO_GETHIT = 0x08, + AFLAG_CUST_ANI_NO_FIDGET1 = 0x10, + AFLAG_CUST_ANI_NO_FIDGET2 = 0x20, + AFLAG_CUST_ANI_NO_LIEDOWN = 0x40, + AFLAG_CUST_ANI_NO_DIE2 = 0x80 +}; + enum CRESND_TYPE // Placeholders (not real sound IDs): the SoundChar method chooses the best sound for each creature { diff --git a/src/game/uo_files/uofiles_enums_creid.h b/src/game/uo_files/uofiles_enums_creid.h index 29f9d0a8d..cb22346d2 100644 --- a/src/game/uo_files/uofiles_enums_creid.h +++ b/src/game/uo_files/uofiles_enums_creid.h @@ -405,10 +405,11 @@ enum CREID_TYPE : uint32_t // enum the creature animations. (dont allow any othe CREID_DRAGON_STYGIAN = 0x33A, CREID_TROGLODYTE = 0x10B, CREID_GRUBBER = 0x10E, - CREID_BLOODWORM = 0x11E, + CREID_BLOODWORM = 0x11F, CREID_VOLLEM = 0x125, CREID_GOBLIN_GRAY = 0x14E, CREID_BOURA_AR = 0x1B0, // Armored boura + CREID_ANIMATED_WEAPON = 0x2B4, CREID_STONE_FORM = 0x2C1, CREID_ABYSSAL_INFERNAL = 0x2C9, CREID_BEETLE_IRON = 0x2CA, @@ -438,12 +439,16 @@ enum CREID_TYPE : uint32_t // enum the creature animations. (dont allow any othe CREID_WOLF_LEATHER = 0x2E3, CREID_DREAM_WRAITH = 0x2E4, CREID_SLASHER_VEILS = 0x2E5, + CREID_TUNNEL_SPIRIT_BODY = 0x2E6, + CREID_TS_TENTACLE = 0x2E7, CREID_VAMPIRE = 0x2E8, CREID_VAMPIRE_FEMALE = 0x2E9, CREID_GARG_ENSLAVED = 0x2F1, + CREID_RISING_COLOSSUS = 0x33d, CREID_LICH_PRIMEVAL = 0x33e, - CREID_RISING_COLOSSUS = 0x33d, + CREID_PARROT_BIRD = 0x33f, + CREID_PHOENIX = 0x340, CREID_TURKEY_GIANT = 0x402, // HS (High Seas) monsters @@ -501,6 +506,22 @@ enum CREID_TYPE : uint32_t // enum the creature animations. (dont allow any othe CREID_STRATOS = 0x598, CREID_PYROS = 0x599, CREID_DRAGON_SERPENTINE_ETH = 0x59A, + CREID_TIGER_UNDEAD = 0x5A1, + CREID_KHAL_ANKUR = 0x5C7, + CREID_KRUMPUS_IMP = 0x5CD, + CREID_CRAB_COCONUT_MOUNT = 0x5E6, + CREID_CRAB_COCONUT_SMALL = 0x5E7, + CREID_CRAB_COCONUT_LARGE = 0x5E8, + CREID_WAR_BOAR_MOUNT = 0x5F6, + CREID_WAR_CAPYBARA = 0x5F7, + CREID_WAR_CAPYBARA_BABY = 0x5F8, + CREID_RABBIT_DOOM_BABY = 0x606, + CREID_DOG_NEWFOUNDLAND = 0x60A, + CREID_DOG_ALASKAN_MALAMUTE = 0x60B, + CREID_DOG_GREAT_DANE = 0x60C, + CREID_DOG_SAINT_BERNARD = 0x60D, + CREID_DOG_BLACK_RUSSIAN_TERRIER = 0x60F, + CREID_DOG_ROTTWEILER = 0x610, /* ---- Special ---- */ diff --git a/src/sphere.ini b/src/sphere.ini index 737c8a22d..bf500f6a2 100644 --- a/src/sphere.ini +++ b/src/sphere.ini @@ -115,6 +115,9 @@ MapViewSize=18 // Max visibility for normal items, default 24. MapViewSizeMax=24 +// To enable the use of Mobtypes.txt file to check chars animations types +UseMobTypes=0 + /////////////////////////////////////////////////////////////// //////// World Save Information /////////////////////////////////////////////////////////////// From a5fbc8ded6ca7bcc1abfada23dd900862fe72679 Mon Sep 17 00:00:00 2001 From: cbnolok Date: Sat, 10 Aug 2024 19:43:24 +0200 Subject: [PATCH 02/86] Merged PR from GladieUO: CAN_I_DAMAGEABLE not updating status bar #1259 --- Changelog.txt | 3 +++ src/game/components/CCItemDamageable.cpp | 2 ++ 2 files changed, 5 insertions(+) diff --git a/Changelog.txt b/Changelog.txt index 56d6c719a..0ab9942ea 100644 --- a/Changelog.txt +++ b/Changelog.txt @@ -3858,3 +3858,6 @@ Added: 'H' shortcut for variables to get the value as hexadecimal. So for example if you have a MONSTER (H slot) flying custom anim, with Cast2 action but not Pillage action you can set ANIM=020A0 If you have a custom anim with default configuration, you don't need to set ANIM= +10-08-2024, Gladie +- Fixed: CAN_I_DAMAGEABLE not updating status bar (PR #1259, issues #1248, #1260). + diff --git a/src/game/components/CCItemDamageable.cpp b/src/game/components/CCItemDamageable.cpp index c42e996e4..cd20d1229 100644 --- a/src/game/components/CCItemDamageable.cpp +++ b/src/game/components/CCItemDamageable.cpp @@ -35,6 +35,7 @@ void CCItemDamageable::SetCurHits(word iCurHits) _fNeedUpdate = true; } _iCurHits = iCurHits; + OnTickStatsUpdate(); } void CCItemDamageable::SetMaxHits(word iMaxHits) @@ -44,6 +45,7 @@ void CCItemDamageable::SetMaxHits(word iMaxHits) _fNeedUpdate = true; } _iMaxHits = iMaxHits; + OnTickStatsUpdate(); } word CCItemDamageable::GetCurHits() const From 68caf992a21170d66fe506bcde3d2bd55ea6dcfd Mon Sep 17 00:00:00 2001 From: cbnolok Date: Sat, 17 Aug 2024 10:35:42 +0200 Subject: [PATCH 03/86] - Fixed: script cacher ignored newlines, causing wrong script line context data in server logs. - Fixed: custom triggers not firing. - Fixed: CUOClientVersion not parsing correctly new string format. - Fixed: TOOLTIP Dialog keyword sending the cliloc number in hex notation if ini DecimalVariables == 0 (unsupported by client, making some of them crash). - Fixed: some integer data type size inconsistencies. - Fixed: initialization order fiasco for CAccounts at server shutdown. - Changed: Str_To* functions to return a std::optional value, in order to get the best error handling (before, it depended on errno and there were ambiguous return values for invalid or "0" zero strings. - Changed: Refactored CUOMobTypes. - Changed: replaced localtime function with thread-safe alternatives, avoiding data race conditions. - Added: stypecast.h. It has utilities to cast numbers with strong guarantees and error checking at compile time, to avoid undefined behaviors, involuntary wrong sign/size cast or overflowing. --- cmake/toolchains/Windows-MSVC.cmake | 6 +- src/CMakeSources.cmake | 1 + src/common/CCacheableScriptFile.cpp | 60 +++-- src/common/CPointBase.cpp | 40 ++- src/common/CScriptObj.cpp | 26 +- src/common/CUOClientVersion.cpp | 30 ++- src/common/basic_threading.h | 18 +- src/common/common.cpp | 17 +- src/common/common.h | 169 +------------ src/common/os_windows.h | 2 +- src/common/resource/CResourceDef.cpp | 2 +- src/common/resource/sections/CDialogDef.cpp | 35 ++- src/common/sphere_library/CSString.h | 40 +-- src/common/sphere_library/CSTime.cpp | 106 +++++--- src/common/sphere_library/CSTime.h | 14 +- src/common/sphere_library/sstring.cpp | 80 ++++-- src/common/sphere_library/sstring.h | 60 ++++- src/common/sphere_library/stypecast.h | 255 ++++++++++++++++++++ src/common/sphereproto.h | 22 +- src/common/target_info.h | 8 +- src/game/CObjBase.cpp | 4 +- src/game/CRegion.cpp | 10 +- src/game/CServer.cpp | 4 +- src/game/CServer.h | 2 +- src/game/CServerConfig.cpp | 16 +- src/game/CServerDef.cpp | 15 +- src/game/CServerDef.h | 2 +- src/game/CWorldImport.cpp | 206 +++++++++++++--- src/game/chars/CChar.cpp | 12 +- src/game/chars/CChar.h | 2 +- src/game/chars/CCharAct.cpp | 106 ++++---- src/game/chars/CCharSpell.cpp | 38 +-- src/game/clients/CAccount.cpp | 8 +- src/game/clients/CAccount.h | 7 +- src/game/clients/CClient.cpp | 4 +- src/game/clients/CClient.h | 2 +- src/game/clients/CClientDialog.cpp | 8 +- src/game/clients/CClientLog.cpp | 28 ++- src/game/items/CItemMap.cpp | 8 +- src/game/spheresvr.cpp | 51 ++-- src/game/triggers.cpp | 5 +- src/game/uo_files/CUOMobtypes.cpp | 101 +++++--- src/game/uo_files/CUOMobtypes.h | 31 ++- src/network/CIPHistoryManager.h | 2 +- src/network/CNetworkManager.cpp | 10 +- src/network/CNetworkManager.h | 12 +- src/network/send.cpp | 12 +- src/sphere/threads.cpp | 6 + 48 files changed, 1136 insertions(+), 567 deletions(-) create mode 100644 src/common/sphere_library/stypecast.h diff --git a/cmake/toolchains/Windows-MSVC.cmake b/cmake/toolchains/Windows-MSVC.cmake index 29b032cb1..df29d25d6 100644 --- a/cmake/toolchains/Windows-MSVC.cmake +++ b/cmake/toolchains/Windows-MSVC.cmake @@ -116,9 +116,9 @@ function (toolchain_exe_stuff) target_compile_options(spheresvr PRIVATE ${cxx_compiler_flags_common} - $<$: $,/MT,/MD> /EHsc /Oy /GL /GA /Gw /Gy /GF /GR- $,/O1 /Zi,/O2>> - $<$: $,/MT,/MD> /EHa /Oy /GL /GA /Gw /Gy /GF $,/O1 /Zi,/O2>> - $<$: $,/MTd,/MDd> /EHsc /Oy- /MDd /ob1 /Od $,/Zi,/ZI>> #/Gs + $<$: $,/MT,/MD> /EHa /Oy /GL /GA /Gw /Gy /GF $,/O1 /Zi,/O2>> + $<$: $,/MT,/MD> /EHa /Oy /GL /GA /Gw /Gy /GF $,/O1 /Zi,/O2>> + $<$: $,/MTd,/MDd> /EHsc /Oy- /MDd /ob1 /Od /Gs $,/Zi,/ZI>> # ASan (and compilation for ARM arch) doesn't support edit and continue option (ZI) ) diff --git a/src/CMakeSources.cmake b/src/CMakeSources.cmake index 4c5feb64b..70f06ba74 100644 --- a/src/CMakeSources.cmake +++ b/src/CMakeSources.cmake @@ -270,6 +270,7 @@ src/common/sphere_library/sstring.cpp src/common/sphere_library/sstring.h src/common/sphere_library/sstringobjs.cpp src/common/sphere_library/sstringobjs.h +src/common/sphere_library/stypecast.h ) SOURCE_GROUP (common\\sphere_library FILES ${spherelibrary_SRCS}) diff --git a/src/common/CCacheableScriptFile.cpp b/src/common/CCacheableScriptFile.cpp index 25f50267a..be1f53ed0 100644 --- a/src/common/CCacheableScriptFile.cpp +++ b/src/common/CCacheableScriptFile.cpp @@ -99,9 +99,34 @@ bool CCacheableScriptFile::_Open(lpctstr ptcFilename, uint uiModeFlags) _fileContent = new std::vector; _fileContent->reserve(iFileLength / 25); + auto _SkipOneEndline = [](lpctstr &str_end) -> size_t // return how much i have moved past + { + bool fDoneN = false, fDoneR = false; + lpctstr before = str_end; + while (true) + { + const char ch = *str_end; + if (ch == '\n' && !fDoneN) + { + fDoneN = true; + ++str_end; + } + else if (ch == '\r' && !fDoneR) + { + fDoneR = true; + ++str_end; + } + else + { + break; + } + } + return str_end - before; + }; + const char *fileCursor = fileContentCopy.get(); size_t uiFileCursorRemainingLegth = iFileLength; - ssize_t iStrLen; + ssize_t iStrLen = 0; for (;; fileCursor += (size_t)iStrLen, uiFileCursorRemainingLegth -= (size_t)iStrLen) { if (uiFileCursorRemainingLegth == 0) @@ -109,11 +134,16 @@ bool CCacheableScriptFile::_Open(lpctstr ptcFilename, uint uiModeFlags) iStrLen = sGetLine_StaticBuf(fileCursor, minimum(uiFileCursorRemainingLegth, SCRIPT_MAX_LINE_LEN)); if (iStrLen < 0) - break; + break; if (iStrLen < 1 /*|| (fileCursor[iStrLen] != '\n') It can also be a '\0' value, but it might not be necessary to check for either of the two...*/) { - ++ iStrLen; // Skip \n + lpctstr str_end = fileCursor; + size_t uiSkip = _SkipOneEndline(str_end); + ASSERT(uiSkip > 0); + //iStrLen = (ssize_t)std::max((size_t)1, uiSkip); + iStrLen = (ssize_t)uiSkip; + _fileContent->emplace_back(); continue; } @@ -128,24 +158,14 @@ bool CCacheableScriptFile::_Open(lpctstr ptcFilename, uint uiModeFlags) const lpctstr str_start = (fUTF ? &fileCursor[3] : fileCursor); size_t len_to_copy = (size_t)iStrLen - (fUTF ? 3 : 0); - while (len_to_copy > 0) - { - const int ch = str_start[len_to_copy - 1]; - if (ch == '\n' || ch == '\r') - { - // Do not copy that, but skip it. - len_to_copy -= 1; - iStrLen += 1; - } - else { - break; - } - } + ASSERT(len_to_copy > 0); + + // go past the end of this substring, there should be the delimiter/newline/etc, just skip it. + lpctstr str_end = &str_start[len_to_copy]; + _SkipOneEndline(str_end); + _fileContent->emplace_back(str_start, len_to_copy); + iStrLen += (str_end - len_to_copy - str_start); - if (len_to_copy == 0) - _fileContent->emplace_back(); - else - _fileContent->emplace_back(str_start, len_to_copy); fFirstLine = false; fUTF = false; } // closes while diff --git a/src/common/CPointBase.cpp b/src/common/CPointBase.cpp index 5f09b249c..377aafaac 100644 --- a/src/common/CPointBase.cpp +++ b/src/common/CPointBase.cpp @@ -905,6 +905,7 @@ int CPointBase::Read( tchar * pszVal ) CPointBase ptTest; ptTest.m_z = 0; ptTest.m_map = 0; + bool fError = false; tchar * ppVal[4]; int iArgs = Str_ParseCmds( pszVal, ppVal, ARRAY_COUNT( ppVal ), " ,\t" ); @@ -914,7 +915,14 @@ int CPointBase::Read( tchar * pszVal ) case 4: // m_map if ( IsDigit(ppVal[3][0])) { - ptTest.m_map = (uchar)(Str_ToUI(ppVal[3])); + const std::optional from = Str_ToU8(ppVal[3]); + if (!from.has_value()) + { + fError = true; + break; + } + + ptTest.m_map = from.value(); if ( !g_MapList.IsMapSupported(ptTest.m_map) ) { g_Log.EventError("Unsupported map #%d specified. Auto-fixing that to 0.\n", ptTest.m_map); @@ -925,26 +933,48 @@ int CPointBase::Read( tchar * pszVal ) case 3: // m_z if (IsDigit(ppVal[2][0]) || ppVal[2][0] == '-') { - ptTest.m_z = (char)(Str_ToI(ppVal[2])); + const std::optional from = Str_ToI8(ppVal[2]); + if (!from.has_value()) + { + fError = true; + break; + } + + ptTest.m_z = from.value(); } FALLTHROUGH; case 2: if (IsDigit(ppVal[1][0])) { - ptTest.m_y = (short)(Str_ToI(ppVal[1])); + const std::optional from = Str_ToI16(ppVal[1]); + if (!from.has_value()) + { + fError = true; + break; + } + + ptTest.m_y = from.value(); } FALLTHROUGH; case 1: if (IsDigit(ppVal[0][0])) { - ptTest.m_x = (short)(Str_ToI(ppVal[0])); + std::optional from = Str_ToI16(ppVal[0]); + if (!from.has_value()) + { + fError = true; + break; + } + + ptTest.m_x = from.value(); } FALLTHROUGH; case 0: break; } - if (!ptTest.IsValidPoint()) + fError |= !ptTest.IsValidPoint(); + if (fError) { InitPoint(); return 0; diff --git a/src/common/CScriptObj.cpp b/src/common/CScriptObj.cpp index d418ebc78..0836fdc77 100644 --- a/src/common/CScriptObj.cpp +++ b/src/common/CScriptObj.cpp @@ -1103,9 +1103,20 @@ bool CScriptObj::r_WriteVal( lpctstr ptcKey, CSString &sVal, CTextConsole * pSrc int iQty = Str_ParseCmds(const_cast(ptcKey), ppCmd, ARRAY_COUNT(ppCmd), ", "); if ( iQty < 3 ) return false; - int iPrefixCode = Str_ToI(ppCmd[0]); - int iCost = Str_ToI(ppCmd[1]); - CSString sHash = CBCrypt::HashBCrypt(ppCmd[2], iPrefixCode, maximum(4,minimum(31,iCost))); + + std::optional iconv; + + iconv = Str_ToI(ppCmd[0]); + if (!iconv.has_value()) + return false; + int iPrefixCode = *iconv; + + iconv = Str_ToI(ppCmd[1]); + if (!iconv.has_value()) + return false; + int iCost = *iconv; + + CSString sHash(CBCrypt::HashBCrypt(ppCmd[2], iPrefixCode, maximum(4,minimum(31,iCost)))); sVal.Format("%s", sHash.GetBuffer()); } return true; @@ -1115,6 +1126,7 @@ bool CScriptObj::r_WriteVal( lpctstr ptcKey, CSString &sVal, CTextConsole * pSrc int iQty = Str_ParseCmds(const_cast(ptcKey), ppCmd, ARRAY_COUNT(ppCmd), ", "); if ( iQty < 2 ) return false; + bool fValidated = CBCrypt::ValidateBCrypt(ppCmd[0], ppCmd[1]); sVal.FormatVal((int)fValidated); } return true; @@ -1897,7 +1909,7 @@ int CScriptObj::ParseScriptText(tchar * ptcResponse, CTextConsole * pSrc, int iF pContext->_fParseScriptText_Brackets = false; tchar* ptcRecurseParse = ptcResponse + i; - const size_t iLen = ParseScriptText(ptcRecurseParse, pSrc, 4, pArgs); + const int iLen = ParseScriptText(ptcRecurseParse, pSrc, 4, pArgs); pContext->_fParseScriptText_Brackets = true; -- pContext->_iParseScriptText_Reentrant; @@ -2136,7 +2148,11 @@ bool CScriptObj::Execute_FullTrigger(CScript& s, CTextConsole* pSrc, CScriptTrig CScriptObj* pRef = this; if (iArgQty == 2) { - CChar* pCharFound = CUID::CharFindFromUID(Str_ToI(piCmd[1])); + std::optional iconv = Str_ToU(piCmd[1]); + if (!iconv.has_value()) + return false; + + CChar* pCharFound = CUID::CharFindFromUID(*iconv); if (pCharFound) pRef = pCharFound; } diff --git a/src/common/CUOClientVersion.cpp b/src/common/CUOClientVersion.cpp index 3d393c1e3..07113de19 100644 --- a/src/common/CUOClientVersion.cpp +++ b/src/common/CUOClientVersion.cpp @@ -1,5 +1,6 @@ #include "CUOClientVersion.h" #include "CExpression.h" +#include "CLog.h" #include "sphereproto.h" #include #include @@ -18,11 +19,13 @@ uint CUOClientVersion::GetLegacyVersionNumber() const noexcept uint factor_revision = 100; uint factor_minor = 100'00; uint factor_major = 100'00'00; - if (m_revision > 100) { + if (m_revision > 100) + { factor_minor *= 10; factor_major *= 10; } - if (m_minor > 100) { + if (m_minor > 100) + { factor_major *= 10; } @@ -75,7 +78,7 @@ CUOClientVersion::CUOClientVersion(dword uiClientVersionNumber) noexcept : m_major = uiClientVersionNumber / 100'000'00; m_minor = (uiClientVersionNumber / 1000'00) % 100; m_revision = (uiClientVersionNumber / 100 ) % 1000; - + } else if (uiClientVersionNumber > 10'00'000'00) { @@ -120,13 +123,16 @@ CUOClientVersion::CUOClientVersion(lpctstr ptcVersion) noexcept : // Ranges algorithms not yet supported by Apple Clang... // const ptrdiff_t count = std::ranges::count(std::string_view(ptcVersion), '.'); const auto svVersion = std::string_view(ptcVersion); - const auto count = std::count(svVersion.cbegin(), svVersion.cend(), '_'); + const auto count = std::count(svVersion.cbegin(), svVersion.cend(), '.'); if (count == 2) ApplyVersionFromStringOldFormat(ptcVersion); else if (count == 3) - ApplyVersionFromStringOldFormat(ptcVersion); + ApplyVersionFromStringNewFormat(ptcVersion); else - ASSERT(false); // Malformed string? + { + // Malformed string? + g_Log.Event(LOGL_CRIT|LOGM_CLIENTS_LOG|LOGM_NOCONTEXT, "Received malformed client version string?.\n"); + } } @@ -167,7 +173,7 @@ void CUOClientVersion::ApplyVersionFromStringOldFormat(lpctstr ptcVersion) noexc // Get version of old clients, which report the client version as ASCII string (eg: '5.0.2b') byte uiLetter = 0; - size_t uiMax = strlen(ptcVersion); + const size_t uiMax = strnlen(ptcVersion, 20); for (size_t i = 0; i < uiMax; ++i) { if (IsAlpha(ptcVersion[i])) @@ -195,7 +201,7 @@ void CUOClientVersion::ApplyVersionFromStringNewFormat(lpctstr ptcVersion) noexc { // Get version of newer clients, which use only 4 numbers separated by dots (example: 6.0.1.1) - std::string_view sw(ptcVersion); + const std::string_view sw(ptcVersion); const size_t dot1 = sw.find_first_of('.', 0); const size_t dot2 = sw.find_first_of('.', dot1 + 1); const size_t dot3 = sw.find_first_of('.', dot2 + 1); @@ -210,10 +216,10 @@ void CUOClientVersion::ApplyVersionFromStringNewFormat(lpctstr ptcVersion) noexc uint val1, val2, val3, val4; bool ok = true; - ok = ok && svtonum(sw1, val1); - ok = ok && svtonum(sw2, val2); - ok = ok && svtonum(sw3, val3); - ok = ok && svtonum(sw4, val4); + ok = ok && sv_to_num(sw1, &val1); + ok = ok && sv_to_num(sw2, &val2); + ok = ok && sv_to_num(sw3, &val3); + ok = ok && sv_to_num(sw4, &val4); if (!ok) return; diff --git a/src/common/basic_threading.h b/src/common/basic_threading.h index 5f1d802ca..d5c7193fc 100644 --- a/src/common/basic_threading.h +++ b/src/common/basic_threading.h @@ -50,15 +50,15 @@ #if MT_ENGINES == 1 //_DEBUG -#define MT_ENGINE_SHARED_LOCK_SET MT_SHARED_LOCK_SET -#define MT_ENGINE_SHARED_LOCK MT_SHARED_LOCK -#define MT_ENGINE_SHARED_UNLOCK MT_SHARED_UNLOCK -#define MT_ENGINE_UNIQUE_LOCK_SET MT_UNIQUE_LOCK_SET -#define MT_ENGINE_UNIQUE_UNLOCK MT_UNIQUE_UNLOCK - -#define MT_ENGINE_RETURN(x) MT_RETURN(x) -#define MT_ENGINE_SHARED_LOCK_RETURN(x) MT_SHARED_LOCK_RETURN(x) -#define MT_ENGINE_UNIQUE_LOCK_RETURN(x) MT_UNIQUE_LOCK_RETURN(x) + #define MT_ENGINE_SHARED_LOCK_SET MT_SHARED_LOCK_SET + #define MT_ENGINE_SHARED_LOCK MT_SHARED_LOCK + #define MT_ENGINE_SHARED_UNLOCK MT_SHARED_UNLOCK + #define MT_ENGINE_UNIQUE_LOCK_SET MT_UNIQUE_LOCK_SET + #define MT_ENGINE_UNIQUE_UNLOCK MT_UNIQUE_UNLOCK + + #define MT_ENGINE_RETURN(x) MT_RETURN(x) + #define MT_ENGINE_SHARED_LOCK_RETURN(x) MT_SHARED_LOCK_RETURN(x) + #define MT_ENGINE_UNIQUE_LOCK_RETURN(x) MT_UNIQUE_LOCK_RETURN(x) #else #define MT_ENGINE_SHARED_LOCK_SET (void)0 diff --git a/src/common/common.cpp b/src/common/common.cpp index d88a4361b..d7b937b8b 100644 --- a/src/common/common.cpp +++ b/src/common/common.cpp @@ -7,7 +7,8 @@ extern "C" { - void globalstartsymbol() {} // put this here as just the starting offset. + // Put this here as just the starting offset. Needed by Windows crash dump. + void globalstartsymbol() {} } #ifndef _WIN32 @@ -16,7 +17,7 @@ extern "C" #include #include #include - int getTimezone() + int getTimezone() noexcept { tm tp; memset(&tp, 0x00, sizeof(tp)); @@ -27,7 +28,7 @@ extern "C" #else // _WIN32 - const OSVERSIONINFO * Sphere_GetOSInfo() + const OSVERSIONINFO * Sphere_GetOSInfo() noexcept { // NEVER return nullptr ! static OSVERSIONINFO g_osInfo; @@ -47,14 +48,16 @@ extern "C" #endif // !_WIN32 -CLanguageID::CLanguageID(int iDefault) : +// TODO: move those in a separate cpp file. + +CLanguageID::CLanguageID(int iDefault) noexcept : m_codes{} { UnreferencedParameter(iDefault); ASSERT(iDefault == 0); } -void CLanguageID::GetStrDef(tchar* pszLang) +void CLanguageID::GetStrDef(tchar* pszLang) noexcept { if (!IsDef()) { @@ -67,7 +70,7 @@ void CLanguageID::GetStrDef(tchar* pszLang) } } -void CLanguageID::GetStr(tchar* pszLang) const +void CLanguageID::GetStr(tchar* pszLang) const noexcept { memcpy(pszLang, m_codes, 3); pszLang[3] = '\0'; @@ -80,7 +83,7 @@ lpctstr CLanguageID::GetStr() const return pszTmp; } -bool CLanguageID::Set(lpctstr pszLang) +bool CLanguageID::Set(lpctstr pszLang) noexcept { // needs not be terminated! if (pszLang != nullptr) diff --git a/src/common/common.h b/src/common/common.h index 36312c656..a9f037a06 100644 --- a/src/common/common.h +++ b/src/common/common.h @@ -20,7 +20,6 @@ // C abs function has different in/out types the std:: ones in cmath. It's defined in stdlib.h. #include #include // for smart pointers -#include #include "assertion.h" #include "basic_threading.h" @@ -32,6 +31,8 @@ #include "os_unix.h" #endif +#include "sphere_library/stypecast.h" + // Strings #define _STRINGIFY_AUX(x) #x @@ -61,7 +62,7 @@ */ #undef UNREFERENCED_PARAMETER template -inline void UnreferencedParameter(T const&) noexcept { +inline constexpr void UnreferencedParameter(T const&) noexcept { ; } @@ -130,192 +131,44 @@ inline void UnreferencedParameter(T const&) noexcept { #define MAKEDWORD(low, high) ((dword)(((word)low) | (((dword)((word)high)) << 16))) -//-- Explicitly promote to a larger type or narrow to a smaller type, instead of inattentive casts. - -// Promote to the corresponding 32 bits numeric type a smaller numeric variable. -template -auto i_promote32(const T a) noexcept -{ - static_assert(std::is_arithmetic_v, "Input variable is not an arithmetic type."); - static_assert(std::is_integral_v || (std::is_floating_point_v && std::is_signed_v), "Unsigned floating point numbers are unsupported by the language standard"); - static_assert(sizeof(T) < 4, "Input variable is not smaller than a 32 bit number."); - if constexpr (std::is_signed_v) - { - if constexpr (std::is_floating_point_v) - return static_cast(a); - return static_cast(a); - } - else - return static_cast(a); -} - -// Promote to the corresponding 64 bits numeric type a smaller numeric variable. -template -auto i_promote64(const T a) noexcept -{ - static_assert(std::is_arithmetic_v, "Input variable is not an arithmetic type."); - static_assert(std::is_integral_v || (std::is_floating_point_v && std::is_signed_v), "Unsigned floating point numbers are unsupported by the language standard"); - static_assert(sizeof(T) < 8, "Input variable is not smaller than a 64 bit number."); - if constexpr (std::is_signed_v) - { - if constexpr (std::is_floating_point_v) - return static_cast(a); - return static_cast(a); - } - else - return static_cast(a); -} - -template -auto i_narrow32(const T a) noexcept -{ - static_assert(std::is_arithmetic_v, "Input variable is not an arithmetic type."); - static_assert(std::is_integral_v || (std::is_floating_point_v && std::is_signed_v), "Unsigned floating point numbers are unsupported by the language standard"); - static_assert(sizeof(T) >= 4, "Input variable is smaller than a 32 bit number."); - - // Since the narrowing can be implementation specific, here we decide that we take only the lower 32 bytes and discard the upper ones. - constexpr uint64 umask = 0x0000'0000'FFFF'FFFF; - if constexpr (std::is_signed_v) - { - if constexpr (std::is_floating_point_v) - return static_cast(static_cast(a) & umask); - return static_cast(static_cast(a) & umask); - } - else - return static_cast(static_cast(a) & umask); -} - -template -auto i_narrow16(const T a) noexcept -{ - static_assert(std::is_arithmetic_v, "Input variable is not an arithmetic type."); - static_assert(std::is_integral_v || (std::is_floating_point_v && std::is_signed_v), "Unsigned floating point numbers are unsupported by the language standard"); - static_assert(sizeof(T) >= 2, "Input variable is smaller than a 16 bit number."); - - // Since the narrowing can be implementation specific, here we decide that we take only the lower 32 bytes and discard the upper ones. - constexpr uint64 umask = 0x0000'0000'FFFF'FFFF; - if constexpr (std::is_signed_v) - { - if constexpr (std::is_floating_point_v) - return static_cast(static_cast(a) & umask); - return static_cast(static_cast(a) & umask); - } - else - return static_cast(static_cast(a) & umask); -} - -template -auto i64_narrow32(const T a) noexcept -{ - static_assert(std::is_arithmetic_v, "Input variable is not an arithmetic type."); - static_assert(std::is_integral_v || (std::is_floating_point_v && std::is_signed_v), "Unsigned floating point numbers are unsupported by the language standard"); - static_assert(sizeof(T) == 8, "Input variable is not a 64 bit number."); - - // Since the narrowing can be implementation specific, here we decide that we take only the lower 32 bytes and discard the upper ones. - constexpr uint64 umask = 0x0000'0000'FFFF'FFFF; - if constexpr (std::is_signed_v) - { - if constexpr (std::is_floating_point_v) - return static_cast(a & umask); - return static_cast(a & umask); - } - else - return static_cast(a & umask); -} - -template -auto i64_narrow16(const T a) noexcept -{ - static_assert(std::is_arithmetic_v, "Input variable is not an arithmetic type."); - static_assert(std::is_integral_v || (std::is_floating_point_v && std::is_signed_v), "Unsigned floating point numbers are unsupported by the language standard"); - static_assert(sizeof(T) == 8, "Input variable is not a 64 bit number."); - - // Since the narrowing can be implementation specific, here we decide that we take only the lower 32 bytes and discard the upper ones. - constexpr uint64 umask = 0x0000'0000'0000'FFFF; - if constexpr (std::is_signed_v) - { - if constexpr (std::is_floating_point_v) - return static_cast(a & umask); - return static_cast(a & umask); - } - else - return static_cast(a & umask); -} - -template -auto i32_narrow16(const T a) noexcept -{ - static_assert(std::is_arithmetic_v, "Input variable is not an arithmetic type."); - static_assert(std::is_integral_v || (std::is_floating_point_v && std::is_signed_v), "Unsigned floating point numbers are unsupported by the language standard"); - static_assert(sizeof(T) == 4, "Input variable is not a 32 bit number."); - - // Since the narrowing can be implementation specific, here we decide that we take only the lower 16 bytes and discard the upper ones. - constexpr uint32 umask = 0x0000'FFFF; - if constexpr (std::is_signed_v) - { - if constexpr (std::is_floating_point_v) - return static_cast(a & umask); - return static_cast(a & umask); - } - else - return static_cast(a & umask); -} - -template -auto i16_narrow8(const T a) noexcept -{ - static_assert(std::is_arithmetic_v, "Input variable is not an arithmetic type."); - static_assert(std::is_integral_v, "Only integral types are supported by this function."); - static_assert(sizeof(T) == 2, "Input variable is not a 16 bit number."); - - // Since the narrowing can be implementation specific, here we decide that we take only the lower 16 bytes and discard the upper ones. - constexpr uint16 umask = 0x00FF; - if constexpr (std::is_signed_v) - { - return static_cast(a & umask); - } - else - return static_cast(a & umask); -} - - //#define IMulDiv(a,b,c) (((((int)(a)*(int)(b)) + (int)(c / 2)) / (int)(c)) - (IsNegative((int)(a)*(int)(b)))) -inline int IMulDiv(const int a, const int b, const int c) noexcept +inline constexpr int IMulDiv(const int a, const int b, const int c) noexcept { const int ab = a*b; return ((ab + (c/2)) / c) - IsNegative(ab); } -inline uint UIMulDiv(const uint a, const uint b, const uint c) noexcept +inline constexpr uint UIMulDiv(const uint a, const uint b, const uint c) noexcept { const int ab = a * b; return ((ab + (c / 2)) / c) - IsNegative(ab); } //#define IMulDivLL(a,b,c) (((((llong)(a)*(llong)(b)) + (llong)(c / 2)) / (llong)(c)) - (IsNegative((llong)(a)*(llong)(b)))) -inline llong IMulDivLL(const llong a, const llong b, const llong c) noexcept +inline constexpr llong IMulDivLL(const llong a, const llong b, const llong c) noexcept { const llong ab = a*b; return ((ab + (c/2)) / c) - IsNegative(ab); } -inline realtype IMulDivRT(const realtype a, const realtype b, const realtype c) noexcept +inline constexpr realtype IMulDivRT(const realtype a, const realtype b, const realtype c) noexcept { const realtype ab = a*b; return ((ab + (c/2)) / c) - IsNegative(ab); } //#define IMulDivDown(a,b,c) (((a)*(b))/(c)) -inline int IMulDivDown(const int a, const int b, const int c) noexcept +inline constexpr int IMulDivDown(const int a, const int b, const int c) noexcept { return (a*b)/c; } -inline llong IMulDivDownLL(const llong a, const llong b, const llong c) noexcept +inline constexpr llong IMulDivDownLL(const llong a, const llong b, const llong c) noexcept { return (a*b)/c; } //#define sign(n) (((n) < 0) ? -1 : (((n) > 0) ? 1 : 0)) -template inline T sign(const T n) noexcept +template +inline constexpr T sign(const T n) noexcept { static_assert(std::is_arithmetic::value, "Invalid data type."); return ( (n < 0) ? -1 : ((n > 0) ? 1 : 0) ); diff --git a/src/common/os_windows.h b/src/common/os_windows.h index ee7990582..c564ef059 100644 --- a/src/common/os_windows.h +++ b/src/common/os_windows.h @@ -77,7 +77,7 @@ #define __except(P) catch(int) #endif // _MSC_VER -const OSVERSIONINFO * Sphere_GetOSInfo(); +const OSVERSIONINFO * Sphere_GetOSInfo() noexcept; #endif // _INC_OS_WINDOWS_H diff --git a/src/common/resource/CResourceDef.cpp b/src/common/resource/CResourceDef.cpp index 15ff928a1..23fa784a4 100644 --- a/src/common/resource/CResourceDef.cpp +++ b/src/common/resource/CResourceDef.cpp @@ -139,7 +139,7 @@ bool CResourceDef::MakeResourceName() // Is this is subsequent key with a number? Get the highest (plus one) if ( IsStrNumericDec( ptcKey ) ) { - size_t uiVarThis = Str_ToUI( ptcKey ); + size_t uiVarThis = Str_ToU( ptcKey ); if ( uiVarThis >= uiVar ) uiVar = uiVarThis + 1; } diff --git a/src/common/resource/sections/CDialogDef.cpp b/src/common/resource/sections/CDialogDef.cpp index ce4a091c3..b0a4f90db 100644 --- a/src/common/resource/sections/CDialogDef.cpp +++ b/src/common/resource/sections/CDialogDef.cpp @@ -139,7 +139,7 @@ bool CDialogDef::r_Verb( CScript & s, CTextConsole * pSrc ) // some command on t // The first part of the key is GUMPCTL_TYPE lpctstr ptcKey = s.GetKey(); - int index = FindTableSorted( ptcKey, sm_szLoadKeys, ARRAY_COUNT(sm_szLoadKeys)-1 ); + const int index = FindTableSorted( ptcKey, sm_szLoadKeys, ARRAY_COUNT(sm_szLoadKeys)-1 ); if ( index < 0 ) { const size_t uiFunctionIndex = r_GetFunctionIndex(ptcKey); @@ -151,13 +151,13 @@ bool CDialogDef::r_Verb( CScript & s, CTextConsole * pSrc ) // some command on t if ( r_Call(uiFunctionIndex, pSrc, &Args, &sVal) ) return true; } + if (!m_pObj) return CResourceLink::r_Verb(s, pSrc); return m_pObj->r_Verb(s, pSrc); } lpctstr pszArgs = s.GetArgStr(); - switch( index ) { case GUMPCTL_PAGE: @@ -177,6 +177,7 @@ bool CDialogDef::r_Verb( CScript & s, CTextConsole * pSrc ) // some command on t m_sControls.emplace_back(false).Format( "page %d", iNewPage ); return true; } + case GUMPCTL_BUTTON: // 7 = X,Y,Down gump,Up gump,pressable(1/0),page,id case GUMPCTL_BUTTONTILEART: // 11 = X,Y,Down gump,Up gump,pressable(1/0),page,id,tileart,hue,X,Y { @@ -210,6 +211,7 @@ bool CDialogDef::r_Verb( CScript & s, CTextConsole * pSrc ) // some command on t return true; } + case GUMPCTL_GUMPPIC: { GET_RELATIVE( x, m_iOriginX ); @@ -220,6 +222,7 @@ bool CDialogDef::r_Verb( CScript & s, CTextConsole * pSrc ) // some command on t m_sControls.emplace_back(false).Format( "gumppic %d %d %d%s%s", x, y, id, *pszArgs ? " hue=" : "", *pszArgs ? pszArgs : "" ); return true; } + case GUMPCTL_GUMPPICTILED: { GET_RELATIVE( x, m_iOriginX ); @@ -231,6 +234,7 @@ bool CDialogDef::r_Verb( CScript & s, CTextConsole * pSrc ) // some command on t m_sControls.emplace_back(false).Format( "gumppictiled %d %d %d %d %d", x, y, sX, sY, id ); return true; } + case GUMPCTL_PICINPIC: { GET_RELATIVE(x, m_iOriginX); @@ -244,6 +248,7 @@ bool CDialogDef::r_Verb( CScript & s, CTextConsole * pSrc ) // some command on t m_sControls.emplace_back(false).Format("picinpic %d %d %d %d %d %d %d", x, y, id, w, h, sX, sY); return true; } + case GUMPCTL_RESIZEPIC: { GET_RELATIVE( x, m_iOriginX ); @@ -255,6 +260,7 @@ bool CDialogDef::r_Verb( CScript & s, CTextConsole * pSrc ) // some command on t m_sControls.emplace_back(false).Format( "resizepic %d %d %d %d %d", x, y, id, sX, sY ); return true; } + case GUMPCTL_TILEPIC: case GUMPCTL_TILEPICHUE: { @@ -271,6 +277,7 @@ bool CDialogDef::r_Verb( CScript & s, CTextConsole * pSrc ) // some command on t return true; } + case GUMPCTL_DTEXT: { GET_RELATIVE( x, m_iOriginX ); @@ -284,6 +291,7 @@ bool CDialogDef::r_Verb( CScript & s, CTextConsole * pSrc ) // some command on t m_sControls.emplace_back(false).Format( "text %d %d %d %u", x, y, hue, iText ); return true; } + case GUMPCTL_DCROPPEDTEXT: { GET_RELATIVE( x, m_iOriginX ); @@ -298,6 +306,7 @@ bool CDialogDef::r_Verb( CScript & s, CTextConsole * pSrc ) // some command on t m_sControls.emplace_back(false).Format( "croppedtext %d %d %d %d %d %u", x, y, w, h, hue, iText ); return true; } + case GUMPCTL_DHTMLGUMP: { GET_RELATIVE( x, m_iOriginX ); @@ -312,6 +321,7 @@ bool CDialogDef::r_Verb( CScript & s, CTextConsole * pSrc ) // some command on t m_sControls.emplace_back(false).Format( "htmlgump %d %d %d %d %u %d %d", x, y, w, h, iText, bck, options ); return true; } + case GUMPCTL_DTEXTENTRY: { GET_RELATIVE( x, m_iOriginX ); @@ -326,6 +336,7 @@ bool CDialogDef::r_Verb( CScript & s, CTextConsole * pSrc ) // some command on t m_sControls.emplace_back(false).Format( "textentry %d %d %d %d %d %d %u", x, y, w, h, hue, id, iText ); return true; } + case GUMPCTL_DTEXTENTRYLIMITED: { GET_RELATIVE( x, m_iOriginX ); @@ -341,6 +352,7 @@ bool CDialogDef::r_Verb( CScript & s, CTextConsole * pSrc ) // some command on t m_sControls.emplace_back(false).Format( "textentrylimited %d %d %d %d %d %d %u %d", x, y, w, h, hue, id, iText, charLimit ); return true; } + case GUMPCTL_CHECKBOX: { GET_RELATIVE( x, m_iOriginX ); @@ -353,6 +365,7 @@ bool CDialogDef::r_Verb( CScript & s, CTextConsole * pSrc ) // some command on t m_sControls.emplace_back(false).Format( "checkbox %d %d %d %d %d %d", x, y, down, up, state, id ); return true; } + case GUMPCTL_RADIO: { GET_RELATIVE( x, m_iOriginX ); @@ -365,6 +378,18 @@ bool CDialogDef::r_Verb( CScript & s, CTextConsole * pSrc ) // some command on t m_sControls.emplace_back(false).Format( "radio %d %d %d %d %d %d", x, y, down, up, state, id ); return true; } + + case GUMPCTL_TOOLTIP: + { + // The client expects this to be sent as a string in decimal notation. + std::optional conv = Str_ToU(pszArgs); + if (!conv.has_value()) + return false; + + m_sControls.emplace_back(false).Format( "tooltip %u", conv.value() ); + return true; + } + case GUMPCTL_CHECKERTRANS: { GET_RELATIVE( x, m_iOriginX ); @@ -375,6 +400,7 @@ bool CDialogDef::r_Verb( CScript & s, CTextConsole * pSrc ) // some command on t m_sControls.emplace_back(false).Format( "checkertrans %d %d %d %d", x, y, width, height ); return true; } + case GUMPCTL_DORIGIN: { // GET_RELATIVE( x, m_iOriginX ); @@ -400,9 +426,11 @@ bool CDialogDef::r_Verb( CScript & s, CTextConsole * pSrc ) // some command on t return true; } + case GUMPCTL_NODISPOSE: m_fNoDispose = true; break; + case GUMPCTL_CROPPEDTEXT: case GUMPCTL_TEXT: case GUMPCTL_TEXTENTRY: @@ -427,6 +455,7 @@ bool CDialogDef::r_Verb( CScript & s, CTextConsole * pSrc ) // some command on t m_sControls.emplace_back(false).Format( "xmfhtmlgumpcolor %d %d %d %d %d %d %d%s%s", x, y, sX, sY, cliloc, hasBack, canScroll, *pszArgs ? " " : "", *pszArgs ? pszArgs : "" ); return true; } + case GUMPCTL_XMFHTMLTOK: // 9 = x y width height has_background has_scrollbar color cliloc_id @args { GET_RELATIVE(x, m_iOriginX); @@ -442,6 +471,7 @@ bool CDialogDef::r_Verb( CScript & s, CTextConsole * pSrc ) // some command on t m_sControls.emplace_back(false).Format("xmfhtmltok %d %d %d %d %d %d %d %d %s", x, y, sX, sY, hasBack, canScroll, color, cliloc, *pszArgs ? pszArgs : ""); return true; } + default: break; } @@ -536,6 +566,7 @@ bool CDialogDef::GumpSetup( int iPage, CClient * pClient, CObjBase * pObjSrc, lp const auto trigRet = OnTriggerRunVal( s, TRIGRUN_SECTION_TRUE, pClient->GetChar(), &Args ); m_sText.shrink_to_fit(); m_sControls.shrink_to_fit(); + if ( trigRet == TRIGRET_RET_TRUE ) return false; return true; diff --git a/src/common/sphere_library/CSString.h b/src/common/sphere_library/CSString.h index ecadf8b94..d68e70329 100644 --- a/src/common/sphere_library/CSString.h +++ b/src/common/sphere_library/CSString.h @@ -130,14 +130,14 @@ class CSString * @brief Check the length of the CSString. * @return true if length is 0, false otherwise. */ - NODISCARD + [[nodiscard]] inline bool IsEmpty() const noexcept; /** * @brief Check if there is data allocated and if has zero length. * @return false if no data or zero length, true otherwise. */ - NODISCARD + [[nodiscard]] bool IsValid() const noexcept; /** @@ -155,14 +155,14 @@ class CSString * @brief Get the length of the held string. * @return the length of the CSString. */ - NODISCARD + [[nodiscard]] inline int GetLength() const noexcept; /** * @brief Get the length of the internal buffer, which can be greater than the held string length. * @return the length of the CSString. */ - NODISCARD + [[nodiscard]] inline int GetCapacity() const noexcept; ///@} @@ -177,7 +177,7 @@ class CSString * @param nIndex position of the character. * @return character in position nIndex. */ - NODISCARD + [[nodiscard]] inline tchar operator[](int nIndex) const; /** @@ -186,7 +186,7 @@ class CSString * @param nIndex position of the character. * @return reference to character in position nIndex. */ - NODISCARD + [[nodiscard]] inline tchar& operator[](int nIndex); /** @@ -194,7 +194,7 @@ class CSString * @param nIndex position of the character. * @return character in position nIndex. */ - NODISCARD + [[nodiscard]] inline tchar GetAt(int nIndex) const; /** @@ -202,7 +202,7 @@ class CSString * @param nIndex position of the character. * @return reference to character in position nIndex. */ - NODISCARD + [[nodiscard]] inline tchar& ReferenceAt(int nIndex); /** @@ -478,7 +478,7 @@ class CSString * @brief cast as const lpcstr. * @return internal data pointer. */ - NODISCARD + [[nodiscard]] inline operator lpctstr() const noexcept; /** @@ -491,7 +491,7 @@ class CSString * @param pStr string to compare. * @return <0 if the first character that not match has lower value in CSString than in pStr. 0 if the contents of both are equal. >0 if the first character that does not match has greater value in CSString than pStr. */ - NODISCARD + [[nodiscard]] inline int Compare(lpctstr pStr) const noexcept; /** @@ -504,14 +504,14 @@ class CSString * @param pStr string to compare. * @return <0 if the first character that not match has lower value in CSString than in pStr. 0 if the contents of both are equal. >0 if the first character that does not match has greater value in CSString than pStr. */ - NODISCARD + [[nodiscard]] inline int CompareNoCase(lpctstr pStr) const noexcept; /** * @brief Gets the internal pointer. * @return Pointer to internal data. */ - NODISCARD + [[nodiscard]] inline lpctstr GetBuffer() const noexcept; // Provide only a read-only buffer: if we modify it we'll break the internal length counter, other than possibly write past the end of the string (the buffer is small). @@ -522,7 +522,7 @@ class CSString * @param c character to look for. * @return position of the character in CSString if any, -1 otherwise. */ - NODISCARD + [[nodiscard]] inline int indexOf(tchar c) noexcept; /** @@ -531,7 +531,7 @@ class CSString * @param offset position from start the search. * @return position of the character in CSString if any, -1 otherwise. */ - NODISCARD + [[nodiscard]] int indexOf(tchar c, int offset) noexcept; /** @@ -539,7 +539,7 @@ class CSString * @param str substring to look for. * @return position of the substring in CSString if any, -1 otherwise. */ - NODISCARD + [[nodiscard]] inline int indexOf(const CSString& str) noexcept; /** @@ -548,7 +548,7 @@ class CSString * @param offset position from start the search. * @return position of the substring in CSString if any, -1 otherwise. */ - NODISCARD + [[nodiscard]] int indexOf(const CSString& str, int offset) noexcept; /** @@ -556,7 +556,7 @@ class CSString * @param c character to look for. * @return position of the character in CSString if any, -1 otherwise. */ - NODISCARD + [[nodiscard]] inline int lastIndexOf(tchar c) noexcept; /** @@ -565,7 +565,7 @@ class CSString * @param from position where stop the search. * @return position of the character in CSString if any, -1 otherwise. */ - NODISCARD + [[nodiscard]] int lastIndexOf(tchar c, int from) noexcept; /** @@ -573,7 +573,7 @@ class CSString * @param str substring to look for. * @return position of the substring in CSString if any, -1 otherwise. */ - NODISCARD + [[nodiscard]] inline int lastIndexOf(const CSString& str) noexcept; /** @@ -582,7 +582,7 @@ class CSString * @param from position where stop the search. * @return position of the substring in CSString if any, -1 otherwise. */ - NODISCARD + [[nodiscard]] int lastIndexOf(const CSString& str, int from) noexcept; ///@} diff --git a/src/common/sphere_library/CSTime.cpp b/src/common/sphere_library/CSTime.cpp index 9ad60d751..54c6dc423 100644 --- a/src/common/sphere_library/CSTime.cpp +++ b/src/common/sphere_library/CSTime.cpp @@ -5,6 +5,7 @@ // #include +#include #include "CSTime.h" #include "CSString.h" #include "../../common/CLog.h" @@ -13,7 +14,7 @@ // Windows epoch is January 1, 1601 (start of Gregorian calendar cycle) // Unix epoch is January 1, 1970 (adjustment in "ticks" 100 nanosecond) -#define UNIX_TICKS_PER_SECOND 10000000 //a tick is 100ns +//#define UNIX_TICKS_PER_SECOND 10000000 //a tick is 100ns #if _WIN32 //# define UNIX_TIME_START 0x019DB1DED53E8000LL // January 1, 1970 (start of Unix epoch) in "ticks" //# define WINDOWS_UNIX_EPOCH_OFFSET 11644473600 // (number of seconds between January 1, 1601 and January 1, 1970). @@ -142,6 +143,12 @@ CSTime CSTime::GetCurrentTime() noexcept // static return CSTime(::time(nullptr)); } +/* +CSTime::CSTime( struct tm atm ) noexcept +{ + m_time = mktime(&atm); +} +*/ CSTime::CSTime(int nYear, int nMonth, int nDay, int nHour, int nMin, int nSec, int nDST) noexcept @@ -157,24 +164,69 @@ CSTime::CSTime(int nYear, int nMonth, int nDay, int nHour, int nMin, int nSec, m_time = mktime(&atm); } -CSTime::CSTime( struct tm atm ) noexcept +static std::tm safe_localtime(const time_t t) noexcept { - m_time = mktime(&atm); + std::tm atm {}; + + // Standard C localtime is not thread-safe. We need alternatives. + // https://stackoverflow.com/questions/38034033/c-localtime-this-function-or-variable-may-be-unsafe + +#if defined(__unix__) + localtime_r(&t, &atm); +#elif defined(_MSC_VER) + localtime_s(&atm, &t); +#elif defined(__STDC_LIB_EXT1__) + localtime_s(&t, &atm); +#else + + // To be tested! C++20 way. + // https://stackoverflow.com/questions/61190884/current-time-and-date-in-c20-days + static_assert(false, "Untested yet. If needed, test it and if it's fine delete this static_assert"); + + using namespace std::chrono; + const auto current_zoned_time = zoned_time{current_zone(), system_clock::from_time_t(t)}; + const auto local_time_point = current_zoned_time.get_local_time(); + //const auto local_duration = local_time_point.time_since_epoch(); + + // Get a local time_point with days precision + const auto ld = floor(local_time_point); + + // Convert local days-precision time_point to a local {y, m, d} calendar + const year_month_day ymd{ld}; + + // Split time since local midnight into {h, m, s, subseconds} + const hh_mm_ss hms{local_time_point - ld}; + + // get_info(): Returns a std::chrono::time_zone::transition_info object, which provides information about whether DST is currently active. + const bool is_dst = (current_zoned_time.get_info().save != std::chrono::seconds{0}); + + atm.tm_sec = (int)hms.seconds().count(); + atm.tm_min = (int)hms.minutes().count(); + atm.tm_hour = (int)hms.hours().count(); + atm.tm_mday = (int)(uint)ymd.day(); + atm.tm_mon = (int)(uint)ymd.month() - 1; + atm.tm_year = (int)ymd.year() - 1900; + atm.tm_isdst= (int)is_dst; +#endif + + return atm; } -struct tm* CSTime::GetLocalTm(struct tm* ptm) const noexcept +static std::tm safe_localtime_unoffset(std::tm atm) noexcept { - if (ptm != nullptr) - { - struct tm* ptmTemp = localtime(&m_time); - if (ptmTemp == nullptr) - return nullptr; // indicates the m_time was not initialized! + atm.tm_year += 1900; + atm.tm_mon += 1; + return atm; +} - *ptm = *ptmTemp; - return ptm; - } - else - return localtime(&m_time); +std::tm CSTime::GetLocalTm() const noexcept +{ + return safe_localtime(m_time); +} + +std::tm CSTime::GetLocalTmPlain() const noexcept +{ + return safe_localtime_unoffset(safe_localtime(m_time)); } //////////////////////////////////////////////////////////////////////////// @@ -297,19 +349,19 @@ bool CSTime::Read(tchar *pszVal) return true; } -CSTime::CSTime() noexcept +CSTime::CSTime() noexcept : + m_time(0) { - m_time = 0; } -CSTime::CSTime(time_t time) noexcept +CSTime::CSTime(time_t time) noexcept : + m_time(time) { - m_time = time; } -CSTime::CSTime(const CSTime& timeSrc) noexcept +CSTime::CSTime(const CSTime& timeSrc) noexcept : + m_time(timeSrc.m_time) { - m_time = timeSrc.m_time; } const CSTime& CSTime::operator=(const CSTime& timeSrc) noexcept @@ -341,36 +393,36 @@ bool CSTime::operator!=( time_t t ) const noexcept time_t CSTime::GetTime() const noexcept { - // Although not defined by the C standard, this is almost always an integral value holding the number of seconds + // Although not defined by the C standard, this is almost always an integral value holding the number of seconds // (not counting leap seconds) since 00:00, Jan 1 1970 UTC, corresponding to UNIX time. - // + // // TODO: Is this on Windows defined since January 1, 1601 ? return m_time; } int CSTime::GetYear() const noexcept { - return (GetLocalTm(nullptr)->tm_year) + 1900; + return (GetLocalTm().tm_year) + 1900; } int CSTime::GetMonth() const noexcept // month of year (1 = Jan) { - return GetLocalTm(nullptr)->tm_mon + 1; + return GetLocalTm().tm_mon + 1; } int CSTime::GetDay() const noexcept // day of month { - return GetLocalTm(nullptr)->tm_mday; + return GetLocalTm().tm_mday; } int CSTime::GetHour() const noexcept { - return GetLocalTm(nullptr)->tm_hour; + return GetLocalTm().tm_hour; } int CSTime::GetMinute() const noexcept { - return GetLocalTm(nullptr)->tm_min; + return GetLocalTm().tm_min; } void CSTime::Init() noexcept diff --git a/src/common/sphere_library/CSTime.h b/src/common/sphere_library/CSTime.h index 0a5114f09..4d173aacf 100644 --- a/src/common/sphere_library/CSTime.h +++ b/src/common/sphere_library/CSTime.h @@ -6,13 +6,19 @@ #ifndef _INC_CSTIME_H #define _INC_CSTIME_H +/* #ifdef _WIN32 #include #else #include #endif +*/ +#define __STDC_WANT_LIB_EXT1__ 1 +#include + #include "../common.h" + // Similar to the MFC CTime and CTimeSpan or COleDateTime: // Get time stamp in the real world. based on struct tm class CSTime @@ -43,7 +49,7 @@ class CSTime // int tm_yday; // days since January 1 - [0, 365] // int tm_isdst; // daylight savings time flag 0, 0, 0, - 1, 0, 0, + 1, 0, 0, 0, 0, -1 }; */ @@ -64,7 +70,7 @@ class CSTime CSTime(time_t time) noexcept; CSTime(const CSTime& timeSrc) noexcept; - CSTime(struct tm time) noexcept; + //CSTime(struct tm time) noexcept; CSTime(int nYear, int nMonth, int nDay, int nHour, int nMin, int nSec, int nDST = -1) noexcept; const CSTime& operator=(const CSTime& timeSrc) noexcept; @@ -77,6 +83,8 @@ class CSTime // Attributes time_t GetTime() const noexcept; + std::tm GetLocalTmPlain() const noexcept; + int GetYear() const noexcept; int GetMonth() const noexcept; int GetDay() const noexcept; @@ -94,7 +102,7 @@ class CSTime int GetDaysTotal() const noexcept; private: - struct tm* GetLocalTm(struct tm* ptm = nullptr) const noexcept; + std::tm GetLocalTm() const noexcept; }; #endif // _INC_CTIME_H diff --git a/src/common/sphere_library/sstring.cpp b/src/common/sphere_library/sstring.cpp index 78fea0a92..8156f2045 100644 --- a/src/common/sphere_library/sstring.cpp +++ b/src/common/sphere_library/sstring.cpp @@ -41,36 +41,76 @@ void Str_Reverse(char* string) } #endif -int Str_ToI (lpctstr ptcStr, int base) noexcept +std::optional Str_ToI8 (lpctstr ptcStr, int base) noexcept { - const auto e = errno; - const auto ret = int(::strtol(ptcStr, nullptr, base)); - errno = e; - return ret; + char val = 0; + const bool fSuccess = cstr_to_num(ptcStr, &val, base); + if (!fSuccess) + return std::nullopt; + return val; } -uint Str_ToUI(lpctstr ptcStr, int base) noexcept +std::optional Str_ToU8 (lpctstr ptcStr, int base) noexcept { - const auto e = errno; - const auto ret = uint(::strtoul(ptcStr, nullptr, base)); - errno = e; - return ret; + uchar val = 0; + const bool fSuccess = cstr_to_num(ptcStr, &val, base); + if (!fSuccess) + return std::nullopt; + return val; } -llong Str_ToLL(lpctstr ptcStr, int base) noexcept +std::optional Str_ToI16 (lpctstr ptcStr, int base) noexcept { - const auto e = errno; - const auto ret = ::strtoll(ptcStr, nullptr, base); - errno = e; - return ret; + short val = 0; + const bool fSuccess = cstr_to_num(ptcStr, &val, base); + if (!fSuccess) + return std::nullopt; + return val; } -ullong Str_ToULL(lpctstr ptcStr, int base) noexcept +std::optional Str_ToU16 (lpctstr ptcStr, int base) noexcept { - const auto e = errno; - const auto ret = ::strtoull(ptcStr, nullptr, base); - errno = e; - return ret; + ushort val = 0; + const bool fSuccess = cstr_to_num(ptcStr, &val, base); + if (!fSuccess) + return std::nullopt; + return val; +} + +std::optional Str_ToI (lpctstr ptcStr, int base) noexcept +{ + int val = 0; + const bool fSuccess = cstr_to_num(ptcStr, &val, base); + if (!fSuccess) + return std::nullopt; + return val; +} + +std::optional Str_ToU(lpctstr ptcStr, int base) noexcept +{ + uint val = 0; + const bool fSuccess = cstr_to_num(ptcStr, &val, base); + if (!fSuccess) + return std::nullopt; + return val; +} + +std::optional Str_ToLL(lpctstr ptcStr, int base) noexcept +{ + llong val = 0; + const bool fSuccess = cstr_to_num(ptcStr, &val, base); + if (!fSuccess) + return std::nullopt; + return val; +} + +std::optional Str_ToULL(lpctstr ptcStr, int base) noexcept +{ + ullong val = 0; + const bool fSuccess = cstr_to_num(ptcStr, &val, base); + if (!fSuccess) + return std::nullopt; + return val; } #define STR_FROM_SET_ZEROSTR \ diff --git a/src/common/sphere_library/sstring.h b/src/common/sphere_library/sstring.h index 0bf5063b3..acbfecfeb 100644 --- a/src/common/sphere_library/sstring.h +++ b/src/common/sphere_library/sstring.h @@ -4,6 +4,7 @@ #include "../common.h" #include #include +#include #include @@ -21,6 +22,7 @@ #define IsAlpha(c) iswalpha((wint_t)c) #define IsAlnum(c) iswalnum((wint_t)c) #else + // TODO: remove INT_CHARACTER and adapt those calls to unicode chars #define IsDigit(c) isdigit(INT_CHARACTER(c)) #define IsSpace(c) isspace(INT_CHARACTER(c)) #define IsAlpha(c) isalpha(INT_CHARACTER(c)) @@ -64,17 +66,23 @@ struct KeyTableDesc_s */ // If you want to use base = 16 to convert an hexadecimal string, it has to be in the format: 0x*** -int Str_ToI (lpctstr ptcStr, int base = 10) noexcept; -uint Str_ToUI (lpctstr ptcStr, int base = 10) noexcept; -llong Str_ToLL (lpctstr ptcStr, int base = 10) noexcept; -ullong Str_ToULL(lpctstr ptcStr, int base = 10) noexcept; +[[nodiscard]] std::optional Str_ToI8 (lpctstr ptcStr, int base = 10) noexcept; +[[nodiscard]] std::optional Str_ToU8 (lpctstr ptcStr, int base = 10) noexcept; +[[nodiscard]] std::optional Str_ToI16(lpctstr ptcStr, int base = 10) noexcept; +[[nodiscard]] std::optional Str_ToU16(lpctstr ptcStr, int base = 10) noexcept; +[[nodiscard]] std::optional Str_ToI (lpctstr ptcStr, int base = 10) noexcept; +[[nodiscard]] std::optional Str_ToU (lpctstr ptcStr, int base = 10) noexcept; +[[nodiscard]] std::optional Str_ToLL (lpctstr ptcStr, int base = 10) noexcept; +[[nodiscard]] std::optional Str_ToULL(lpctstr ptcStr, int base = 10) noexcept; +[[nodiscard]] inline +std::optional Str_ToST(lpctstr ptcStr, int base = 10) noexcept; // The _Fast variants write from the end of the given buffer and return a pointer to the new start of the string, which in most // cases is different from the pointer passed as argument! -NODISCARD tchar* Str_FromI_Fast (int val, tchar* buf, size_t buf_length, uint base = 10) noexcept; -NODISCARD tchar* Str_FromUI_Fast (uint val, tchar* buf, size_t buf_length, uint base = 10) noexcept; -NODISCARD tchar* Str_FromLL_Fast (llong val, tchar* buf, size_t buf_length, uint base = 10) noexcept; -NODISCARD tchar* Str_FromULL_Fast (ullong val, tchar* buf, size_t buf_length, uint base = 10) noexcept; +[[nodiscard]] tchar* Str_FromI_Fast (int val, tchar* buf, size_t buf_length, uint base = 10) noexcept; +[[nodiscard]] tchar* Str_FromUI_Fast (uint val, tchar* buf, size_t buf_length, uint base = 10) noexcept; +[[nodiscard]] tchar* Str_FromLL_Fast (llong val, tchar* buf, size_t buf_length, uint base = 10) noexcept; +[[nodiscard]] tchar* Str_FromULL_Fast (ullong val, tchar* buf, size_t buf_length, uint base = 10) noexcept; // These functions use the _Fast methods, but do move the string from the end of the buffer to the beginning, so that the input pointer is still valid. void Str_FromI (int val, tchar* buf, size_t buf_length, uint base = 10) noexcept; @@ -417,17 +425,47 @@ inline ssize_t sGetLine_StaticBuf(const char *data, const size_t datasize) noexc return sGetDelimiter_StaticBuf('\n', data, datasize); } -//--- + +//--- Inline methods + +std::optional Str_ToST(lpctstr ptcStr, int base) noexcept +{ + if constexpr (sizeof(size_t) == 4) + return Str_ToU(ptcStr, base); + else + return Str_ToULL(ptcStr, base); +} + + +//--- Template methods template -bool svtonum(std::string_view const& view, T& value) +bool sv_to_num(std::string_view const& view, T* value, int base = 10) noexcept { + static_assert(std::is_arithmetic_v, "Input variable is not an arithmetic type."); if (view.empty()) return false; const char* first = view.data(); const char* last = view.data() + view.length(); - const std::from_chars_result res = std::from_chars(first, last, value); + const std::from_chars_result res = std::from_chars(first, last, *value, base); + + if (res.ec != std::errc()) + return false; + if (res.ptr != last) + return false; + return true; +} + +template +bool cstr_to_num(const char * str, T* value, int base = 10, uint str_max_length = SCRIPT_MAX_LINE_LEN) noexcept +{ + static_assert(std::is_arithmetic_v, "Input variable is not an arithmetic type."); + if (!str || ('\0' == *str)) + return false; + + const char* last = str + strnlen(str, str_max_length); + const std::from_chars_result res = std::from_chars(str, last, *value, base); if (res.ec != std::errc()) return false; diff --git a/src/common/sphere_library/stypecast.h b/src/common/sphere_library/stypecast.h new file mode 100644 index 000000000..3b02f5423 --- /dev/null +++ b/src/common/sphere_library/stypecast.h @@ -0,0 +1,255 @@ +#ifndef _INC_STYPECAST_H +#define _INC_STYPECAST_H + +#include +#include + +//-- Explicitly promote to a larger type or narrow to a smaller type, instead of inattentive casts. + +// Promote to the corresponding 32 bits numeric type a smaller numeric variable. +template +[[nodiscard]] +constexpr auto i_promote32(const T a) noexcept +{ + static_assert(std::is_arithmetic_v, "Input variable is not an arithmetic type."); + static_assert(std::is_integral_v || (std::is_floating_point_v && std::is_signed_v), "Unsigned floating point numbers are unsupported by the language standard"); + static_assert(sizeof(T) < 4, "Input variable is not smaller than a 32 bit number."); + if constexpr (std::is_signed_v) + { + if constexpr (std::is_floating_point_v) + return static_cast(a); + return static_cast(a); + } + else + return static_cast(a); +} + +// Promote to the corresponding 64 bits numeric type a smaller numeric variable. +template +[[nodiscard]] +constexpr auto i_promote64(const T a) noexcept +{ + static_assert(std::is_arithmetic_v, "Input variable is not an arithmetic type."); + static_assert(std::is_integral_v || (std::is_floating_point_v && std::is_signed_v), "Unsigned floating point numbers are unsupported by the language standard"); + static_assert(sizeof(T) < 8, "Input variable is not smaller than a 64 bit number."); + if constexpr (std::is_signed_v) + { + if constexpr (std::is_floating_point_v) + return static_cast(a); + return static_cast(a); + } + else + return static_cast(a); +} + +template +[[nodiscard]] +constexpr auto i_narrow32(const T a) noexcept +{ + static_assert(std::is_arithmetic_v, "Input variable is not an arithmetic type."); + static_assert(std::is_integral_v || (std::is_floating_point_v && std::is_signed_v), "Unsigned floating point numbers are unsupported by the language standard"); + static_assert(sizeof(T) >= 4, "Input variable is smaller than a 32 bit number."); + + // Since the narrowing can be implementation specific, here we decide that we take only the lower 32 bytes and discard the upper ones. + constexpr uint64 umask = 0x0000'0000'FFFF'FFFF; + if constexpr (std::is_signed_v) + { + if constexpr (std::is_floating_point_v) + return static_cast(static_cast(a) & umask); + return static_cast(static_cast(a) & umask); + } + else + return static_cast(static_cast(a) & umask); +} + +template +[[nodiscard]] +constexpr auto i_narrow16(const T a) noexcept +{ + static_assert(std::is_arithmetic_v, "Input variable is not an arithmetic type."); + static_assert(std::is_integral_v || (std::is_floating_point_v && std::is_signed_v), "Unsigned floating point numbers are unsupported by the language standard"); + static_assert(sizeof(T) >= 2, "Input variable is smaller than a 16 bit number."); + + // Since the narrowing can be implementation specific, here we decide that we take only the lower 32 bytes and discard the upper ones. + constexpr uint64 umask = 0x0000'0000'FFFF'FFFF; + if constexpr (std::is_signed_v) + { + if constexpr (std::is_floating_point_v) + return static_cast(static_cast(a) & umask); + return static_cast(static_cast(a) & umask); + } + else + return static_cast(static_cast(a) & umask); +} + +template +[[nodiscard]] +constexpr auto i64_narrow32(const T a) noexcept +{ + static_assert(std::is_arithmetic_v, "Input variable is not an arithmetic type."); + static_assert(std::is_integral_v || (std::is_floating_point_v && std::is_signed_v), "Unsigned floating point numbers are unsupported by the language standard"); + static_assert(sizeof(T) == 8, "Input variable is not a 64 bit number."); + + // Since the narrowing can be implementation specific, here we decide that we take only the lower 32 bytes and discard the upper ones. + constexpr uint64 umask = 0x0000'0000'FFFF'FFFF; + if constexpr (std::is_signed_v) + { + if constexpr (std::is_floating_point_v) + return static_cast(a & umask); + return static_cast(a & umask); + } + else + return static_cast(a & umask); +} + +template +[[nodiscard]] +constexpr auto i64_narrow16(const T a) noexcept +{ + static_assert(std::is_arithmetic_v, "Input variable is not an arithmetic type."); + static_assert(std::is_integral_v || (std::is_floating_point_v && std::is_signed_v), "Unsigned floating point numbers are unsupported by the language standard"); + static_assert(sizeof(T) == 8, "Input variable is not a 64 bit number."); + + // Since the narrowing can be implementation specific, here we decide that we take only the lower 32 bytes and discard the upper ones. + constexpr uint64 umask = 0x0000'0000'0000'FFFF; + if constexpr (std::is_signed_v) + { + if constexpr (std::is_floating_point_v) + return static_cast(a & umask); + return static_cast(a & umask); + } + else + return static_cast(a & umask); +} + +template +[[nodiscard]] +constexpr auto i32_narrow16(const T a) noexcept +{ + static_assert(std::is_arithmetic_v, "Input variable is not an arithmetic type."); + static_assert(std::is_integral_v || (std::is_floating_point_v && std::is_signed_v), "Unsigned floating point numbers are unsupported by the language standard"); + static_assert(sizeof(T) == 4, "Input variable is not a 32 bit number."); + + // Since the narrowing can be implementation specific, here we decide that we take only the lower 16 bytes and discard the upper ones. + constexpr uint32 umask = 0x0000'FFFF; + if constexpr (std::is_signed_v) + { + if constexpr (std::is_floating_point_v) + return static_cast(a & umask); + return static_cast(a & umask); + } + else + return static_cast(a & umask); +} + +template +[[nodiscard]] +constexpr auto i16_narrow8(const T a) noexcept +{ + static_assert(std::is_arithmetic_v, "Input variable is not an arithmetic type."); + static_assert(std::is_integral_v, "Only integral types are supported by this function."); + static_assert(sizeof(T) == 2, "Input variable is not a 16 bit number."); + + // Since the narrowing can be implementation specific, here we decide that we take only the lower 16 bytes and discard the upper ones. + constexpr uint16 umask = 0x00FF; + if constexpr (std::is_signed_v) + return static_cast(a & umask); + else + return static_cast(a & umask); +} + + +[[nodiscard]] +inline int8 i8_from_u8_checked(const uint8 a) // not clamping/capping +{ + ASSERT(a <= INT8_MAX); + return static_cast(a); +} +template int8 i8_from_u8_checked(T) = delete; + +[[nodiscard]] +inline int16 i16_from_u16_checked(const uint16 a) // not clamping/capping +{ + ASSERT(a <= INT16_MAX); + return static_cast(a); +} +template int16 i16_from_u16_checked(T) = delete; + +[[nodiscard]] +inline int32 i32_from_u32_checked(const uint32 a) // not clamping/capping +{ + ASSERT(a <= INT32_MAX); + return static_cast(a); +} +template int32 i32_from_u32_checked(T) = delete; + +[[nodiscard]] +inline int64 i64_from_u64_checked(const uint64 a) // not clamping/capping +{ + ASSERT(a <= INT64_MAX); + return static_cast(a); +} +template int64 i64_from_u64_checked(T) = delete; + + +[[nodiscard]] constexpr +inline int8 i8_from_u8_clamping(const uint8 a) noexcept +{ + return (a > (uint8)INT8_MAX) ? INT8_MAX : (int8)a; +} + +[[nodiscard]] constexpr +inline int16 i16_from_u16_clamping(const uint16 a) noexcept +{ + return (a > (uint16)INT16_MAX) ? INT16_MAX : (int16)a; +} + +[[nodiscard]] constexpr +inline int32 i32_from_u32_clamping(const uint32 a) noexcept +{ + return (a > (uint32)INT32_MAX) ? INT32_MAX : (int32)a; +} + +[[nodiscard]] constexpr +inline int64 i64_from_u64_clamping(const uint64 a) noexcept +{ + return (a > (uint64)INT64_MAX) ? INT64_MAX : (int64)a; +} + +[[nodiscard]] constexpr +inline int32 i32_from_usize_clamping(const size_t a) noexcept +{ + return (a > (size_t)INT32_MAX) ? INT32_MAX : (int32)a; +} + +[[nodiscard]] constexpr +inline int64 i64_from_usize_clamping(const size_t a) noexcept +{ + return (a > (size_t)INT64_MAX) ? INT64_MAX : (int64)a; +} + +[[nodiscard]] constexpr +inline uint32 u32_from_usize_clamping(const size_t a) noexcept +{ + if constexpr (sizeof(size_t) == 8) + return (a > (size_t)UINT32_MAX) ? UINT32_MAX : (uint32)a; + else + return a; +} + + +// Use this as a double check, to be sure at compile time that the two variables have the same size and sign. +template +[[nodiscard]] +constexpr Tout num_alias_cast(const Tin a) noexcept +{ + static_assert(std::is_arithmetic_v || std::is_enum_v, "Input variable is not a numeric type."); + static_assert(std::is_arithmetic_v || std::is_enum_v, "Output variable is not a numeric type."); + static_assert(sizeof(Tin) == sizeof(Tout), "Input and output types do not have the same size."); + static_assert(!(std::is_signed_v && std::is_unsigned_v), "Casting signed to unsigned."); + static_assert(!(std::is_signed_v && std::is_unsigned_v ), "Casting unsigned to signed."); + return static_cast(a); +} + + +#endif // _INC_STYPECAST_H diff --git a/src/common/sphereproto.h b/src/common/sphereproto.h index be460764d..2f659c7a2 100644 --- a/src/common/sphereproto.h +++ b/src/common/sphereproto.h @@ -16,29 +16,30 @@ class CLanguageID { -private: // 3 letter code for language. // ENU,FRA,DEU,etc. (see langcode.iff) // terminate with a 0 // 0 = english default. char m_codes[4]; // UNICODE language pref. ('ENU'=english) + public: - CLanguageID() : + CLanguageID() noexcept : m_codes{} {} - CLanguageID( const char * pszInit ) + CLanguageID( const char * pszInit ) noexcept { Set( pszInit ); } - CLanguageID(int iDefault); - bool IsDef() const + CLanguageID(int iDefault) noexcept; + + bool IsDef() const noexcept { return ( m_codes[0] != 0 ); } - void GetStrDef(tchar* pszLang); - void GetStr(tchar* pszLang) const; + void GetStrDef(tchar* pszLang) noexcept; + void GetStr(tchar* pszLang) const noexcept; lpctstr GetStr() const; - bool Set(lpctstr pszLang); + bool Set(lpctstr pszLang) noexcept; }; enum XCMD_TYPE // XCMD_* messages are unique in both directions. @@ -384,11 +385,11 @@ enum SEASON_TYPE : uchar enum BBOARDF_TYPE // Bulletin Board Flags. m_flag { BBOARDF_NAME = 0, // board name - BBOARDF_MSG_HEAD, // 1=message header, + BBOARDF_MSG_HEAD, // 1=message header, BBOARDF_MSG_BODY, // 2=message body BBOARDF_REQ_FULL, // 3=request for full msg. BBOARDF_REQ_HEAD, // 4=request for just head. - BBOARDF_NEW_MSG, // 5=new message, + BBOARDF_NEW_MSG, // 5=new message, BBOARDF_DELETE // 6=Delete }; @@ -718,6 +719,7 @@ enum RACE_TYPE // character race, used in new character creation (0x8D) and sta /* Client Versions numeric constants. WARNING: DEPRECATED! Use CUOClientVersion (or at least wrap those numbers in that class). + TODO: convert them to CUOClientVersion. */ // client versions (expansions) diff --git a/src/common/target_info.h b/src/common/target_info.h index cf1f75b05..dfd9f643f 100644 --- a/src/common/target_info.h +++ b/src/common/target_info.h @@ -2,13 +2,13 @@ #define _INC_TARGET_INFO_H -[[maybe_unused]] +[[maybe_unused, nodiscard]] constexpr const char* get_target_os_str() { #if defined(_WIN32) return "Windows"; #elif defined(_BSD) - return "FreeBSD"; + return "BSD"; #elif defined(__linux__) return "Linux"; #elif defined(__APPLE__) @@ -18,14 +18,14 @@ constexpr const char* get_target_os_str() #endif } -[[maybe_unused]] +[[maybe_unused, nodiscard]] constexpr const char* get_target_word_size_str() { return (sizeof(void*) == 8) ? "64" : "32"; } // __ARM_ARCH -[[maybe_unused]] +[[maybe_unused, nodiscard]] constexpr const char* get_target_arch_str() { #if defined(__x86_64__) || defined(_M_X64) diff --git a/src/game/CObjBase.cpp b/src/game/CObjBase.cpp index 18fbbb946..d7c213b6a 100644 --- a/src/game/CObjBase.cpp +++ b/src/game/CObjBase.cpp @@ -1702,7 +1702,7 @@ bool CObjBase::r_WriteVal( lpctstr ptcKey, CSString &sVal, CTextConsole * pSrc, SKIP_SEPARATORS( ptcKey ); if (! *ptcKey ) - sVal.Format("%d=%s", ct->m_clilocid, ct->m_args); + sVal.Format("%u=%s", ct->m_clilocid, ct->m_args); else if ( !strnicmp( ptcKey, "ID", 2 )) //Cliloc. sVal.FormatDWVal(ct->m_clilocid); else if ( !strnicmp( ptcKey, "VAL", 3 )) //Arguments. @@ -2347,7 +2347,7 @@ bool CObjBase::r_Verb( CScript & s, CTextConsole * pSrc ) // Execute command fro CSString sPrompt; sPrompt.Format("%s (# = default)", (lpctstr)(Arg_ppCmd[0])); - pClientSrc->addGumpInpVal( true, INPVAL_STYLE_TEXTEDIT, + pClientSrc->addGumpInputVal( true, INPVAL_STYLE_TEXTEDIT, iMaxLength, sPrompt, sOrgValue, this ); } break; diff --git a/src/game/CRegion.cpp b/src/game/CRegion.cpp index 4de1a06e8..7ffcef3b4 100644 --- a/src/game/CRegion.cpp +++ b/src/game/CRegion.cpp @@ -193,9 +193,13 @@ bool CRegion::MakeRegionDefname() // Is this is subsequent key with a number? Get the highest (plus one) if ( IsStrNumericDec( ptcKey ) ) { - int iVarThis = Str_ToI( ptcKey ); - if ( iVarThis >= iVar ) - iVar = iVarThis + 1; + std::optional iconv = Str_ToI( ptcKey ); + if (iconv.has_value()) + { + int iVarThis = iconv.value(); + if ( iVarThis >= iVar ) + iVar = iVarThis + 1; + } } else ++iVar; diff --git a/src/game/CServer.cpp b/src/game/CServer.cpp index d93589ce9..2091b2c09 100644 --- a/src/game/CServer.cpp +++ b/src/game/CServer.cpp @@ -1060,8 +1060,8 @@ void CServer::ProfileDump( CTextConsole * pSrc, bool bDump ) ftDump->Printf("Profiles %s: (%d sec total)\n", GetCurrentProfileData().IsActive() ? "ON" : "OFF", GetCurrentProfileData().GetActiveWindow()); } - size_t iThreadCount = ThreadHolder::get().getActiveThreads(); - for ( size_t iThreads = 0; iThreads < iThreadCount; ++iThreads) + size_t uiThreadCount = ThreadHolder::get().getActiveThreads(); + for ( size_t iThreads = 0; iThreads < uiThreadCount; ++iThreads) { IThread* thrCurrent = ThreadHolder::get().getThreadAt(iThreads); if (thrCurrent == nullptr) diff --git a/src/game/CServer.h b/src/game/CServer.h index 608df7a48..7070f0aa2 100644 --- a/src/game/CServer.h +++ b/src/game/CServer.h @@ -73,7 +73,7 @@ extern class CServer : public CServerDef, public CTextConsole public: CServer(); - virtual ~CServer(); + virtual ~CServer() override; CServer(const CServer& copy) = delete; CServer& operator=(const CServer& other) = delete; diff --git a/src/game/CServerConfig.cpp b/src/game/CServerConfig.cpp index 87f9f526f..456963106 100644 --- a/src/game/CServerConfig.cpp +++ b/src/game/CServerConfig.cpp @@ -2686,7 +2686,11 @@ CPointMap CServerConfig::GetRegionPoint( lpctstr pCmd ) const // Decode a telepo return CPointMap(); SKIP_NONNUM(pCmd); - size_t i = Str_ToUI(pCmd); + std::optional iconv = Str_ToU(pCmd); + if (!iconv.has_value()) + return CPointMap(); + + size_t i = iconv.value(); if (i > 0) { i -= 1; @@ -3764,8 +3768,14 @@ bool CServerConfig::LoadResourceSection( CScript * pScript ) if (iStartVersion == 2) { - if ( pScript->ReadKey()) - pStart->iClilocDescription = Str_ToI(pScript->GetKey()); + if ( pScript->ReadKey()) + { + std::optional iconv = Str_ToI(pScript->GetKey()); + if (!iconv.has_value()) + continue; + + pStart->iClilocDescription = *iconv; + } } } m_StartDefs.emplace_back(pStart); diff --git a/src/game/CServerDef.cpp b/src/game/CServerDef.cpp index ae0c78199..e23d12c29 100644 --- a/src/game/CServerDef.cpp +++ b/src/game/CServerDef.cpp @@ -63,6 +63,7 @@ size_t CServerDef::StatGet(SERV_STAT_TYPE i) const ADDTOCALLSTACK("CServerDef::StatGet"); ASSERT( i >= 0 && i < SERV_STAT_QTY ); size_t d = m_stStat[i]; + EXC_TRY("StatGet"); if ( i == SERV_STAT_MEM ) // memory information { @@ -168,7 +169,7 @@ void CServerDef::SetName( lpctstr pszName ) // No HTML tags using <> either. tchar szName[ 2*MAX_SERVER_NAME_SIZE ]; - size_t len = Str_GetBare( szName, pszName, sizeof(szName), "<>/\"\\" ); + const int len = Str_GetBare( szName, pszName, sizeof(szName), "<>/\"\\" ); if ( len <= 0 ) return; @@ -194,10 +195,10 @@ void CServerDef::StatDec(SERV_STAT_TYPE i) --m_stStat[i]; } -void CServerDef::SetStat(SERV_STAT_TYPE i, dword dwVal) +void CServerDef::SetStat(SERV_STAT_TYPE i, size_t uiVal) { ASSERT(i >= 0 && i < SERV_STAT_QTY); - m_stStat[i] = dwVal; + m_stStat[i] = uiVal; } lpctstr CServerDef::GetName() const // virtual override @@ -361,7 +362,7 @@ bool CServerDef::r_LoadVal( CScript & s ) SetName( s.GetArgStr() ); break; case SC_SERVPORT: - m_ip.SetPort( (word)s.GetArgVal() ); + m_ip.SetPort( s.GetArgWVal() ); break; case SC_ACCOUNTS: @@ -379,10 +380,10 @@ bool CServerDef::r_LoadVal( CScript & s ) } break; case SC_ITEMS: - SetStat( SERV_STAT_ITEMS, s.GetArgVal() ); + SetStat( SERV_STAT_ITEMS, s.GetArgDWVal() ); break; case SC_CHARS: - SetStat( SERV_STAT_CHARS, s.GetArgVal() ); + SetStat( SERV_STAT_CHARS, s.GetArgDWVal() ); break; case SC_TIMEZONE: m_TimeZone = (char)s.GetArgVal(); @@ -464,7 +465,7 @@ bool CServerDef::r_WriteVal( lpctstr ptcKey, CSString &sVal, CTextConsole * pSrc sVal = GetName(); // What the name should be. Fill in from ping. break; case SC_SERVPORT: - sVal.FormatVal( m_ip.GetPort() ); + sVal.FormatWVal( m_ip.GetPort() ); break; case SC_ACCOUNTS: sVal.FormatSTVal( StatGet( SERV_STAT_ACCOUNTS ) ); diff --git a/src/game/CServerDef.h b/src/game/CServerDef.h index b0da41106..b89174c20 100644 --- a/src/game/CServerDef.h +++ b/src/game/CServerDef.h @@ -81,7 +81,7 @@ class CServerDef : public CScriptObj size_t StatGet( SERV_STAT_TYPE i ) const; void StatInc( SERV_STAT_TYPE i ); void StatDec( SERV_STAT_TYPE i ); - void SetStat( SERV_STAT_TYPE i, dword dwVal ); + void SetStat( SERV_STAT_TYPE i, size_t uiVal ); virtual lpctstr GetName() const override; void SetName( lpctstr pszName ); diff --git a/src/game/CWorldImport.cpp b/src/game/CWorldImport.cpp index 0c8ca381f..56439bcac 100644 --- a/src/game/CWorldImport.cpp +++ b/src/game/CWorldImport.cpp @@ -424,58 +424,98 @@ bool CImportFile::ImportWSC( CScript & s, word wModeFlags ) if ( s.IsKey("X" )) { - CPointMap pt = pItem->GetUnkPoint(); - pt.m_x = (short)( atoi(pArg) ); + std::optional iconv = Str_ToI16(pArg); + if (!iconv.has_value()) + continue; + + CPointMap pt(pItem->GetUnkPoint()); + pt.m_x = *iconv; pItem->SetUnkPoint(pt); continue; } else if ( s.IsKey("Y" )) { - CPointMap pt = pItem->GetUnkPoint(); - pt.m_y = (short)( atoi(pArg) ); + std::optional iconv = Str_ToI16(pArg); + if (!iconv.has_value()) + continue; + + CPointMap pt(pItem->GetUnkPoint()); + pt.m_y = (*iconv); pItem->SetUnkPoint(pt); continue; } else if ( s.IsKey("Z" )) { - CPointMap pt = pItem->GetUnkPoint(); - pt.m_z = (char)( atoi(pArg) ); + std::optional iconv = Str_ToU8(pArg); + if (!iconv.has_value()) + continue; + + CPointMap pt(pItem->GetUnkPoint()); + pt.m_z = *iconv; pItem->SetUnkPoint(pt); continue; } else if ( s.IsKey("COLOR" )) { - pItem->SetHue( (HUE_TYPE)( atoi(pArg) ) ); + std::optional iconv = Str_ToU16(pArg); + if (!iconv.has_value()) + continue; + + pItem->SetHue(*iconv); continue; } else if ( s.IsKey("AMOUNT" )) { - pItem->SetAmount( (word)atoi(pArg) ); + std::optional iconv = Str_ToI16(pArg); + if (!iconv.has_value()) + continue; + + pItem->SetAmount(*iconv); continue; } else if ( s.IsKey("MOREX" )) { - pItem->m_itNormal.m_morep.m_x = (short)(atoi(pArg)); + std::optional iconv = Str_ToI16(pArg); + if (!iconv.has_value()) + continue; + + pItem->m_itNormal.m_morep.m_x = *iconv; continue; } else if ( s.IsKey("MOREY" )) { - pItem->m_itNormal.m_morep.m_y = (short)(atoi(pArg)); + std::optional iconv = Str_ToI16(pArg); + if (!iconv.has_value()) + continue; + + pItem->m_itNormal.m_morep.m_y = *iconv; continue; } else if ( s.IsKey("MOREZ" )) { - pItem->m_itNormal.m_morep.m_z = (char)( atoi(pArg) ); + std::optional iconv = Str_ToI8(pArg); + if (!iconv.has_value()) + continue; + + pItem->m_itNormal.m_morep.m_z = *iconv; continue; } else if ( s.IsKey("MORE" )) { - pItem->m_itNormal.m_more1 = Str_ToUI(pArg); + std::optional iconv = Str_ToU(pArg); + if (!iconv.has_value()) + continue; + + pItem->m_itNormal.m_more1 = *iconv; continue; } else if ( s.IsKey("MORE2" )) { - pItem->m_itNormal.m_more2 = Str_ToUI(pArg); + std::optional iconv = Str_ToU(pArg); + if (!iconv.has_value()) + continue; + + pItem->m_itNormal.m_more2 = *iconv; continue; } else if ( s.IsKey("DYEABLE" )) @@ -484,6 +524,7 @@ bool CImportFile::ImportWSC( CScript & s, word wModeFlags ) pItem->m_CanMask |= CAN_I_DYE; continue; } + /* else if ( s.IsKey("ATT" )) { // pItem->m_pDef->m_attackBase = atoi(pArg); @@ -493,6 +534,7 @@ bool CImportFile::ImportWSC( CScript & s, word wModeFlags ) // ??? translate the type field. //int i = atoi(pArg); } + */ } if ( mode == IMPFLAGS_CHARS ) @@ -520,65 +562,109 @@ bool CImportFile::ImportWSC( CScript & s, word wModeFlags ) if ( s.IsKey("X" )) { - CPointMap pt = pChar->GetUnkPoint(); - pt.m_x = (short)(atoi(pArg)); + std::optional iconv = Str_ToI16(pArg); + if (!iconv.has_value()) + return false; + + CPointMap pt(pChar->GetUnkPoint()); + pt.m_x = *iconv; pChar->SetUnkPoint(pt); continue; } else if ( s.IsKey("Y" )) { - CPointMap pt = pChar->GetUnkPoint(); - pt.m_y = (short)(atoi(pArg)); + std::optional iconv = Str_ToI16(pArg); + if (!iconv.has_value()) + return false; + + CPointMap pt(pChar->GetUnkPoint()); + pt.m_y = *iconv; pChar->SetUnkPoint(pt); continue; } else if ( s.IsKey("Z" )) { - CPointMap pt = pChar->GetUnkPoint(); - pt.m_z = (char)(atoi(pArg)); + std::optional iconv = Str_ToI8(pArg); + if (!iconv.has_value()) + return false; + + CPointMap pt(pChar->GetUnkPoint()); + pt.m_z = *iconv; pChar->SetUnkPoint(pt); continue; } else if ( s.IsKey("BODY" )) { - pChar->SetID((CREID_TYPE)(atoi(pArg))); + std::optional iconv = Str_ToU(pArg); + if (!iconv.has_value()) + return false; + + pChar->SetID(num_alias_cast(*iconv)); continue; } else if ( s.IsKey("SKIN" )) { - pChar->SetHue( (HUE_TYPE)( atoi(pArg) )); + std::optional iconv = Str_ToU16(pArg); + if (!iconv.has_value()) + return false; + + pChar->SetHue(num_alias_cast(*iconv)); continue; } else if ( s.IsKey("DIR" )) { - pChar->m_dirFace = (DIR_TYPE)(atoi(pArg)); + std::optional iconv = Str_ToI(pArg); + if (!iconv.has_value()) + return false; + + pChar->m_dirFace = num_alias_cast(*iconv); if ( (pChar->m_dirFace < 0) || (pChar->m_dirFace >= DIR_QTY) ) pChar->m_dirFace = DIR_SE; continue; } else if ( s.IsKey("XBODY" )) { - pChar->_iPrev_id = (CREID_TYPE)(atoi(pArg)); + std::optional iconv = Str_ToU(pArg); + if (!iconv.has_value()) + return false; + + pChar->_iPrev_id = num_alias_cast(*iconv); continue; } else if ( s.IsKey("XSKIN" )) { - pChar->_wPrev_Hue = (HUE_TYPE)( atoi(pArg) ); + std::optional iconv = Str_ToU16(pArg); + if (!iconv.has_value()) + return false; + + pChar->_wPrev_Hue = num_alias_cast(*iconv); continue; } else if ( s.IsKey("FONT" )) { - pChar->m_fonttype = (FONT_TYPE)(atoi(pArg)); + std::optional iconv = Str_ToU16(pArg); + if (!iconv.has_value()) + return false; + + pChar->m_fonttype = num_alias_cast(*iconv); continue; } else if ( s.IsKey("KARMA" )) { - pChar->SetKarma((short)(atoi(pArg))); + std::optional iconv = Str_ToI16(pArg); + if (!iconv.has_value()) + return false; + + pChar->SetKarma(*iconv); continue; } else if ( s.IsKey("FAME" )) { - pChar->SetFame((ushort)(atoi(pArg))); + std::optional iconv = Str_ToU16(pArg); + if (!iconv.has_value()) + return false; + + pChar->SetFame(*iconv); continue; } else if ( s.IsKey("TITLE" )) @@ -588,33 +674,67 @@ bool CImportFile::ImportWSC( CScript & s, word wModeFlags ) } else if ( s.IsKey("STRENGTH" )) { - pChar->Stat_SetBase(STAT_STR, (ushort)(atoi(pArg))); + std::optional iconv = Str_ToU16(pArg); + if (!iconv.has_value()) + return false; + + pChar->Stat_SetBase(STAT_STR, *iconv); } else if ( s.IsKey("DEXTERITY" )) { - pChar->Stat_SetBase(STAT_DEX, (ushort)(atoi(pArg))); + std::optional iconv = Str_ToU16(pArg); + if (!iconv.has_value()) + return false; + + pChar->Stat_SetBase(STAT_DEX, *iconv); } else if ( s.IsKey("INTELLIGENCE" )) { - pChar->Stat_SetBase(STAT_INT, (ushort)(atoi(pArg))); + std::optional iconv = Str_ToU16(pArg); + if (!iconv.has_value()) + return false; + + pChar->Stat_SetBase(STAT_INT, *iconv); } else if ( s.IsKey("HITPOINTS" )) { - pChar->Stat_SetVal(STAT_STR,(ushort)(atoi(pArg))); + std::optional iconv = Str_ToU16(pArg); + if (!iconv.has_value()) + return false; + + pChar->Stat_SetVal(STAT_STR, *iconv); } else if ( s.IsKey("STAMINA" )) { - pChar->Stat_SetVal(STAT_DEX,(ushort)(atoi(pArg))); + std::optional iconv = Str_ToU16(pArg); + if (!iconv.has_value()) + return false; + + pChar->Stat_SetVal(STAT_DEX, *iconv); } else if ( s.IsKey( "MANA" )) { - pChar->Stat_SetVal(STAT_INT,(ushort)(atoi(pArg))); + std::optional iconv = Str_ToU16(pArg); + if (!iconv.has_value()) + return false; + + pChar->Stat_SetVal(STAT_INT, *iconv); } else if ( s.IsKeyHead( "SKILL", 5 )) { - SKILL_TYPE skill = (SKILL_TYPE)(atoi( &(s.GetKey()[5]) )); + // TODO: they are not saved like this anymore (not by index but by proper name) + std::optional iconv_int = Str_ToI(s.GetKey() + 5); + if (!iconv_int.has_value()) + return false; + + const auto skill = num_alias_cast(*iconv_int); + + std::optional iconv = Str_ToU16(pArg); + if (!iconv.has_value()) + return false; + if ( pChar->IsSkillBase(skill) && g_Cfg.m_SkillIndexDefs.valid_index(skill) ) - pChar->Skill_SetBase( skill, (ushort)atoi(pArg)); + pChar->Skill_SetBase( skill, *iconv); } else if ( s.IsKey("ACCOUNT" )) { @@ -623,20 +743,28 @@ bool CImportFile::ImportWSC( CScript & s, word wModeFlags ) } else if ( s.IsKey("KILLS" ) && pChar->m_pPlayer ) { - pChar->m_pPlayer->m_wMurders = (word)(atoi(pArg)); + std::optional iconv = Str_ToU16(pArg); + if (!iconv.has_value()) + return false; + + pChar->m_pPlayer->m_wMurders = *iconv; } else if ( s.IsKey("NPCAITYPE" )) { // Convert to proper NPC type. - int i = atoi( pArg ); + std::optional iconv = Str_ToI(pArg); + if (!iconv.has_value()) + return false; + + const int i = *iconv; switch ( i ) { case 0x01: pChar->SetNPCBrain( NPCBRAIN_HEALER ); break; case 0x02: pChar->SetNPCBrain( NPCBRAIN_MONSTER ); break; - case 0x04: + case 0x04: FALLTHROUGH; case 0x40: pChar->SetNPCBrain( NPCBRAIN_GUARD ); break; case 0x08: pChar->SetNPCBrain( NPCBRAIN_BANKER ); break; - default: pChar->SetNPCBrain( pChar->GetNPCBrainAuto() ); break; + default: pChar->SetNPCBrain( pChar->GetNPCBrainAuto() ); break; } } continue; diff --git a/src/game/chars/CChar.cpp b/src/game/chars/CChar.cpp index 60c3bba6d..bbeea5c4f 100644 --- a/src/game/chars/CChar.cpp +++ b/src/game/chars/CChar.cpp @@ -4540,15 +4540,21 @@ bool CChar::r_Verb( CScript &s, CTextConsole * pSrc ) // Execute command from sc GETNONWHITESPACE( psTmp ); tchar * ttVal[2]; int iTmp = 1; - int iArg = Str_ParseCmds( psTmp, ttVal, ARRAY_COUNT( ttVal ), " ,\t" ); + const int iArg = Str_ParseCmds( psTmp, ttVal, ARRAY_COUNT( ttVal ), " ,\t" ); if (!iArg) { return false; } if ( iArg == 2 ) { - if ( IsDigit( ttVal[1][0] ) ) - iTmp = Str_ToI( ttVal[1] ); + if ( IsDigit( ttVal[1][0] ) ) + { + std::optional iconv = Str_ToI(ttVal[1]); + if (!iconv.has_value()) + return false; + + iTmp = *iconv; + } } //DEBUG_ERR(( "CHV_MAKEITEM iTmp is %d, arg was %s\n",iTmp,psTmp )); diff --git a/src/game/chars/CChar.h b/src/game/chars/CChar.h index 6a7a52fcd..58b1b1dd2 100644 --- a/src/game/chars/CChar.h +++ b/src/game/chars/CChar.h @@ -1007,7 +1007,7 @@ public: void StatFlag_Mod(uint64 uiStatFlag, bool fMod) noexcept; bool Spell_CastDone(); virtual bool OnSpellEffect( SPELL_TYPE spell, CChar * pCharSrc, int iSkillLevel, CItem * pSourceItem, bool fReflecting = false, int64 iDuration = 0) override; bool Spell_CanCast( SPELL_TYPE &spellRef, bool fTest, CObjBase * pSrc, bool fFailMsg, bool fCheckAntiMagic = true ); - CChar * Spell_Summon_Try(SPELL_TYPE spell, CPointMap ptTarg, CREID_TYPE iC1); + CChar* Spell_Summon_Try(SPELL_TYPE spell, CPointMap ptTarg, CREID_TYPE uiCreature); int64 GetSpellDuration( SPELL_TYPE spell, int iSkillLevel, CChar * pCharSrc = nullptr ); // in tenths of second // Memories about objects in the world. ------------------- diff --git a/src/game/chars/CCharAct.cpp b/src/game/chars/CCharAct.cpp index 481093daa..6e3ac6137 100644 --- a/src/game/chars/CCharAct.cpp +++ b/src/game/chars/CCharAct.cpp @@ -914,27 +914,35 @@ ANIM_TYPE CChar::GenerateAnimate( ANIM_TYPE action, bool fTranslate, bool fBackw { // Animals have certain anims. Monsters have others. - CUOMobTypesType mobTypesRow = { 0, 0 }; - + CUOMobTypesEntry mobTypesRow {MOBTE_QTY, 0}; CREID_TYPE dispID = GetDispID(); + bool fUseMobTypes = g_Cfg.m_fUseMobTypes && g_Install.m_mobtypes.IsLoaded(); //Check mobtypes.txt to get the anim type - if (g_Cfg.m_fUseMobTypes && g_Install.m_mobtypes.IsLoaded()) + if (fUseMobTypes) { - mobTypesRow.m_type = g_Install.m_mobtypes.GetEntry((ushort)dispID)->m_type; - mobTypesRow.m_flags = g_Install.m_mobtypes.GetEntry((ushort)dispID)->m_flags; + const CUOMobTypesEntry *pMobtEntry = g_Install.m_mobtypes.GetEntry(dispID); + + if (pMobtEntry->m_uiType == MOBTE_QTY) + { + // Invalid entry, fall back to old method. + fUseMobTypes = false; + } + else + { + mobTypesRow.m_uiType = pMobtEntry->m_uiType; + mobTypesRow.m_uiFlags = pMobtEntry->m_uiFlags; + } } - else + + if (!fUseMobTypes) { //Old Method - if (GetDispID() >= CREID_HORSE_TAN) - { - mobTypesRow.m_type = 2; - } + mobTypesRow.m_uiType = (dispID >= CREID_HORSE_TAN) ? MOBTE_ANIMAL : MOBTE_MONSTER; } //Standard UOP Animations - if (mobTypesRow.m_flags & ATFLAG_UseUopAnimation) + if (mobTypesRow.m_uiFlags & ATFLAG_UseUopAnimation) { //Only mount animations, 3 actions @@ -1031,7 +1039,7 @@ ANIM_TYPE CChar::GenerateAnimate( ANIM_TYPE action, bool fTranslate, bool fBackw case ANIM_RUN_UNARM: case ANIM_RUN_ARMED: //If the creature can fly we can use flying action for running - if (mobTypesRow.m_flags & ATFLAG_CanFlying) + if (mobTypesRow.m_uiFlags & ATFLAG_CanFlying) { //Phoenix and Parrot Bird don't have run anims if (IsStatFlag(STATF_FLY | STATF_HOVERING) || (dispID == CREID_PARROT_BIRD || dispID == CREID_PHOENIX) ) @@ -1080,7 +1088,7 @@ ANIM_TYPE CChar::GenerateAnimate( ANIM_TYPE action, bool fTranslate, bool fBackw else { return ANIM_UOP_STAND_COMBAT; - } + } case ANIM_FIDGET1: case ANIM_BOW: @@ -1124,7 +1132,7 @@ ANIM_TYPE CChar::GenerateAnimate( ANIM_TYPE action, bool fTranslate, bool fBackw case ANIM_THROW: // 2 actions for cast - if (dispID == CREID_CLOCKWORK_EXODUS) + if (dispID == CREID_CLOCKWORK_EXODUS) { switch (g_Rand.GetVal(2)) { @@ -1152,12 +1160,12 @@ ANIM_TYPE CChar::GenerateAnimate( ANIM_TYPE action, bool fTranslate, bool fBackw } else if (dispID == CREID_TS_TENTACLE || dispID == CREID_CHARYBDIS_TENTACLE) { - return ANIM_UOP_ATTACK_1; + return ANIM_UOP_ATTACK_1; } else if (dispID == CREID_CHARYBDIS) { return ANIM_UOP_GETHIT; - } + } else if (dispID == CREID_PUMPKIN_DEMON) { return ANIM_UOP_PEACE_TO_COMBAT; @@ -1209,7 +1217,7 @@ ANIM_TYPE CChar::GenerateAnimate( ANIM_TYPE action, bool fTranslate, bool fBackw case 1: return ANIM_UOP_ATTACK_2; break; } break; - } + } case ANIM_DIE_BACK: return ANIM_UOP_DIE_BACKWARD; @@ -1225,7 +1233,7 @@ ANIM_TYPE CChar::GenerateAnimate( ANIM_TYPE action, bool fTranslate, bool fBackw else { return ANIM_UOP_DIE_FORWARD; - } + } case ANIM_BLOCK: //No Block @@ -1305,7 +1313,7 @@ ANIM_TYPE CChar::GenerateAnimate( ANIM_TYPE action, bool fTranslate, bool fBackw } //Sea Monster: H slot with only 9 actions in L slot order //Only Sea Serpent and Dolphin - else if (mobTypesRow.m_type == 1) + else if (mobTypesRow.m_uiType == MOBTE_SEA_MONSTER) { switch (action) { @@ -1330,13 +1338,13 @@ ANIM_TYPE CChar::GenerateAnimate( ANIM_TYPE action, bool fTranslate, bool fBackw return ANIM_MON_ATTACK1; case ANIM_CAST_DIR: - if (dispID == CREID_DOLPHIN) //Dolphin doesn't have ANIM_MON_ATTACK2 and ANIM_MON_ATTACK3 + if (dispID == CREID_DOLPHIN) //Dolphin doesn't have ANIM_MON_ATTACK2 and ANIM_MON_ATTACK3 return ANIM_MON_AttackBow; else return ANIM_MON_ATTACK2; case ANIM_CAST_AREA: - if (dispID == CREID_DOLPHIN) //Dolphin doesn't have ANIM_MON_ATTACK2 and ANIM_MON_ATTACK3 + if (dispID == CREID_DOLPHIN) //Dolphin doesn't have ANIM_MON_ATTACK2 and ANIM_MON_ATTACK3 return ANIM_MON_DIE2; else return ANIM_MON_ATTACK3; @@ -1353,7 +1361,7 @@ ANIM_TYPE CChar::GenerateAnimate( ANIM_TYPE action, bool fTranslate, bool fBackw case ANIM_ATTACK_BOW: case ANIM_ATTACK_XBOW: case ANIM_ATTACK_WRESTLE: - if (dispID == CREID_DOLPHIN) //Dolphin doesn't have ANIM_MON_ATTACK2 and ANIM_MON_ATTACK3 + if (dispID == CREID_DOLPHIN) //Dolphin doesn't have ANIM_MON_ATTACK2 and ANIM_MON_ATTACK3 { switch (g_Rand.GetVal(2)) { @@ -1388,7 +1396,7 @@ ANIM_TYPE CChar::GenerateAnimate( ANIM_TYPE action, bool fTranslate, bool fBackw return ANIM_MON_DIE2; case ANIM_THROW: - if (dispID == CREID_DOLPHIN) //Dolphin doesn't have ANIM_MON_ATTACK2 and ANIM_MON_ATTACK3 + if (dispID == CREID_DOLPHIN) //Dolphin doesn't have ANIM_MON_ATTACK2 and ANIM_MON_ATTACK3 { return ANIM_MON_AttackBow; } @@ -1405,8 +1413,8 @@ ANIM_TYPE CChar::GenerateAnimate( ANIM_TYPE action, bool fTranslate, bool fBackw } } //Animal - else if ((mobTypesRow.m_type == 2 && !(mobTypesRow.m_flags & ATFLAG_CalculateOffsetLowGroupExtended)) - || (mobTypesRow.m_type == 0 && (mobTypesRow.m_flags & ATFLAG_CalculateOffsetByLowGroup))) + else if ((mobTypesRow.m_uiType == MOBTE_ANIMAL && !(mobTypesRow.m_uiFlags & ATFLAG_CalculateOffsetLowGroupExtended)) + || (mobTypesRow.m_uiType == MOBTE_MONSTER && (mobTypesRow.m_uiFlags & ATFLAG_CalculateOffsetByLowGroup))) { //Partial actions if (dispID == CREID_PARROT || dispID == CREID_BIRD_CROW) @@ -1693,7 +1701,7 @@ ANIM_TYPE CChar::GenerateAnimate( ANIM_TYPE action, bool fTranslate, bool fBackw ANIM_TYPE attack1 = ANIM_MON_ATTACK1; ANIM_TYPE cast1 = ANIM_MON_WALK, cast2 = ANIM_MON_WALK, cast3 = ANIM_MON_WALK; ushort castActions = 0, attackActions = 3, blockActions = 2; - + //Standard and Custom Anims switch (action) { @@ -1705,7 +1713,7 @@ ANIM_TYPE CChar::GenerateAnimate( ANIM_TYPE action, bool fTranslate, bool fBackw case ANIM_RUN_UNARM: case ANIM_RUN_ARMED: //If the creature can fly we can use flying action for running - if ((mobTypesRow.m_flags & ATFLAG_CanFlying) + if ((mobTypesRow.m_uiFlags & ATFLAG_CanFlying) || (pCharDef->m_Anims & AFLAG_CUST_MON_FLY)) //Custom anims with Fly action { return ANIM_MON_FLY; @@ -1719,7 +1727,7 @@ ANIM_TYPE CChar::GenerateAnimate( ANIM_TYPE action, bool fTranslate, bool fBackw case ANIM_STAND_WAR_1H: case ANIM_STAND_WAR_2H: //Stand action in crossbow - if (mobTypesRow.m_flags & ATFLAG_IdleAt8Frame) + if (mobTypesRow.m_uiFlags & ATFLAG_IdleAt8Frame) { return ANIM_MON_AttackXBow; } @@ -1770,13 +1778,13 @@ ANIM_TYPE CChar::GenerateAnimate( ANIM_TYPE action, bool fTranslate, bool fBackw } case ANIM_CAST_DIR: - case ANIM_CAST_AREA: + case ANIM_CAST_AREA: case ANIM_ATTACK_BOW: //return ANIM_MON_AttackBow; //Always Empty except for standard ID 13, 15 and 16 case ANIM_ATTACK_XBOW: //return ANIM_MON_AttackXBow; //Always Empty except for standard ID 13, 15 and 16 //Check how many cast actions are present //Stomp action is not a cast for Corpser, Earth Elemental and Gorilla - if (((mobTypesRow.m_flags & ATFLAG_StompAction) + if (((mobTypesRow.m_uiFlags & ATFLAG_StompAction) && (dispID != CREID_CORPSER && dispID != CREID_EARTH_ELEM && dispID != CREID_GORILLA)) || (pCharDef->m_Anims & AFLAG_CUST_MON_STOMP)) //Custom Anim with Stomp action { @@ -1827,7 +1835,7 @@ ANIM_TYPE CChar::GenerateAnimate( ANIM_TYPE action, bool fTranslate, bool fBackw } else //No cast Actions { - if (mobTypesRow.m_flags & ATFLAG_ReplaceAttack1With2) + if (mobTypesRow.m_uiFlags & ATFLAG_ReplaceAttack1With2) { attack1 = ANIM_MON_ATTACK2; } @@ -1886,17 +1894,17 @@ ANIM_TYPE CChar::GenerateAnimate( ANIM_TYPE action, bool fTranslate, bool fBackw case ANIM_GET_HIT: if (IsStatFlag(STATF_FLY | STATF_HOVERING)) //Running or Flying { - if (mobTypesRow.m_flags & ATFLAG_Use2IfHittedWhileRunning) + if (mobTypesRow.m_uiFlags & ATFLAG_Use2IfHittedWhileRunning) { return ANIM_MON_DIE1; } //GetHit while flying - else if ((mobTypesRow.m_flags & ATFLAG_CanFlying) && !(mobTypesRow.m_flags & ATFLAG_Use10IfHittedWhileFlying)) + else if ((mobTypesRow.m_uiFlags & ATFLAG_CanFlying) && !(mobTypesRow.m_uiFlags & ATFLAG_Use10IfHittedWhileFlying)) { return ANIM_MON_DIE_FLIGHT; } } - if (mobTypesRow.m_flags & ATFLAG_ReplaceGetHitBlockPillage) + if (mobTypesRow.m_uiFlags & ATFLAG_ReplaceGetHitBlockPillage) { return ANIM_MON_STAND; } @@ -1945,7 +1953,7 @@ ANIM_TYPE CChar::GenerateAnimate( ANIM_TYPE action, bool fTranslate, bool fBackw case ANIM_ATTACK_2H_PIERCE: case ANIM_ATTACK_WRESTLE: - if (mobTypesRow.m_flags & ATFLAG_ReplaceAttack1With2) + if (mobTypesRow.m_uiFlags & ATFLAG_ReplaceAttack1With2) { attack1 = ANIM_MON_ATTACK2; } @@ -2002,7 +2010,7 @@ ANIM_TYPE CChar::GenerateAnimate( ANIM_TYPE action, bool fTranslate, bool fBackw case ANIM_DIE_BACK: //Die while flying animation - if ((mobTypesRow.m_flags & ATFLAG_StompAction) && (mobTypesRow.m_flags & ATFLAG_CanFlying) && (mobTypesRow.m_flags & ATFLAG_Use10IfHittedWhileFlying) + if ((mobTypesRow.m_uiFlags & ATFLAG_StompAction) && (mobTypesRow.m_uiFlags & ATFLAG_CanFlying) && (mobTypesRow.m_uiFlags & ATFLAG_Use10IfHittedWhileFlying) && IsStatFlag(STATF_FLY | STATF_HOVERING)) { return ANIM_MON_DIE_FLIGHT; @@ -2014,7 +2022,7 @@ ANIM_TYPE CChar::GenerateAnimate( ANIM_TYPE action, bool fTranslate, bool fBackw case ANIM_DIE_FORWARD: //Die while flying animation - if ((mobTypesRow.m_flags & ATFLAG_StompAction) && (mobTypesRow.m_flags & ATFLAG_CanFlying) && (mobTypesRow.m_flags & ATFLAG_Use10IfHittedWhileFlying) + if ((mobTypesRow.m_uiFlags & ATFLAG_StompAction) && (mobTypesRow.m_uiFlags & ATFLAG_CanFlying) && (mobTypesRow.m_uiFlags & ATFLAG_Use10IfHittedWhileFlying) && IsStatFlag(STATF_FLY | STATF_HOVERING)) { return ANIM_MON_DIE_FLIGHT; @@ -2033,7 +2041,7 @@ ANIM_TYPE CChar::GenerateAnimate( ANIM_TYPE action, bool fTranslate, bool fBackw } case ANIM_BLOCK: - if (mobTypesRow.m_flags & ATFLAG_ReplaceGetHitBlockPillage) + if (mobTypesRow.m_uiFlags & ATFLAG_ReplaceGetHitBlockPillage) { return ANIM_MON_STAND; } @@ -2075,11 +2083,11 @@ ANIM_TYPE CChar::GenerateAnimate( ANIM_TYPE action, bool fTranslate, bool fBackw break; case ANIM_THROW: - if (mobTypesRow.m_flags & ATFLAG_IdleAt8Frame) //Action Throw in Bow action + if (mobTypesRow.m_uiFlags & ATFLAG_IdleAt8Frame) //Action Throw in Bow action { return ANIM_MON_AttackBow; } - else if (((mobTypesRow.m_flags & ATFLAG_StompAction) + else if (((mobTypesRow.m_uiFlags & ATFLAG_StompAction) && (dispID != CREID_CORPSER && dispID != CREID_EARTH_ELEM && dispID != CREID_GORILLA)) || (pCharDef->m_Anims & AFLAG_CUST_MON_STOMP)) //Custom anims with Stomp action { @@ -2103,7 +2111,7 @@ ANIM_TYPE CChar::GenerateAnimate( ANIM_TYPE action, bool fTranslate, bool fBackw } case ANIM_PILLAGE: - if (mobTypesRow.m_flags & ATFLAG_ReplaceGetHitBlockPillage) + if (mobTypesRow.m_uiFlags & ATFLAG_ReplaceGetHitBlockPillage) { return ANIM_MON_FIDGET1; } @@ -2135,11 +2143,11 @@ ANIM_TYPE CChar::GenerateAnimate( ANIM_TYPE action, bool fTranslate, bool fBackw case ANIM_STOMP: case ANIM_SPECIAL: case ANIM_SUMMON: - if ((mobTypesRow.m_flags & ATFLAG_StompAction) || (pCharDef->m_Anims & AFLAG_CUST_MON_STOMP)) + if ((mobTypesRow.m_uiFlags & ATFLAG_StompAction) || (pCharDef->m_Anims & AFLAG_CUST_MON_STOMP)) { return ANIM_MON_Stomp; } - else if ((mobTypesRow.m_flags & ATFLAG_CanFlying) && !(pCharDef->m_Anims & AFLAG_CUST_MON_FLY)) //Standard flying anims with Land/TakeOff action + else if ((mobTypesRow.m_uiFlags & ATFLAG_CanFlying) && !(pCharDef->m_Anims & AFLAG_CUST_MON_FLY)) //Standard flying anims with Land/TakeOff action { return ANIM_MON_LAND; } @@ -2164,12 +2172,12 @@ ANIM_TYPE CChar::GenerateAnimate( ANIM_TYPE action, bool fTranslate, bool fBackw } case ANIM_ALERT: - if (((mobTypesRow.m_flags & ATFLAG_StompAction) && dispID != CREID_CORPSER && dispID != CREID_EARTH_ELEM) + if (((mobTypesRow.m_uiFlags & ATFLAG_StompAction) && dispID != CREID_CORPSER && dispID != CREID_EARTH_ELEM) || (pCharDef->m_Anims & AFLAG_CUST_MON_STOMP)) //Custom anims with Stomp action { return ANIM_MON_Stomp; } - else if ((mobTypesRow.m_flags & ATFLAG_CanFlying) && !(pCharDef->m_Anims & AFLAG_CUST_MON_FLY)) //Standard flying anims with Land/TakeOff action + else if ((mobTypesRow.m_uiFlags & ATFLAG_CanFlying) && !(pCharDef->m_Anims & AFLAG_CUST_MON_FLY)) //Standard flying anims with Land/TakeOff action { return ANIM_MON_LAND; } @@ -2179,7 +2187,7 @@ ANIM_TYPE CChar::GenerateAnimate( ANIM_TYPE action, bool fTranslate, bool fBackw } case ANIM_FLY: - if (mobTypesRow.m_flags & ATFLAG_ReplaceFlyAction) + if (mobTypesRow.m_uiFlags & ATFLAG_ReplaceFlyAction) { return ANIM_MON_WALK; } @@ -2189,7 +2197,7 @@ ANIM_TYPE CChar::GenerateAnimate( ANIM_TYPE action, bool fTranslate, bool fBackw } case ANIM_LAND: - if (mobTypesRow.m_flags & ATFLAG_ReplaceFlyAction) + if (mobTypesRow.m_uiFlags & ATFLAG_ReplaceFlyAction) { return ANIM_MON_STAND; } @@ -2199,11 +2207,11 @@ ANIM_TYPE CChar::GenerateAnimate( ANIM_TYPE action, bool fTranslate, bool fBackw } case ANIM_GETHIT_AIR: - if (mobTypesRow.m_flags & ATFLAG_ReplaceFlyAction) + if (mobTypesRow.m_uiFlags & ATFLAG_ReplaceFlyAction) { return ANIM_MON_STAND; } - else if (mobTypesRow.m_flags & ATFLAG_Use10IfHittedWhileFlying) + else if (mobTypesRow.m_uiFlags & ATFLAG_Use10IfHittedWhileFlying) { return ANIM_MON_GETHIT; } diff --git a/src/game/chars/CCharSpell.cpp b/src/game/chars/CCharSpell.cpp index 922a9f068..9b7aed598 100644 --- a/src/game/chars/CCharSpell.cpp +++ b/src/game/chars/CCharSpell.cpp @@ -2316,15 +2316,15 @@ bool CChar::Spell_CanCast( SPELL_TYPE &spellRef, bool fTest, CObjBase * pSrc, bo if ( !Skill_CanUse(skill) ) return false; - ushort iManaUse = g_Cfg.Calc_SpellManaCost(this, pSpellDef, pSrc); - ushort iTithingUse = g_Cfg.Calc_SpellTithingCost(this, pSpellDef, pSrc); + ushort uiManaUse = g_Cfg.Calc_SpellManaCost(this, pSpellDef, pSrc); + ushort uiTithingUse = g_Cfg.Calc_SpellTithingCost(this, pSpellDef, pSrc); - CScriptTriggerArgs Args( spellRef, iManaUse, pSrc ); + CScriptTriggerArgs Args( spellRef, uiManaUse, pSrc ); if ( fTest ) Args.m_iN3 |= 0x0001; if ( fFailMsg ) Args.m_iN3 |= 0x0002; - Args.m_VarsLocal.SetNum("TithingUse",iTithingUse); + Args.m_VarsLocal.SetNum("TithingUse",uiTithingUse); if ( IsTrigUsed(TRIGGER_SELECT) ) { @@ -2356,8 +2356,8 @@ bool CChar::Spell_CanCast( SPELL_TYPE &spellRef, bool fTest, CObjBase * pSrc, bo return false; spellRef = (SPELL_TYPE)(Args.m_iN1); } - iManaUse = (ushort)(Args.m_iN2); - iTithingUse = (ushort)(Args.m_VarsLocal.GetKeyNum("TithingUse")); + uiManaUse = (ushort)(Args.m_iN2); + uiTithingUse = (ushort)(Args.m_VarsLocal.GetKeyNum("TithingUse")); if ( !pSrc->IsChar() )// Looking for non-character sources { @@ -2365,12 +2365,14 @@ bool CChar::Spell_CanCast( SPELL_TYPE &spellRef, bool fTest, CObjBase * pSrc, bo CItem * pItem = dynamic_cast (pSrc); if ( !pItem ) return false; + if ( ! pItem->IsAttr( ATTR_MAGIC )) { if ( fFailMsg ) SysMessageDefault( DEFMSG_SPELL_ENCHANT_LACK ); return false; } + CObjBaseTemplate * pObjTop = pSrc->GetTopLevelObj(); if ( pObjTop != this ) // magic items must be on your person to use. { @@ -2430,6 +2432,7 @@ bool CChar::Spell_CanCast( SPELL_TYPE &spellRef, bool fTest, CObjBase * pSrc, bo SysMessageDefault( DEFMSG_SPELL_TRY_NOBOOK ); return false; } + if ( ! pBook->IsSpellInBook( spellRef )) { if ( fFailMsg ) @@ -2452,15 +2455,16 @@ bool CChar::Spell_CanCast( SPELL_TYPE &spellRef, bool fTest, CObjBase * pSrc, bo // Check for Tithing CVarDefContNum* pVarTithing = GetDefKeyNum("Tithing", false); int64 iValTithing = pVarTithing ? pVarTithing->GetValNum() : 0; - if (iValTithing < iTithingUse) + if (iValTithing < uiTithingUse) { if (fFailMsg) - SysMessagef(g_Cfg.GetDefaultMsg(DEFMSG_SPELL_TRY_NOTITHING), iTithingUse); + SysMessagef(g_Cfg.GetDefaultMsg(DEFMSG_SPELL_TRY_NOTITHING), uiTithingUse); return false; } + // Consume tithing points if casting is successfull. - if (!fTest && iTithingUse) - pVarTithing->SetValNum(iValTithing - iTithingUse); + if (!fTest && uiTithingUse) + pVarTithing->SetValNum(iValTithing - uiTithingUse); } } @@ -2470,25 +2474,26 @@ bool CChar::Spell_CanCast( SPELL_TYPE &spellRef, bool fTest, CObjBase * pSrc, bo { if ( fFailMsg ) SysMessageDefault( DEFMSG_MAGERY_6 ); // An anti-magic field disturbs the spells. + m_Act_Difficulty = -1; // Give very little credit for failure ! return false; } } // Check for mana - if (Stat_GetVal(STAT_INT) < iManaUse) + if (Stat_GetVal(STAT_INT) < uiManaUse) { if (fFailMsg) SysMessageDefault(DEFMSG_SPELL_TRY_NOMANA); return false; } // Consume mana if casting is successfull - if (!fTest && iManaUse) - UpdateStatVal(STAT_INT, -iManaUse); + if (!fTest && uiManaUse) + UpdateStatVal(STAT_INT, -uiManaUse); return true; } -CChar * CChar::Spell_Summon_Try(SPELL_TYPE spell, CPointMap ptTarg, CREID_TYPE iC1) +CChar * CChar::Spell_Summon_Try(SPELL_TYPE spell, CPointMap ptTarg, CREID_TYPE uiCreature) { ADDTOCALLSTACK("CChar::Spell_CanSummon"); //Create the NPC and check if we can actually place it in the world, but do not place it yet. @@ -2498,9 +2503,9 @@ CChar * CChar::Spell_Summon_Try(SPELL_TYPE spell, CPointMap ptTarg, CREID_TYPE i if (!pSpellDef || !pSpellDef->GetPrimarySkill(&iSkill, nullptr)) return nullptr; - if (iC1)//if iC1 is set that means we are overriding the default summoned creature. + if (uiCreature)//if iC1 is set that means we are overriding the default summoned creature. { - m_atMagery.m_iSummonID = iC1; + m_atMagery.m_iSummonID = uiCreature; } else { @@ -2626,6 +2631,7 @@ CChar * CChar::Spell_Summon_Try(SPELL_TYPE spell, CPointMap ptTarg, CREID_TYPE i } return pChar; } + bool CChar::Spell_TargCheck_Face() { ADDTOCALLSTACK("CChar::Spell_TargCheck_Face"); diff --git a/src/game/clients/CAccount.cpp b/src/game/clients/CAccount.cpp index 6c1b536a4..8e40a704d 100644 --- a/src/game/clients/CAccount.cpp +++ b/src/game/clients/CAccount.cpp @@ -219,7 +219,7 @@ bool CAccounts::Account_Delete( CAccount * pAccount ) { return false; } - + pAccount->DeleteChars(); m_Accounts.RemovePtr( pAccount ); return true; @@ -498,7 +498,7 @@ bool CAccounts::Account_OnCmd( tchar * pszArgs, CTextConsole * pSrc ) CClient *pClient = pAccount->FindClient(); char *z = Str_GetTemp(); - snprintf(z, Str_TempLength(), + snprintf(z, Str_TempLength(), "Account '%s': PLEVEL:%d, BLOCK:%d, IP:%s, CONNECTED:%s, ONLINE:%s\n", pAccount->GetName(), pAccount->GetPrivLevel(), pAccount->IsPriv(PRIV_BLOCKED), pAccount->m_Last_IP.GetAddrStr(), pAccount->_dateConnectedLast.Format(nullptr), @@ -637,11 +637,9 @@ CAccount::~CAccount() DeleteChars(); if (CClient * pClient = FindClient()) - { pClient->m_pAccount = nullptr; - } - ClearPasswordTries(true); + //ClearPasswordTries(true); // I'm destroying the account. Does it even matter? -> no. } lpctstr CAccount::GetDefStr( lpctstr ptcKey, bool fZero ) const diff --git a/src/game/clients/CAccount.h b/src/game/clients/CAccount.h index 270c20e95..0d2913bcb 100644 --- a/src/game/clients/CAccount.h +++ b/src/game/clients/CAccount.h @@ -106,7 +106,7 @@ class CAccount : public CScriptObj * We should go track down and delete all the chars and clients that use this account ! */ // virtual not required at the moment but might be if subclassed - virtual ~CAccount(); + virtual ~CAccount() override; /************************************************************************ * SCP related section. @@ -349,8 +349,9 @@ class CAccounts static lpctstr const sm_szVerbKeys[]; // ACCOUNT action list. CObjNameSortArray m_Accounts; // Sorted CAccount list. public: - CAccounts() : m_fLoading(false) { - + CAccounts() noexcept + : m_fLoading(false) + { } /** * CAccount needs CAccounts methods. diff --git a/src/game/clients/CClient.cpp b/src/game/clients/CClient.cpp index 26c9f3335..d19e1fade 100644 --- a/src/game/clients/CClient.cpp +++ b/src/game/clients/CClient.cpp @@ -123,7 +123,7 @@ CClient::~CClient() } if (m_net->isClosed() == false) - g_Log.EventError("Client being deleted without being safely removed from the network system\n"); + g_Log.EventError("Client being deleted without being safely removed from the network system.\n"); EXC_CATCH; } @@ -932,7 +932,7 @@ bool CClient::r_Verb( CScript & s, CTextConsole * pSrc ) // Execute command from } CResourceID rid = g_Cfg.ResourceGetID(RES_QTY, ppszArgs[0], 0, true); - /* + /* if (rid.IsEmpty()) { m_tmAdd.m_id = 0; diff --git a/src/game/clients/CClient.h b/src/game/clients/CClient.h index 4a1aae0dd..092ff56b7 100644 --- a/src/game/clients/CClient.h +++ b/src/game/clients/CClient.h @@ -536,7 +536,7 @@ class CClient : public CSObjListRec, public CScriptObj, public CChatChanMember, #define MAX_DIALOG_CONTROLTYPE_QTY 1000 void addGumpTextDisp( const CObjBase * pObj, GUMP_TYPE gump, lpctstr pszName, lpctstr pszText ); - void addGumpInpVal( bool fcancel, INPVAL_STYLE style, dword dwmask, lpctstr ptext1, lpctstr ptext2, CObjBase * pObj ); + void addGumpInputVal( bool fcancel, INPVAL_STYLE style, dword dwmask, lpctstr ptext1, lpctstr ptext2, CObjBase * pObj ); void addItemMenu( CLIMODE_TYPE mode, const CMenuItem * item, uint count, CObjBase * pObj = nullptr ); void addGumpDialog( CLIMODE_TYPE mode, std::vector const* vsControls, std::vector const* vsText, int x, int y, CObjBase * pObj = nullptr, dword dwRid = 0 ); diff --git a/src/game/clients/CClientDialog.cpp b/src/game/clients/CClientDialog.cpp index a88019a7b..981536aa3 100644 --- a/src/game/clients/CClientDialog.cpp +++ b/src/game/clients/CClientDialog.cpp @@ -16,8 +16,8 @@ bool CClient::Dialog_Setup( CLIMODE_TYPE mode, const CResourceID& rid, int iPage if ( pObj == nullptr ) return false; - CResourceDef * pRes = g_Cfg.RegisteredResourceGetDef( rid ); - CDialogDef * pDlg = dynamic_cast (pRes); + CResourceDef * pRes = g_Cfg.RegisteredResourceGetDef( rid ); + CDialogDef * pDlg = dynamic_cast (pRes); if ( !pRes || !pDlg ) { DEBUG_ERR(("Invalid RES_DIALOG.\n")); @@ -48,13 +48,13 @@ bool CClient::Dialog_Setup( CLIMODE_TYPE mode, const CResourceID& rid, int iPage } -void CClient::addGumpInpVal( bool fCancel, INPVAL_STYLE style, +void CClient::addGumpInputVal( bool fCancel, INPVAL_STYLE style, dword iMaxLength, lpctstr pszText1, lpctstr pszText2, CObjBase * pObj ) { - ADDTOCALLSTACK("CClient::addGumpInpVal"); + ADDTOCALLSTACK("CClient::addGumpInputVal"); // CLIMODE_INPVAL // Should result in PacketGumpValueInputResponse::onReceive // just input an objects attribute. diff --git a/src/game/clients/CClientLog.cpp b/src/game/clients/CClientLog.cpp index 29707aa9e..e4e18bc12 100644 --- a/src/game/clients/CClientLog.cpp +++ b/src/game/clients/CClientLog.cpp @@ -136,7 +136,7 @@ bool CClient::addLoginErr(byte code) if (code >= ARRAY_COUNT(sm_Login_ErrMsg)) code = PacketLoginError::Other; - + g_Log.EventWarn( "%x:Bad Login %d. %s.\n", GetSocketID(), code, sm_Login_ErrMsg[(size_t)code] ); // translate the code into a code the client will understand @@ -254,7 +254,7 @@ bool CClient::addRelay( const CServerDef * pServ ) EXC_SET_BLOCK("server relay packet"); new PacketServerRelay(this, dwAddr, pServ->m_ip.GetPort(), dwCustomerId); - + m_Targ_Mode = CLIMODE_SETUP_RELAY; return true; EXC_CATCH; @@ -680,7 +680,7 @@ bool CClient::OnRxPing( const byte * pData, uint iLen ) bool CClient::OnRxWebPageRequest( byte * pRequest, size_t uiLen ) { ADDTOCALLSTACK("CClient::OnRxWebPageRequest"); - + // Seems to be a web browser pointing at us ? typical stuff : if ( GetConnectType() != CONNECT_HTTP ) return false; @@ -730,7 +730,11 @@ bool CClient::OnRxWebPageRequest( byte * pRequest, size_t uiLen ) { pszArgs += 15; GETNONWHITESPACE(pszArgs); - uiContentLength = Str_ToUI(pszArgs, 10); + std::optional iconv = Str_ToU(pszArgs, 10); + if (!iconv.has_value()) + continue; + + uiContentLength = *iconv; } else if ( ! strnicmp( pszArgs, "If-Modified-Since:", 18 )) { @@ -787,7 +791,7 @@ bool CClient::OnRxWebPageRequest( byte * pRequest, size_t uiLen ) CheckReportNetAPIErr(iSocketRet, "CClient::Webpage.TCP_NODELAY"); if (iSocketRet) return false; - + if ( memcmp(ppLines[0], "POST", 4) == 0 ) { if (uiContentLength > strlen(ppLines[iQtyLines-1]) ) @@ -863,7 +867,7 @@ bool CClient::xProcessClientSetup( CEvent * pEvent, uint uiLen ) addLoginErr( PacketLoginError::BadEncLength ); return false; } - + GetNetState()->detectAsyncMode(); SetConnectType( m_Crypt.GetConnectType() ); @@ -877,7 +881,7 @@ bool CClient::xProcessClientSetup( CEvent * pEvent, uint uiLen ) addLoginErr( PacketLoginError::BadVersion ); return false; } - + ASSERT(uiLen <= sizeof(CEvent)); std::unique_ptr bincopy = std::make_unique(); // in buffer. (from client) memcpy(bincopy->m_Raw, pEvent->m_Raw, uiLen); @@ -886,7 +890,7 @@ bool CClient::xProcessClientSetup( CEvent * pEvent, uint uiLen ) g_Log.EventError("NET-IN: xProcessClientSetup failed (Decrypt).\n"); return false; } - + byte lErr = PacketLoginError::EncUnknown; tchar szAccount[MAX_ACCOUNT_NAME_SIZE+3]; @@ -993,7 +997,7 @@ bool CClient::xProcessClientSetup( CEvent * pEvent, uint uiLen ) } #endif } - + xRecordPacketData(this, pEvent->m_Raw, uiLen, "client->server"); if ( lErr != PacketLoginError::Success ) // it never matched any crypt format. @@ -1010,15 +1014,15 @@ bool CClient::xCanEncLogin(bool bCheckCliver) if ( !bCheckCliver ) { if ( m_Crypt.GetEncryptionType() == ENC_NONE ) - return ( g_Cfg.m_fUsenocrypt ); // Server don't want no-crypt clients - + return ( g_Cfg.m_fUsenocrypt ); // Server don't want no-crypt clients + return ( g_Cfg.m_fUsecrypt ); // Server don't want crypt clients } else { if ( !g_Serv.m_ClientVersion.GetClientVerNumber() ) // Any Client allowed return true; - + if ( m_Crypt.GetEncryptionType() != ENC_NONE ) return ( m_Crypt.GetClientVerNumber() == g_Serv.m_ClientVersion.GetClientVerNumber() ); else diff --git a/src/game/items/CItemMap.cpp b/src/game/items/CItemMap.cpp index bffacdd28..847d5e502 100644 --- a/src/game/items/CItemMap.cpp +++ b/src/game/items/CItemMap.cpp @@ -48,7 +48,7 @@ bool CItemMap::r_LoadVal(CScript & s) // load an item script CPointMap pntTemp; pntTemp.Read(s.GetArgStr()); CMapPinRec pin(pntTemp.m_x, pntTemp.m_y); - m_Pins.emplace_back(pin); + m_Pins.emplace_back(std::move(pin)); return true; } return CItem::r_LoadVal(s); @@ -73,7 +73,11 @@ bool CItemMap::r_WriteVal(lpctstr ptcKey, CSString &sVal, CTextConsole *pSrc, bo if ( !strnicmp(ptcKey, "PIN.", 4) ) { ptcKey += 4; - uint i = Exp_GetUVal(ptcKey) - 1; + uint i = Exp_GetUVal(ptcKey); + if (i == 0) + return false; + + i -= 1; if ( m_Pins.IsValidIndex(i) ) { sVal.Format("%i,%i", m_Pins[i].m_x, m_Pins[i].m_y); diff --git a/src/game/spheresvr.cpp b/src/game/spheresvr.cpp index 0a3361304..b407cc5f4 100644 --- a/src/game/spheresvr.cpp +++ b/src/game/spheresvr.cpp @@ -121,6 +121,9 @@ void GlobalInitializer::PeriodicSyncTimeConstants() // static #endif // _WIN32 } + +/* Start global declarations */ + static GlobalInitializer g_GlobalInitializer; #ifdef _WIN32 @@ -135,8 +138,12 @@ UnixTerminal g_UnixTerminal; LinuxEv g_NetworkEvent; #endif +CServer g_Serv; // current state, stuff not saved. +CLog g_Log; + // Config data from sphere.ini is needed from the beginning. CServerConfig g_Cfg; +CAccounts g_Accounts; // All the player accounts. name sorted CAccount // Game servers stuff. CWorld g_World; // the world. (we save this stuff) @@ -150,15 +157,10 @@ CWorld g_World; // the world. (we save this stuff) // Again, game servers stuff. -CServer g_Serv; // current state, stuff not saved. - - CUOInstall g_Install; CVerDataMul g_VerData; CSRand g_Rand; CExpression g_Exp; // Global script variables. -CLog g_Log; -CAccounts g_Accounts; // All the player accounts. name sorted CAccount CSStringList g_AutoComplete; // auto-complete list CScriptProfiler g_profiler; // script profiler CUOMapList g_MapList; // global maps information @@ -509,23 +511,24 @@ void defragSphere(char *path) CSFileText inf; CSFile ouf; char z[_MAX_PATH], z1[_MAX_PATH], buf[1024]; - size_t i; char *p = nullptr, *p1 = nullptr; - size_t dBytesRead; + size_t uiBytesRead; size_t dTotalMb; const size_t mb10 = 10*1024*1024; const size_t mb5 = 5*1024*1024; - bool bSpecial; + bool fSpecial; g_Log.Event(LOGM_INIT, "Defragmentation (UID alteration) of " SPHERE_TITLE " saves.\n" "Use it on your risk and if you know what you are doing since it can possibly harm your server.\n" "The process can take up to several hours depending on the CPU you have.\n" "After finished, you will have your '" SPHERE_FILE "*.scp' files converted and saved as '" SPHERE_FILE "*.scp.new'.\n"); - constexpr dword MAX_UID = 40'000'000U; // limit to 100mln of objects, takes 100mln*4 ~= 400mb + // UID_O_INDEX_MASK ? + constexpr dword MAX_UID = 40'000'000U; // limit to 40mln of objects, takes 40mln*4bytes ~= 160mb + dword dwIdxUID = 0; dword* puids = (dword*)calloc(MAX_UID, sizeof(dword)); - for ( i = 0; i < 3; ++i ) + for ( uint i = 0; i < 3; ++i ) { Str_CopyLimitNull(z, path, sizeof(z)); if ( i == 0 ) strcat(z, SPHERE_FILE "statics" SPHERE_SCRIPT); @@ -538,14 +541,14 @@ void defragSphere(char *path) g_Log.Event(LOGM_INIT, "Cannot open file for reading. Skipped!\n"); continue; } - dBytesRead = dTotalMb = 0; + uiBytesRead = dTotalMb = 0; while ((dwIdxUID < MAX_UID) && !feof(inf._pStream)) { fgets(buf, sizeof(buf), inf._pStream); - dBytesRead += strlen(buf); - if ( dBytesRead > mb10 ) + uiBytesRead += strlen(buf); + if ( uiBytesRead > mb10 ) { - dBytesRead -= mb10; + uiBytesRead -= mb10; dTotalMb += 10; g_Log.Event(LOGM_INIT, "Total read %" PRIuSIZE_T " Mb\n", dTotalMb); } @@ -574,7 +577,7 @@ void defragSphere(char *path) g_Log.Event(LOGM_INIT, "Quick-Sorting the UIDs array...\n"); dword_q_sort(puids, 0, dwTotalUIDs -1); - for ( i = 0; i < 5; ++i ) + for ( uint i = 0; i < 5; ++i ) { Str_CopyLimitNull(z, path, sizeof(z)); if ( !i ) strcat(z, SPHERE_FILE "accu.scp"); @@ -595,7 +598,7 @@ void defragSphere(char *path) continue; } - dBytesRead = dTotalMb = 0; + uiBytesRead = dTotalMb = 0; while ( inf.ReadString(buf, sizeof(buf)) ) { dwIdxUID = (dword)strlen(buf); @@ -604,11 +607,11 @@ void defragSphere(char *path) buf[dwIdxUID] = buf[dwIdxUID +1] = buf[dwIdxUID +2] = 0; // just to be sure to be in line always // NOTE: it is much faster than to use memcpy to clear before reading - bSpecial = false; - dBytesRead += dwIdxUID; - if ( dBytesRead > mb5 ) + fSpecial = false; + uiBytesRead += dwIdxUID; + if ( uiBytesRead > mb5 ) { - dBytesRead -= mb5; + uiBytesRead -= mb5; dTotalMb += 5; g_Log.Event(LOGM_INIT, "Total processed %" PRIuSIZE_T " Mb\n", dTotalMb); } @@ -631,7 +634,7 @@ void defragSphere(char *path) else if (( buf[0] == 'M' ) && ( strstr(buf, "MEMBER=0") == buf )) // MEMBER= { p += 7; - bSpecial = true; + fSpecial = true; } else if (( buf[0] == 'M' ) && ( strstr(buf, "MORE1=0") == buf )) // MORE1= p += 6; @@ -668,7 +671,7 @@ void defragSphere(char *path) ((( *p1 >= '0' ) && ( *p1 <= '9' )) || (( *p1 >= 'a' ) && ( *p1 <= 'f' ))) ) ++p1; - if ( !bSpecial ) + if ( !fSpecial ) { if ( *p1 && ( *p1 != '\r' ) && ( *p1 != '\n' )) // some more text in line p = nullptr; @@ -759,6 +762,7 @@ void defragSphere(char *path) inf.Close(); ouf.Close(); } + free(puids); g_Log.Event(LOGM_INIT, "Defragmentation complete.\n"); } @@ -788,9 +792,10 @@ int _cdecl main( int argc, char * argv[] ) { // Ensure i have this to have context for ADDTOCALLSTACK and other operations. - const IThread* curthread = ThreadHolder::get().current(); + const IThread* curthread = ThreadHolder::get().current(); ASSERT(curthread != nullptr); ASSERT(dynamic_cast(curthread)); + (void)curthread; } #ifndef _WIN32 diff --git a/src/game/triggers.cpp b/src/game/triggers.cpp index 8958d1114..760b686c5 100644 --- a/src/game/triggers.cpp +++ b/src/game/triggers.cpp @@ -38,10 +38,11 @@ bool IsTrigUsed(const char *name) if ( g_Serv.IsLoading() == true) return false; - int index = FindTableSorted(name, kOrderedTrigsNames, ARRAY_COUNT(kOrderedTrigsNames)); + const int index = FindTableSorted(name, kOrderedTrigsNames, ARRAY_COUNT(kOrderedTrigsNames)); if (index >= 0) return IsTrigUsed((E_TRIGGERS)index); - return false; + + return true; //Must return true for custom triggers } void TriglistInit() diff --git a/src/game/uo_files/CUOMobtypes.cpp b/src/game/uo_files/CUOMobtypes.cpp index 2cf64a7ee..0d289b957 100644 --- a/src/game/uo_files/CUOMobtypes.cpp +++ b/src/game/uo_files/CUOMobtypes.cpp @@ -10,89 +10,112 @@ #include "../../common/CUOInstall.h" #include "../../game/uo_files/uofiles_enums_creid.h" #include "CUOMobtypes.h" +#include void CUOMobTypes::Load() { ADDTOCALLSTACK("CUOMobTypes::Load"); g_Log.Event(LOGM_INIT, "Caching mobtypes.txt...\n"); - CUOMobTypesType mobTypesRow = {0,0}; - - _mobTypesEntries.clear(); - + _vMobTypesEntries.clear(); CSFileText csvMobTypes; if (g_Install.OpenFile(csvMobTypes, "mobtypes.txt", (word)(OF_READ | OF_TEXT | OF_DEFAULTMODE))) { - _mobTypesEntries.resize(CREID_QTY); - for (int i = 0; i < _mobTypesEntries.size(); i++) + _vMobTypesEntries.resize(CREID_QTY); + for (size_t i = 0; i < _vMobTypesEntries.size(); ++i) { - mobTypesRow.m_type = 4; - mobTypesRow.m_flags = 0; - _mobTypesEntries[i] = mobTypesRow; + _vMobTypesEntries[i] = CUOMobTypesEntry{MOBTE_QTY, 0}; } - tchar* pszTemp = Str_GetTemp(); - size_t count = 0; + tchar* ptcTemp = Str_GetTemp(); + size_t uiLineCount = 0; + CUOMobTypesEntry mobTypesRow {}; while (!csvMobTypes.IsEOF()) { - csvMobTypes.ReadString(pszTemp, 200); - if (*pszTemp) + csvMobTypes.ReadString(ptcTemp, 200); + if (*ptcTemp) { - count++; + ++ uiLineCount; - std::string tmpString = pszTemp; + int iLineLength = (int)strnlen(ptcTemp, Str_TempLength()); + iLineLength = Str_TrimEndWhitespace(ptcTemp, iLineLength); - int len = (int)tmpString.length(); - len = Str_TrimEndWhitespace(tmpString.data(), len); - - if (len == 0 || tmpString[0] == '#') //Empty line or commented + if (iLineLength == 0 || ptcTemp[0] == '#') //Empty line or commented continue; //Split the string - std::vector splitArray; - splitArray.resize(3); - size_t iQty = Str_ParseCmds(tmpString.data(), splitArray.data(), 3, " \t#"); - - if (splitArray.size() < 3) + tchar* pptcSplitArray[3]; + const int iQty = Str_ParseCmds(ptcTemp, pptcSplitArray, ARRAY_COUNT(pptcSplitArray), " \t#"); + if (iQty < 3) { - g_Log.EventError("Mobtypes.txt: not enough parameters on line %" PRIuSIZE_T " \n", count); + g_Log.EventError("Mobtypes.txt: not enough parameters on line %" PRIuSIZE_T " \n", uiLineCount); continue; } - if (!IsStrNumeric(splitArray[0])) + //if (!IsStrNumeric(pptcSplitArray[0])) + //{ + // g_Log.EventError("Mobtypes.txt: non numeric ID on line %" PRIuSIZE_T " \n", uiLineCount); + // continue; + //} + // const uint uiAnimIndex = (uint)std::stoul(pptcSplitArray[0]); + + std::optional iconv = Str_ToU(pptcSplitArray[0], 10); + if (!iconv.has_value()) { - g_Log.EventError("Mobtypes.txt: non numeric ID on line %" PRIuSIZE_T " \n", count); + g_Log.EventError( + "Mobtypes.txt: Invalid char ID on line %" PRIuSIZE_T ".\n", uiLineCount); continue; } + const uint uiAnimIndex = *iconv; - int animIndex = std::stoi(splitArray[0]); - std::string sType = splitArray[1]; + const std::string_view sType(pptcSplitArray[1]); if (sType == "MONSTER") - mobTypesRow.m_type = 0; + mobTypesRow.m_uiType = MOBTE_MONSTER; else if (sType == "SEA_MONSTER") - mobTypesRow.m_type = 1; + mobTypesRow.m_uiType = MOBTE_SEA_MONSTER; else if (sType == "ANIMAL") - mobTypesRow.m_type = 2; + mobTypesRow.m_uiType = MOBTE_ANIMAL; else if (sType == "HUMAN") - mobTypesRow.m_type = 3; + mobTypesRow.m_uiType = MOBTE_HUMAN; else if (sType == "EQUIPMENT") - mobTypesRow.m_type = 4; + mobTypesRow.m_uiType = MOBTE_EQUIPMENT; else { - mobTypesRow.m_type = 0; - g_Log.EventError("Mobtypes.txt: wrong type found on line %" PRIuSIZE_T " \n", count); + mobTypesRow.m_uiType = MOBTE_QTY; + g_Log.EventError("Mobtypes.txt: wrong type found on line %" PRIuSIZE_T " \n", uiLineCount); } - mobTypesRow.m_flags = std::strtol(splitArray[2], NULL, 16); + //mobTypesRow.m_flags = (dword)std::strtoul(pptcSplitArray[2], nullptr, 16); + iconv = Str_ToU(pptcSplitArray[2], 16); + if (!iconv.has_value()) + { + g_Log.EventError( + "Mobtypes.txt: Invalid flags for char ID %" PRIu32 " on line %" PRIuSIZE_T ".\n", + uiAnimIndex, uiLineCount); + continue; + } + mobTypesRow.m_uiFlags = *iconv; - if (animIndex <= _mobTypesEntries.size()) //Safety check + if (uiAnimIndex <= _vMobTypesEntries.size()) //Safety check + { + _vMobTypesEntries[uiAnimIndex] = mobTypesRow; + } + else { - _mobTypesEntries[animIndex] = mobTypesRow; + g_Log.EventError( + "Mobtypes.txt: trying to load data for an invalid char ID %" PRIu32 " on line %" PRIuSIZE_T ".\n", + uiAnimIndex, uiLineCount); } } } + csvMobTypes.Close(); } } +const CUOMobTypesEntry* CUOMobTypes::GetEntry(uint id) const +{ + ASSERT(id < _vMobTypesEntries.size()); + return &(_vMobTypesEntries[id]); +} diff --git a/src/game/uo_files/CUOMobtypes.h b/src/game/uo_files/CUOMobtypes.h index 7b7c2bbb7..d4514bddf 100644 --- a/src/game/uo_files/CUOMobtypes.h +++ b/src/game/uo_files/CUOMobtypes.h @@ -9,33 +9,40 @@ #include #include "../../common/common.h" + /** * mobtypes.txt */ -struct CUOMobTypesType + +enum MOBTYPES_ENTITY_TYPE : ushort { - ushort m_type; // 0 = MONSTER, 1 = SEA_MONSTER, 2 = ANIMAL, 3 = HUMAN, 4 = EQUIPMENT - dword m_flags; + MOBTE_MONSTER, + MOBTE_SEA_MONSTER, + MOBTE_ANIMAL, + MOBTE_HUMAN, + MOBTE_EQUIPMENT, + MOBTE_QTY +}; +struct CUOMobTypesEntry +{ + MOBTYPES_ENTITY_TYPE m_uiType; + uint m_uiFlags; }; + class CUOMobTypes { - std::vector _mobTypesEntries; + std::vector _vMobTypesEntries; public: void Load(); - inline const bool IsLoaded() { - if (_mobTypesEntries.size() > 0) - return true; - else - return false; + bool IsLoaded() const noexcept { + return !_vMobTypesEntries.empty(); } - inline const CUOMobTypesType* GetEntry(ushort id) { - return &(_mobTypesEntries[id]); - } + const CUOMobTypesEntry* GetEntry(uint id) const; }; diff --git a/src/network/CIPHistoryManager.h b/src/network/CIPHistoryManager.h index 03ec8c749..6fe6adb95 100644 --- a/src/network/CIPHistoryManager.h +++ b/src/network/CIPHistoryManager.h @@ -25,7 +25,7 @@ struct HistoryIP int m_connected; bool m_blocked; int m_ttl; - size_t m_connectionAttempts; // since i remember of this IP + int64 m_connectionAttempts; // since i remember of this IP int64 m_timeLastConnectedMs; int64 m_blockExpire; int m_pingDecay; diff --git a/src/network/CNetworkManager.cpp b/src/network/CNetworkManager.cpp index 8bb74068a..51231dc37 100644 --- a/src/network/CNetworkManager.cpp +++ b/src/network/CNetworkManager.cpp @@ -178,7 +178,7 @@ void CNetworkManager::acceptNewConnection(void) return; } - if ((g_Cfg._iMaxConnectRequestsPerIP > 0) && (ip.m_connectionAttempts >= (size_t)g_Cfg._iMaxConnectRequestsPerIP)) + if ((g_Cfg._iMaxConnectRequestsPerIP > 0) && (ip.m_connectionAttempts >= (int64)g_Cfg._iMaxConnectRequestsPerIP)) { // Call this special scripted function. CScriptTriggerArgs fargs_ex(client_addr.GetAddrStr()); @@ -192,7 +192,7 @@ void CNetworkManager::acceptNewConnection(void) { // reject CLOSESOCKET(h); - + _printIPBlocked(); g_Log.Event(LOGM_CLIENTS_LOG | LOGL_ERROR, "Reject reason: requested kick via script 'f_onserver_connectreq_ex'.\n"); } @@ -206,7 +206,7 @@ void CNetworkManager::acceptNewConnection(void) g_Log.Event(LOGM_CLIENTS_LOG | LOGL_ERROR, "Reject reason: requested kick + IP block via script 'f_onserver_connectreq_ex'.\n"); } } - + /* // Check if there's already more data waiting to be read (suspicious?). // Classic client (but not some 3rd party clients) have pending data after the second connection request @@ -272,8 +272,8 @@ void CNetworkManager::acceptNewConnection(void) { // not enough empty slots EXC_SET_BLOCK("no slot available"); - _printIPBlocked(); - + _printIPBlocked(); + g_Log.Event(LOGM_CLIENTS_LOG | LOGL_ERROR, "Reject reason: CLIENTMAX reached.\n"); CLOSESOCKET(h); return; diff --git a/src/network/CNetworkManager.h b/src/network/CNetworkManager.h index 2ebb8941b..18e95f1c9 100644 --- a/src/network/CNetworkManager.h +++ b/src/network/CNetworkManager.h @@ -51,15 +51,15 @@ class CNetworkManager void flushAllClients(void); // force each thread to flush output public: - inline const PacketManager& getPacketManager(void) const { return m_packets; } // get packet manager - inline IPHistoryManager& getIPHistoryManager(void) { return m_ips; } // get ip history manager - inline bool isThreaded(void) const { return m_isThreaded; } // are threads active - inline bool isInputThreaded(void) const // is network input handled by thread + inline const PacketManager& getPacketManager(void) const noexcept { return m_packets; } // get packet manager + inline IPHistoryManager& getIPHistoryManager(void) noexcept { return m_ips; } // get ip history manager + inline bool isThreaded(void) const noexcept { return m_isThreaded; } // are threads active + inline bool isInputThreaded(void) const noexcept // is network input handled by thread { return m_isThreaded; } - inline bool isOutputThreaded(void) const // is network output handled by thread + inline bool isOutputThreaded(void) const noexcept // is network output handled by thread { return m_isThreaded; } @@ -79,4 +79,4 @@ class CNetworkManager extern CNetworkManager g_NetworkManager; -#endif // _INC_CNETWORKMANAGER_H \ No newline at end of file +#endif // _INC_CNETWORKMANAGER_H diff --git a/src/network/send.cpp b/src/network/send.cpp index a4813b3f7..99c9e76c4 100644 --- a/src/network/send.cpp +++ b/src/network/send.cpp @@ -2,6 +2,7 @@ #ifndef _WIN32 #include #endif +#include #include "../common/resource/CResourceLock.h" #include "../common/CLog.h" @@ -3387,11 +3388,11 @@ PacketCharacterList::PacketCharacterList(CClient* target) : PacketSend(XCMD_Char } } - if (tmVerReported > 1260000) + if (tmVerReported > 1'26'00'00) { const CNetState* ns = target->GetNetState(); dword flags = g_Cfg.GetPacketFlag(true, (RESDISPLAY_VERSION)(account->GetResDisp()), - maximum(account->GetMaxChars(), (byte)(account->m_Chars.GetCharCount()))); + std::max(account->GetMaxChars(), (byte)(account->m_Chars.GetCharCount()))); if (ns->getClientType() == CLIENTTYPE_2D) flags |= 0x400; writeInt32(flags); @@ -3597,16 +3598,17 @@ void PacketGumpDialog::writeCompressedControls(std::vector const* cont // compress and write controls uint controlLength = 1; for (CSString const& ctrl : *controls) - controlLength += (uint)ctrl.GetLength() + 2; // String terminator not needed. + { + controlLength += (uint)ctrl.GetLength() + 2; // String terminator not needed. + } char* toCompress = new char[controlLength]; - uint controlLengthCurrent = 0; for (CSString const& ctrl : *controls) { const uint uiAvailableLength = std::max(0u, controlLength - controlLengthCurrent); const int iJustWrittenLength = snprintf(&toCompress[controlLengthCurrent], uiAvailableLength, "{%s}", ctrl.GetBuffer()); - controlLengthCurrent += iJustWrittenLength; + controlLengthCurrent += iJustWrittenLength; } ++ controlLengthCurrent; diff --git a/src/sphere/threads.cpp b/src/sphere/threads.cpp index bd69b5e74..3f93148c4 100644 --- a/src/sphere/threads.cpp +++ b/src/sphere/threads.cpp @@ -142,6 +142,12 @@ IThread* ThreadHolder::current() if (m_spherethreadpairs_systemid_ptr.empty()) { auto thread = static_cast(DummySphereThread::getInstance()); + if (!thread) { + // Should never happen. + EXC_NOTIFY_DEBUGGER; + std::abort(); + } + thread->m_threadSystemId = tid; lock.unlock(); push(thread); From dc59957c466d5712f10ea4f7b3890e6ef41f5b0a Mon Sep 17 00:00:00 2001 From: cbnolok Date: Mon, 26 Aug 2024 15:14:37 +0200 Subject: [PATCH 04/86] Added more functions to typecast.h --- src/common/sphere_library/stypecast.h | 206 +++++++++++++++++--------- src/game/CSectorEnviron.cpp | 6 +- src/game/CSectorEnviron.h | 8 +- src/game/clients/CChatChanMember.cpp | 8 +- src/game/clients/CClientTarg.cpp | 18 +-- src/game/components/CCSpawn.cpp | 4 +- src/game/items/CItem.cpp | 4 +- src/network/CNetworkOutput.cpp | 2 +- src/network/send.cpp | 9 +- 9 files changed, 168 insertions(+), 97 deletions(-) diff --git a/src/common/sphere_library/stypecast.h b/src/common/sphere_library/stypecast.h index 3b02f5423..3ace00813 100644 --- a/src/common/sphere_library/stypecast.h +++ b/src/common/sphere_library/stypecast.h @@ -1,15 +1,22 @@ #ifndef _INC_STYPECAST_H #define _INC_STYPECAST_H -#include +//#include +#include #include -//-- Explicitly promote to a larger type or narrow to a smaller type, instead of inattentive casts. + +// Explicitly promote to a larger type or narrow to a smaller type, instead of inattentive raw casts. +// Function prefixes: +// - n: works regardless of the sign, it deduces and uses the right types automatically. +// - i: expects a signed number as input +// - u: expects an unsigned number as input + // Promote to the corresponding 32 bits numeric type a smaller numeric variable. template [[nodiscard]] -constexpr auto i_promote32(const T a) noexcept +constexpr auto n_promote32(const T a) noexcept { static_assert(std::is_arithmetic_v, "Input variable is not an arithmetic type."); static_assert(std::is_integral_v || (std::is_floating_point_v && std::is_signed_v), "Unsigned floating point numbers are unsupported by the language standard"); @@ -27,7 +34,7 @@ constexpr auto i_promote32(const T a) noexcept // Promote to the corresponding 64 bits numeric type a smaller numeric variable. template [[nodiscard]] -constexpr auto i_promote64(const T a) noexcept +constexpr auto n_promote64(const T a) noexcept { static_assert(std::is_arithmetic_v, "Input variable is not an arithmetic type."); static_assert(std::is_integral_v || (std::is_floating_point_v && std::is_signed_v), "Unsigned floating point numbers are unsupported by the language standard"); @@ -42,76 +49,77 @@ constexpr auto i_promote64(const T a) noexcept return static_cast(a); } +// Narrow a 64 bits number to a 32 bits number, discarding any upper exceeding bytes. template [[nodiscard]] -constexpr auto i_narrow32(const T a) noexcept +constexpr auto n64_narrow32(const T a) noexcept { static_assert(std::is_arithmetic_v, "Input variable is not an arithmetic type."); static_assert(std::is_integral_v || (std::is_floating_point_v && std::is_signed_v), "Unsigned floating point numbers are unsupported by the language standard"); - static_assert(sizeof(T) >= 4, "Input variable is smaller than a 32 bit number."); + static_assert(sizeof(T) == 8, "Input variable is not a 64 bit number."); // Since the narrowing can be implementation specific, here we decide that we take only the lower 32 bytes and discard the upper ones. constexpr uint64 umask = 0x0000'0000'FFFF'FFFF; if constexpr (std::is_signed_v) { if constexpr (std::is_floating_point_v) - return static_cast(static_cast(a) & umask); - return static_cast(static_cast(a) & umask); + return static_cast(a & umask); + return static_cast(a & umask); } else - return static_cast(static_cast(a) & umask); + return static_cast(a & umask); } +// Narrow a 64 bits number to a 32 bits number and ASSERT (because you're reasonably sure but not absolutely certain) that it won't overflow. template -[[nodiscard]] -constexpr auto i_narrow16(const T a) noexcept +[[nodiscard]] inline +auto n64_narrow32_checked(const T a) { - static_assert(std::is_arithmetic_v, "Input variable is not an arithmetic type."); - static_assert(std::is_integral_v || (std::is_floating_point_v && std::is_signed_v), "Unsigned floating point numbers are unsupported by the language standard"); - static_assert(sizeof(T) >= 2, "Input variable is smaller than a 16 bit number."); - - // Since the narrowing can be implementation specific, here we decide that we take only the lower 32 bytes and discard the upper ones. - constexpr uint64 umask = 0x0000'0000'FFFF'FFFF; - if constexpr (std::is_signed_v) - { - if constexpr (std::is_floating_point_v) - return static_cast(static_cast(a) & umask); - return static_cast(static_cast(a) & umask); - } - else - return static_cast(static_cast(a) & umask); + ASSERT(a < std::numeric_limits::max()); + return n64_narrow32(a); } +// Narrow a 64 bits number to a 16 bits number, discarding any upper exceeding bytes. template [[nodiscard]] -constexpr auto i64_narrow32(const T a) noexcept +constexpr auto n64_narrow16(const T a) noexcept { static_assert(std::is_arithmetic_v, "Input variable is not an arithmetic type."); static_assert(std::is_integral_v || (std::is_floating_point_v && std::is_signed_v), "Unsigned floating point numbers are unsupported by the language standard"); static_assert(sizeof(T) == 8, "Input variable is not a 64 bit number."); // Since the narrowing can be implementation specific, here we decide that we take only the lower 32 bytes and discard the upper ones. - constexpr uint64 umask = 0x0000'0000'FFFF'FFFF; + constexpr uint64 umask = 0x0000'0000'0000'FFFF; if constexpr (std::is_signed_v) { if constexpr (std::is_floating_point_v) - return static_cast(a & umask); - return static_cast(a & umask); + return static_cast(a & umask); + return static_cast(a & umask); } else - return static_cast(a & umask); + return static_cast(a & umask); } +// Narrow a 64 bits number to a 16 bits number and ASSERT (because you're reasonably sure but not absolutely certain) that it won't overflow. +template +[[nodiscard]] inline +auto n64_narrow16_checked(const T a) +{ + ASSERT(a < std::numeric_limits::max()); + return n64_narrow16(a); +} + +// Narrow a 32 bits number to a 16 bits number, discarding any upper exceeding bytes. template [[nodiscard]] -constexpr auto i64_narrow16(const T a) noexcept +constexpr auto n32_narrow16(const T a) noexcept { static_assert(std::is_arithmetic_v, "Input variable is not an arithmetic type."); static_assert(std::is_integral_v || (std::is_floating_point_v && std::is_signed_v), "Unsigned floating point numbers are unsupported by the language standard"); - static_assert(sizeof(T) == 8, "Input variable is not a 64 bit number."); + static_assert(sizeof(T) == 4, "Input variable is not a 32 bit number."); - // Since the narrowing can be implementation specific, here we decide that we take only the lower 32 bytes and discard the upper ones. - constexpr uint64 umask = 0x0000'0000'0000'FFFF; + // Since the narrowing can be implementation specific, here we decide that we take only the lower 16 bytes and discard the upper ones. + constexpr uint32 umask = 0x0000'FFFF; if constexpr (std::is_signed_v) { if constexpr (std::is_floating_point_v) @@ -122,29 +130,44 @@ constexpr auto i64_narrow16(const T a) noexcept return static_cast(a & umask); } +// Narrow a 32 bits number to a 16 bits number and ASSERT (because you're reasonably sure but not absolutely certain) that it won't overflow. +template +[[nodiscard]] inline +auto n32_narrow16_checked(const T a) +{ + ASSERT(a < std::numeric_limits::max()); + return n32_narrow16(a); +} + +// Narrow a 32 bits number to a 8 bits number, discarding any upper exceeding bytes. template [[nodiscard]] -constexpr auto i32_narrow16(const T a) noexcept +constexpr auto n32_narrow8(const T a) noexcept { static_assert(std::is_arithmetic_v, "Input variable is not an arithmetic type."); - static_assert(std::is_integral_v || (std::is_floating_point_v && std::is_signed_v), "Unsigned floating point numbers are unsupported by the language standard"); static_assert(sizeof(T) == 4, "Input variable is not a 32 bit number."); // Since the narrowing can be implementation specific, here we decide that we take only the lower 16 bytes and discard the upper ones. - constexpr uint32 umask = 0x0000'FFFF; + constexpr uint32 umask = 0x0000'00FF; if constexpr (std::is_signed_v) - { - if constexpr (std::is_floating_point_v) - return static_cast(a & umask); - return static_cast(a & umask); - } + return static_cast (a & umask); else - return static_cast(a & umask); + return static_cast(a & umask); +} + +// Narrow a 32 bits number to an 8 bits number and ASSERT (because you're reasonably sure but not absolutely certain) that it won't overflow. +template +[[nodiscard]] inline +auto n32_narrow8_checked(const T a) +{ + ASSERT(a < std::numeric_limits::max()); + return n32_narrow8(a); } +// Narrow a 16 bits number to an 8 bits number, discarding any upper exceeding bytes. template [[nodiscard]] -constexpr auto i16_narrow8(const T a) noexcept +constexpr auto n16_narrow8(const T a) noexcept { static_assert(std::is_arithmetic_v, "Input variable is not an arithmetic type."); static_assert(std::is_integral_v, "Only integral types are supported by this function."); @@ -158,81 +181,126 @@ constexpr auto i16_narrow8(const T a) noexcept return static_cast(a & umask); } +// Narrow a 16 bits number to an 8 bits number and ASSERT (because you're reasonably sure but not absolutely certain) that it won't overflow. +template +[[nodiscard]] inline +auto n16_narrow8_checked(const T a) +{ + ASSERT(a < std::numeric_limits::max()); + return n16_narrow8(a); +} +// If size_t is bigger than a 32 bits number, narrow it to a 32 bits number discarding any upper exceeding bytes, otherwise plain return the same value.. [[nodiscard]] -inline int8 i8_from_u8_checked(const uint8 a) // not clamping/capping +constexpr uint32 usize_narrow32(const size_t a) noexcept +{ + // This doesn't work for some reason, n64_narrow32 static_asserts will be evaluated and fail on 32 bits compilation + /* + if constexpr (sizeof(size_t) == 8) + return n64_narrow32(a); + else + return a; + */ +#if UINTPTR_MAX == ULONG_LONG_MAX + // ptr size is 8 -> 64 bits + return n64_narrow32(a); +#elif UINTPTR_MAX == UINT_MAX + // ptr size is 4 -> 32 bits + return a; +#else +# error "Pointer size is neither 8 nor 4?" +#endif +} + +// If size_t is bigger than a 32 bits number, narrow it to a 32 bits number and ASSERT (because you're reasonably sure but not absolutely certain) that it won't overflow. If size_t has 32 bits size, plain return the same value. +[[nodiscard]] inline +uint32 usize_narrow32_checked(const size_t a) { - ASSERT(a <= INT8_MAX); + ASSERT(a < std::numeric_limits::max()); + return usize_narrow32(a); +} + + +// Unsigned (and size_t) to signed. + +// Convert an 8 bits unsigned value to signed and ASSERT (because you're reasonably sure but not absolutely certain) that it will fit into its signed datatype counterpart (unsigned variables can store greater values than signed ones). +[[nodiscard]] inline +int8 i8_from_u8_checked(const uint8 a) // not clamping/capping +{ + ASSERT(a <= (uint8_t)std::numeric_limits::max()); return static_cast(a); } template int8 i8_from_u8_checked(T) = delete; -[[nodiscard]] -inline int16 i16_from_u16_checked(const uint16 a) // not clamping/capping +// Convert a 16 bits unsigned value to signed and ASSERT (because you're reasonably sure but not absolutely certain) that it will fit into its signed datatype counterpart (unsigned variables can store greater values than signed ones). +[[nodiscard]] inline +int16 i16_from_u16_checked(const uint16 a) // not clamping/capping { - ASSERT(a <= INT16_MAX); + ASSERT(a <= (uint16_t)std::numeric_limits::max()); return static_cast(a); } template int16 i16_from_u16_checked(T) = delete; -[[nodiscard]] -inline int32 i32_from_u32_checked(const uint32 a) // not clamping/capping +// Convert a 32 bits unsigned value to signed and ASSERT (because you're reasonably sure but not absolutely certain) that it will fit into its signed datatype counterpart (unsigned variables can store greater values than signed ones). +[[nodiscard]] inline +int32 i32_from_u32_checked(const uint32 a) // not clamping/capping { - ASSERT(a <= INT32_MAX); + ASSERT(a <= (uint32_t)std::numeric_limits::max()); return static_cast(a); } template int32 i32_from_u32_checked(T) = delete; -[[nodiscard]] -inline int64 i64_from_u64_checked(const uint64 a) // not clamping/capping +// Convert a 64 bits unsigned value to signed and ASSERT (because you're reasonably sure but not absolutely certain) that it will fit into its signed datatype counterpart (unsigned variables can store greater values than signed ones). +[[nodiscard]] inline +int64 i64_from_u64_checked(const uint64 a) // not clamping/capping { - ASSERT(a <= INT64_MAX); + ASSERT(a <= (uint64_t)std::numeric_limits::max()); return static_cast(a); } template int64 i64_from_u64_checked(T) = delete; [[nodiscard]] constexpr -inline int8 i8_from_u8_clamping(const uint8 a) noexcept +int8 i8_from_u8_clamping(const uint8 a) noexcept { - return (a > (uint8)INT8_MAX) ? INT8_MAX : (int8)a; + return (a > (uint8_t)std::numeric_limits::max()) ? std::numeric_limits::max() : (int8_t)a; } [[nodiscard]] constexpr -inline int16 i16_from_u16_clamping(const uint16 a) noexcept +int16 i16_from_u16_clamping(const uint16 a) noexcept { - return (a > (uint16)INT16_MAX) ? INT16_MAX : (int16)a; + return (a > (uint16_t)std::numeric_limits::max()) ? (uint16_t)std::numeric_limits::max() : (int16_t)a; } [[nodiscard]] constexpr -inline int32 i32_from_u32_clamping(const uint32 a) noexcept +int32 i32_from_u32_clamping(const uint32 a) noexcept { - return (a > (uint32)INT32_MAX) ? INT32_MAX : (int32)a; + return (a > (uint32_t)std::numeric_limits::max()) ? (uint32_t)std::numeric_limits::max() : (int32_t)a; } [[nodiscard]] constexpr -inline int64 i64_from_u64_clamping(const uint64 a) noexcept +int64 i64_from_u64_clamping(const uint64 a) noexcept { - return (a > (uint64)INT64_MAX) ? INT64_MAX : (int64)a; + return (a > (uint64_t)std::numeric_limits::max()) ? (uint64_t)std::numeric_limits::max() : (int64_t)a; } [[nodiscard]] constexpr -inline int32 i32_from_usize_clamping(const size_t a) noexcept +int32 i32_from_usize_clamping(const size_t a) noexcept { - return (a > (size_t)INT32_MAX) ? INT32_MAX : (int32)a; + return (a > (size_t)std::numeric_limits::max()) ? std::numeric_limits::max() : (int32_t)a; } [[nodiscard]] constexpr -inline int64 i64_from_usize_clamping(const size_t a) noexcept +int64 i64_from_usize_clamping(const size_t a) noexcept { - return (a > (size_t)INT64_MAX) ? INT64_MAX : (int64)a; + return (a > (size_t)std::numeric_limits::max()) ? std::numeric_limits::max() : (int64_t)a; } [[nodiscard]] constexpr -inline uint32 u32_from_usize_clamping(const size_t a) noexcept +uint32 u32_from_usize_clamping(const size_t a) noexcept { if constexpr (sizeof(size_t) == 8) - return (a > (size_t)UINT32_MAX) ? UINT32_MAX : (uint32)a; + return (a > (size_t)std::numeric_limits::max()) ? std::numeric_limits::max() : (uint32_t)a; else return a; } diff --git a/src/game/CSectorEnviron.cpp b/src/game/CSectorEnviron.cpp index 98d44efb3..98fcb7a48 100644 --- a/src/game/CSectorEnviron.cpp +++ b/src/game/CSectorEnviron.cpp @@ -2,17 +2,17 @@ #include "CSectorEnviron.h" -CSectorEnviron::CSectorEnviron() +CSectorEnviron::CSectorEnviron() noexcept { m_Light = LIGHT_BRIGHT; // set based on time later. m_Season = SEASON_Summer; m_Weather = WEATHER_DRY; } -void CSectorEnviron::SetInvalid() +void CSectorEnviron::SetInvalid() noexcept { // Force a resync of all this. we changed location by teleport etc. m_Light = UINT8_MAX; // set based on time later. m_Season = SEASON_QTY; m_Weather = WEATHER_DEFAULT; -} \ No newline at end of file +} diff --git a/src/game/CSectorEnviron.h b/src/game/CSectorEnviron.h index b4e90bb48..50a20347e 100644 --- a/src/game/CSectorEnviron.h +++ b/src/game/CSectorEnviron.h @@ -12,13 +12,13 @@ struct CSectorEnviron // When these change it is an CTRIG_EnvironChange, { #define LIGHT_OVERRIDE 0x80 // are we overriding the sector's light? (character LIGHT property doesn't count as overriding the sector's light) -public: + byte m_Light; // the calculated light level in this area. |0x80 = override. SEASON_TYPE m_Season; // What is the season for this sector. WEATHER_TYPE m_Weather; // the weather in this area now. -public: - CSectorEnviron(); - void SetInvalid(); + + CSectorEnviron() noexcept; + void SetInvalid() noexcept; }; diff --git a/src/game/clients/CChatChanMember.cpp b/src/game/clients/CChatChanMember.cpp index 476e6a7de..e310d0415 100644 --- a/src/game/clients/CChatChanMember.cpp +++ b/src/game/clients/CChatChanMember.cpp @@ -184,13 +184,15 @@ void CChatChanMember::ToggleWhoIs() CClient * CChatChanMember::GetClientActive() { ADDTOCALLSTACK("CChatChanMember::GetClientActive"); - return( static_cast ( this )); + DEBUG_ASSERT(dynamic_cast(this)); + return static_cast ( this ); } const CClient * CChatChanMember::GetClientActive() const { - ADDTOCALLSTACK("CChatChanMember::GetClientActive"); - return( static_cast ( this )); + ADDTOCALLSTACK("CChatChanMember::GetClientActive(const)"); + DEBUG_ASSERT(dynamic_cast(this)); + return static_cast ( this ); } lpctstr CChatChanMember::GetChatName() const diff --git a/src/game/clients/CClientTarg.cpp b/src/game/clients/CClientTarg.cpp index 85d379fcf..cdf48ffcb 100644 --- a/src/game/clients/CClientTarg.cpp +++ b/src/game/clients/CClientTarg.cpp @@ -1067,12 +1067,12 @@ int CClient::OnSkill_ArmsLore( CUID uid, int iSkillLevel, bool fTest ) // Poisoned ? if ( fWeapon && pItem->m_itWeapon.m_poison_skill ) { - uint iLevel = (uint)IMulDiv( - i_promote32(pItem->m_itWeapon.m_poison_skill), - i_narrow32(ARRAY_COUNT(sm_szPoisonMessages)), + uint iLevel = (uint)IMulDiv( + n_promote32(pItem->m_itWeapon.m_poison_skill), + usize_narrow32(ARRAY_COUNT(sm_szPoisonMessages)), 100); if ( iLevel >= ARRAY_COUNT(sm_szPoisonMessages)) - iLevel = i_narrow32(ARRAY_COUNT(sm_szPoisonMessages)) - 1; + iLevel = usize_narrow32(ARRAY_COUNT(sm_szPoisonMessages)) - 1; len += snprintf( pszTemp+len, Str_TempLength() - len, " %s", sm_szPoisonMessages[iLevel] ); } @@ -1288,7 +1288,7 @@ int CClient::OnSkill_TasteID( CUID uid, int iSkillLevel, bool fTest ) { uint iLevel = (uint)IMulDiv( iPoisonLevel, ARRAY_COUNT(sm_szPoisonMessages), 1000 ); if ( iLevel >= ARRAY_COUNT(sm_szPoisonMessages)) - iLevel = i_narrow32(ARRAY_COUNT(sm_szPoisonMessages) - 1); + iLevel = usize_narrow32(ARRAY_COUNT(sm_szPoisonMessages) - 1); SysMessage(sm_szPoisonMessages[iLevel] ); } else @@ -1441,7 +1441,7 @@ bool CClient::OnTarg_Skill_Magery( CObjBase * pObj, const CPointMap & pt ) return false; const CSpellDef * pSpell = g_Cfg.GetSpellDef( m_tmSkillMagery.m_iSpell ); - if ( ! pSpell ) + if ( ! pSpell ) return false; if ( pObj ) @@ -1649,7 +1649,7 @@ CItem * CClient::OnTarg_Use_Multi(const CItemBase * pItemDef, CPointMap & pt, CI if ((pItemDef == nullptr) || !pt.GetRegion(REGION_TYPE_AREA)) return nullptr; - + return CItemMulti::Multi_Create(GetChar(), pItemDef, pt, pDeed); } @@ -1991,9 +1991,9 @@ bool CClient::OnTarg_Use_Item( CObjBase * pObjTarg, CPointMap & pt, ITEMID_TYPE m_pChar->m_Act_UID = m_Targ_UID; //The target. /*An NPC will be healed by the Veterinary skill if the following conditions are satisfied: - It has a Taming value above > 0 AND its ID is not the ID one of the playable races (Human, Elf or Gargoyle) + It has a Taming value above > 0 AND its ID is not the ID one of the playable races (Human, Elf or Gargoyle) */ - if (pCharTarg->m_pNPC && pCharTarg->Skill_GetBase(SKILL_TAMING) > 0 && + if (pCharTarg->m_pNPC && pCharTarg->Skill_GetBase(SKILL_TAMING) > 0 && !pCharTarg->IsPlayableCharacter() ) { switch (pCharTarg->GetNPCBrain()) diff --git a/src/game/components/CCSpawn.cpp b/src/game/components/CCSpawn.cpp index af37ae458..57cb6fa91 100644 --- a/src/game/components/CCSpawn.cpp +++ b/src/game/components/CCSpawn.cpp @@ -468,7 +468,7 @@ CChar* CCSpawn::GenerateChar(CResourceIDBase rid) CResourceIDBase CCSpawn::GetCharRid() { ADDTOCALLSTACK("CCSpawn::GetCharRid"); - const CItem* pSpawnItem = static_cast(GetLink()); + auto pSpawnItem = static_cast(GetLink()); CResourceIDBase rid; const CResourceDef* pDef = FixDef(); @@ -483,7 +483,7 @@ CResourceIDBase CCSpawn::GetCharRid() RES_TYPE iRidType = rid.GetResType(); if (iRidType == RES_SPAWN) { - const CRandGroupDef* pSpawnGroup = static_cast(pDef); + auto pSpawnGroup = dynamic_cast(pDef); ASSERT(pSpawnGroup); size_t i = pSpawnGroup->GetRandMemberIndex(); if (i != sl::scont_bad_index()) diff --git a/src/game/items/CItem.cpp b/src/game/items/CItem.cpp index d011d9744..7b9f14883 100644 --- a/src/game/items/CItem.cpp +++ b/src/game/items/CItem.cpp @@ -614,7 +614,7 @@ CItem * CItem::ReadTemplate( CResourceLock & s, CObjBase * pCont ) // static continue; if ( pItem->IsItemInContainer()) { - pItem->SetContainedLayer(i16_narrow8(pItem->GetAmount())); // set the Restock amount. + pItem->SetContainedLayer(n16_narrow8(pItem->GetAmount())); // set the Restock amount. } } continue; @@ -669,7 +669,7 @@ CItem * CItem::ReadTemplate( CResourceLock & s, CObjBase * pCont ) // static { pItem->r_Call(ptcFunctionName, &g_Serv, pScriptArgs.get()); } - + if (pItem->IsDeleted()) { pItem = nullptr; diff --git a/src/network/CNetworkOutput.cpp b/src/network/CNetworkOutput.cpp index b2168ec91..3abf84731 100644 --- a/src/network/CNetworkOutput.cpp +++ b/src/network/CNetworkOutput.cpp @@ -352,7 +352,7 @@ bool CNetworkOutput::processByteQueue(CNetState* state) if (result > 0) { - state->_iOutByteCounter += minimum(INT64_MAX, result); + state->_iOutByteCounter += minimum((uint64)INT64_MAX, (uint64)result); state->m_outgoing.bytes.RemoveDataAmount(result); } diff --git a/src/network/send.cpp b/src/network/send.cpp index 99c9e76c4..57d8d429d 100644 --- a/src/network/send.cpp +++ b/src/network/send.cpp @@ -3346,7 +3346,8 @@ PacketCharacterList::PacketCharacterList(CClient* target) : PacketSend(XCMD_Char uint countPos = getPosition(); skip(1); - uint count = target->Setup_FillCharList(this, account->m_uidLastChar.CharFind()); + uchar count = n32_narrow8( + target->Setup_FillCharList(this, account->m_uidLastChar.CharFind())); seek(countPos); writeByte((byte)count); @@ -3399,7 +3400,7 @@ PacketCharacterList::PacketCharacterList(CClient* target) : PacketSend(XCMD_Char if (ns->isClientEnhanced() ) { - word iLastCharSlot = 0; + word wLastCharSlot = 0; for ( ushort i = 0; i < count; ++i ) { if ( !account->m_Chars.IsValidIndex(i) ) @@ -3407,10 +3408,10 @@ PacketCharacterList::PacketCharacterList(CClient* target) : PacketSend(XCMD_Char if ( account->m_Chars.GetChar(i) != account->m_uidLastChar ) continue; - iLastCharSlot = (word)i; + wLastCharSlot = (word)i; break; } - writeInt16(iLastCharSlot); + writeInt16(wLastCharSlot); } } From dffa6fb84faa16cd96d8c1bdf753ff8cb17f0aea Mon Sep 17 00:00:00 2001 From: cbnolok Date: Mon, 26 Aug 2024 15:16:37 +0200 Subject: [PATCH 05/86] Added Linux-AArch64 and OSX-AArch64 toolchains, cleanup of other toolchains. --- .github/workflows/build_osx_arm.yml | 6 +- CMakeLists.txt | 4 + cmake/CMakeDefaultToolchain.cmake | 16 ++-- cmake/CMakeDetectArch.cmake | 47 ++++------- cmake/toolchains/Linux-Clang-AArch64.cmake | 67 ++++++++++++++++ cmake/toolchains/Linux-Clang-native.cmake | 62 ++++++++++++--- cmake/toolchains/Linux-Clang-x86.cmake | 76 ++++++++++++++++-- cmake/toolchains/Linux-Clang-x86_64.cmake | 57 +++++++++++-- cmake/toolchains/Linux-GNU-AArch64.cmake | 69 ++++++++++++++++ cmake/toolchains/Linux-GNU-native.cmake | 45 ++++++++--- cmake/toolchains/Linux-GNU-x86.cmake | 79 +++++++++++++++++-- cmake/toolchains/Linux-GNU-x86_64.cmake | 60 ++++++++++++-- cmake/toolchains/OSX-AppleClang-AArch64.cmake | 40 ++++++++++ cmake/toolchains/OSX-AppleClang-native.cmake | 38 ++++++--- cmake/toolchains/OSX-AppleClang-x86_64.cmake | 27 +++++-- cmake/toolchains/Windows-Clang-native.cmake | 45 +++++++---- cmake/toolchains/Windows-Clang-x86.cmake | 35 ++++++-- cmake/toolchains/Windows-Clang-x86_64.cmake | 35 ++++++-- cmake/toolchains/Windows-GNU-native.cmake | 30 ++++--- cmake/toolchains/Windows-GNU-x86.cmake | 26 ++++-- cmake/toolchains/Windows-GNU-x86_64.cmake | 26 ++++-- cmake/toolchains/Windows-MSVC.cmake | 14 +--- .../include/Linux-Clang_common.inc.cmake | 36 ++------- .../include/Linux-GNU_common.inc.cmake | 34 ++------ .../include/OSX-AppleClang_common.inc.cmake | 9 +-- .../include/Windows-Clang_common.inc.cmake | 18 +---- .../include/Windows-GNU_common.inc.cmake | 5 -- src/common/sphere_library/stypecast.h | 8 +- 28 files changed, 749 insertions(+), 265 deletions(-) create mode 100644 cmake/toolchains/Linux-Clang-AArch64.cmake create mode 100644 cmake/toolchains/Linux-GNU-AArch64.cmake create mode 100644 cmake/toolchains/OSX-AppleClang-AArch64.cmake diff --git a/.github/workflows/build_osx_arm.yml b/.github/workflows/build_osx_arm.yml index e90805be4..8639c67be 100644 --- a/.github/workflows/build_osx_arm.yml +++ b/.github/workflows/build_osx_arm.yml @@ -17,7 +17,8 @@ jobs: runs-on: macos-14 # apple silicon env: CMAKE_GEN: Ninja - CMAKE_TCH: cmake/toolchains/OSX-AppleClang-native.cmake + #CMAKE_TCH: cmake/toolchains/OSX-AppleClang-native.cmake + CMAKE_TCH: cmake/toolchains/OSX-AppleClang-AArch64.cmake steps: - name: Checkout repository @@ -50,7 +51,8 @@ jobs: pwd mkdir accounts logs save scripts zip -r SphereSvrX-osx-arm64-nightly.zip accounts/ logs/ save/ scripts/ - zip SphereSvrX-osx-arm64-nightly.zip src/sphere.ini src/sphereCrypt.ini build/bin-native64/* + zip SphereSvrX-osx-arm64-nightly.zip src/sphere.ini src/sphereCrypt.ini build/bin-aarch64/* + # zip SphereSvrX-osx-arm64-nightly.zip src/sphere.ini src/sphereCrypt.ini build/bin-native64/* # Upload artifact linked to the workflow run - only if the run is for a pull request, or for selected branches - name: Upload artifact diff --git a/CMakeLists.txt b/CMakeLists.txt index 4bd1cac74..7fb98d1fd 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -8,6 +8,10 @@ option (CMAKE_NO_GIT_REVISION "Do not try to retrieve the current git revision. Useful for building source not git-cloned from Github." FALSE ) +option (CROSSCOMPILE + "Are we compiling for a different target architecture?" + FALSE +) option (RUNTIME_STATIC_LINK "Statically link inside the executable the runtime libraries? (MSVC, libc/libcc, libstdc++)." FALSE diff --git a/cmake/CMakeDefaultToolchain.cmake b/cmake/CMakeDefaultToolchain.cmake index ba350b168..72ce5a897 100644 --- a/cmake/CMakeDefaultToolchain.cmake +++ b/cmake/CMakeDefaultToolchain.cmake @@ -3,21 +3,23 @@ IF (MSVC) INCLUDE ("cmake/toolchains/Windows-MSVC.cmake") ELSE () IF (APPLE) - MESSAGE (STATUS "Defaulting to x86_64 arch.") - INCLUDE ("cmake/toolchains/OSX-AppleClang-x86_64.cmake") + MESSAGE (STATUS "Defaulting to AArch64 (ARM) arch.") + INCLUDE ("cmake/toolchains/OSX-AppleClang-AArch64.cmake") ELSEIF (UNIX) - IF (NOT ARCH_HAS_x86_64 EQUAL -1) + IF ("${ARCH}" STREQUAL "x86_64") INCLUDE ("cmake/toolchains/Linux-GNU-x86_64.cmake") - ELSEIF (NOT ARCH_HAS_x86 EQUAL -1) + ELSEIF ("${ARCH}" STREQUAL "x86") INCLUDE ("cmake/toolchains/Linux-GNU-x86.cmake") - ELSE () + ELSEIF ("${ARCH}" STREQUAL "arm64") + INCLUDE ("cmake/toolchains/Linux-Clang-AArch64.cmake") + ELSE () MESSAGE (STATUS "Unsupported architecture, defaulting to native.") INCLUDE ("cmake/toolchains/Linux-GNU-native.cmake") ENDIF () ELSE () - IF (NOT ARCH_HAS_x86_64 EQUAL -1) + IF ("${ARCH}" STREQUAL "x86_64") INCLUDE ("cmake/toolchains/Windows-GNU-x86_64.cmake") - ELSEIF (NOT ARCH_HAS_x86 EQUAL -1) + ELSEIF ("${ARCH}" STREQUAL "x86") INCLUDE ("cmake/toolchains/Windows-GNU-x86.cmake") ELSE () MESSAGE (STATUS "Unsupported architecture, defaulting to native.") diff --git a/cmake/CMakeDetectArch.cmake b/cmake/CMakeDetectArch.cmake index 2f0f0eec0..1846b3713 100644 --- a/cmake/CMakeDetectArch.cmake +++ b/cmake/CMakeDetectArch.cmake @@ -24,8 +24,7 @@ if ("${HOST_OS}" STREQUAL "LINUX") endif() endif() -message (STATUS "Detecting target arch from SYSTEM_PROCESSOR: ${CMAKE_SYSTEM_PROCESSOR}") -message (STATUS "Host machine: ${HOST_OS}") +message (STATUS "Host machine: [OS] ${HOST_OS} [Arch] ${CMAKE_HOST_SYSTEM_PROCESSOR}") if(MINGW) execute_process(COMMAND ${CMAKE_C_COMPILER} -dumpmachine @@ -36,22 +35,6 @@ if(MINGW) endif() endif() - -if (ARCH_BITS) - if ( NOT (ARCH_BITS EQUAL 64 OR ARCH_BITS EQUAL 32) ) - message(ERROR "Invalid ARCH_BITS?") - endif () -else () - if (${CMAKE_SIZEOF_VOID_P} EQUAL 8) - set (ARCH_BITS 64 CACHE INTERNAL "") - elseif (${CMAKE_SIZEOF_VOID_P} EQUAL 4) - set (ARCH_BITS 32 CACHE INTERNAL "") - else () - #set (ARCH_BITS -1) - message(ERROR "Unknown arch?") - endif () -endif () - # Pretty thorough determination of arch. Add more if needed if(CMAKE_CL_64 OR MINGW64) if ("${CMAKE_SYSTEM_PROCESSOR}" MATCHES "^(aarch64.*|AARCH64.*|arm64.*|ARM64.*)") @@ -70,29 +53,29 @@ elseif("${CMAKE_SYSTEM_PROCESSOR}" MATCHES "loongarch64.*") elseif("${CMAKE_SYSTEM_PROCESSOR}" MATCHES "riscv64.*") set(RISCV64 1) elseif("${CMAKE_SYSTEM_PROCESSOR}" MATCHES "amd64.*|x86_64.*|AMD64.*" OR ("${CMAKE_SYSTEM_NAME}" MATCHES "Darwin" AND "${CMAKE_SYSTEM_PROCESSOR}" MATCHES "i686.*|i386.*|x86.*")) - if (${ARCH_BITS} EQUAL 64) + #if (${ARCH_BITS} EQUAL 64) set(X86_64 1) - else () - set(X86 1) - endif() -elseif("${CMAKE_SYSTEM_PROCESSOR}" MATCHES "i686.*|i386.*|x86.*|x86_64.*|amd64.*|AMD64.*") - if (${ARCH_BITS} EQUAL 64) - set(X86_64 1) - else () + #else () + # set(X86 1) + #endif() +elseif("${CMAKE_SYSTEM_PROCESSOR}" MATCHES "i686.*|i386.*|x86.*") + #if (${ARCH_BITS} EQUAL 64) + # set(X86_64 1) + #else () set(X86 1) - endif() + #endif() elseif("${CMAKE_SYSTEM_PROCESSOR}" MATCHES "^(aarch64.*|AARCH64.*|arm64.*|ARM64.*|armv8.*)") - if (${ARCH_BITS} EQUAL 64) + #if (${ARCH_BITS} EQUAL 64) set(ARM64 1) - else() - set(ARM 1) - endif() + #else() + # set(ARM 1) + #endif() elseif("${CMAKE_SYSTEM_PROCESSOR}" MATCHES "^(arm.*|ARM.*)") set(ARM 1) elseif (CMAKE_CROSSCOMPILING) if ("${TARGET}" STREQUAL "CORE2") if (NOT ARCH_BITS) - set(X86 1) + set(X86 1) elseif (${ARCH_BITS} EQUAL 64) set(X86_64 1) else () diff --git a/cmake/toolchains/Linux-Clang-AArch64.cmake b/cmake/toolchains/Linux-Clang-AArch64.cmake new file mode 100644 index 000000000..c3a7fb8f1 --- /dev/null +++ b/cmake/toolchains/Linux-Clang-AArch64.cmake @@ -0,0 +1,67 @@ +INCLUDE("${CMAKE_CURRENT_LIST_DIR}/include/Linux-Clang_common.inc.cmake") + + +function (toolchain_force_compiler) + SET (CMAKE_C_COMPILER "clang" CACHE STRING "C compiler" FORCE) + SET (CMAKE_CXX_COMPILER "clang++" CACHE STRING "C++ compiler" FORCE) + + if (CROSSCOMPILING_ARCH) + # where is the target environment located + set(CMAKE_FIND_ROOT_PATH "/usr/aarch64-linux-gnu" CACHE INTERNAL "" FORCE) + + # adjust the default behavior of the FIND_XXX() commands: + # search programs in the host environment + set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM "NEVER" CACHE INTERNAL "" FORCE) + + # search headers and libraries in the target environment + set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE "ONLY" CACHE INTERNAL "" FORCE) + set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY "ONLY" CACHE INTERNAL "" FORCE) + endif() +endfunction () + + +function (toolchain_after_project) + MESSAGE (STATUS "Toolchain: Linux-Clang-AArch64.cmake.") + # Do not set CMAKE_SYSTEM_NAME if compiling for the same OS, otherwise CMAKE_CROSSCOMPILING will be set to TRUE + #SET(CMAKE_SYSTEM_NAME "Linux" CACHE INTERNAL "" FORCE) + SET(CMAKE_SYSTEM_PROCESSOR "aarch64" CACHE INTERNAL "" FORCE) + SET(CMAKE_RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/bin-aarch64" PARENT_SCOPE) + #set(ARCH_BITS 64 CACHE INTERNAL "" FORCE) # provide it + + if (CROSSCOMPILING_ARCH) + # possible cross-compilation foreign arch lib locations + set (lib_search_paths + "/usr/aarch64-linux-gnu/usr/lib/libmariadb3" + "/usr/aarch64-linux-gnu/usr/lib/mysql" + "/usr/aarch64-linux-gnu/usr/lib/" + CACHE STRING "Library search paths" FORCE + ) + else () + # possible native/host lib locations + set (lib_search_paths + "/usr/aarch64-linux-gnu/libmariadb3" + "/usr/aarch64-linux-gnu/mysql" + "/usr/aarch64-linux-gnu" + "/usr/lib64/mysql" + "/usr/lib64" + "/usr/lib/mysql" + "/usr/lib" + CACHE STRING "Library search paths" FORCE + ) + endif () + + toolchain_after_project_common() + + SET (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} --target=aarch64-linux-gnu" PARENT_SCOPE) + SET (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} --target=aarch64-linux-gnu" PARENT_SCOPE) +endfunction() + + +function (toolchain_exe_stuff) + toolchain_exe_stuff_common() + + # Propagate global variables set in toolchain_exe_stuff_common to the upper scope + #SET (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${C_ARCH_OPTS}" PARENT_SCOPE) + #SET (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${CXX_ARCH_OPTS}" PARENT_SCOPE) + #SET (CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS}" PARENT_SCOPE) +endfunction() diff --git a/cmake/toolchains/Linux-Clang-native.cmake b/cmake/toolchains/Linux-Clang-native.cmake index 1dff5b9af..22fbf79e5 100644 --- a/cmake/toolchains/Linux-Clang-native.cmake +++ b/cmake/toolchains/Linux-Clang-native.cmake @@ -1,24 +1,60 @@ INCLUDE("${CMAKE_CURRENT_LIST_DIR}/include/Linux-Clang_common.inc.cmake") + +function (toolchain_force_compiler) + if (CROSSCOMPILING_ARCH) + message(FATAL_ERROR "Can't cross-compile with a 'native' toolchain.") + endif () + + SET (CMAKE_C_COMPILER "clang" CACHE STRING "C compiler" FORCE) + SET (CMAKE_CXX_COMPILER "clang++" CACHE STRING "C++ compiler" FORCE) +endfunction () + + function (toolchain_after_project) MESSAGE (STATUS "Toolchain: Linux-Clang-native.cmake.") + # Do not set CMAKE_SYSTEM_NAME if compiling for the same OS, otherwise CMAKE_CROSSCOMPILING will be set to TRUE + #SET(CMAKE_SYSTEM_NAME "Linux" CACHE INTERNAL "" FORCE) # target OS + IF (CMAKE_SIZEOF_VOID_P EQUAL 8) + SET(CMAKE_RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/bin-native64" PARENT_SCOPE) + ELSE () + SET(CMAKE_RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/bin-native32" PARENT_SCOPE) + ENDIF () - #SET(CMAKE_SYSTEM_NAME "Linux" PARENT_SCOPE) + # possible native/host lib locations + set (local_usr_lib_subfolders + "libmariadb3" + "mysql" + ) + foreach (local_usr_lib_subfolders subfolder) + # ARCH variable is set by CMakeGitStatus + set (local_lib_search_paths + ${local_lib_search_paths} + "/usr/${ARCH}-linux-gnu/${subfolder}" + ) + endforeach() + set (lib_search_paths + ${local_lib_search_paths} + "/usr/lib64/mysql" + "/usr/lib64" + "/usr/lib/mysql" + "/usr/lib" + CACHE STRING "Library search paths" FORCE + ) toolchain_after_project_common() - IF (CMAKE_SIZEOF_VOID_P EQUAL 8) - #MESSAGE (STATUS "Detected 64 bits architecture") - #SET(ARCH_BITS 64 CACHE INTERNAL) # override - SET(CMAKE_RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/bin-native64" PARENT_SCOPE) - ELSE () - #MESSAGE (STATUS "Detected 32 bits architecture") - #SET(ARCH_BITS 32 CACHE INTERNAL) # override - SET(CMAKE_RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/bin-native32" PARENT_SCOPE) - ENDIF () - - SET (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -march=native" PARENT_SCOPE) - SET (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -march=native" PARENT_SCOPE) + if ("${ARCH_BASE}" STREQUAL "arm") + # Clang doesn't support -march=native for ARM (but it IS supported by Apple Clang, btw) + # Also: + # https://community.arm.com/arm-community-blogs/b/tools-software-ides-blog/posts/compiler-flags-across-architectures-march-mtune-and-mcpu + # https://code.fmsolvr.fz-juelich.de/i.lilikakis/fmsolvr/commit/bd010058b8b8c92385d1ccc321912bf1359d66b0 + set (local_arch_cmd -mcpu=native) + else () + set (local_arch_cmd -march=native -mtune=native) + endif () + SET (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${local_arch_cmd}" PARENT_SCOPE) + SET (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${local_arch_cmd}" PARENT_SCOPE) endfunction() diff --git a/cmake/toolchains/Linux-Clang-x86.cmake b/cmake/toolchains/Linux-Clang-x86.cmake index c7c69b4e5..0cc39338d 100644 --- a/cmake/toolchains/Linux-Clang-x86.cmake +++ b/cmake/toolchains/Linux-Clang-x86.cmake @@ -1,17 +1,79 @@ INCLUDE("${CMAKE_CURRENT_LIST_DIR}/include/Linux-Clang_common.inc.cmake") + +function (toolchain_force_compiler) + SET (CMAKE_C_COMPILER "clang" CACHE STRING "C compiler" FORCE) + SET (CMAKE_CXX_COMPILER "clang++" CACHE STRING "C++ compiler" FORCE) + + if (CROSSCOMPILING_ARCH) + message(FATAL_ERROR "Incomplete/to be tested.") # are the names/paths correct? + + # where is the target environment located + set(CMAKE_FIND_ROOT_PATH "/usr/i386-pc-linux-gnu" CACHE INTERNAL "" FORCE) + + # adjust the default behavior of the FIND_XXX() commands: + # search programs in the host environment + set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM "NEVER" CACHE INTERNAL "" FORCE) + + # search headers and libraries in the target environment + set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE "ONLY" CACHE INTERNAL "" FORCE) + set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY "ONLY" CACHE INTERNAL "" FORCE) + endif() +endfunction () + + function (toolchain_after_project) MESSAGE (STATUS "Toolchain: Linux-Clang-x86.cmake.") - #SET(CMAKE_SYSTEM_NAME "Linux" PARENT_SCOPE) - SET(ARCH_BASE "x86" CACHE INTERNAL "" FORCE) # override - SET(ARCH_BITS 32 CACHE INTERNAL "" FORCE) # override - SET(ARCH "x86" CACHE INTERNAL "" FORCE) # override - SET(CMAKE_SYSTEM_PROCESSOR "${ARCH}" CACHE INTERNAL "" FORCE) + # Do not set CMAKE_SYSTEM_NAME if compiling for the same OS, otherwise CMAKE_CROSSCOMPILING will be set to TRUE + #SET(CMAKE_SYSTEM_NAME "Linux" CACHE INTERNAL "" FORCE) # target OS + SET(CMAKE_SYSTEM_PROCESSOR "x86" CACHE INTERNAL "" FORCE) # target arch + SET(CMAKE_RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/bin-x86" PARENT_SCOPE) + #set(ARCH_BITS 32 CACHE INTERNAL "" FORCE) # provide it - toolchain_after_project_common() + if (CROSSCOMPILING_ARCH) + # possible cross-compilation foreign arch lib locations + set (lib_search_paths + "/usr/i686-linux-gnu/usr/lib/libmariadb3" + "/usr/i686-linux-gnu/usr/lib/mysql" + "/usr/i686-linux-gnu/usr/lib/" + "/usr/i386-linux-gnu/usr/lib/libmariadb3" + "/usr/i386-linux-gnu/usr/lib/mysql" + "/usr/i386-linux-gnu/usr/lib/" + CACHE STRING "Library search paths" FORCE + ) + else (CROSSCOMPILING_ARCH) + set (local_lib_search_paths + "/usr/i686-linux-gnu/libmariadb3" + "/usr/i686-linux-gnu/mysql" + "/usr/i686-linux-gnu" + "/usr/i386-linux-gnu/libmariadb3" + "/usr/i386-linux-gnu/mysql" + "/usr/i386-linux-gnu" + "/usr/lib32/mysql" + "/usr/lib32" + ) + + if ("${CMAKE_HOST_SYSTEM_PROCESSOR}" STREQUAL "x86_64") + # I'm compiling for x86 on an x86_64 host. + set (CMAKE_LIBRARY_PATH ${local_lib_search_paths} CACHE PATH "") + else () + # I'm compiling for x86 on an x86 OS (32 bits), so natively: i have libs on /usr/lib and not /usr/lib32. + set (local_extra_lib_search_paths + "/usr/lib/mysql" + "/usr/lib" + ) + endif() - SET(CMAKE_RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/bin-x86" PARENT_SCOPE) + set (lib_search_paths + ${local_lib_search_paths} + ${local_extra_lib_search_paths} + CACHE STRING "Library search paths (hint)" FORCE + ) + endif (CROSSCOMPILING_ARCH) + + toolchain_after_project_common() + # --target=-x86-unknown-linux-gnu? SET (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -march=i686 -m32" PARENT_SCOPE) SET (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -march=i686 -m32" PARENT_SCOPE) endfunction() diff --git a/cmake/toolchains/Linux-Clang-x86_64.cmake b/cmake/toolchains/Linux-Clang-x86_64.cmake index a7636ccb8..874b3940e 100644 --- a/cmake/toolchains/Linux-Clang-x86_64.cmake +++ b/cmake/toolchains/Linux-Clang-x86_64.cmake @@ -1,17 +1,60 @@ INCLUDE("${CMAKE_CURRENT_LIST_DIR}/include/Linux-Clang_common.inc.cmake") + +function (toolchain_force_compiler) + SET (CMAKE_C_COMPILER "clang" CACHE STRING "C compiler" FORCE) + SET (CMAKE_CXX_COMPILER "clang++" CACHE STRING "C++ compiler" FORCE) + + if (CROSSCOMPILING_ARCH) + message(FATAL_ERROR "Incomplete/to be tested.") # are the names/paths correct? + + # where is the target environment located + set(CMAKE_FIND_ROOT_PATH "/usr/x86_64-pc-linux-gnu" CACHE INTERNAL "" FORCE) + + # adjust the default behavior of the FIND_XXX() commands: + # search programs in the host environment + set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM "NEVER" CACHE INTERNAL "" FORCE) + + # search headers and libraries in the target environment + set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE "ONLY" CACHE INTERNAL "" FORCE) + set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY "ONLY" CACHE INTERNAL "" FORCE) + endif() +endfunction () + + function (toolchain_after_project) MESSAGE (STATUS "Toolchain: Linux-Clang-x86_64.cmake.") - #SET(CMAKE_SYSTEM_NAME "Linux" PARENT_SCOPE) - SET(ARCH_BASE "x86" CACHE INTERNAL "" FORCE) # override - SET(ARCH_BITS 64 CACHE INTERNAL "" FORCE) # override - SET(ARCH "x86_64" CACHE INTERNAL "" FORCE) # override - SET(CMAKE_SYSTEM_PROCESSOR "${ARCH}" CACHE INTERNAL "" FORCE) + # Do not set CMAKE_SYSTEM_NAME if compiling for the same OS, otherwise CMAKE_CROSSCOMPILING will be set to TRUE + #SET(CMAKE_SYSTEM_NAME "Linux" CACHE INTERNAL "" FORCE) # target OS + SET(CMAKE_SYSTEM_PROCESSOR "x86_64" CACHE INTERNAL "" FORCE) # target arch + SET(CMAKE_RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/bin-x86_64" PARENT_SCOPE) + set(ARCH_BITS 64 CACHE INTERNAL "" FORCE) # provide it - toolchain_after_project_common() + if (CROSSCOMPILING_ARCH) + # possible cross-compilation foreign arch lib locations + set (lib_search_paths + "/usr/x86_64-linux-gnu/usr/lib/libmariadb3" + "/usr/x86_64-linux-gnu/usr/lib/mysql" + "/usr/x86_64-linux-gnu/usr/lib/" + CACHE STRING "Library search paths (hint)" FORCE + ) + else () + # possible native/host lib locations + set (lib_search_paths + "/usr/x86_64-linux-gnu/libmariadb3" + "/usr/x86_64-linux-gnu/mysql" + "/usr/x86_64-linux-gnu" + "/usr/lib64/mysql" + "/usr/lib64" + "/usr/lib/mysql" + "/usr/lib" + CACHE STRING "Library search paths (hint)" FORCE + ) + endif () - SET(CMAKE_RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/bin-x86_64" PARENT_SCOPE) + toolchain_after_project_common() + # --target=-x86_64-unknown-linux-gnu ? SET (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -march=x86-64 -m64" PARENT_SCOPE) SET (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -march=x86-64 -m64" PARENT_SCOPE) endfunction() diff --git a/cmake/toolchains/Linux-GNU-AArch64.cmake b/cmake/toolchains/Linux-GNU-AArch64.cmake new file mode 100644 index 000000000..9784f47d9 --- /dev/null +++ b/cmake/toolchains/Linux-GNU-AArch64.cmake @@ -0,0 +1,69 @@ +INCLUDE("${CMAKE_CURRENT_LIST_DIR}/include/Linux-GNU_common.inc.cmake") + + +function (toolchain_force_compiler) + if (NOT CROSSCOMPILING_ARCH) + SET (CMAKE_C_COMPILER "gcc" CACHE STRING "C compiler" FORCE) + SET (CMAKE_CXX_COMPILER "g++" CACHE STRING "C++ compiler" FORCE) + else () + set(CMAKE_C_COMPILER "aarch64-linux-gnu-gcc" CACHE STRING "C compiler" FORCE) + set(CMAKE_CXX_COMPILER "aarch64-linux-gnu-g++" CACHE STRING "C++ compiler" FORCE) + + # where is the target environment located + set(CMAKE_FIND_ROOT_PATH "/usr/aarch64-linux-gnu" CACHE INTERNAL "" FORCE) + + # adjust the default behavior of the FIND_XXX() commands: + # search programs in the host environment + set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM "NEVER" CACHE INTERNAL "" FORCE) + + # search headers and libraries in the target environment + set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE "ONLY" CACHE INTERNAL "" FORCE) + set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY "ONLY" CACHE INTERNAL "" FORCE) + endif() +endfunction () + + +function (toolchain_after_project) + MESSAGE (STATUS "Toolchain: Linux-GNU-AArch64.cmake.") + # Do not set CMAKE_SYSTEM_NAME if compiling for the same OS, otherwise CMAKE_CROSSCOMPILING will be set to TRUE + #SET(CMAKE_SYSTEM_NAME "Linux" CACHE INTERNAL "" FORCE) + SET(CMAKE_SYSTEM_PROCESSOR "aarch64" CACHE INTERNAL "" FORCE) + SET(CMAKE_RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/bin-aarch64" CACHE INTERNAL "" FORCE) + set(ARCH_BITS 64 CACHE INTERNAL "" FORCE) # provide it + + if (CROSSCOMPILING_ARCH) + # possible cross-compilation foreign arch lib locations + set (lib_search_paths + "/usr/aarch64-linux-gnu/usr/lib/libmariadb3" + "/usr/aarch64-linux-gnu/usr/lib/mysql" + "/usr/aarch64-linux-gnu/usr/lib/" + CACHE STRING "Library search paths (hint)" FORCE + ) + else () + # possible native/host lib locations + set (lib_search_paths + "/usr/aarch64-linux-gnu/libmariadb3" + "/usr/aarch64-linux-gnu/mysql" + "/usr/aarch64-linux-gnu" + "/usr/lib64/mysql" + "/usr/lib64" + "/usr/lib/mysql" + "/usr/lib" + CACHE STRING "Library search paths (hint)" FORCE + ) + endif () + + toolchain_after_project_common() + + SET (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -march=armv8-a" PARENT_SCOPE) + SET (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -march=armv8-a" PARENT_SCOPE) +endfunction() + +function (toolchain_exe_stuff) + toolchain_exe_stuff_common() + + # Propagate global variables set in toolchain_exe_stuff_common to the upper scope + #SET (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${C_ARCH_OPTS}" PARENT_SCOPE) + #SET (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${CXX_ARCH_OPTS}" PARENT_SCOPE) + #SET (CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS}" PARENT_SCOPE) +endfunction() diff --git a/cmake/toolchains/Linux-GNU-native.cmake b/cmake/toolchains/Linux-GNU-native.cmake index 40a288449..b22b02163 100644 --- a/cmake/toolchains/Linux-GNU-native.cmake +++ b/cmake/toolchains/Linux-GNU-native.cmake @@ -1,24 +1,51 @@ INCLUDE("${CMAKE_CURRENT_LIST_DIR}/include/Linux-GNU_common.inc.cmake") -function (toolchain_after_project) - MESSAGE (STATUS "Toolchain: Linux-GNU-native.cmake.") - #SET(CMAKE_SYSTEM_NAME "Linux" PARENT_SCOPE) +function (toolchain_force_compiler) + if (CROSSCOMPILING_ARCH) + message(FATAL_ERROR "Can't cross-compile with a 'native' toolchain.") + endif () + + SET (CMAKE_C_COMPILER "gcc" CACHE STRING "C compiler" FORCE) + SET (CMAKE_CXX_COMPILER "g++" CACHE STRING "C++ compiler" FORCE) +endfunction () + +function (toolchain_after_project) + MESSAGE (STATUS "Toolchain: Linux-GNU-native.cmake.") + # Do not set CMAKE_SYSTEM_NAME if compiling for the same OS, otherwise CMAKE_CROSSCOMPILING will be set to TRUE + #SET(CMAKE_SYSTEM_NAME "Linux" CACHE INTERNAL "" FORCE) # target OS IF (CMAKE_SIZEOF_VOID_P EQUAL 8) - #MESSAGE (STATUS "Detected 64 bits architecture") - #SET(ARCH_BITS 64 CACHE INTERNAL) # override SET(CMAKE_RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/bin-native64" PARENT_SCOPE) ELSE () - #MESSAGE (STATUS "Detected 32 bits architecture") - #SET(ARCH_BITS 32 CACHE INTERNAL) # override SET(CMAKE_RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/bin-native32" PARENT_SCOPE) ENDIF () + # possible native/host lib locations + set (local_usr_lib_subfolders + "libmariadb3" + "mysql" + ) + foreach (local_usr_lib_subfolders subfolder) + # ARCH variable is set by CMakeGitStatus + set (local_lib_search_paths + ${local_lib_search_paths} + "/usr/${ARCH}-linux-gnu/${subfolder}" + ) + endforeach() + set (lib_search_paths + ${local_lib_search_paths} + "/usr/lib64/mysql" + "/usr/lib64" + "/usr/lib/mysql" + "/usr/lib" + CACHE STRING "Library search paths" FORCE + ) + toolchain_after_project_common() - SET (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -march=native" PARENT_SCOPE) - SET (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -march=native" PARENT_SCOPE) + SET (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -march=native -mtune=native" PARENT_SCOPE) + SET (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -march=native -mtune=native" PARENT_SCOPE) endfunction() diff --git a/cmake/toolchains/Linux-GNU-x86.cmake b/cmake/toolchains/Linux-GNU-x86.cmake index 6b32b9504..9901f44cc 100644 --- a/cmake/toolchains/Linux-GNU-x86.cmake +++ b/cmake/toolchains/Linux-GNU-x86.cmake @@ -1,16 +1,81 @@ INCLUDE("${CMAKE_CURRENT_LIST_DIR}/include/Linux-GNU_common.inc.cmake") +# For this toolchain, the operating system is the same between host and target, but target can have a different arch than host's. + + +function (toolchain_force_compiler) + if (NOT CROSSCOMPILING_ARCH) + SET (CMAKE_C_COMPILER "gcc" CACHE STRING "C compiler" FORCE) + SET (CMAKE_CXX_COMPILER "g++" CACHE STRING "C++ compiler" FORCE) + else () + message(FATAL_ERROR "Incomplete/to be tested.") # are the names/paths correct? + + set(CMAKE_C_COMPILER "i386-pc-linux-gnu-gcc" CACHE STRING "C compiler" FORCE) + set(CMAKE_CXX_COMPILER "i386-pc-linux-gnu-g++" CACHE STRING "C++ compiler" FORCE) + + # where is the target environment located + set(CMAKE_FIND_ROOT_PATH "/usr/i386-pc-linux-gnu" CACHE INTERNAL "" FORCE) + + # adjust the default behavior of the FIND_XXX() commands: + # search programs in the host environment + set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM "NEVER" CACHE INTERNAL "" FORCE) + + # search headers and libraries in the target environment + set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE "ONLY" CACHE INTERNAL "" FORCE) + set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY "ONLY" CACHE INTERNAL "" FORCE) + endif() +endfunction () + function (toolchain_after_project) MESSAGE (STATUS "Toolchain: Linux-GNU-x86.cmake.") - #SET(CMAKE_SYSTEM_NAME "Linux" PARENT_SCOPE) - SET(ARCH_BASE "x86" CACHE INTERNAL "" FORCE) # override - SET(ARCH_BITS 32 CACHE INTERNAL "" FORCE) # override - SET(ARCH "x86" CACHE INTERNAL "" FORCE) # override - SET(CMAKE_SYSTEM_PROCESSOR "${ARCH}" CACHE INTERNAL "" FORCE) + # Do not set CMAKE_SYSTEM_NAME if compiling for the same OS, otherwise CMAKE_CROSSCOMPILING will be set to TRUE + #SET(CMAKE_SYSTEM_NAME "Linux" CACHE INTERNAL "" FORCE) + SET(CMAKE_SYSTEM_PROCESSOR "x86" CACHE INTERNAL "" FORCE) + SET(CMAKE_RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/bin-x86" PARENT_SCOPE) + #set(ARCH_BITS 32 CACHE INTERNAL "" FORCE) # provide it + + if (CROSSCOMPILING_ARCH) + # possible cross-compilation foreign arch lib locations + set (lib_search_paths + "/usr/i686-linux-gnu/usr/lib/libmariadb3" + "/usr/i686-linux-gnu/usr/lib/mysql" + "/usr/i686-linux-gnu/usr/lib/" + "/usr/i386-linux-gnu/usr/lib/libmariadb3" + "/usr/i386-linux-gnu/usr/lib/mysql" + "/usr/i386-linux-gnu/usr/lib/" + CACHE STRING "Library search paths" FORCE + ) + else (CROSSCOMPILING_ARCH) + set (local_lib_search_paths + "/usr/i686-linux-gnu/libmariadb3" + "/usr/i686-linux-gnu/mysql" + "/usr/i686-linux-gnu" + "/usr/i386-linux-gnu/libmariadb3" + "/usr/i386-linux-gnu/mysql" + "/usr/i386-linux-gnu" + "/usr/lib32/mysql" + "/usr/lib32" + ) + + if ("${CMAKE_HOST_SYSTEM_PROCESSOR}" STREQUAL "x86_64") + # I'm compiling for x86 on an x86_64 host. + set (CMAKE_LIBRARY_PATH ${local_lib_search_paths} CACHE PATH "" + else () + # I'm compiling for x86 on an x86 OS (32 bits), so natively: i have libs on /usr/lib and not /usr/lib32. + set (local_extra_lib_search_paths + "/usr/lib/mysql" + "/usr/lib" + ) + endif() - toolchain_after_project_common() + set (lib_search_paths + ${local_lib_search_paths} + ${local_extra_lib_search_paths} + CACHE STRING "Library search paths (hint)" FORCE + ) + endif (CROSSCOMPILING_ARCH) - SET(CMAKE_RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/bin-x86" PARENT_SCOPE) + toolchain_after_project_common() SET (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -march=i686 -m32" PARENT_SCOPE) SET (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -march=i686 -m32" PARENT_SCOPE) diff --git a/cmake/toolchains/Linux-GNU-x86_64.cmake b/cmake/toolchains/Linux-GNU-x86_64.cmake index 1d6afcaa7..c43e54d1a 100644 --- a/cmake/toolchains/Linux-GNU-x86_64.cmake +++ b/cmake/toolchains/Linux-GNU-x86_64.cmake @@ -1,16 +1,62 @@ INCLUDE("${CMAKE_CURRENT_LIST_DIR}/include/Linux-GNU_common.inc.cmake") +# For this toolchain, the operating system is the same between host and target, but target can have a different arch than host's. + + +function (toolchain_force_compiler) + if (NOT CROSSCOMPILING_ARCH) + SET (CMAKE_C_COMPILER "gcc" CACHE STRING "C compiler" FORCE) + SET (CMAKE_CXX_COMPILER "g++" CACHE STRING "C++ compiler" FORCE) + else () + message(FATAL_ERROR "Incomplete/to be tested.") # are the names/paths correct? + + set(CMAKE_C_COMPILER "x86_64-pc-linux-gnu-gcc" CACHE STRING "C compiler" FORCE) + set(CMAKE_CXX_COMPILER "x86_64-pc-linux-gnu-g++" CACHE STRING "C++ compiler" FORCE) + + # where is the target environment located + set(CMAKE_FIND_ROOT_PATH "/usr/x86_64-pc-linux-gnu" CACHE INTERNAL "" FORCE) + + # adjust the default behavior of the FIND_XXX() commands: + # search programs in the host environment + set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM "NEVER" CACHE INTERNAL "" FORCE) + + # search headers and libraries in the target environment + set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE "ONLY" CACHE INTERNAL "" FORCE) + set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY "ONLY" CACHE INTERNAL "" FORCE) + endif() +endfunction () + function (toolchain_after_project) MESSAGE (STATUS "Toolchain: Linux-GNU-x86_64.cmake.") - #SET(CMAKE_SYSTEM_NAME "Linux" PARENT_SCOPE) - SET(ARCH_BASE "x86" CACHE INTERNAL "" FORCE) # override - SET(ARCH_BITS 64 CACHE INTERNAL "" FORCE) # override - SET(ARCH "x86_64" CACHE INTERNAL "" FORCE) # override - SET(CMAKE_SYSTEM_PROCESSOR "${ARCH}" CACHE INTERNAL "" FORCE) + # Do not set CMAKE_SYSTEM_NAME if compiling for the same OS, otherwise CMAKE_CROSSCOMPILING will be set to TRUE + #SET(CMAKE_SYSTEM_NAME "Linux" CACHE INTERNAL "" FORCE) # target os + SET(CMAKE_SYSTEM_PROCESSOR "x86_64" CACHE INTERNAL "" FORCE) # target arch + SET(CMAKE_RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/bin-x86_64" PARENT_SCOPE) + #set(ARCH_BITS 64 CACHE INTERNAL "" FORCE) # provide it - toolchain_after_project_common() + if (CROSSCOMPILING_ARCH) + # possible cross-compilation foreign arch lib locations + set (lib_search_paths + "/usr/x86_64-linux-gnu/usr/lib/libmariadb3" + "/usr/x86_64-linux-gnu/usr/lib/mysql" + "/usr/x86_64-linux-gnu/usr/lib/" + CACHE STRING "Library search paths (hint)" FORCE + ) + else () + # possible native/host lib locations + set (lib_search_paths + "/usr/x86_64-linux-gnu/libmariadb3" + "/usr/x86_64-linux-gnu/mysql" + "/usr/x86_64-linux-gnu" + "/usr/lib64/mysql" + "/usr/lib64" + "/usr/lib/mysql" + "/usr/lib" + CACHE STRING "Library search paths (hint)" FORCE + ) + endif () - SET(CMAKE_RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/bin-x86_64" PARENT_SCOPE) + toolchain_after_project_common() SET (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -march=x86-64 -m64" PARENT_SCOPE) SET (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -march=x86-64 -m64" PARENT_SCOPE) diff --git a/cmake/toolchains/OSX-AppleClang-AArch64.cmake b/cmake/toolchains/OSX-AppleClang-AArch64.cmake new file mode 100644 index 000000000..0508d1b86 --- /dev/null +++ b/cmake/toolchains/OSX-AppleClang-AArch64.cmake @@ -0,0 +1,40 @@ +INCLUDE("${CMAKE_CURRENT_LIST_DIR}/include/OSX-AppleClang_common.inc.cmake") + + +function (toolchain_force_compiler) + if (CROSSCOMPILING_ARCH) + message(FATAL_ERROR "This toolchain (as it is now) doesn't support cross-compilation.") + endif () + + SET (CMAKE_C_COMPILER "clang" CACHE STRING "C compiler" FORCE) + SET (CMAKE_CXX_COMPILER "clang++" CACHE STRING "C++ compiler" FORCE) + + # In order to enable ninja to be verbose + set(CMAKE_VERBOSE_MAKEFILE ON CACHE BOOL "ON") +endfunction () + + +function (toolchain_after_project) + MESSAGE (STATUS "Toolchain: OSX-AppleClang-AArch64.cmake.") + # Do not set CMAKE_SYSTEM_NAME if compiling for the same OS, otherwise CMAKE_CROSSCOMPILING will be set to TRUE + #SET(CMAKE_SYSTEM_NAME "Darwin" CACHE INTERNAL "" FORCE) + SET(CMAKE_SYSTEM_PROCESSOR "aarch64" CACHE INTERNAL "" FORCE) + SET(CMAKE_RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/bin-aarch64" PARENT_SCOPE) + #set(ARCH_BITS 64 CACHE INTERNAL "" FORCE) # provide it + + toolchain_after_project_common() + + # Official Clang doesn't support -march=native for ARM arch, but Apple Clang does... + SET (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} --target=aarch64-apple-darwin" PARENT_SCOPE) + SET (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} --target=aarch64-apple-darwin" PARENT_SCOPE) +endfunction() + + +function (toolchain_exe_stuff) + toolchain_exe_stuff_common() + + # Propagate global variables set in toolchain_exe_stuff_common to the upper scope + #SET (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${C_ARCH_OPTS}" PARENT_SCOPE) + #SET (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${CXX_ARCH_OPTS}" PARENT_SCOPE) + #SET (CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS}" PARENT_SCOPE) +endfunction() diff --git a/cmake/toolchains/OSX-AppleClang-native.cmake b/cmake/toolchains/OSX-AppleClang-native.cmake index 2960b5ba5..e9d80cecf 100644 --- a/cmake/toolchains/OSX-AppleClang-native.cmake +++ b/cmake/toolchains/OSX-AppleClang-native.cmake @@ -1,23 +1,35 @@ INCLUDE("${CMAKE_CURRENT_LIST_DIR}/include/OSX-AppleClang_common.inc.cmake") + +function (toolchain_force_compiler) + if (CROSSCOMPILING_ARCH) + message(FATAL_ERROR "Can't cross-compile with a 'native' toolchain.") + endif () + + SET (CMAKE_C_COMPILER "clang" CACHE STRING "C compiler" FORCE) + SET (CMAKE_CXX_COMPILER "clang++" CACHE STRING "C++ compiler" FORCE) + + # In order to enable ninja to be verbose + set(CMAKE_VERBOSE_MAKEFILE ON CACHE BOOL "ON") +endfunction () + + function (toolchain_after_project) MESSAGE (STATUS "Toolchain: OSX-AppleClang-native.cmake.") - #SET(CMAKE_SYSTEM_NAME "OSX" PARENT_SCOPE) # Darwin + # Do not set CMAKE_SYSTEM_NAME if compiling for the same OS, otherwise CMAKE_CROSSCOMPILING will be set to TRUE + #SET(CMAKE_SYSTEM_NAME "Darwin" CACHE INTERNAL "" FORCE) + IF (CMAKE_SIZEOF_VOID_P EQUAL 8) + SET(CMAKE_RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/bin-native64" PARENT_SCOPE) + ELSE () + SET(CMAKE_RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/bin-native32" PARENT_SCOPE) + ENDIF () toolchain_after_project_common() - IF (CMAKE_SIZEOF_VOID_P EQUAL 8) - #MESSAGE (STATUS "Detected 64 bits architecture") - #SET(ARCH_BITS 64 CACHE INTERNAL) # override - SET(CMAKE_RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/bin-native64" PARENT_SCOPE) - ELSE (CMAKE_SIZEOF_VOID_P EQUAL 8) - #MESSAGE (STATUS "Detected 32 bits architecture") - #SET(ARCH_BITS 32 CACHE INTERNAL) # override - SET(CMAKE_RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/bin-native32" PARENT_SCOPE) - ENDIF (CMAKE_SIZEOF_VOID_P EQUAL 8) - - SET (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -march=native" PARENT_SCOPE) - SET (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -march=native" PARENT_SCOPE) + # Official Clang doesn't support -march=native for ARM arch, but Apple Clang does... + # Otherwise, mind this for ARM crossbuilding -march=apple-m1' + SET (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -march=native -mcpu=native" PARENT_SCOPE) + SET (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -march=native -mcpu=native" PARENT_SCOPE) endfunction() diff --git a/cmake/toolchains/OSX-AppleClang-x86_64.cmake b/cmake/toolchains/OSX-AppleClang-x86_64.cmake index a21f849ef..17f71e3ab 100644 --- a/cmake/toolchains/OSX-AppleClang-x86_64.cmake +++ b/cmake/toolchains/OSX-AppleClang-x86_64.cmake @@ -1,17 +1,30 @@ INCLUDE("${CMAKE_CURRENT_LIST_DIR}/include/OSX-AppleClang_common.inc.cmake") +# UNTESTED ! + +function (toolchain_force_compiler) + if (CROSSCOMPILE_ARCH) + message(FATAL_ERROR "This toolchain (as it is now) doesn't support cross-compilation.") + endif () + + SET (CMAKE_C_COMPILER "clang" CACHE STRING "C compiler" FORCE) + SET (CMAKE_CXX_COMPILER "clang++" CACHE STRING "C++ compiler" FORCE) + + # In order to enable ninja to be verbose + set(CMAKE_VERBOSE_MAKEFILE ON CACHE BOOL "ON") +endfunction () + function (toolchain_after_project) MESSAGE (STATUS "Toolchain: OSX-AppleClang-x86_64.cmake.") - #SET(CMAKE_SYSTEM_NAME "OSX" PARENT_SCOPE) # Darwin - SET(ARCH_BASE "x86" CACHE INTERNAL "" FORCE) # override - SET(ARCH_BITS 64 CACHE INTERNAL "" FORCE) # override - SET(ARCH "x86_64" CACHE INTERNAL "" FORCE) # override - SET(CMAKE_SYSTEM_PROCESSOR "${ARCH}" CACHE INTERNAL "" FORCE) + # Do not set CMAKE_SYSTEM_NAME if compiling for the same OS, otherwise CMAKE_CROSSCOMPILING will be set to TRUE + #SET(CMAKE_SYSTEM_NAME "Darwin" CACHE INTERNAL "" FORCE) + SET(CMAKE_SYSTEM_PROCESSOR "x86_64" CACHE INTERNAL "" FORCE) + SET(CMAKE_RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/bin-x86_64" PARENT_SCOPE) + #set(ARCH_BITS 64 CACHE INTERNAL "" FORCE) # provide it toolchain_after_project_common() - SET(CMAKE_RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/bin-x86_64" PARENT_SCOPE) - + # -target=-x86_64-apple-darwin ? SET (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -march=x86-64 -m64" PARENT_SCOPE) SET (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -march=x86-64 -m64" PARENT_SCOPE) endfunction() diff --git a/cmake/toolchains/Windows-Clang-native.cmake b/cmake/toolchains/Windows-Clang-native.cmake index 298fd8449..3121a48e0 100644 --- a/cmake/toolchains/Windows-Clang-native.cmake +++ b/cmake/toolchains/Windows-Clang-native.cmake @@ -1,23 +1,37 @@ INCLUDE("${CMAKE_CURRENT_LIST_DIR}/include/Windows-Clang_common.inc.cmake") -function (toolchain_after_project) - MESSAGE (STATUS "Toolchain: Windows-Clang-native.cmake.") - #SET(CMAKE_SYSTEM_NAME "Windows" PARENT_SCOPE) +function (toolchain_force_compiler) + if (CROSSCOMPILING_ARCH) + message(FATAL_ERROR "Can't cross-compile with a 'native' toolchain.") + endif () - toolchain_after_project_common() # To enable RC language, to compile Windows Resource files + SET (CMAKE_C_COMPILER "clang" CACHE STRING "C compiler" FORCE) + SET (CMAKE_CXX_COMPILER "clang++" CACHE STRING "C++ compiler" FORCE) + + # In order to enable ninja to be verbose + #set(CMAKE_VERBOSE_MAKEFILE ON CACHE BOOL "ON") + + IF (CLANG_USE_GCC_LINKER) + # Not working, see CLANG_USE_GCC_LINKER option. Use MSVC. + SET (CLANG_VENDOR "gnu" PARENT_SCOPE) + ELSE () + SET (CLANG_VENDOR "msvc" PARENT_SCOPE) + ENDIF () +endfunction () + +function (toolchain_after_project) + MESSAGE (STATUS "Toolchain: Windows-Clang-native.cmake.") + # Do not set CMAKE_SYSTEM_NAME if compiling for the same OS, otherwise CMAKE_CROSSCOMPILING will be set to TRUE + #SET(CMAKE_SYSTEM_NAME "Windows" INTERNAL "" FORCE) IF (CMAKE_SIZEOF_VOID_P EQUAL 8) - #MESSAGE (STATUS "Detected 64 bits architecture") - #SET(ARCH_BITS 64 CACHE INTERNAL) # override SET(CMAKE_RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/bin-native64" PARENT_SCOPE) - LINK_DIRECTORIES ("lib/_bin/x86_64/mariadb/") - ELSE (CMAKE_SIZEOF_VOID_P EQUAL 8) - MESSAGE (STATUS "Detected 32 bits architecture") - #SET(ARCH_BITS 32 CACHE INTERNAL) # override - #SET(CMAKE_RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/bin-native32" PARENT_SCOPE) - LINK_DIRECTORIES ("lib/_bin/x86/mariadb/") - ENDIF (CMAKE_SIZEOF_VOID_P EQUAL 8) + ELSE () + SET(CMAKE_RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/bin-native32" PARENT_SCOPE) + ENDIF () + + toolchain_after_project_common() # To enable RC language, to compile Windows Resource files #SET (CLANG_TARGET "--target=x86_64-pc-windows-${CLANG_VENDOR}") #SET (C_ARCH_OPTS "-march=native ${CLANG_TARGET}") @@ -25,8 +39,9 @@ function (toolchain_after_project) #SET (RC_FLAGS "${CLANG_TARGET}") # TODO: fix the target, maybe using CMAKE_HOST_SYSTEM_PROCESSOR ? - SET (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -march=native" PARENT_SCOPE) - SET (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -march=native" PARENT_SCOPE) + LINK_DIRECTORIES ("lib/_bin/{ARCH}/mariadb/") + SET (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -march=native -mtune=native" PARENT_SCOPE) + SET (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -march=native -mtune=native" PARENT_SCOPE) endfunction() diff --git a/cmake/toolchains/Windows-Clang-x86.cmake b/cmake/toolchains/Windows-Clang-x86.cmake index 3bf957ce5..d874dabae 100644 --- a/cmake/toolchains/Windows-Clang-x86.cmake +++ b/cmake/toolchains/Windows-Clang-x86.cmake @@ -1,18 +1,37 @@ INCLUDE("${CMAKE_CURRENT_LIST_DIR}/include/Windows-Clang_common.inc.cmake") + +function (toolchain_force_compiler) + if (CROSSCOMPILE_ARCH) + message(FATAL_ERROR "This toolchain (as it is now) doesn't support cross-compilation.") + endif () + + SET (CMAKE_C_COMPILER "clang" CACHE STRING "C compiler" FORCE) + SET (CMAKE_CXX_COMPILER "clang++" CACHE STRING "C++ compiler" FORCE) + + # In order to enable ninja to be verbose + #set(CMAKE_VERBOSE_MAKEFILE ON CACHE BOOL "ON") + + IF (CLANG_USE_GCC_LINKER) + # Not working, see CLANG_USE_GCC_LINKER option. Use MSVC. + SET (CLANG_VENDOR "gnu" PARENT_SCOPE) + ELSE () + SET (CLANG_VENDOR "msvc" PARENT_SCOPE) + ENDIF () +endfunction () + + function (toolchain_after_project) MESSAGE (STATUS "Toolchain: Windows-Clang-x86.cmake.") - #SET(CMAKE_SYSTEM_NAME "Windows" PARENT_SCOPE) - SET(ARCH_BASE "x86" CACHE INTERNAL "" FORCE) # override - SET(ARCH_BITS 32 CACHE INTERNAL "" FORCE) # override - SET(ARCH "x86" CACHE INTERNAL "" FORCE) # override - SET(CMAKE_SYSTEM_PROCESSOR "${ARCH}" CACHE INTERNAL "" FORCE) + # Do not set CMAKE_SYSTEM_NAME if compiling for the same OS, otherwise CMAKE_CROSSCOMPILING will be set to TRUE + #SET(CMAKE_SYSTEM_NAME "Windows" CACHE INTERNAL "" FORCE) + SET(CMAKE_SYSTEM_PROCESSOR "x86" CACHE INTERNAL "" FORCE) + SET(CMAKE_RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/bin-x86" PARENT_SCOPE) + #set(ARCH_BITS 32 CACHE INTERNAL "" FORCE) # provide it toolchain_after_project_common() # To enable RC language, to compile Windows Resource files - LINK_DIRECTORIES ("lib/_bin/x86/mariadb/") - SET(CMAKE_RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/bin-x86" PARENT_SCOPE) - + LINK_DIRECTORIES ("lib/_bin/x86/mariadb/") SET (CLANG_TARGET "--target=i686-pc-windows-${CLANG_VENDOR}") SET (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -march=i686 -m32 ${CLANG_TARGET}" PARENT_SCOPE) SET (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -march=i686 -m32 ${CLANG_TARGET}" PARENT_SCOPE) diff --git a/cmake/toolchains/Windows-Clang-x86_64.cmake b/cmake/toolchains/Windows-Clang-x86_64.cmake index 7d360d96d..620a4572c 100644 --- a/cmake/toolchains/Windows-Clang-x86_64.cmake +++ b/cmake/toolchains/Windows-Clang-x86_64.cmake @@ -1,18 +1,37 @@ INCLUDE("${CMAKE_CURRENT_LIST_DIR}/include/Windows-Clang_common.inc.cmake") + +function (toolchain_force_compiler) + if (CROSSCOMPILE_ARCH) + message(FATAL_ERROR "This toolchain (as it is now) doesn't support cross-compilation.") + endif () + + SET (CMAKE_C_COMPILER "clang" CACHE STRING "C compiler" FORCE) + SET (CMAKE_CXX_COMPILER "clang++" CACHE STRING "C++ compiler" FORCE) + + # In order to enable ninja to be verbose + #set(CMAKE_VERBOSE_MAKEFILE ON CACHE BOOL "ON") + + IF (CLANG_USE_GCC_LINKER) + # Not working, see CLANG_USE_GCC_LINKER option. Use MSVC. + SET (CLANG_VENDOR "gnu" PARENT_SCOPE) + ELSE () + SET (CLANG_VENDOR "msvc" PARENT_SCOPE) + ENDIF () +endfunction () + + function (toolchain_after_project) MESSAGE (STATUS "Toolchain: Windows-Clang-x86_64.cmake.") - #SET(CMAKE_SYSTEM_NAME "Windows" PARENT_SCOPE) - SET(ARCH_BASE "x86" CACHE INTERNAL "" FORCE) # override - SET(ARCH_BITS 64 CACHE INTERNAL "" FORCE) # override - SET(ARCH "x86_64" CACHE INTERNAL "" FORCE) # override - SET(CMAKE_SYSTEM_PROCESSOR "${ARCH}" CACHE INTERNAL "" FORCE) + # Do not set CMAKE_SYSTEM_NAME if compiling for the same OS, otherwise CMAKE_CROSSCOMPILING will be set to TRUE + #SET(CMAKE_SYSTEM_NAME "Windows" CACHE INTERNAL "" FORCE) + SET(CMAKE_SYSTEM_PROCESSOR "x86_64" CACHE INTERNAL "" FORCE) + SET(CMAKE_RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/bin-x86_64" PARENT_SCOPE) + #set(ARCH_BITS 64 CACHE INTERNAL "" FORCE) # provide it toolchain_after_project_common() # To enable RC language, to compile Windows Resource files - LINK_DIRECTORIES ("lib/_bin/x86_64/mariadb/") - SET(CMAKE_RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/bin-x86_64" PARENT_SCOPE) - + LINK_DIRECTORIES ("lib/_bin/x86_64/mariadb/") SET (CLANG_TARGET "--target=x86_64-pc-windows-${CLANG_VENDOR}") SET (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -march=x86-64 -m64 ${CLANG_TARGET}" PARENT_SCOPE) SET (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -march=x86-64 -m64 ${CLANG_TARGET}" PARENT_SCOPE) diff --git a/cmake/toolchains/Windows-GNU-native.cmake b/cmake/toolchains/Windows-GNU-native.cmake index 84eb79e36..443ef04ad 100644 --- a/cmake/toolchains/Windows-GNU-native.cmake +++ b/cmake/toolchains/Windows-GNU-native.cmake @@ -1,24 +1,32 @@ INCLUDE("${CMAKE_CURRENT_LIST_DIR}/include/Windows-GNU_common.inc.cmake") -function (toolchain_after_project) - MESSAGE (STATUS "Toolchain: Windows-GNU-native.cmake.") - #SET(CMAKE_SYSTEM_NAME "Windows" PARENT_SCOPE) +function (toolchain_force_compiler) + if (CROSSCOMPILE_ARCH) + message(FATAL_ERROR "Can't cross-compile with a 'native' toolchain.") + endif () + + SET (CMAKE_C_COMPILER "gcc" CACHE STRING "C compiler" FORCE) + SET (CMAKE_CXX_COMPILER "g++" CACHE STRING "C++ compiler" FORCE) + + # In order to enable ninja to be verbose + #set(CMAKE_VERBOSE_MAKEFILE ON CACHE BOOL "ON") +endfunction () + +function (toolchain_after_project) + MESSAGE (STATUS "Toolchain: Windows-GNU-native.cmake.") + # Do not set CMAKE_SYSTEM_NAME if compiling for the same OS, otherwise CMAKE_CROSSCOMPILING will be set to TRUE + #SET(CMAKE_SYSTEM_NAME "Windows" CACHE INTERNAL "" FORCE) IF (CMAKE_SIZEOF_VOID_P EQUAL 8) - #MESSAGE (STATUS "Detected 64 bits architecture") - #SET(ARCH_BITS 64 CACHE INTERNAL) # override SET(CMAKE_RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/bin-native64" PARENT_SCOPE) - LINK_DIRECTORIES ("lib/_bin/x86_64/mariadb/") - ELSE (CMAKE_SIZEOF_VOID_P EQUAL 8) - #MESSAGE (STATUS "Detected 32 bits architecture") - #SET(ARCH_BITS 32 CACHE INTERNAL) # override + ELSE () SET(CMAKE_RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/bin-native32" PARENT_SCOPE) - LINK_DIRECTORIES ("lib/_bin/x86/mariadb/") - ENDIF (CMAKE_SIZEOF_VOID_P EQUAL 8) + ENDIF () toolchain_after_project_common() # To enable RC language, to compile Windows Resource files + LINK_DIRECTORIES ("lib/_bin/${ARCH}/mariadb/") SET (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -march=native" PARENT_SCOPE) SET (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -march=native" PARENT_SCOPE) endfunction() diff --git a/cmake/toolchains/Windows-GNU-x86.cmake b/cmake/toolchains/Windows-GNU-x86.cmake index 28f3a1aa7..e5ecdc995 100644 --- a/cmake/toolchains/Windows-GNU-x86.cmake +++ b/cmake/toolchains/Windows-GNU-x86.cmake @@ -1,18 +1,30 @@ INCLUDE("${CMAKE_CURRENT_LIST_DIR}/include/Windows-GNU_common.inc.cmake") + +function (toolchain_force_compiler) + if (CROSSCOMPILE_ARCH) + message(FATAL_ERROR "This toolchain (as it is now) doesn't support cross-compilation.") + endif () + + SET (CMAKE_C_COMPILER "gcc" CACHE STRING "C compiler" FORCE) + SET (CMAKE_CXX_COMPILER "g++" CACHE STRING "C++ compiler" FORCE) + + # In order to enable ninja to be verbose + #set(CMAKE_VERBOSE_MAKEFILE ON CACHE BOOL "ON") +endfunction () + + function (toolchain_after_project) MESSAGE (STATUS "Toolchain: Windows-GNU-x86.cmake.") - #SET(CMAKE_SYSTEM_NAME "Windows" PARENT_SCOPE) - SET(ARCH_BASE "x86" CACHE INTERNAL "" FORCE) # override - SET(ARCH_BITS 32 CACHE INTERNAL "" FORCE) # override - SET(ARCH "x86" CACHE INTERNAL "" FORCE) # override - SET(CMAKE_SYSTEM_PROCESSOR "${ARCH}" CACHE INTERNAL "" FORCE) + # Do not set CMAKE_SYSTEM_NAME if compiling for the same OS, otherwise CMAKE_CROSSCOMPILING will be set to TRUE + #SET(CMAKE_SYSTEM_NAME "Windows" CACHE INTERNAL "" FORCE) + SET(CMAKE_SYSTEM_PROCESSOR "x86" CACHE INTERNAL "" FORCE) + SET(CMAKE_RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/bin_x86" PARENT_SCOPE) + #set(ARCH_BITS 32 CACHE INTERNAL "" FORCE) # provide it toolchain_after_project_common() # Also to enable RC language, to compile Windows Resource files LINK_DIRECTORIES ("lib/_bin/x86/mariadb/") - SET(CMAKE_RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/bin_x86" PARENT_SCOPE) - SET (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -march=i686 -m32" PARENT_SCOPE) SET (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -march=i686 -m32" PARENT_SCOPE) SET (RC_FLAGS "--target=pe-i386" PARENT_SCOPE) diff --git a/cmake/toolchains/Windows-GNU-x86_64.cmake b/cmake/toolchains/Windows-GNU-x86_64.cmake index 2c1ce7b94..bcaf199b1 100644 --- a/cmake/toolchains/Windows-GNU-x86_64.cmake +++ b/cmake/toolchains/Windows-GNU-x86_64.cmake @@ -1,18 +1,30 @@ INCLUDE("${CMAKE_CURRENT_LIST_DIR}/include/Windows-GNU_common.inc.cmake") + +function (toolchain_force_compiler) + if (CROSSCOMPILE_ARCH) + message(FATAL_ERROR "This toolchain (as it is now) doesn't support cross-compilation.") + endif () + + SET (CMAKE_C_COMPILER "gcc" CACHE STRING "C compiler" FORCE) + SET (CMAKE_CXX_COMPILER "g++" CACHE STRING "C++ compiler" FORCE) + + # In order to enable ninja to be verbose + #set(CMAKE_VERBOSE_MAKEFILE ON CACHE BOOL "ON") +endfunction () + + function (toolchain_after_project) MESSAGE (STATUS "Toolchain: Windows-GNU-x86_64.cmake.") - #SET(CMAKE_SYSTEM_NAME "Windows" PARENT_SCOPE) - SET(ARCH_BASE "x86" CACHE INTERNAL "" FORCE) # override - SET(ARCH_BITS 64 CACHE INTERNAL "" FORCE) # override - SET(ARCH "x86_64" CACHE INTERNAL "" FORCE) # override - SET(CMAKE_SYSTEM_PROCESSOR "${ARCH}" CACHE INTERNAL "" FORCE) + # Do not set CMAKE_SYSTEM_NAME if compiling for the same OS, otherwise CMAKE_CROSSCOMPILING will be set to TRUE + #SET(CMAKE_SYSTEM_NAME "Windows" CACHE INTERNAL "" FORCE) + SET(CMAKE_SYSTEM_PROCESSOR "x86_64" CACHE INTERNAL "" FORCE) + SET(CMAKE_RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/bin-x86_64" PARENT_SCOPE) + #set(ARCH_BITS 64 CACHE INTERNAL "" FORCE) # provide it toolchain_after_project_common() # To enable RC language, to compile Windows Resource files LINK_DIRECTORIES ("lib/_bin/x86_64/mariadb/") - SET(CMAKE_RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/bin-x86_64" PARENT_SCOPE) - SET (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -march=x86-64 -m64" PARENT_SCOPE) SET (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -march=x86-64 -m64" PARENT_SCOPE) SET (RC_FLAGS "--target=pe-x86-64" PARENT_SCOPE) diff --git a/cmake/toolchains/Windows-MSVC.cmake b/cmake/toolchains/Windows-MSVC.cmake index df29d25d6..72bbab297 100644 --- a/cmake/toolchains/Windows-MSVC.cmake +++ b/cmake/toolchains/Windows-MSVC.cmake @@ -6,31 +6,21 @@ function (toolchain_force_compiler) #SET (CMAKE_CXX_COMPILER "...cl.exe" CACHE STRING "C++ compiler" FORCE) MESSAGE (STATUS "Toolchain: Windows-MSVC.cmake.") - #SET(CMAKE_SYSTEM_NAME "Windows" PARENT_SCOPE) + #SET(CMAKE_SYSTEM_NAME "Windows" CACHE INTERNAL "" FORCE) endfunction () function (toolchain_after_project) -#[[ - IF (CMAKE_SIZEOF_VOID_P EQUAL 8) - MESSAGE (STATUS "Detected 64 bits architecture") - SET(ARCH_BITS 64 CACHE INTERNAL "" FORCE) # override - ELSE () - MESSAGE (STATUS "Detected 32 bits architecture") - SET(ARCH_BITS 32 CACHE INTERNAL "" FORCE) # override - ENDIF () -]] if (NOT CMAKE_VS_PLATFORM_NAME) set (CMAKE_VS_PLATFORM_NAME "${CMAKE_VS_PLATFORM_NAME_DEFAULT}") endif () if (${CMAKE_VS_PLATFORM_NAME} STREQUAL "Win32") - set (CMAKE_SYSTEM_PROCESSOR "x86" CACHE INTERNAL "" FORCE) + set (CMAKE_SYSTEM_PROCESSOR "x86" CACHE INTERNAL "" FORCE) endif () set (CMAKE_SYSTEM_PROCESSOR "${CMAKE_VS_PLATFORM_NAME}" CACHE INTERNAL "" FORCE) include ("${CMAKE_SOURCE_DIR}/cmake/CMakeDetectArch.cmake") - MESSAGE (STATUS "Target Arch: ${ARCH}") MESSAGE (STATUS "Generating for MSVC platform ${CMAKE_VS_PLATFORM_NAME}.") endfunction() diff --git a/cmake/toolchains/include/Linux-Clang_common.inc.cmake b/cmake/toolchains/include/Linux-Clang_common.inc.cmake index 0cf3452a2..b5be67004 100644 --- a/cmake/toolchains/include/Linux-Clang_common.inc.cmake +++ b/cmake/toolchains/include/Linux-Clang_common.inc.cmake @@ -1,14 +1,10 @@ SET (TOOLCHAIN_LOADED 1) -function (toolchain_force_compiler) - SET (CMAKE_C_COMPILER "clang" CACHE STRING "C compiler" FORCE) - SET (CMAKE_CXX_COMPILER "clang++" CACHE STRING "C++ compiler" FORCE) -endfunction () - function (toolchain_after_project_common) include ("${CMAKE_SOURCE_DIR}/cmake/CMakeDetectArch.cmake") endfunction () + function (toolchain_exe_stuff_common) #-- Find libraries to be linked to. @@ -20,29 +16,11 @@ function (toolchain_exe_stuff_common) dl ) FOREACH (LIB_NAME ${LIBS_LINK_LIST}) - IF (${ARCH_BITS} EQUAL 64) - FIND_LIBRARY( - LIB_${LIB_NAME}_WITH_PATH ${LIB_NAME} - HINT - "/usr/lib/x86_64-linux-gnu/libmariadb3" - "/usr/lib/x86_64-linux-gnu/mysql" - "/usr/lib/x86_64-linux-gnu" - "/usr/lib64/mysql" - "/usr/lib64" - "/usr/lib/mysql" - "/usr/lib" - ) - ELSE () - FIND_LIBRARY( - LIB_${LIB_NAME}_WITH_PATH ${LIB_NAME} - HINT - "/usr/lib/i386-linux-gnu/libmariadb3" - "/usr/lib/i386-linux-gnu/mysql" - "/usr/lib/i386-linux-gnu" - "/usr/lib/mysql" - "/usr/lib" - ) - ENDIF () + FIND_LIBRARY( + LIB_${LIB_NAME}_WITH_PATH ${LIB_NAME} + PATH ${lib_search_paths} + ) + MESSAGE (STATUS "Library ${LIB_NAME}: ${LIB_${LIB_NAME}_WITH_PATH}") ENDFOREACH () @@ -52,6 +30,7 @@ function (toolchain_exe_stuff_common) # From https://clang.llvm.org/docs/ClangCommandLineReference.html # -static-libsan Statically link the sanitizer runtime (Not supported for ASan, TSan or UBSan on darwin) + #string(REPLACE ";" " " CXX_FLAGS_EXTRA "${CXX_FLAGS_EXTRA}") IF (${USE_ASAN}) SET (CXX_FLAGS_EXTRA ${CXX_FLAGS_EXTRA} # -fsanitize=safe-stack # Can't be used with asan! @@ -117,6 +96,7 @@ See comments in the toolchain and: https://github.com/google/sanitizers/wiki/Mem -pipe -ffast-math ) set (cxx_compiler_options_common ${cxx_local_opts_warnings} ${cxx_local_opts} ${CXX_FLAGS_EXTRA}) + #separate_arguments(cxx_compiler_options_common) # GCC flags not supported by clang: # Warnings: "-Wno-nonnull-compare -Wno-maybe-uninitialized" diff --git a/cmake/toolchains/include/Linux-GNU_common.inc.cmake b/cmake/toolchains/include/Linux-GNU_common.inc.cmake index bdc27ced5..cbd362cfe 100644 --- a/cmake/toolchains/include/Linux-GNU_common.inc.cmake +++ b/cmake/toolchains/include/Linux-GNU_common.inc.cmake @@ -1,14 +1,10 @@ SET (TOOLCHAIN_LOADED 1) -function (toolchain_force_compiler) - SET (CMAKE_C_COMPILER "gcc" CACHE STRING "C compiler" FORCE) - SET (CMAKE_CXX_COMPILER "g++" CACHE STRING "C++ compiler" FORCE) -endfunction () - function (toolchain_after_project_common) include ("${CMAKE_SOURCE_DIR}/cmake/CMakeDetectArch.cmake") endfunction () + function (toolchain_exe_stuff_common) #-- Find libraries to be linked to. @@ -20,29 +16,11 @@ function (toolchain_exe_stuff_common) dl ) FOREACH (LIB_NAME ${LIBS_LINK_LIST}) - IF (${ARCH_BITS} EQUAL 64) - FIND_LIBRARY( - LIB_${LIB_NAME}_WITH_PATH ${LIB_NAME} - HINT - "/usr/lib/x86_64-linux-gnu/libmariadb3" - "/usr/lib/x86_64-linux-gnu/mysql" - "/usr/lib/x86_64-linux-gnu" - "/usr/lib64/mysql" - "/usr/lib64" - "/usr/lib/mysql" - "/usr/lib" - ) - ELSE () - FIND_LIBRARY( - LIB_${LIB_NAME}_WITH_PATH ${LIB_NAME} - HINT - "/usr/lib/i386-linux-gnu/libmariadb3" - "/usr/lib/i386-linux-gnu/mysql" - "/usr/lib/i386-linux-gnu" - "/usr/lib/mysql" - "/usr/lib" - ) - ENDIF () + FIND_LIBRARY( + LIB_${LIB_NAME}_WITH_PATH ${LIB_NAME} + PATH ${lib_search_paths} + ) + MESSAGE (STATUS "Library ${LIB_NAME}: ${LIB_${LIB_NAME}_WITH_PATH}") ENDFOREACH () diff --git a/cmake/toolchains/include/OSX-AppleClang_common.inc.cmake b/cmake/toolchains/include/OSX-AppleClang_common.inc.cmake index d37042fc8..8d2ecedb3 100644 --- a/cmake/toolchains/include/OSX-AppleClang_common.inc.cmake +++ b/cmake/toolchains/include/OSX-AppleClang_common.inc.cmake @@ -1,17 +1,11 @@ SET (TOOLCHAIN_LOADED 1) -function (toolchain_force_compiler) - SET (CMAKE_C_COMPILER "clang" CACHE STRING "C compiler" FORCE) - SET (CMAKE_CXX_COMPILER "clang++" CACHE STRING "C++ compiler" FORCE) - - # In order to enable ninja to be verbose - set(CMAKE_VERBOSE_MAKEFILE ON CACHE BOOL "ON") -endfunction () function (toolchain_after_project_common) include ("${CMAKE_SOURCE_DIR}/cmake/CMakeDetectArch.cmake") endfunction () + function (toolchain_exe_stuff_common) #-- Find libraries to be linked to. @@ -30,6 +24,7 @@ function (toolchain_exe_stuff_common) "/opt/homebrew/var/mariadb-connector-c/lib/mariadb" "/opt/homebrew/lib/mariadb" ) + MESSAGE (STATUS "Library ${LIB_NAME}: ${LIB_${LIB_NAME}_WITH_PATH}") ENDFOREACH () diff --git a/cmake/toolchains/include/Windows-Clang_common.inc.cmake b/cmake/toolchains/include/Windows-Clang_common.inc.cmake index bdb48a40b..a0233ae4b 100644 --- a/cmake/toolchains/include/Windows-Clang_common.inc.cmake +++ b/cmake/toolchains/include/Windows-Clang_common.inc.cmake @@ -1,19 +1,9 @@ SET (TOOLCHAIN_LOADED 1) -SET (CLANG_USE_GCC_LINKER false CACHE BOOL "NOT CURRENTLY WORKING. By default, Clang requires MSVC (Microsoft's) linker. With this flag, it can be asked to use MinGW-GCC's one.") - - -function (toolchain_force_compiler) - SET (CMAKE_C_COMPILER "clang" CACHE STRING "C compiler" FORCE) - SET (CMAKE_CXX_COMPILER "clang++" CACHE STRING "C++ compiler" FORCE) - - IF (CLANG_USE_GCC_LINKER) - # Not working, see above. Use MSVC. - SET (CLANG_VENDOR "gnu" PARENT_SCOPE) - ELSE () - SET (CLANG_VENDOR "msvc" PARENT_SCOPE) - ENDIF () -endfunction () +option (CLANG_USE_GCC_LINKER + "NOT CURRENTLY WORKING. By default, Clang requires MSVC (Microsoft's) linker. With this flag, it can be asked to use MinGW-GCC's one." + FALSE +) function (toolchain_after_project_common) diff --git a/cmake/toolchains/include/Windows-GNU_common.inc.cmake b/cmake/toolchains/include/Windows-GNU_common.inc.cmake index dad1e3a26..4912acc8e 100644 --- a/cmake/toolchains/include/Windows-GNU_common.inc.cmake +++ b/cmake/toolchains/include/Windows-GNU_common.inc.cmake @@ -1,10 +1,5 @@ SET (TOOLCHAIN_LOADED 1) -function (toolchain_force_compiler) - SET (CMAKE_C_COMPILER "gcc" CACHE STRING "C compiler" FORCE) - SET (CMAKE_CXX_COMPILER "g++" CACHE STRING "C++ compiler" FORCE) -endfunction () - function (toolchain_after_project_common) ENABLE_LANGUAGE(RC) diff --git a/src/common/sphere_library/stypecast.h b/src/common/sphere_library/stypecast.h index 3ace00813..bce210d15 100644 --- a/src/common/sphere_library/stypecast.h +++ b/src/common/sphere_library/stypecast.h @@ -1,7 +1,7 @@ #ifndef _INC_STYPECAST_H #define _INC_STYPECAST_H -//#include +#include #include #include @@ -194,17 +194,17 @@ auto n16_narrow8_checked(const T a) [[nodiscard]] constexpr uint32 usize_narrow32(const size_t a) noexcept { - // This doesn't work for some reason, n64_narrow32 static_asserts will be evaluated and fail on 32 bits compilation + // This doesn't work because n64_narrow32 static_asserts will be evaluated and fail on 32 bits compilation. /* if constexpr (sizeof(size_t) == 8) return n64_narrow32(a); else return a; */ -#if UINTPTR_MAX == ULONG_LONG_MAX +#if SIZE_MAX == ULLONG_MAX // ptr size is 8 -> 64 bits return n64_narrow32(a); -#elif UINTPTR_MAX == UINT_MAX +#elif SIZE_MAX == UINT_MAX // ptr size is 4 -> 32 bits return a; #else From 89c192dce20d7031492e7d6c9525f96fd2d678c8 Mon Sep 17 00:00:00 2001 From: cbnolok Date: Mon, 26 Aug 2024 16:32:41 +0200 Subject: [PATCH 06/86] Fixed localtime on MacOS, added safe_gmtime for thread-safety --- src/common/sphere_library/CSTime.cpp | 40 +++++++++++++++++----------- 1 file changed, 25 insertions(+), 15 deletions(-) diff --git a/src/common/sphere_library/CSTime.cpp b/src/common/sphere_library/CSTime.cpp index 54c6dc423..b2d28dc8a 100644 --- a/src/common/sphere_library/CSTime.cpp +++ b/src/common/sphere_library/CSTime.cpp @@ -171,7 +171,7 @@ static std::tm safe_localtime(const time_t t) noexcept // Standard C localtime is not thread-safe. We need alternatives. // https://stackoverflow.com/questions/38034033/c-localtime-this-function-or-variable-may-be-unsafe -#if defined(__unix__) +#if defined(__unix__) || defined(__APPLE__) || defined(_POSIX_VERSION) localtime_r(&t, &atm); #elif defined(_MSC_VER) localtime_s(&atm, &t); @@ -212,6 +212,26 @@ static std::tm safe_localtime(const time_t t) noexcept return atm; } +static std::tm safe_gmtime(const time_t t) noexcept +{ + std::tm atm {}; + + // gmtime is in Coordinated Universal Time (UTC), while localtime is in your timezone + // Standard C gmtime is not thread-safe. We need alternatives. + +#if defined(__unix__) || defined(__APPLE__) || defined(_POSIX_VERSION) + gmtime_r(&t, &atm); +#elif defined(_MSC_VER) + gmtime_s(&atm, &t); +#elif defined(__STDC_LIB_EXT1__) + gmtime_s(&t, &atm); +#else + static_assert(false, "This platform doesn't look to have a thread-safe gmtime function?"); +#endif + + return atm; +} + static std::tm safe_localtime_unoffset(std::tm atm) noexcept { atm.tm_year += 1900; @@ -292,14 +312,9 @@ lpctstr CSTime::Format(lpctstr pszFormat) const if ( pszFormat == nullptr ) pszFormat = "%Y/%m/%d %H:%M:%S"; - struct tm* ptmTemp = localtime(&m_time); - if (ptmTemp == nullptr ) - { - pszTemp[0] = '\0'; - return( pszTemp ); - } + const std::tm ptmTemp = safe_localtime(m_time); - FormatDateTime(pszTemp, pszFormat, ptmTemp); + FormatDateTime(pszTemp, pszFormat, &ptmTemp); return pszTemp; } @@ -309,14 +324,9 @@ lpctstr CSTime::FormatGmt(lpctstr pszFormat) const if ( pszFormat == nullptr ) pszFormat = "%a, %d %b %Y %H:%M:%S GMT"; - struct tm* ptmTemp = gmtime(&m_time); - if (ptmTemp == nullptr ) - { - pszTemp[0] = '\0'; - return( pszTemp ); - } + const std::tm ptmTemp = safe_gmtime(m_time); - FormatDateTime(pszTemp, pszFormat, ptmTemp); + FormatDateTime(pszTemp, pszFormat, &ptmTemp); return pszTemp; } From 60bb843e4276811cc5b18309f557e34b63d13cc3 Mon Sep 17 00:00:00 2001 From: cbnolok Date: Mon, 26 Aug 2024 16:34:25 +0200 Subject: [PATCH 07/86] Incremented MaxConnectRequestPerIp default value to 40. Refactor defragSphere function and CUOInstall methods. --- src/common/CUOInstall.cpp | 96 ++++++++------- src/game/spheresvr.cpp | 210 ++++++++++++++++---------------- src/network/CIPHistoryManager.h | 7 +- src/network/CNetworkManager.cpp | 2 +- src/sphere.ini | 12 +- 5 files changed, 165 insertions(+), 162 deletions(-) diff --git a/src/common/CUOInstall.cpp b/src/common/CUOInstall.cpp index d22146431..5fd909e33 100644 --- a/src/common/CUOInstall.cpp +++ b/src/common/CUOInstall.cpp @@ -5,6 +5,9 @@ #include "CUOInstall.h" #include "common.h" #include "CException.h" +#include + +#define MAP_MAX_SUPPORTED_INDEX 6 ////////////////////////////////////////////////////////////////// @@ -32,7 +35,7 @@ bool CUOInstall::FindInstall() #ifdef _WIN32 // Get the install path from the registry. - static lpctstr m_szKeys[] = + static constexpr lpctstr m_szKeys[] = { "Software\\Origin Worlds Online\\Ultima Online\\1.0", "Software\\Origin Worlds Online\\Ultima Online Third Dawn\\1.0", @@ -40,7 +43,7 @@ bool CUOInstall::FindInstall() "Software\\Electronic Arts\\EA Games\\Ultima Online Stygian Abyss Classic", "Software\\Electronic Arts\\EA Games\\Ultima Online Classic" }; - + HKEY hKey = nullptr; LSTATUS lRet = 0; for ( size_t i = 0; i < ARRAY_COUNT(m_szKeys); ++i ) @@ -104,7 +107,7 @@ void CUOInstall::DetectMulVersions() // this can be tested for by checking the file size, which was 3188736 bytes at release if ( m_File[VERFILE_TILEDATA].IsFileOpen() && m_File[VERFILE_TILEDATA].GetLength() >= 3188736 ) m_FileFormat[VERFILE_TILEDATA] = VERFORMAT_HIGHSEAS; - + // check for High Seas multi format // we can't use multi.mul length because it varies and multi.idx is always 98184 bytes, the best option // so far seems to be to check the size of the first entry to see if its length is divisible by the new @@ -235,7 +238,7 @@ VERFILE_TYPE CUOInstall::OpenFiles( ullong ullMask ) if ( GetBaseFileName((VERFILE_TYPE)i) == nullptr ) continue; - bool bFileLoaded = true; + bool fFileLoaded = true; switch (i) { default: @@ -248,7 +251,7 @@ VERFILE_TYPE CUOInstall::OpenFiles( ullong ullMask ) break; default: - bFileLoaded = false; + fFileLoaded = false; break; } } @@ -257,14 +260,14 @@ VERFILE_TYPE CUOInstall::OpenFiles( ullong ullMask ) case VERFILE_MAP: { // map file is handled differently - tchar z[256]; + tchar verdata_str_buf[256]; // check for map files of custom maps for (int m = 0; m < MAP_SUPPORTED_QTY; ++m) { if (g_MapList.IsInitialized(m) || (m == 0)) //Need at least a minimum of map0... (Ben) { - int index = g_MapList.m_mapGeoData.maps[m].num; + const int index = g_MapList.m_mapGeoData.maps[m].num; if (index == -1) { g_MapList.m_mapGeoData.maps[m].enabled = false; @@ -273,8 +276,8 @@ VERFILE_TYPE CUOInstall::OpenFiles( ullong ullMask ) if (!m_Maps[index].IsFileOpen()) { - sprintf(z, "map%d.mul", index); - OpenFile(m_Maps[index], z, OF_READ | OF_SHARE_DENY_WRITE); + sprintf(verdata_str_buf, "map%d.mul", index); + OpenFile(m_Maps[index], verdata_str_buf, OF_READ | OF_SHARE_DENY_WRITE); if (m_Maps[index].IsFileOpen()) { @@ -282,8 +285,8 @@ VERFILE_TYPE CUOInstall::OpenFiles( ullong ullMask ) } else { - sprintf(z, "map%dLegacyMUL.uop", index); - OpenFile(m_Maps[index], z, OF_READ | OF_SHARE_DENY_WRITE); + sprintf(verdata_str_buf, "map%dLegacyMUL.uop", index); + OpenFile(m_Maps[index], verdata_str_buf, OF_READ | OF_SHARE_DENY_WRITE); //Should parse uop file here for faster reference later. if (m_Maps[index].IsFileOpen()) @@ -330,8 +333,8 @@ VERFILE_TYPE CUOInstall::OpenFiles( ullong ullMask ) for (dword x = 0; x < dwLoop; ++x) { - sprintf(z, "build/map%dlegacymul/%.8u.dat", index, x); - if (HashFileName(z) == qwHash) + sprintf(verdata_str_buf, "build/map%dlegacymul/%.8u.dat", index, x); + if (HashFileName(verdata_str_buf) == qwHash) { pMapAddress.dwFirstBlock = x * 4096; pMapAddress.dwLastBlock = (x * 4096) + (dwCompressedSize / 196) - 1; @@ -346,47 +349,47 @@ VERFILE_TYPE CUOInstall::OpenFiles( ullong ullMask ) }//End of UOP Map parsing else if (index == 0) // neither file exists, map0 is required { - bFileLoaded = false; + fFileLoaded = false; break; } } } if (!m_Staidx[index].IsFileOpen()) { - sprintf(z, "staidx%d.mul", index); - OpenFile(m_Staidx[index], z, OF_READ | OF_SHARE_DENY_WRITE); + sprintf(verdata_str_buf, "staidx%d.mul", index); + OpenFile(m_Staidx[index], verdata_str_buf, OF_READ | OF_SHARE_DENY_WRITE); } if (!m_Statics[index].IsFileOpen()) { - sprintf(z, "statics%d.mul", index); - OpenFile(m_Statics[index], z, OF_READ | OF_SHARE_DENY_WRITE); + sprintf(verdata_str_buf, "statics%d.mul", index); + OpenFile(m_Statics[index], verdata_str_buf, OF_READ | OF_SHARE_DENY_WRITE); } if (g_Cfg.m_fUseMapDiffs) { if (!m_Mapdif[index].IsFileOpen()) { - sprintf(z, "mapdif%d.mul", index); - OpenFile(m_Mapdif[index], z, OF_READ | OF_SHARE_DENY_WRITE); + sprintf(verdata_str_buf, "mapdif%d.mul", index); + OpenFile(m_Mapdif[index], verdata_str_buf, OF_READ | OF_SHARE_DENY_WRITE); } if (!m_Mapdifl[index].IsFileOpen()) { - sprintf(z, "mapdifl%d.mul", index); - OpenFile(m_Mapdifl[index], z, OF_READ | OF_SHARE_DENY_WRITE); + sprintf(verdata_str_buf, "mapdifl%d.mul", index); + OpenFile(m_Mapdifl[index], verdata_str_buf, OF_READ | OF_SHARE_DENY_WRITE); } if (!m_Stadif[index].IsFileOpen()) { - sprintf(z, "stadif%d.mul", index); - OpenFile(m_Stadif[index], z, OF_READ | OF_SHARE_DENY_WRITE); + sprintf(verdata_str_buf, "stadif%d.mul", index); + OpenFile(m_Stadif[index], verdata_str_buf, OF_READ | OF_SHARE_DENY_WRITE); } if (!m_Stadifi[index].IsFileOpen()) { - sprintf(z, "stadifi%d.mul", index); - OpenFile(m_Stadifi[index], z, OF_READ | OF_SHARE_DENY_WRITE); + sprintf(verdata_str_buf, "stadifi%d.mul", index); + OpenFile(m_Stadifi[index], verdata_str_buf, OF_READ | OF_SHARE_DENY_WRITE); } if (!m_Stadifl[index].IsFileOpen()) { - sprintf(z, "stadifl%d.mul", index); - OpenFile(m_Stadifl[index], z, OF_READ | OF_SHARE_DENY_WRITE); + sprintf(verdata_str_buf, "stadifl%d.mul", index); + OpenFile(m_Stadifl[index], verdata_str_buf, OF_READ | OF_SHARE_DENY_WRITE); } } @@ -437,7 +440,7 @@ VERFILE_TYPE CUOInstall::OpenFiles( ullong ullMask ) } // stop if we hit a failure - if (bFileLoaded == false) + if (fFileLoaded == false) return (VERFILE_TYPE)i; } @@ -449,11 +452,11 @@ VERFILE_TYPE CUOInstall::OpenFiles( ullong ullMask ) g_MapList.Init(); - tchar * z = Str_GetTemp(); - tchar * z1 = Str_GetTemp(); - for ( uchar j = 0; j < 7; ++j ) + std::stringstream maps_ss; + tchar * mapname_str_buf = Str_GetTemp(); + for ( uchar j = 0; j <= MAP_MAX_SUPPORTED_INDEX; ++j ) { - if ( j == 5 ) // ML just added some changes on maps 0/1 instead a new map + if ( j == 5 ) // ML just added some changes on maps 0/1 instead of a new map continue; bool fSup = false; @@ -466,21 +469,22 @@ VERFILE_TYPE CUOInstall::OpenFiles( ullong ullMask ) { switch ( j ) { - case 0: sprintf(z1, "Felucca (%d)", j); break; - case 1: sprintf(z1, "Trammel (%d)", j); break; - case 2: sprintf(z1, "Ilshenar (%d)", j); break; - case 3: sprintf(z1, "Malas (%d)", j); break; - case 4: sprintf(z1, "Tokuno Islands (%d)", j); break; - case 6: sprintf(z1, "Ter Mur (%d)", j-1); break; + case 0: sprintf(mapname_str_buf, "Felucca (%d)", j); break; + case 1: sprintf(mapname_str_buf, "Trammel (%d)", j); break; + case 2: sprintf(mapname_str_buf, "Ilshenar (%d)", j); break; + case 3: sprintf(mapname_str_buf, "Malas (%d)", j); break; + case 4: sprintf(mapname_str_buf, "Tokuno Islands (%d)", j); break; + case 6: sprintf(mapname_str_buf, "Ter Mur (%d)", j-1); break; } - if ( *z ) - strcat(z, ", "); - strcat(z, z1); + if (maps_ss.peek() != std::char_traits::eof()) //( !maps_ss.view().empty() ) + maps_ss << ", "; + maps_ss << mapname_str_buf; } } - if ( *z ) - g_Log.Event(LOGM_INIT, "Expansion maps supported: %s\n", z); + const std::string maps_str(maps_ss.str()); + if ( !maps_str.empty() ) + g_Log.Event(LOGM_INIT, "Expansion maps supported: %s\n", maps_str.c_str()); // -- @@ -796,9 +800,9 @@ ullong HashFileName(CSString csFile) ebx += (int32) csFile[ i + 2 ] << 16; case 2: ebx += (int32) csFile[ i + 1 ] << 8; - case 1: + case 1: ebx += (int32) csFile[ i ]; - break; + break; } esi = ( esi ^ edi ) - ( ( edi >> 18 ) ^ ( edi << 14 ) ); diff --git a/src/game/spheresvr.cpp b/src/game/spheresvr.cpp index b407cc5f4..5588e1b66 100644 --- a/src/game/spheresvr.cpp +++ b/src/game/spheresvr.cpp @@ -508,15 +508,14 @@ void defragSphere(char *path) { ASSERT(path != nullptr); + constexpr size_t mb10 = 10*1024*1024; + constexpr size_t mb5 = 5*1024*1024; + CSFileText inf; CSFile ouf; - char z[_MAX_PATH], z1[_MAX_PATH], buf[1024]; - char *p = nullptr, *p1 = nullptr; - size_t uiBytesRead; - size_t dTotalMb; - const size_t mb10 = 10*1024*1024; - const size_t mb5 = 5*1024*1024; - bool fSpecial; + char file_buf[1024]; + char path_buf[_MAX_PATH], path_buf_2[_MAX_PATH]; + char *str_ptr = nullptr, *str_ptr_2 = nullptr; g_Log.Event(LOGM_INIT, "Defragmentation (UID alteration) of " SPHERE_TITLE " saves.\n" "Use it on your risk and if you know what you are doing since it can possibly harm your server.\n" @@ -530,43 +529,43 @@ void defragSphere(char *path) dword* puids = (dword*)calloc(MAX_UID, sizeof(dword)); for ( uint i = 0; i < 3; ++i ) { - Str_CopyLimitNull(z, path, sizeof(z)); - if ( i == 0 ) strcat(z, SPHERE_FILE "statics" SPHERE_SCRIPT); - else if ( i == 1 ) strcat(z, SPHERE_FILE "world" SPHERE_SCRIPT); - else strcat(z, SPHERE_FILE "chars" SPHERE_SCRIPT); + Str_CopyLimitNull(path_buf, path, sizeof(path_buf)); + if ( i == 0 ) strcat(path_buf, SPHERE_FILE "statics" SPHERE_SCRIPT); + else if ( i == 1 ) strcat(path_buf, SPHERE_FILE "world" SPHERE_SCRIPT); + else strcat(path_buf, SPHERE_FILE "chars" SPHERE_SCRIPT); - g_Log.Event(LOGM_INIT, "Reading current UIDs: %s\n", z); - if ( !inf.Open(z, OF_READ|OF_TEXT|OF_DEFAULTMODE) ) + g_Log.Event(LOGM_INIT, "Reading current UIDs: %s\n", path_buf); + if ( !inf.Open(path_buf, OF_READ|OF_TEXT|OF_DEFAULTMODE) ) { g_Log.Event(LOGM_INIT, "Cannot open file for reading. Skipped!\n"); continue; } - uiBytesRead = dTotalMb = 0; + size_t uiBytesRead = 0, uiTotalMb = 0; while ((dwIdxUID < MAX_UID) && !feof(inf._pStream)) { - fgets(buf, sizeof(buf), inf._pStream); - uiBytesRead += strlen(buf); + fgets(file_buf, sizeof(file_buf), inf._pStream); + uiBytesRead += strlen(file_buf); if ( uiBytesRead > mb10 ) { uiBytesRead -= mb10; - dTotalMb += 10; - g_Log.Event(LOGM_INIT, "Total read %" PRIuSIZE_T " Mb\n", dTotalMb); + uiTotalMb += 10; + g_Log.Event(LOGM_INIT, "Total read %" PRIuSIZE_T " Mb\n", uiTotalMb); } - if (( buf[0] == 'S' ) && ( strstr(buf, "SERIAL=") == buf )) + if (( file_buf[0] == 'S' ) && ( strstr(file_buf, "SERIAL=") == file_buf )) { - p = buf + 7; - p1 = p; - while (*p1 && (*p1 != '\r') && (*p1 != '\n')) + str_ptr = file_buf + 7; + str_ptr_2 = str_ptr; + while (*str_ptr_2 && (*str_ptr_2 != '\r') && (*str_ptr_2 != '\n')) { - ++p1; + ++str_ptr_2; } - *p1 = 0; + *str_ptr_2 = 0; // prepare new uid - *(p-1) = '0'; - *p = 'x'; - --p; - puids[dwIdxUID++] = strtoul(p, &p1, 16); + *(str_ptr-1) = '0'; + *str_ptr = 'x'; + --str_ptr; + puids[dwIdxUID++] = strtoul(str_ptr, &str_ptr_2, 16); } } inf.Close(); @@ -579,125 +578,125 @@ void defragSphere(char *path) for ( uint i = 0; i < 5; ++i ) { - Str_CopyLimitNull(z, path, sizeof(z)); - if ( !i ) strcat(z, SPHERE_FILE "accu.scp"); - else if ( i == 1 ) strcat(z, SPHERE_FILE "chars" SPHERE_SCRIPT); - else if ( i == 2 ) strcat(z, SPHERE_FILE "data" SPHERE_SCRIPT); - else if ( i == 3 ) strcat(z, SPHERE_FILE "world" SPHERE_SCRIPT); - else if ( i == 4 ) strcat(z, SPHERE_FILE "statics" SPHERE_SCRIPT); - g_Log.Event(LOGM_INIT, "Updating UID-s in %s to %s.new\n", z, z); - if ( !inf.Open(z, OF_READ|OF_TEXT|OF_DEFAULTMODE) ) + Str_CopyLimitNull(path_buf, path, sizeof(path_buf)); + if ( !i ) strcat(path_buf, SPHERE_FILE "accu.scp"); + else if ( i == 1 ) strcat(path_buf, SPHERE_FILE "chars" SPHERE_SCRIPT); + else if ( i == 2 ) strcat(path_buf, SPHERE_FILE "data" SPHERE_SCRIPT); + else if ( i == 3 ) strcat(path_buf, SPHERE_FILE "world" SPHERE_SCRIPT); + else if ( i == 4 ) strcat(path_buf, SPHERE_FILE "statics" SPHERE_SCRIPT); + g_Log.Event(LOGM_INIT, "Updating UID-s in %s to %s.new\n", path_buf, path_buf); + if ( !inf.Open(path_buf, OF_READ|OF_TEXT|OF_DEFAULTMODE) ) { g_Log.Event(LOGM_INIT, "Cannot open file for reading. Skipped!\n"); continue; } - Str_ConcatLimitNull(z, ".new", sizeof(z)); - if ( !ouf.Open(z, OF_WRITE|OF_CREATE|OF_DEFAULTMODE) ) + Str_ConcatLimitNull(path_buf, ".new", sizeof(path_buf)); + if ( !ouf.Open(path_buf, OF_WRITE|OF_CREATE|OF_DEFAULTMODE) ) { g_Log.Event(LOGM_INIT, "Cannot open file for writing. Skipped!\n"); continue; } - uiBytesRead = dTotalMb = 0; - while ( inf.ReadString(buf, sizeof(buf)) ) + size_t uiBytesRead = 0, uiTotalMb = 0; + while ( inf.ReadString(file_buf, sizeof(file_buf)) ) { - dwIdxUID = (dword)strlen(buf); - if (dwIdxUID > (ARRAY_COUNT(buf) - 3)) - dwIdxUID = ARRAY_COUNT(buf) - 3; + dwIdxUID = (dword)strlen(file_buf); + if (dwIdxUID > (ARRAY_COUNT(file_buf) - 3)) + dwIdxUID = ARRAY_COUNT(file_buf) - 3; - buf[dwIdxUID] = buf[dwIdxUID +1] = buf[dwIdxUID +2] = 0; // just to be sure to be in line always + file_buf[dwIdxUID] = file_buf[dwIdxUID +1] = file_buf[dwIdxUID +2] = 0; // just to be sure to be in line always // NOTE: it is much faster than to use memcpy to clear before reading - fSpecial = false; + bool fSpecial = false; uiBytesRead += dwIdxUID; if ( uiBytesRead > mb5 ) { uiBytesRead -= mb5; - dTotalMb += 5; - g_Log.Event(LOGM_INIT, "Total processed %" PRIuSIZE_T " Mb\n", dTotalMb); + uiTotalMb += 5; + g_Log.Event(LOGM_INIT, "Total processed %" PRIuSIZE_T " Mb\n", uiTotalMb); } - p = buf; + str_ptr = file_buf; // Note 28-Jun-2004 // mounts seems having ACTARG1 > 0x30000000. The actual UID is ACTARG1-0x30000000. The // new also should be new+0x30000000. need investigation if this can help making mounts // not to disappear after the defrag - if (( buf[0] == 'A' ) && ( strstr(buf, "ACTARG1=0") == buf )) // ACTARG1= - p += 8; - else if (( buf[0] == 'C' ) && ( strstr(buf, "CONT=0") == buf )) // CONT= - p += 5; - else if (( buf[0] == 'C' ) && ( strstr(buf, "CHARUID=0") == buf )) // CHARUID= - p += 8; - else if (( buf[0] == 'L' ) && ( strstr(buf, "LASTCHARUID=0") == buf )) // LASTCHARUID= - p += 12; - else if (( buf[0] == 'L' ) && ( strstr(buf, "LINK=0") == buf )) // LINK= - p += 5; - else if (( buf[0] == 'M' ) && ( strstr(buf, "MEMBER=0") == buf )) // MEMBER= + if (( file_buf[0] == 'A' ) && ( strstr(file_buf, "ACTARG1=0") == file_buf )) // ACTARG1= + str_ptr += 8; + else if (( file_buf[0] == 'C' ) && ( strstr(file_buf, "CONT=0") == file_buf )) // CONT= + str_ptr += 5; + else if (( file_buf[0] == 'C' ) && ( strstr(file_buf, "CHARUID=0") == file_buf )) // CHARUID= + str_ptr += 8; + else if (( file_buf[0] == 'L' ) && ( strstr(file_buf, "LASTCHARUID=0") == file_buf )) // LASTCHARUID= + str_ptr += 12; + else if (( file_buf[0] == 'L' ) && ( strstr(file_buf, "LINK=0") == file_buf )) // LINK= + str_ptr += 5; + else if (( file_buf[0] == 'M' ) && ( strstr(file_buf, "MEMBER=0") == file_buf )) // MEMBER= { - p += 7; + str_ptr += 7; fSpecial = true; } - else if (( buf[0] == 'M' ) && ( strstr(buf, "MORE1=0") == buf )) // MORE1= - p += 6; - else if (( buf[0] == 'M' ) && ( strstr(buf, "MORE2=0") == buf )) // MORE2= - p += 6; - else if (( buf[0] == 'S' ) && ( strstr(buf, "SERIAL=0") == buf )) // SERIAL= - p += 7; - else if ((( buf[0] == 'T' ) && ( strstr(buf, "TAG.") == buf )) || // TAG.= - (( buf[0] == 'R' ) && ( strstr(buf, "REGION.TAG") == buf ))) + else if (( file_buf[0] == 'M' ) && ( strstr(file_buf, "MORE1=0") == file_buf )) // MORE1= + str_ptr += 6; + else if (( file_buf[0] == 'M' ) && ( strstr(file_buf, "MORE2=0") == file_buf )) // MORE2= + str_ptr += 6; + else if (( file_buf[0] == 'S' ) && ( strstr(file_buf, "SERIAL=0") == file_buf )) // SERIAL= + str_ptr += 7; + else if ((( file_buf[0] == 'T' ) && ( strstr(file_buf, "TAG.") == file_buf )) || // TAG.= + (( file_buf[0] == 'R' ) && ( strstr(file_buf, "REGION.TAG") == file_buf ))) { - while ( *p && ( *p != '=' )) - ++p; - ++p; + while ( *str_ptr && ( *str_ptr != '=' )) + ++str_ptr; + ++str_ptr; } - else if (( i == 2 ) && strchr(buf, '=')) // spheredata.scp - plain VARs + else if (( i == 2 ) && strchr(file_buf, '=')) // spheredata.scp - plain VARs { - while ( *p && ( *p != '=' )) - ++p; - ++p; + while ( *str_ptr && ( *str_ptr != '=' )) + ++str_ptr; + ++str_ptr; } else - p = nullptr; + str_ptr = nullptr; // UIDs are always hex, so prefixed by 0 - if ( p && ( *p != '0' )) - p = nullptr; + if ( str_ptr && ( *str_ptr != '0' )) + str_ptr = nullptr; // here we got potentialy UID-contained variable // check if it really is only UID-like var containing - if ( p ) + if ( str_ptr ) { - p1 = p; - while ( *p1 && - ((( *p1 >= '0' ) && ( *p1 <= '9' )) || - (( *p1 >= 'a' ) && ( *p1 <= 'f' ))) ) - ++p1; + str_ptr_2 = str_ptr; + while ( *str_ptr_2 && + ((( *str_ptr_2 >= '0' ) && ( *str_ptr_2 <= '9' )) || + (( *str_ptr_2 >= 'a' ) && ( *str_ptr_2 <= 'f' ))) ) + ++str_ptr_2; if ( !fSpecial ) { - if ( *p1 && ( *p1 != '\r' ) && ( *p1 != '\n' )) // some more text in line - p = nullptr; + if ( *str_ptr_2 && ( *str_ptr_2 != '\r' ) && ( *str_ptr_2 != '\n' )) // some more text in line + str_ptr = nullptr; } } // here we definitely know that this is very uid-like - if ( p ) + if ( str_ptr ) { char c, c1, c2; - c = *p1; + c = *str_ptr_2; - *p1 = 0; + *str_ptr_2 = 0; // here in p we have the current value of the line. // check if it is a valid UID // prepare converting 0.. to 0x.. - c1 = *(p-1); - c2 = *p; - *(p-1) = '0'; - *p = 'x'; - --p; - dwIdxUID = strtoul(p, &p1, 16); - ++p; - *(p-1) = c1; - *p = c2; + c1 = *(str_ptr-1); + c2 = *str_ptr; + *(str_ptr-1) = '0'; + *str_ptr = 'x'; + --str_ptr; + dwIdxUID = strtoul(str_ptr, &str_ptr_2, 16); + ++str_ptr; + *(str_ptr-1) = c1; + *str_ptr = c2; // Note 28-Jun-2004 // The search algourytm is very simple and fast. But maybe integrate some other, at least /2 algorythm // since has amount/2 tryes at worst chance to get the item and never scans the whole array @@ -746,18 +745,19 @@ void defragSphere(char *path) }*/ // replace UID by the new one since it has been found - *p1 = c; + *str_ptr_2 = c; if (dwIdxUID != 0xFFFFFFFFL ) { - *p = 0; - strcpy(z, p1); - snprintf(z1, sizeof(z1), "0%" PRIx32, dwIdxUID); - strcat(buf, z1); - strcat(buf, z); + *str_ptr = 0; + ASSERT(strlen(str_ptr_2) < sizeof(path_buf)); + Str_CopyLimitNull(path_buf, str_ptr_2, sizeof(path_buf)); // here we don't need anymore the old values of path_buf, so i can reuse it here + snprintf(path_buf_2, sizeof(path_buf_2), "0%" PRIx32, dwIdxUID); + strcat(file_buf, path_buf_2); + strcat(file_buf, path_buf); } } // output the resulting line - ouf.Write(buf, (int)strlen(buf)); + ouf.Write(file_buf, (int)strlen(file_buf)); } inf.Close(); ouf.Close(); diff --git a/src/network/CIPHistoryManager.h b/src/network/CIPHistoryManager.h index 6fe6adb95..49010ca84 100644 --- a/src/network/CIPHistoryManager.h +++ b/src/network/CIPHistoryManager.h @@ -56,12 +56,11 @@ class IPHistoryManager IPHistoryManager(void); ~IPHistoryManager(void); -private: - IPHistoryManager(const IPHistoryManager& copy); - IPHistoryManager& operator=(const IPHistoryManager& other); + IPHistoryManager(const IPHistoryManager& copy) = delete; + IPHistoryManager& operator=(const IPHistoryManager& other) = delete; public: - void tick(void); // period events + void tick(void); // periodic events HistoryIP& getHistoryForIP(const CSocketAddressIP& ip) noexcept; // get history for an ip HistoryIP& getHistoryForIP(const char* ip); // get history for an ip diff --git a/src/network/CNetworkManager.cpp b/src/network/CNetworkManager.cpp index 51231dc37..26421ee38 100644 --- a/src/network/CNetworkManager.cpp +++ b/src/network/CNetworkManager.cpp @@ -203,7 +203,7 @@ void CNetworkManager::acceptNewConnection(void) ip.setBlocked(true, fargs_ex.m_VarsLocal.GetKeyNum("BAN_TIMEOUT")); _printIPBlocked(); - g_Log.Event(LOGM_CLIENTS_LOG | LOGL_ERROR, "Reject reason: requested kick + IP block via script 'f_onserver_connectreq_ex'.\n"); + g_Log.Event(LOGM_CLIENTS_LOG | LOGL_ERROR, "Reject reason: requested kick + IP block allowed by script 'f_onserver_connectreq_ex'.\n"); } } diff --git a/src/sphere.ini b/src/sphere.ini index bf500f6a2..e0307c96e 100644 --- a/src/sphere.ini +++ b/src/sphere.ini @@ -194,7 +194,7 @@ ClientMax=256 // Maximum open connections to server per IP ClientMaxIP=16 -// Maximum total (not-in-game, not per-IP) connections to server +// Maximum total (not-in-game, not per-IP) connections to server ConnectingMax=32 // Maximum total simultaneous (not-in-game) connections to server per IP @@ -353,7 +353,7 @@ ContainerMaxItems=255 DragWeightMax=300 // Addition weight in stones allowed over the calculated maxweight in main backpack (-1 = unlimited ; 0 = Player can't go over maxweight) -// This will allow player to add item on their backpack and surcharge themself. (StaminaLossOverweight will be use) +// This will allow player to add item on their backpack and surcharge themself. (StaminaLossOverweight will be use) BackpackOverload=40 // Maximum number of items allowed in bank @@ -828,7 +828,7 @@ Secure=1 // EF_WalkCheckHeightMounted 040000 // Unlike the client does, assume an height increased by 4 in walkchecks if the char is mounted. Enabling this may prevent mounted characters to walk under places they could before. Experimental=0 -// Option flags +// Option flags // Flags for options that affect server behaviour but not compatibility // See the revisions.txt file for more details on this // OF_NoDClickTarget 00000001 // Weapons won't open a target in the cursor after DClicking them for equip. @@ -1103,8 +1103,8 @@ MaxSizeClientOut=80000 // 0 = disabled. Default behavior: disconnect. MaxSizeClientIn=10000 -// Maximum number of connection requests before rejecting/blocking IP. Reset after seconds elapsed after last connection attempt. -MaxConnectRequestsPerIP=5 +// Maximum number of connection requests before rejecting/blocking IP (reset after seconds elapsed after last connection attempt). +MaxConnectRequestsPerIP=40 // Maximum time in milliseconds to wait before closing a connection request wich did not make it into a successful login (classic DDoS just asks to connect without doing anything else, or sends garbage data). TimeoutIncompleteConn=5 * 1000 // 5 seconds @@ -1122,7 +1122,7 @@ NetworkThreads = 0 // 1 = Normal = tick 100ms // 2 = High = tick 50ms // 3 = Highest = tick 5ms -// 4 = RealTime = tick almost instantly +// 4 = RealTime = tick almost instantly NetworkThreadPriority = 1 // Use asynchronous data sends, valid for both single and multi threaded networking From c0727c690d2658b36613be9dcddfe85c0cd30c6b Mon Sep 17 00:00:00 2001 From: cbnolok Date: Mon, 26 Aug 2024 17:21:45 +0200 Subject: [PATCH 08/86] Fix library search path. --- cmake/toolchains/Linux-Clang-AArch64.cmake | 6 +++--- cmake/toolchains/Linux-Clang-x86.cmake | 14 +++++++------- cmake/toolchains/Linux-Clang-x86_64.cmake | 10 +++++----- cmake/toolchains/Linux-GNU-AArch64.cmake | 6 +++--- cmake/toolchains/Linux-GNU-x86.cmake | 14 +++++++------- cmake/toolchains/Linux-GNU-x86_64.cmake | 10 +++++----- 6 files changed, 30 insertions(+), 30 deletions(-) diff --git a/cmake/toolchains/Linux-Clang-AArch64.cmake b/cmake/toolchains/Linux-Clang-AArch64.cmake index c3a7fb8f1..ca47e0bbe 100644 --- a/cmake/toolchains/Linux-Clang-AArch64.cmake +++ b/cmake/toolchains/Linux-Clang-AArch64.cmake @@ -39,9 +39,9 @@ function (toolchain_after_project) else () # possible native/host lib locations set (lib_search_paths - "/usr/aarch64-linux-gnu/libmariadb3" - "/usr/aarch64-linux-gnu/mysql" - "/usr/aarch64-linux-gnu" + "/usr/lib/aarch64-linux-gnu/libmariadb3" + "/usr/lib/aarch64-linux-gnu/mysql" + "/usr/lib/aarch64-linux-gnu" "/usr/lib64/mysql" "/usr/lib64" "/usr/lib/mysql" diff --git a/cmake/toolchains/Linux-Clang-x86.cmake b/cmake/toolchains/Linux-Clang-x86.cmake index 0cc39338d..edcfb7904 100644 --- a/cmake/toolchains/Linux-Clang-x86.cmake +++ b/cmake/toolchains/Linux-Clang-x86.cmake @@ -43,12 +43,12 @@ function (toolchain_after_project) ) else (CROSSCOMPILING_ARCH) set (local_lib_search_paths - "/usr/i686-linux-gnu/libmariadb3" - "/usr/i686-linux-gnu/mysql" - "/usr/i686-linux-gnu" - "/usr/i386-linux-gnu/libmariadb3" - "/usr/i386-linux-gnu/mysql" - "/usr/i386-linux-gnu" + "/usr/lib/i686-linux-gnu/libmariadb3" + "/usr/lib/i686-linux-gnu/mysql" + "/usr/lib/i686-linux-gnu" + "/usr/lib/i386-linux-gnu/libmariadb3" + "/usr/lib/i386-linux-gnu/mysql" + "/usr/lib/i386-linux-gnu" "/usr/lib32/mysql" "/usr/lib32" ) @@ -67,7 +67,7 @@ function (toolchain_after_project) set (lib_search_paths ${local_lib_search_paths} ${local_extra_lib_search_paths} - CACHE STRING "Library search paths (hint)" FORCE + CACHE STRING "Library search paths" FORCE ) endif (CROSSCOMPILING_ARCH) diff --git a/cmake/toolchains/Linux-Clang-x86_64.cmake b/cmake/toolchains/Linux-Clang-x86_64.cmake index 874b3940e..ca95c9128 100644 --- a/cmake/toolchains/Linux-Clang-x86_64.cmake +++ b/cmake/toolchains/Linux-Clang-x86_64.cmake @@ -36,19 +36,19 @@ function (toolchain_after_project) "/usr/x86_64-linux-gnu/usr/lib/libmariadb3" "/usr/x86_64-linux-gnu/usr/lib/mysql" "/usr/x86_64-linux-gnu/usr/lib/" - CACHE STRING "Library search paths (hint)" FORCE + CACHE STRING "Library search paths" FORCE ) else () # possible native/host lib locations set (lib_search_paths - "/usr/x86_64-linux-gnu/libmariadb3" - "/usr/x86_64-linux-gnu/mysql" - "/usr/x86_64-linux-gnu" + "/usr/lib/x86_64-linux-gnu/libmariadb3" + "/usr/lib/x86_64-linux-gnu/mysql" + "/usr/lib/x86_64-linux-gnu" "/usr/lib64/mysql" "/usr/lib64" "/usr/lib/mysql" "/usr/lib" - CACHE STRING "Library search paths (hint)" FORCE + CACHE STRING "Library search paths" FORCE ) endif () diff --git a/cmake/toolchains/Linux-GNU-AArch64.cmake b/cmake/toolchains/Linux-GNU-AArch64.cmake index 9784f47d9..7b950296f 100644 --- a/cmake/toolchains/Linux-GNU-AArch64.cmake +++ b/cmake/toolchains/Linux-GNU-AArch64.cmake @@ -42,9 +42,9 @@ function (toolchain_after_project) else () # possible native/host lib locations set (lib_search_paths - "/usr/aarch64-linux-gnu/libmariadb3" - "/usr/aarch64-linux-gnu/mysql" - "/usr/aarch64-linux-gnu" + "/usr/lib/aarch64-linux-gnu/libmariadb3" + "/usr/lib/aarch64-linux-gnu/mysql" + "/usr/lib/aarch64-linux-gnu" "/usr/lib64/mysql" "/usr/lib64" "/usr/lib/mysql" diff --git a/cmake/toolchains/Linux-GNU-x86.cmake b/cmake/toolchains/Linux-GNU-x86.cmake index 9901f44cc..9ffd7aeed 100644 --- a/cmake/toolchains/Linux-GNU-x86.cmake +++ b/cmake/toolchains/Linux-GNU-x86.cmake @@ -47,19 +47,19 @@ function (toolchain_after_project) ) else (CROSSCOMPILING_ARCH) set (local_lib_search_paths - "/usr/i686-linux-gnu/libmariadb3" - "/usr/i686-linux-gnu/mysql" - "/usr/i686-linux-gnu" - "/usr/i386-linux-gnu/libmariadb3" - "/usr/i386-linux-gnu/mysql" - "/usr/i386-linux-gnu" + "/usr/lib/i686-linux-gnu/libmariadb3" + "/usr/lib/i686-linux-gnu/mysql" + "/usr/lib/i686-linux-gnu" + "/usr/lib/i386-linux-gnu/libmariadb3" + "/usr/lib/i386-linux-gnu/mysql" + "/usr/lib/i386-linux-gnu" "/usr/lib32/mysql" "/usr/lib32" ) if ("${CMAKE_HOST_SYSTEM_PROCESSOR}" STREQUAL "x86_64") # I'm compiling for x86 on an x86_64 host. - set (CMAKE_LIBRARY_PATH ${local_lib_search_paths} CACHE PATH "" + set (CMAKE_LIBRARY_PATH ${local_lib_search_paths} CACHE PATH "") else () # I'm compiling for x86 on an x86 OS (32 bits), so natively: i have libs on /usr/lib and not /usr/lib32. set (local_extra_lib_search_paths diff --git a/cmake/toolchains/Linux-GNU-x86_64.cmake b/cmake/toolchains/Linux-GNU-x86_64.cmake index c43e54d1a..a2c2cdd68 100644 --- a/cmake/toolchains/Linux-GNU-x86_64.cmake +++ b/cmake/toolchains/Linux-GNU-x86_64.cmake @@ -40,19 +40,19 @@ function (toolchain_after_project) "/usr/x86_64-linux-gnu/usr/lib/libmariadb3" "/usr/x86_64-linux-gnu/usr/lib/mysql" "/usr/x86_64-linux-gnu/usr/lib/" - CACHE STRING "Library search paths (hint)" FORCE + CACHE STRING "Library search paths" FORCE ) else () # possible native/host lib locations set (lib_search_paths - "/usr/x86_64-linux-gnu/libmariadb3" - "/usr/x86_64-linux-gnu/mysql" - "/usr/x86_64-linux-gnu" + "/usr/lib/x86_64-linux-gnu/libmariadb3" + "/usr/lib/x86_64-linux-gnu/mysql" + "/usr/lib/x86_64-linux-gnu" "/usr/lib64/mysql" "/usr/lib64" "/usr/lib/mysql" "/usr/lib" - CACHE STRING "Library search paths (hint)" FORCE + CACHE STRING "Library search paths" FORCE ) endif () From 844c61b1ecbbace933d35790607f00bcd35f5222 Mon Sep 17 00:00:00 2001 From: cbnolok Date: Mon, 26 Aug 2024 18:42:39 +0200 Subject: [PATCH 09/86] Fixed ARM compilation warnings (compiler defaults char to uchar instead of signed char) and initialization order fiasco for g_Srv --- cmake/toolchains/Linux-GNU-AArch64.cmake | 4 +- src/common/CPointBase.h | 8 +-- src/common/CServerMap.cpp | 22 ++++--- src/common/CServerMap.h | 39 ++++++------ src/common/datatypes.h | 9 +-- src/common/sphere_library/sstring.cpp | 2 +- src/game/chars/CCharStat.cpp | 22 ++----- src/game/items/CItemMultiCustom.cpp | 76 +++++++++++++----------- src/game/items/CItemMultiCustom.h | 32 +++++----- src/game/spheresvr.cpp | 2 +- src/game/uo_files/CUOMapMeter.h | 2 +- 11 files changed, 107 insertions(+), 111 deletions(-) diff --git a/cmake/toolchains/Linux-GNU-AArch64.cmake b/cmake/toolchains/Linux-GNU-AArch64.cmake index 7b950296f..cc278462c 100644 --- a/cmake/toolchains/Linux-GNU-AArch64.cmake +++ b/cmake/toolchains/Linux-GNU-AArch64.cmake @@ -37,7 +37,7 @@ function (toolchain_after_project) "/usr/aarch64-linux-gnu/usr/lib/libmariadb3" "/usr/aarch64-linux-gnu/usr/lib/mysql" "/usr/aarch64-linux-gnu/usr/lib/" - CACHE STRING "Library search paths (hint)" FORCE + CACHE STRING "Library search paths" FORCE ) else () # possible native/host lib locations @@ -49,7 +49,7 @@ function (toolchain_after_project) "/usr/lib64" "/usr/lib/mysql" "/usr/lib" - CACHE STRING "Library search paths (hint)" FORCE + CACHE STRING "Library search paths" FORCE ) endif () diff --git a/src/common/CPointBase.h b/src/common/CPointBase.h index 6ad0f0157..48707e6b4 100644 --- a/src/common/CPointBase.h +++ b/src/common/CPointBase.h @@ -34,10 +34,10 @@ struct CPointBase // Non initialized 3d point. public: // Do NOT change these datatypes: they seem to not have much sense, but are stored this way inside the mul files. - short m_x; // equipped items dont need x,y - short m_y; - char m_z; // this might be layer if equipped ? or equipped on corpse. Not used if in other container. - uchar m_map; // another map? (only if top level.) + int16 m_x; // equipped items dont need x,y + int16 m_y; + int8 m_z; // this might be layer if equipped ? or equipped on corpse. Not used if in other container. + uint8 m_map; // another map? (only if top level.) public: CPointBase& InitPoint() noexcept; diff --git a/src/common/CServerMap.cpp b/src/common/CServerMap.cpp index 29ed1bfc6..9eb6dcaec 100644 --- a/src/common/CServerMap.cpp +++ b/src/common/CServerMap.cpp @@ -45,7 +45,7 @@ int64 CCachedMulItem::GetCacheAge() const return (CWorldGameTime::GetCurrentTime().GetTimeRaw() - m_timeRef ); } -CServerMapBlockingState::CServerMapBlockingState( uint64 uiBlockFlags, char z, int iHeight, height_t zHeight ) noexcept : +CServerMapBlockingState::CServerMapBlockingState( uint64 uiBlockFlags, int8 z, int iHeight, height_t zHeight ) noexcept : m_uiBlockFlags(uiBlockFlags), m_z(z), m_iHeight(iHeight), m_zClimb(0), m_zHeight(zHeight) { // m_z = PLAYER_HEIGHT @@ -67,7 +67,7 @@ CServerMapBlockingState::CServerMapBlockingState( uint64 uiBlockFlags, char z, i m_zClimbHeight = 0; } -CServerMapBlockingState::CServerMapBlockingState( uint64 uiBlockFlags, char z, int iHeight, char zClimb, height_t zHeight ) noexcept : +CServerMapBlockingState::CServerMapBlockingState( uint64 uiBlockFlags, int8 z, int iHeight, int8 zClimb, height_t zHeight ) noexcept : m_uiBlockFlags(uiBlockFlags), m_z(z), m_iHeight(iHeight), m_zClimb(zClimb), m_zHeight(zHeight) { m_Top.m_uiBlockFlags = 0; @@ -108,13 +108,13 @@ lpctstr CServerMapBlockingState::GetTileName( dword dwID ) // static return pStr; } -bool CServerMapBlockingState::CheckTile( uint64 uiItemBlockFlags, char zBottom, height_t zHeight, dword dwID ) noexcept +bool CServerMapBlockingState::CheckTile( uint64 uiItemBlockFlags, int8 zBottom, height_t zHeight, dword dwID ) noexcept { //ADDTOCALLSTACK("CServerMapBlockingState::CheckTile"); // RETURN: // true = continue processing - char zTop = zBottom; + int8 zTop = zBottom; if ( (uiItemBlockFlags & CAN_I_CLIMB) ) zTop = minimum(zTop + ( zHeight / 2 ), UO_SIZE_Z); // standing position is half way up climbable items. else @@ -175,7 +175,7 @@ bool CServerMapBlockingState::CheckTile( uint64 uiItemBlockFlags, char zBottom, return true; } -bool CServerMapBlockingState::CheckTile_Item( uint64 uiItemBlockFlags, char zBottom, height_t zHeight, dword dwID ) noexcept +bool CServerMapBlockingState::CheckTile_Item( uint64 uiItemBlockFlags, int8 zBottom, height_t zHeight, dword dwID ) noexcept { //ADDTOCALLSTACK("CServerMapBlockingState::CheckTile_Item"); // RETURN: @@ -203,7 +203,7 @@ bool CServerMapBlockingState::CheckTile_Item( uint64 uiItemBlockFlags, char zBot if ( zTop < m_Lowest.m_z ) { - m_Lowest = {uiItemBlockFlags, dwID, (char)zTop, zHeight}; + m_Lowest = {uiItemBlockFlags, dwID, (int8)zTop, zHeight}; } // Why was this block of code added? By returning, it blocks the m_Bottom state to be updated @@ -231,7 +231,7 @@ bool CServerMapBlockingState::CheckTile_Item( uint64 uiItemBlockFlags, char zBot else if ( m_Bottom.m_uiBlockFlags & CAN_I_PLATFORM ) //than items with CAN_I_PLATFORM return true; } - m_Bottom = {uiItemBlockFlags, dwID, (char)zTop, zHeight}; + m_Bottom = {uiItemBlockFlags, dwID, (int8)zTop, zHeight}; if (uiItemBlockFlags & CAN_I_CLIMB) // return climb height m_zClimbHeight = (( zHeight + 1 )/2); //if height is an odd number, then we need to add 1; if it isn't, this does nothing @@ -262,7 +262,7 @@ bool CServerMapBlockingState::CheckTile_Item( uint64 uiItemBlockFlags, char zBot } -bool CServerMapBlockingState::CheckTile_Terrain( uint64 uiItemBlockFlags, char z, dword dwID ) noexcept +bool CServerMapBlockingState::CheckTile_Terrain( uint64 uiItemBlockFlags, int8 z, dword dwID ) noexcept { //ADDTOCALLSTACK("CServerMapBlockingState::CheckTile_Terrain"); // RETURN: @@ -534,6 +534,12 @@ CServerMapBlock::~CServerMapBlock() --sm_iCount; } +const CUOMapMeter* CServerMapBlock::GetTerrain(int xo, int yo) const +{ + ASSERT(xo >= 0 && xo < UO_BLOCK_SIZE); + ASSERT(yo >= 0 && yo < UO_BLOCK_SIZE); + return &(m_Terrain.m_Meter[yo * UO_BLOCK_SIZE + xo]); +} ////////////////////////////////////////////////////////////////// // -CUOMulti diff --git a/src/common/CServerMap.h b/src/common/CServerMap.h index 825e1f4eb..3192bb766 100644 --- a/src/common/CServerMap.h +++ b/src/common/CServerMap.h @@ -54,7 +54,7 @@ class CServerStaticsBlock public: // These methods are called so frequently but in so few pieces of code that's very important to inline them - inline uint GetStaticQty() const { + inline uint GetStaticQty() const { return m_iStatics; } inline const CUOStaticItemRec * GetStatic( uint i ) const @@ -75,7 +75,7 @@ struct CServerMapBlocker { uint64 m_uiBlockFlags; // How does this item block ? CAN_I_PLATFORM dword m_dwTile; // TERRAIN_QTY + id. - char m_z; // Top (z + ((climbable item) ? height/2 : height)) of a solid object, or bottom (z) of non blocking one. + int8 m_z; // Top (z + ((climbable item) ? height/2 : height)) of a solid object, or bottom (z) of non blocking one. height_t m_height; // The actual height of the item (0 if terrain) }; @@ -83,7 +83,7 @@ struct CServerMapBlockingState { // Go through the list of stuff at this location to decide what is blocking us and what is not. // dwBlockFlags = what we can pass thru. doors, water, walls ? - // CAN_C_GHOST = Moves thru doors etc. - CAN_I_DOOR = UFLAG4_DOOR + // CAN_C_GHOST = Moves thru doors etc. - CAN_I_DOOR = UFLAG4_DOOR // CAN_C_SWIM = walk thru water - CAN_I_WATER = UFLAG1_WATER // CAN_C_WALK = it is possible that i can step up. - CAN_I_PLATFORM = UFLAG2_PLATFORM // CAN_C_PASSWALLS = walk through all blcking items - CAN_I_BLOCK = UFLAG1_BLOCK @@ -91,28 +91,28 @@ struct CServerMapBlockingState // CAN_C_FIRE_IMMUNE = i can walk into lava etc. - CAN_I_FIRE = UFLAG1_DAMAGE // CAN_C_HOVER = i can follow hover routes. - CAN_I_HOVER = UFLAG4_HOVEROVER - const uint64 m_uiBlockFlags; // The block flags we (the specific char who requested this class instance) can overcome. - const char m_z; // the z we start at. (stay at if we are flying) + const uint64 m_uiBlockFlags; // The block flags we (the specific char who requested this class instance) can overcome. + const int8 m_z; // the z we start at. (stay at if we are flying) const int m_iHeight; // The height we need to stand here. - const char m_zClimb; // We can climb at this height + const int8 m_zClimb; // We can climb at this height const height_t m_zHeight; // our height height_t m_zClimbHeight; // return item climb height here - + CServerMapBlocker m_Top; CServerMapBlocker m_Bottom; // What i would be standing on. - CServerMapBlocker m_Lowest; // the lowest item we have found. + CServerMapBlocker m_Lowest; // the lowest item we have found. public: - CServerMapBlockingState( uint64 uiBlockFlags, char m_z, int iHeight = PLAYER_HEIGHT, height_t zHeight = PLAYER_HEIGHT ) noexcept; - CServerMapBlockingState( uint64 uiBlockFlags, char m_z, int iHeight, char zClimb, height_t zHeight = PLAYER_HEIGHT ) noexcept; + CServerMapBlockingState( uint64 uiBlockFlags, int8 m_z, int iHeight = PLAYER_HEIGHT, height_t zHeight = PLAYER_HEIGHT ) noexcept; + CServerMapBlockingState( uint64 uiBlockFlags, int8 m_z, int iHeight, int8 zClimb, height_t zHeight = PLAYER_HEIGHT ) noexcept; CServerMapBlockingState(const CServerMapBlockingState& copy) = delete; CServerMapBlockingState& operator=(const CServerMapBlockingState& other) = delete; public: - bool CheckTile( uint64 uiItemBlockFlags, char zBottom, height_t zheight, dword wID ) noexcept; - bool CheckTile_Item( uint64 uiItemBlockFlags, char zBottom, height_t zheight, dword wID ) noexcept; - bool CheckTile_Terrain( uint64 uiItemBlockFlags, char z, dword dwID ) noexcept; + bool CheckTile( uint64 uiItemBlockFlags, int8 zBottom, height_t zheight, dword wID ) noexcept; + bool CheckTile_Item( uint64 uiItemBlockFlags, int8 zBottom, height_t zheight, dword wID ) noexcept; + bool CheckTile_Terrain( uint64 uiItemBlockFlags, int8 z, dword dwID ) noexcept; static lpctstr GetTileName( dword dwID ); }; @@ -189,25 +189,20 @@ class CServerMapBlock : // Cache this from the MUL files. 8x8 block of the world CServerMapBlock& operator=(const CServerMapBlock& other) = delete; public: - inline int GetOffsetX(int x) const + inline int GetOffsetX(int x) const noexcept { return (x - m_x); } - inline int GetOffsetY( int y ) const + inline int GetOffsetY( int y ) const noexcept { return (y - m_y); } - inline const CUOMapBlock * GetTerrainBlock() const + inline const CUOMapBlock * GetTerrainBlock() const noexcept { return &m_Terrain; } - const CUOMapMeter* GetTerrain(int xo, int yo) const - { - ASSERT(xo >= 0 && xo < UO_BLOCK_SIZE); - ASSERT(yo >= 0 && yo < UO_BLOCK_SIZE); - return &(m_Terrain.m_Meter[yo * UO_BLOCK_SIZE + xo]); - } + const CUOMapMeter* GetTerrain(int xo, int yo) const; }; class CUOMulti : private CCachedMulItem diff --git a/src/common/datatypes.h b/src/common/datatypes.h index 4c8ed4703..ba4bb17b9 100644 --- a/src/common/datatypes.h +++ b/src/common/datatypes.h @@ -50,22 +50,23 @@ typedef double realtype32; typedef long double realtype64; typedef realtype32 realtype; +typedef signed char schar; // could need to be specified in some places. On x86 char is signed by default, but on ARM it's unsigned! typedef unsigned char uchar; typedef unsigned short ushort; typedef unsigned int uint; -//typedef unsigned long ulong; // long and ulong shouldn't be used... +//typedef unsigned long ulong; // long and ulong shouldn't be used.. can have different sizes on different platforms. typedef long long llong; typedef unsigned long long ullong; /* To be used when coding packets */ -typedef uint8_t byte; // 8 bits +typedef uint8_t byte; // 8 bits typedef uint16_t word; // 16 bits typedef uint32_t dword; // 32 bits /* Use the following types only if you know *why* you need them. -These types have a specified size, while standard data types (short, int, etc) haven't: +These types have a fixed, specified size, while standard data types (short, int, etc) haven't: for example, sizeof(int) is definied to be >= sizeof(short) and <= sizeof(long), so it hasn't a fixed size; -this concept is valid for both non unix and unix OS. +this concept is valid for both non unix and unix OSes. On the vast majority of platforms, base data types have well definied dimensions (for now): char: 1 byte - short: 2 bytes - int: 4 bytes - long: (4 on windows, 8 on unix) bytes - long long: 8 bytes In the future they may change to higher values, so you should use fixed-size types only when you know that diff --git a/src/common/sphere_library/sstring.cpp b/src/common/sphere_library/sstring.cpp index 8156f2045..c4de7b30c 100644 --- a/src/common/sphere_library/sstring.cpp +++ b/src/common/sphere_library/sstring.cpp @@ -692,7 +692,7 @@ int Str_TrimEndWhitespace(tchar * pStr, int len) noexcept while (len > 0) { --len; - if (pStr[len] < 0 || !IsWhitespace(pStr[len])) + if (!IsWhitespace(pStr[len])) { ++len; break; diff --git a/src/game/chars/CCharStat.cpp b/src/game/chars/CCharStat.cpp index 27358095f..9be54887f 100644 --- a/src/game/chars/CCharStat.cpp +++ b/src/game/chars/CCharStat.cpp @@ -71,15 +71,10 @@ void CChar::Stat_SetMod( STAT_TYPE i, int iVal ) int CChar::Stat_GetMod( STAT_TYPE i ) const { - [[unlikely]] - if (i < 0 || i >= STAT_QTY) - { - ADDTOCALLSTACK("CChar::Stat_GetMod"); - ASSERT(i >= 0 && i < STAT_QTY); - } + ADDTOCALLSTACK("CChar::Stat_GetMod"); + ASSERT(i >= 0 && i < STAT_QTY); - [[likely]] - return m_Stat[i].m_mod; + return m_Stat[i].m_mod; } void CChar::Stat_SetMaxMod( STAT_TYPE i, int iVal ) @@ -321,15 +316,10 @@ ushort CChar::Stat_GetAdjusted( STAT_TYPE i ) const ushort CChar::Stat_GetBase( STAT_TYPE i ) const { - [[unlikely]] - if (i < 0 || i >= STAT_QTY) - { - ADDTOCALLSTACK("CChar::Stat_GetBase"); - ASSERT(i >= 0 && i < STAT_QTY); - } + ADDTOCALLSTACK("CChar::Stat_GetBase"); + ASSERT(i >= 0 && i < STAT_QTY); - [[likely]] - return m_Stat[i].m_base; + return m_Stat[i].m_base; } void CChar::Stat_AddBase( STAT_TYPE i, int iVal ) diff --git a/src/game/items/CItemMultiCustom.cpp b/src/game/items/CItemMultiCustom.cpp index 34ff19621..ef9a9a33a 100644 --- a/src/game/items/CItemMultiCustom.cpp +++ b/src/game/items/CItemMultiCustom.cpp @@ -433,7 +433,7 @@ void CItemMultiCustom::CommitChanges(CClient * pClientSrc) Update(); } -void CItemMultiCustom::AddItem(CClient * pClientSrc, ITEMID_TYPE id, short x, short y, char z, short iStairID) +void CItemMultiCustom::AddItem(CClient * pClientSrc, ITEMID_TYPE id, int16 x, int16 y, int8 z, ushort iStairID) { ADDTOCALLSTACK("CItemMultiCustom::AddItem"); // add an item to the building design at the given location @@ -589,7 +589,7 @@ void CItemMultiCustom::AddItem(CClient * pClientSrc, ITEMID_TYPE id, short x, sh } } -void CItemMultiCustom::AddStairs(CClient * pClientSrc, ITEMID_TYPE id, short x, short y, char z) +void CItemMultiCustom::AddStairs(CClient * pClientSrc, ITEMID_TYPE id, int16 x, int16 y, int8 z) { ADDTOCALLSTACK("CItemMultiCustom::AddStairs"); // add a staircase to the building, the given ID must @@ -643,13 +643,13 @@ void CItemMultiCustom::AddStairs(CClient * pClientSrc, ITEMID_TYPE id, short x, if (!pMultiItem->m_visible) continue; - AddItem(nullptr, pMultiItem->GetDispID(), x + pMultiItem->m_dx, y + pMultiItem->m_dy, z + (char)(pMultiItem->m_dz), iStairID); + AddItem(nullptr, pMultiItem->GetDispID(), x + pMultiItem->m_dx, y + pMultiItem->m_dy, z + n16_narrow8(pMultiItem->m_dz), iStairID); } SendStructureTo(pClientSrc); } -void CItemMultiCustom::AddRoof(CClient * pClientSrc, ITEMID_TYPE id, short x, short y, char z) +void CItemMultiCustom::AddRoof(CClient * pClientSrc, ITEMID_TYPE id, int16 x, int16 y, int8 z) { ADDTOCALLSTACK("CItemMultiCustom::AddRoof"); // add a roof piece to the building @@ -664,21 +664,24 @@ void CItemMultiCustom::AddRoof(CClient * pClientSrc, ITEMID_TYPE id, short x, sh CItemBase * pItemBase = CItemBase::FindItemBase(id); if (pItemBase == nullptr) { - g_Log.EventWarn("Unscripted roof tile 0%x being added to building 0%x by 0%x.\n", id, (dword)GetUID(), pCharSrc != nullptr ? (dword)pCharSrc->GetUID() : 0); + g_Log.EventWarn("Unscripted roof tile 0%x being added to building 0%x by 0%x.\n", + id, (dword)GetUID(), pCharSrc != nullptr ? (dword)pCharSrc->GetUID() : 0); SendStructureTo(pClientSrc); return; } if ((pItemBase->GetTFlags() & UFLAG4_ROOF) == 0) { - g_Log.EventWarn("Non-roof tile 0%x being added as a roof to building 0%x by 0%x.\n", id, (dword)GetUID(), pCharSrc != nullptr ? (dword)pCharSrc->GetUID() : 0); + g_Log.EventWarn("Non-roof tile 0%x being added as a roof to building 0%x by 0%x.\n", + id, (dword)GetUID(), pCharSrc != nullptr ? (dword)pCharSrc->GetUID() : 0); SendStructureTo(pClientSrc); return; } if (z < -3 || z > 12 || (z % 3 != 0)) { - g_Log.EventWarn("Roof tile 0%x being added at invalid height %d to building 0%x by 0%x.\n", id, z, (dword)GetUID(), pCharSrc != nullptr ? (dword)pCharSrc->GetUID() : 0); + g_Log.EventWarn("Roof tile 0%x being added at invalid height %d to building 0%x by 0%x.\n", + id, z, (dword)GetUID(), pCharSrc != nullptr ? (dword)pCharSrc->GetUID() : 0); SendStructureTo(pClientSrc); return; } @@ -689,7 +692,7 @@ void CItemMultiCustom::AddRoof(CClient * pClientSrc, ITEMID_TYPE id, short x, sh AddItem(pClientSrc, id, x, y, z); } -void CItemMultiCustom::RemoveItem(CClient * pClientSrc, ITEMID_TYPE id, short x, short y, char z) +void CItemMultiCustom::RemoveItem(CClient * pClientSrc, ITEMID_TYPE id, int16 x, int16 y, int8 z) { ADDTOCALLSTACK("CItemMultiCustom::RemoveItem"); // remove the item that's found at given location @@ -850,9 +853,9 @@ bool CItemMultiCustom::RemoveStairs(CMultiComponent * pStairComponent) fReplaceDirt = true; } - short x = pComp->m_item.m_dx; - short y = pComp->m_item.m_dy; - char z = (char)(pComp->m_item.m_dz); + int16 x = pComp->m_item.m_dx; + int16 y = pComp->m_item.m_dy; + int8 z = n16_narrow8(pComp->m_item.m_dz); it = m_designWorking.m_vectorComponents.erase(it); ++ m_designWorking.m_iRevision; @@ -869,7 +872,7 @@ bool CItemMultiCustom::RemoveStairs(CMultiComponent * pStairComponent) return true; } -void CItemMultiCustom::RemoveRoof(CClient * pClientSrc, ITEMID_TYPE id, short x, short y, char z) +void CItemMultiCustom::RemoveRoof(CClient * pClientSrc, ITEMID_TYPE id, int16 x, int16 y, int8 z) { ADDTOCALLSTACK("CItemMultiCustom::RemoveRoof"); @@ -1138,7 +1141,7 @@ size_t CItemMultiCustom::GetFixtureCount(CDesignDetails * pDesign) return count; } -size_t CItemMultiCustom::GetComponentsAt(short x, short y, char z, CMultiComponent ** pComponents, CDesignDetails * pDesign) +size_t CItemMultiCustom::GetComponentsAt(int16 x, int16 y, int8 z, CMultiComponent ** pComponents, CDesignDetails * pDesign) { ADDTOCALLSTACK("CItemMultiCustom::GetComponentsAt"); // find a list of components that are located at the given @@ -1148,14 +1151,14 @@ size_t CItemMultiCustom::GetComponentsAt(short x, short y, char z, CMultiCompone if (pDesign == nullptr) pDesign = &m_designMain; - const uchar uiPlane = GetPlane(z); + const uint8 uiPlane = GetPlane(z); size_t count = 0; for (CMultiComponent* pComponent : pDesign->m_vectorComponents) { if (pComponent->m_item.m_dx != x || pComponent->m_item.m_dy != y) continue; - if (z != INT8_MIN && GetPlane((char)(pComponent->m_item.m_dz)) != uiPlane) + if (z != INT8_MIN && GetPlane(n16_narrow8(pComponent->m_item.m_dz)) != uiPlane) continue; pComponents[count++] = pComponent; @@ -1170,7 +1173,7 @@ CPointMap CItemMultiCustom::GetComponentPoint(const CMultiComponent * pComp) con return GetComponentPoint(pComp->m_item.m_dx, pComp->m_item.m_dy, (char)(pComp->m_item.m_dz)); } -CPointMap CItemMultiCustom::GetComponentPoint(short dx, short dy, char dz) const +CPointMap CItemMultiCustom::GetComponentPoint(int16 dx, int16 dy, int8 dz) const { ADDTOCALLSTACK("CItemMultiCustom::GetComponentPoint"); // return the real world location from the given offset @@ -1302,15 +1305,15 @@ void CItemMultiCustom::CopyDesign(CDesignDetails * designFrom, CDesignDetails * } } -void CItemMultiCustom::GetLockdownsAt(short dx, short dy, char dz, std::vector &vList) +void CItemMultiCustom::GetLockdownsAt(int16 dx, int16 dy, int8 dz, std::vector &vList) { if (_lLockDowns.empty()) { return; } - short iFixedX = GetTopPoint().m_x + dx; - short iFixedY = GetTopPoint().m_y + dy; - char iFloor = CalculateLevel(GetTopPoint().m_z + dz); // get the Diff Z from the Multi's Z + const int16 iFixedX = GetTopPoint().m_x + dx; + const int16 iFixedY = GetTopPoint().m_y + dy; + const int8 iFloor = CalculateLevel(GetTopPoint().m_z + dz); // get the Diff Z from the Multi's Z for (std::vector::iterator it = _lLockDowns.begin(); it != _lLockDowns.end(); ++it) { CItem *pItem = (*it).ItemFind(); @@ -1324,7 +1327,7 @@ void CItemMultiCustom::GetLockdownsAt(short dx, short dy, char dz, std::vector &vList) +void CItemMultiCustom::GetSecuredAt(int16 dx, int16 dy, int8 dz, std::vector &vList) { if (_lSecureContainers.empty()) { @@ -1346,7 +1349,7 @@ void CItemMultiCustom::GetSecuredAt(short dx, short dy, char dz, std::vector(GetMovingCrate(true).ItemFind()); int i = 0; // Removing Secured Containers. @@ -1367,7 +1370,7 @@ void CItemMultiCustom::ClearFloor(char iFloor) { for (i = 0; i < max; ++i) { - CUID uid = _lSecureContainers[i]; + CUID uid(_lSecureContainers[i]); CItemContainer *pCont = static_cast(uid.ItemFind()); if ((pCont->GetTopPoint().m_z >= iMinZ) && (pCont->GetTopPoint().m_z <= iMaxZ)) { @@ -1584,17 +1587,18 @@ bool CItemMultiCustom::r_Verb(CScript & s, CTextConsole * pSrc) // Execute comma case IMCV_CLEARFLOOR: { - char iFloor = s.GetArgCVal(); + int8 iFloor = s.GetArg8Val(); if (iFloor == -1) { - for (int i = 0; i < _iMaxPlane; ++i) + ASSERT(_iMaxPlane < INT8_MAX); + for (int8 i = 0; i < (int8)_iMaxPlane; ++i) { - ClearFloor((char)i); + ClearFloor(i); } } else { - ClearFloor(s.GetArgCVal()); + ClearFloor(s.GetArg8Val()); } } break; @@ -1867,7 +1871,7 @@ bool CItemMultiCustom::r_LoadVal(CScript & s) return false; } -uchar CItemMultiCustom::GetPlane(char z) +uint8 CItemMultiCustom::GetPlane(int8 z) { if (z >= 67) return 4; @@ -1881,14 +1885,14 @@ uchar CItemMultiCustom::GetPlane(char z) return 0; } -uchar CItemMultiCustom::GetPlane(const CMultiComponent * pComponent) +uint8 CItemMultiCustom::GetPlane(const CMultiComponent * pComponent) { - return GetPlane((char)(pComponent->m_item.m_dz)); + return GetPlane(n16_narrow8(pComponent->m_item.m_dz)); } -char CItemMultiCustom::GetPlaneZ(uchar plane) +int8 CItemMultiCustom::GetPlaneZ(uint8 plane) { - return 7 + ((plane - 1) * 20); + return n32_narrow8_checked(7 + ((plane - 1) * 20)); } bool CItemMultiCustom::IsValidItem(ITEMID_TYPE id, CClient * pClientSrc, bool fMulti) diff --git a/src/game/items/CItemMultiCustom.h b/src/game/items/CItemMultiCustom.h index 237c83628..169345ed5 100644 --- a/src/game/items/CItemMultiCustom.h +++ b/src/game/items/CItemMultiCustom.h @@ -20,7 +20,7 @@ class CItemMultiCustom : public CItemMulti struct CMultiComponent { CUOMultiItemRec_HS m_item; - short m_isStair; + ushort m_isStair; bool m_isFloor; }; @@ -65,8 +65,8 @@ class CItemMultiCustom : public CItemMulti virtual bool r_Verb(CScript & s, CTextConsole * pSrc) override; // Execute command from script CPointMap GetComponentPoint(const CMultiComponent * pComponent) const; - CPointMap GetComponentPoint(short dx, short dy, char dz) const; - + CPointMap GetComponentPoint(int16 dx, int16 dy, int8 dz) const; + /** * @brief Removes a CMultiComponent from the components list. * @param pComponent the component. @@ -74,10 +74,10 @@ class CItemMultiCustom : public CItemMulti virtual void DeleteComponent(const CUID& uidComponent, bool fRemoveFromList) override final; void CopyDesign(CDesignDetails * designFrom, CDesignDetails * designTo); - void GetLockdownsAt(short dx, short dy, char dz, std::vector &vList); - void GetSecuredAt(short dx, short dy, char dz, std::vector &vList); - char CalculateLevel(char z); - void ClearFloor(char iFloor); + void GetLockdownsAt(int16 dx, int16 dy, int8 dz, std::vector &vList); + void GetSecuredAt(int16 dx, int16 dy, int8 dz, std::vector &vList); + int8 CalculateLevel(int8 z); + void ClearFloor(int8 iFloor); private: using ValidItemsContainer = std::map; // ItemID, FeatureMask @@ -99,12 +99,12 @@ class CItemMultiCustom : public CItemMulti void EndCustomize(bool fForce = false); void SwitchToLevel(CClient * pClientSrc, uchar iLevel); void CommitChanges(CClient * pClientSrc = nullptr); - void AddItem(CClient * pClientSrc, ITEMID_TYPE id, short x, short y, char z = INT8_MIN, short iStairID = 0); - void AddStairs(CClient * pClientSrc, ITEMID_TYPE id, short x, short y, char z = INT8_MIN); - void AddRoof(CClient * pClientSrc, ITEMID_TYPE id, short x, short y, char z); - void RemoveItem(CClient * pClientSrc, ITEMID_TYPE id, short x, short y, char z); + void AddItem(CClient * pClientSrc, ITEMID_TYPE id, int16 x, int16 y, int8 z = INT8_MIN, ushort iStairID = 0); + void AddStairs(CClient * pClientSrc, ITEMID_TYPE id, int16 x, int16 y, int8 z = INT8_MIN); + void AddRoof(CClient * pClientSrc, ITEMID_TYPE id, int16 x, int16 y, int8 z); + void RemoveItem(CClient * pClientSrc, ITEMID_TYPE id, int16 x, int16 y, int8 z); bool RemoveStairs(CMultiComponent * pStairComponent); - void RemoveRoof(CClient * pClientSrc, ITEMID_TYPE id, short x, short y, char z); + void RemoveRoof(CClient * pClientSrc, ITEMID_TYPE id, int16 x, int16 y, int8 z); void SendVersionTo(CClient * pClientSrc) const; void SendStructureTo(CClient * pClientSrc); void BackupStructure(); @@ -115,13 +115,13 @@ class CItemMultiCustom : public CItemMulti const CSphereMultiCustom * GetMultiItemDefs(); const CRect GetDesignArea(); size_t GetFixtureCount(CDesignDetails * pDesign = nullptr); - size_t GetComponentsAt(short dx, short dy, char dz, CMultiComponent ** pComponents, CDesignDetails * pDesign = nullptr); + size_t GetComponentsAt(int16 dx, int16 dy, int8 dz, CMultiComponent ** pComponents, CDesignDetails * pDesign = nullptr); int GetRevision(const CClient * pClientSrc = nullptr) const; uchar GetLevelCount(); - static uchar GetPlane(char z); - static uchar GetPlane(const CMultiComponent * pComponent); - static char GetPlaneZ(uchar plane); + static uint8 GetPlane(int8 z); + static uint8 GetPlane(const CMultiComponent * pComponent); + static int8 GetPlaneZ(uint8 plane); static bool IsValidItem(ITEMID_TYPE id, CClient * pClientSrc, bool fMulti); CDesignDetails* GetDesignMain() diff --git a/src/game/spheresvr.cpp b/src/game/spheresvr.cpp index 5588e1b66..070ead4b5 100644 --- a/src/game/spheresvr.cpp +++ b/src/game/spheresvr.cpp @@ -138,11 +138,11 @@ UnixTerminal g_UnixTerminal; LinuxEv g_NetworkEvent; #endif -CServer g_Serv; // current state, stuff not saved. CLog g_Log; // Config data from sphere.ini is needed from the beginning. CServerConfig g_Cfg; +CServer g_Serv; // current state, stuff not saved. CAccounts g_Accounts; // All the player accounts. name sorted CAccount // Game servers stuff. diff --git a/src/game/uo_files/CUOMapMeter.h b/src/game/uo_files/CUOMapMeter.h index eaac0fd12..94350d817 100644 --- a/src/game/uo_files/CUOMapMeter.h +++ b/src/game/uo_files/CUOMapMeter.h @@ -25,7 +25,7 @@ struct CUOMapMeter { word m_wTerrainIndex; // TERRAIN_TYPE index to Radarcol and CUOTerrainTypeRec/CUOTerrainTypeRec_HS - char m_z; + int8 m_z; static bool IsTerrainNull( word wTerrainIndex ); } PACK_NEEDED; From 6194606ab94c6f738498bb21d0cee85e4bc81b2f Mon Sep 17 00:00:00 2001 From: Orfeo Ciano Date: Mon, 26 Aug 2024 17:45:16 +0100 Subject: [PATCH 10/86] Add "getting started" documentation (#1276) --- README.md | 3 + docs/Getting-started.md | 554 ++++++++++++++++++++++++++++++++++++++++ 2 files changed, 557 insertions(+) create mode 100644 docs/Getting-started.md diff --git a/README.md b/README.md index 358cbc58d..eb61d6d6f 100644 --- a/README.md +++ b/README.md @@ -12,6 +12,9 @@ Ultima Online game server, developed in C++. | :---: | | [![Discord Shield](https://discordapp.com/api/guilds/354358315373035542/widget.png?style=shield)](https://discord.gg/ZrMTXrs) | +## Getting Started tutorial +If you're new to the Sphere server and want to setup your first shard, [this is your go-to guide](docs/Getting-started.md)! + ## Releases ### **Core** diff --git a/docs/Getting-started.md b/docs/Getting-started.md new file mode 100644 index 000000000..8a63917cf --- /dev/null +++ b/docs/Getting-started.md @@ -0,0 +1,554 @@ +Table Of Contents +- [Getting Started With Sphere server](#getting-started-with-sphere-server) + - [Downloading the Sphere server](#downloading-the-sphere-server) + - [\[Linux Only\] Download dependencies](#linux-only-download-dependencies) + - [\[Linux Only\] Copy binary into root folder](#linux-only-copy-binary-into-root-folder) + - [Client Installation](#client-installation) + - [Server Configuration](#server-configuration) + - [Acknowledge the usage of a nightly build](#acknowledge-the-usage-of-a-nightly-build) + - [Enable automatic account creations](#enable-automatic-account-creations) + - [MUL files](#mul-files) + - [A. Do not change the Sphere.ini file](#a-do-not-change-the-sphereini-file) + - [B. Specify your client's installation folder](#b-specify-your-clients-installation-folder) + - [C. Copy client's files into the server's folder](#c-copy-clients-files-into-the-servers-folder) + - [Configure maps](#configure-maps) + - [Setup Scripts](#setup-scripts) + - [Download scripts](#download-scripts) + - [Tweak the spheretables.scp](#tweak-the-spheretablesscp) + - [Start the server](#start-the-server) + - [Connect to your server](#connect-to-your-server) + - [Making yourself an admin](#making-yourself-an-admin) + - [Populating the world](#populating-the-world) + - [World decorations](#world-decorations) + - [World spawner](#world-spawner) + - [Next steps](#next-steps) + +# Getting Started With Sphere server +This tutorial is directed to those that have no experience whatsoever with +the Sphere Server. The objective is to just get started with a fully functional +shard which, later on, can be tweaked and customised as needed. + +## Downloading the Sphere server +The first obvious step is to download the Sphere server. + +Go to the [SphereX](https://forum.spherecommunity.net/sshare.php?srt=4) +Download page and download the latest nightly version for your platform. + +Extract the zip or tgz into a new folder. + +### [Linux Only] Download dependencies +In order for the server to work correctly, you'll need to install mariadb +client. Different distros name this library in a different way so, have a quick +check online to understand how to install it on your distro. For instance, +if you're using an Ubuntu-based system, you can install it by running + +``` +sudo apt install mariadb-client +``` + +### [Linux Only] Copy binary into root folder +Once you've extracted your archive, you'll need to move the server's executable +into the root directory of the server. The file is contained into the +`build-xx` folder. + +For instance, for a 64 bits linux installation, your root folder's structure +should go from this: +``` +- accounts/ +- build-64/ + - bin-x86_64 + - SphereSvrX64_nightly +- logs/ +- save/ +- scripts +- sphere.ini +- sphereCrypt.ini +``` + +To this +``` +- accounts/ +- logs/ +- save/ +- scripts +- sphere.ini +- sphereCrypt.ini +- SphereSvrX64_nightly // executable in root +``` + +## Client Installation +Now it's time to pick a client. Take the original installation of your Ultima +Online client and install it. If you don't have it... Google is your friend ;). +For this tutorial we're going to use `Ultima Online Classic 7.0.2.0` client. + +SphereX is compatible with any client, so feel free to pick any version but, +be careful: in order to have the same experience across every participant, +make sure that user is running exactly the same client! + +## Server Configuration +Now it's time make some tweaks to the default server configuration to accomodate +our needs. + +The whole server configuration is contained in the file named `sphere.ini`. +You can open this file with any text editor - notepad should do the job. The +structure of the file is very simple: let's analyse a snippet to explain how +it's organised line by line. +``` +[SPHERE] +// Name of your Sphere shard +ServName=MyShard +``` + +`[SPHERE]`: this is a section of the configuration. It is used to group +properties together. + +`// Name of your Sphere shard`: this is a comment. It gets ignored by the +server. This is used to add additional infos to humans :) + +`ServName=MyShard`: this is a property. This is used to configure specific +behaviours for the server. For instance, this is used to set the name of the +shard. + +### Acknowledge the usage of a nightly build +Before you can start fiddling with different things, you'll need to agree of +using a nightly build. A nightly build gets created automatically every night +based on the latest changes made by the developers. This means it might contain +potential bugs. With this settings you agree to take full responsibility of all +the implications of this choice. + +So, let's open the `sphere.ini` file and add a new line to the `SPHERE` +section with the text `AGREE=1`. After the changes your file should look like +this. + +``` +... +[SPHERE] +// Add this line +AGREE=1 +// Name of your Sphere shard +ServName=MyShard +... +``` + +**Remember** to save the file before you start the server, otherwise the changes +will not be picked up by the server. + +### Enable automatic account creations +The next step is to allow people to easily join your server upon creating a new +account upon a login attempt. + +Moving down into the configuration file, you'll find a property called `AccApp`. +Set this value to `2`, to allow everyone to login and create a new account. + +``` +//Code for servers account application process +// 0=Closed, // Closed. Not accepting more. +// 2=Free, // Anyone can just log in and create a full account. +// 3=GuestAuto, // You get to be a guest and are automatically sent email with u're new password. +// 4=GuestTrial, // You get to be a guest til u're accepted for full by an Admin. +// 6=Unspecified, // Not specified. +// To enable auto account you must set this to 2 +AccApp=2 +``` + +You can change this value later on as per comments above this property. As +usual, remember to save the file before moving on. + +### MUL files +MUL files are called like this because their extensions is `.mul`. These files +are vital for the correct execution of the client and the server because they +contain all the assets of the game. This includes (but not limited to): +- maps; +- animations; +- armors; +- vests; +- decorations; +- ... + +These files are contained into the Ultima Online client's installation. + +**WARNING:** If there a discrepancy between server's muls and client's muls +players will experience serious bugs or crashes. + +For this reason we need to make sure that the server is picking up the mul +files from the Ultima Online client's installation. There are different ways +to achieve this. + +#### A. Do not change the Sphere.ini file +If you're using Windows and you've got just one Ultima Online Client installed +through the official EA installer, you can just skip this step and move on with +the next step of this guide. + +#### B. Specify your client's installation folder +Open your `sphere.ini` file and find the `MulFile` property. Uncomment it +(remove the leading `//`) and change its value to the location of you're +client's installation folder. For instance: + +``` +// UO INSTALLATION - Note that if it's not set ( or commented ), sphere will scan windows registry to auto-detect it. +// If windows can't find the dir, then it must point to install's directory. +// +// For Old installations (client less than 7.0.20) this need: map0.mul, statics0.mul, +// staidx0.mul, multi.mul, multi.idx, hues.mul, tiledata.mul. +// Optional files: verdata.mul, mapX.mul/staticsX.mul/staidxX.mul for higher +// maps support (Malas, etc). +// +// For newer installs this need the same files in .uop format +// +// A full install folder is recommended as required files may change over time. +MulFiles=C:/Program Files/EA Games/Ultima Online/ +``` + +#### C. Copy client's files into the server's folder +Create a new folder into the server's root folder. For instance you can call it +`mul`. + +For simplicity, copy all the contents of your Ultima Online client's +folder into the folder you've just created. + +Now open your `sphere.ini` file and locate the `MulFile` property. Uncomment it +(remove the leading `//`) and change its value to the name of the folder where +you've just created. For instance: + +``` +// UO INSTALLATION - Note that if it's not set ( or commented ), sphere will scan windows registry to auto-detect it. +// If windows can't find the dir, then it must point to install's directory. +// +// For Old installations (client less than 7.0.20) this need: map0.mul, statics0.mul, +// staidx0.mul, multi.mul, multi.idx, hues.mul, tiledata.mul. +// Optional files: verdata.mul, mapX.mul/staticsX.mul/staidxX.mul for higher +// maps support (Malas, etc). +// +// For newer installs this need the same files in .uop format +// +// A full install folder is recommended as required files may change over time. +MulFiles=mul/ +``` + +**NOTE**: You don't need all the files contained into the Ultima Online client's +installation. You just need all the `.mul` and `.idx` files. + +**NOTE 2**: On linux the name of the files is case sensitive so, make sure all +the file names are lowercase! + +### Configure maps +New that we've imported all the maps we need to set each the map's boundaries: +this way the server will know what is the actual playable area. For the +purpose of this guide, we'll just use the maps of Falucca and Trammel. + +As usual, open your `sphere.ini` file and locate all the `MapX` properties. +Leave `Map0` (Felucca) and `Map1` (Trammel) as they are and add a leading `//` +to `Map2`, `Map3`, `Map4` and `Map5`. + +This is how it should look like. +``` +// Map of Felucca +//Map0=6144,4096,-1,0,0 //Old size +Map0=7168,4096,-1,0,0 //ML size + +// Map of Trammel +//Map1=6144,4096,-1,1,1 //Old size +Map1=7168,4096,-1,1,1 //ML size + +// Map of Ilshenar +//Map2=2304,1600,-1,2,2 + +// Map of Malas +//Map3=2560,2048,-1,3,3 + +// Map of Tokuno Islands +//Map4=1448,1448,-1,4,4 + +// Map of Ter Mur +//Map5=1280,4096,-1,5,5 +``` + +## Setup Scripts +We've got a nice server. But it is completely brainless: it doesn't know what +is a vendor, an npc and what are their behaviours. In order to give it a brain +we should add some scripts. If we were to write all of them, it would take +ages. For this reason Sphere comes with a pre-made set of scripts to get you +started in no time. + +### Download scripts +Head out to the +[SphereX Github page](https://github.com/Sphereserver/Scripts-X) click on `Code` +and hit `Download ZIP`. + +Unzip the content of the package into the server's `scripts` folder. + +### Tweak the spheretables.scp +Now we need to tweak few settings according to our `sphere.ini` configuration. +Go ahead and open with your text editor the file `scripts/spheretables.scp`. + +Let's comment out all the configurations related to all non Felucca and +Trammel maps, respectively `map0` and `map1`. + +Here is the before: +``` +// maps +maps/map0/map0_starts.scp +maps/map0/map0_moongates.scp +maps/map0/map0_areas.scp +maps/map0/map0_areas_ml.scp +maps/map0/map0_areas_sa.scp +maps/map0/map0_areas_hs.scp +maps/map0/map0_rooms.scp +maps/map0/map0_teleports.scp +maps/map0/map0_teleports_ml.scp +maps/map0/map0_teleports_hs.scp +maps/map0/map0_teleports_tol.scp + +maps/map1/map1_moongates.scp +maps/map1/map1_areas.scp +//maps/map1/map1_areas_aos_old_haven.scp +maps/map1/map1_areas_ml_new_haven.scp +maps/map1/map1_areas_ml.scp +maps/map1/map1_areas_sa.scp +maps/map1/map1_areas_hs.scp +maps/map1/map1_rooms.scp +maps/map1/map1_teleports.scp +maps/map1/map1_teleports_ml.scp +maps/map1/map1_teleports_ml_new_haven.scp +maps/map1/map1_teleports_hs.scp +maps/map1/map1_teleports_tol.scp + +maps/map2/map2_areas.scp +maps/map2/map2_areas_ml.scp +maps/map2/map2_teleports.scp +maps/map2/map2_teleports_ml.scp +maps/map2/map2_moongates.scp + +maps/map3/map3_areas.scp +maps/map3/map3_areas_ml.scp +maps/map3/map3_areas_se.scp +maps/map3/map3_teleports.scp +maps/map3/map3_teleports_ml.scp +maps/map3/map3_teleports_se.scp +maps/map3/map3_moongates.scp + +maps/map4/map4_areas.scp +maps/map4/map4_teleports.scp +maps/map4/map4_moongates.scp + +maps/map5/map5_areas.scp +maps/map5/map5_areas_tol.scp +maps/map5/map5_teleports.scp +maps/map5/map5_teleports_tol.scp +maps/map5/map5_moongates.scp +maps/map5/map5_moongates_tol.scp + +``` + +and this is how the file should look like after our amendments: +``` +// maps +maps/map0/map0_starts.scp +maps/map0/map0_moongates.scp +maps/map0/map0_areas.scp +maps/map0/map0_areas_ml.scp +maps/map0/map0_areas_sa.scp +maps/map0/map0_areas_hs.scp +maps/map0/map0_rooms.scp +maps/map0/map0_teleports.scp +maps/map0/map0_teleports_ml.scp +maps/map0/map0_teleports_hs.scp +maps/map0/map0_teleports_tol.scp + +maps/map1/map1_moongates.scp +maps/map1/map1_areas.scp +//maps/map1/map1_areas_aos_old_haven.scp +maps/map1/map1_areas_ml_new_haven.scp +maps/map1/map1_areas_ml.scp +maps/map1/map1_areas_sa.scp +maps/map1/map1_areas_hs.scp +maps/map1/map1_rooms.scp +maps/map1/map1_teleports.scp +maps/map1/map1_teleports_ml.scp +maps/map1/map1_teleports_ml_new_haven.scp +maps/map1/map1_teleports_hs.scp +maps/map1/map1_teleports_tol.scp + +//maps/map2/map2_areas.scp +//maps/map2/map2_areas_ml.scp +//maps/map2/map2_teleports.scp +//maps/map2/map2_teleports_ml.scp +//maps/map2/map2_moongates.scp + +//maps/map3/map3_areas.scp +//maps/map3/map3_areas_ml.scp +//maps/map3/map3_areas_se.scp +//maps/map3/map3_teleports.scp +//maps/map3/map3_teleports_ml.scp +//maps/map3/map3_teleports_se.scp +//maps/map3/map3_moongates.scp + +//maps/map4/map4_areas.scp +//maps/map4/map4_teleports.scp +//maps/map4/map4_moongates.scp + +//maps/map5/map5_areas.scp +//maps/map5/map5_areas_tol.scp +//maps/map5/map5_teleports.scp +//maps/map5/map5_teleports_tol.scp +//maps/map5/map5_moongates.scp +//maps/map5/map5_moongates_tol.scp +``` + +Now you can save the file and close your editor. + +## Start the server +It's now time to start the server by running `SphereSvrX64_nightly.exe`. + +If everything's fine, should see on the console this confirmation message: + +``` +Startup complete (items=0, chars=0, Accounts = 0) +Use '?' to view available console commands +``` + +## Connect to your server +Now that you've configured the server, you're finally ready to start playing! + +By default the Ultima Online Client will connect to the official game servers. +However, what we want to do is to connect to our server. There are multiple +tools you can use like Razor - just Google a bit ;). + +For the purpose of this guide we're going to use ClassicUO. So head out to +[their website](https://www.classicuo.eu/) and download the client for your +platform. Extract it into a new folder on your desktop and open the +`ClassicUOLauncher`. + +Create a new profile and fill the fields as follows: +- Profile name: pick a name of your choice +- Server IP: `127.0.0.1` - provided you're running client and server on the +same machine +- Port: `2593` +- Use Encryption: enabled +- UO Path: the installation folder of your Ultima Online client (e.g. `C:/Program Files/EA Games/Ultima Online/`) + +Now save your profile and hit back. On the main screen make sure that the +profile you've just created is selected and hit Play. If you've done everything +correctly, the Ultima Online login screen should pop up. As per previous +configuration you can now try to login with any username and password: this +operation will automatically create a new user for you. + +So, pick a username and password and try to login. Create a new character et +voila': you're the first player of your own personal Ultima Online Shard! + +## Making yourself an admin +Well, since this is your server, I guess it's only fair to set yourself as an +admin of the server. This will allow you to do some special operations that +noone else can do like populating the world with new creatures, items, ban +players, broadcast messages, ... + +Go ahead and open you server's window. If you're on Windows, you'll se that at +the bottom there a grey stripe on which you can type stuff. To promote yourself +as an admin you can just type + +``` +ACCOUNT PLEVEL 7 +``` +And hit enter. + +So, for instance, if your account name (**not player name!**) is `admin`, you +should just type +``` +ACCOUNT admin PLEVEL 7 +``` +and hit enter. + +To check whether it works, go back to your game and type in chat + +``` +.gm +``` + +This command is to transform yourself into a GM (Game Master). If you'll see +a message `GM ON` everything has worked out! + +## Populating the world +I guess you've already noticed that Britain has never been so empty, right? + +We've already got a solution for you to get started straight away!!! + +### World decorations + +Go into your game and type in the game's chat + +``` +.add i_world_decorator +``` +And hit enter. + +The cursor will tranform into a target. Place the item on the floor right next +to you and double-click it. A new window (aka "gump") will appear. + +Under `Basic Items` hit: +- Generate Doors; +- Generate Signs; +- Generate Moongates; +- Generate Book; + +Under Decoration hit: +- Felucca +- Trammel + +remember? We have disabled all the other maps, so it's useless to try and +generate decorations for those maps. + +Now that you're done, you can remove world decorator object. Just type on your +chat + +``` +.remove +``` +The cursor will transform into a target. Choose the world decorator so make it +disappear from the game. + +Once you've completed this step, go back to your server window and type + +``` +## +``` +And hit enter. This will save both, the new account you've just created and +all the objects that have been placed in the game. It will take a few seconds, +so, be patient. + +### World spawner +Last but not least, the world is sad without vendors, mobs, animals, mounts, ... +As usual: there is a solution for this as well. + +Head out to your game window and type in the chat +``` +.add i_world_spawner +``` +Place the item right close to you and double-click it. + +As before, hit Felucca and, in the submenu, click all the spawn items **once**. + +Do the same thing for Trammel. + +Same steps as before: +``` +.remove +``` +and click on the world spawner object. + +Finally save all your changes by going back to the server window and issue the +``` +## +``` +command. + +## Next steps +Congratulations: you've just created your fully functional shard from scratch! + +However, this is just the beginning of your journey: if you want to know more +about Sphere server, access the +[wiki page](https://wiki.spherecommunity.net/index.php?title=Main_Page) + +If you need further help, get into the +[Sphere discord server](https://discord.gg/ZrMTXrs). + +Have fun! \ No newline at end of file From 1f43026f8ddcb2f2d6a06338b1b517c79c4e6916 Mon Sep 17 00:00:00 2001 From: cbnolok Date: Mon, 26 Aug 2024 19:27:57 +0200 Subject: [PATCH 11/86] Minimal refactoring to README.md, formatted the builds table to be more compact. --- README.md | 168 ++++++++++++++++++++++++++---------------------------- 1 file changed, 80 insertions(+), 88 deletions(-) diff --git a/README.md b/README.md index eb61d6d6f..2dc55d47d 100644 --- a/README.md +++ b/README.md @@ -23,12 +23,9 @@ If you're new to the Sphere server and want to setup your first shard, [this is | :--- | :--- | | [![GitHub last commit on Master branch](https://img.shields.io/github/last-commit/Sphereserver/Source-X/master.svg)](https://github.com/Sphereserver/Source-X/)   Changelog | [![GitHub last commit on Dev branch](https://img.shields.io/github/last-commit/Sphereserver/Source-X/dev.svg)](https://github.com/Sphereserver/Source-X/tree/dev)   Changelog | | **Nightly builds:** | **Nightly builds:** | -| [![Build status: Windows x86_64](https://github.com/Sphereserver/Source-X/actions/workflows/build_win_x86_64.yml/badge.svg?branch=master)](https://github.com/Sphereserver/Source-X/actions/workflows/build_win_x86_64.yml) | [![Build status: Windows x86_64](https://github.com/Sphereserver/Source-X/actions/workflows/build_win_x86_64.yml/badge.svg?branch=dev)](https://github.com/Sphereserver/Source-X/actions/workflows/build_win_x86_64.yml) | -| [![Build status: Windows x86](https://github.com/Sphereserver/Source-X/actions/workflows/build_win_x86.yml/badge.svg?branch=master)](https://github.com/Sphereserver/Source-X/actions/workflows/build_win_x86.yml) | [![Build status: Windows x86](https://github.com/Sphereserver/Source-X/actions/workflows/build_win_x86.yml/badge.svg?branch=dev)](https://github.com/Sphereserver/Source-X/actions/workflows/build_win_x86.yml) | -| [![Build status: Linux x86_64](https://github.com/Sphereserver/Source-X/actions/workflows/build_linux_x86_64.yml/badge.svg?branch=master)](https://github.com/Sphereserver/Source-X/actions/workflows/build_linux_x86_64.yml) | [![Build status: Linux x86_64](https://github.com/Sphereserver/Source-X/actions/workflows/build_linux_x86_64.yml/badge.svg?branch=dev)](https://github.com/Sphereserver/Source-X/actions/workflows/build_linux_x86_64.yml) | -| [![Build status: Linux x86](https://github.com/Sphereserver/Source-X/actions/workflows/build_linux_x86.yml/badge.svg?branch=master)](https://github.com/Sphereserver/Source-X/actions/workflows/build_linux_x86.yml) | [![Build status: Linux x86](https://github.com/Sphereserver/Source-X/actions/workflows/build_linux_x86.yml/badge.svg?branch=dev)](https://github.com/Sphereserver/Source-X/actions/workflows/build_linux_x86.yml) | -| [![Build status: MacOS x86_64](https://github.com/Sphereserver/Source-X/actions/workflows/build_osx_x86_64.yml/badge.svg?branch=master)](https://github.com/Sphereserver/Source-X/actions/workflows/build_osx_x86_64.yml) | [![Build status: MacOS x86_64](https://github.com/Sphereserver/Source-X/actions/workflows/build_osx_x86_64.yml/badge.svg?branch=dev)](https://github.com/Sphereserver/Source-X/actions/workflows/build_osx_x86_64.yml) | -| [![Build status: MacOS ARM](https://github.com/Sphereserver/Source-X/actions/workflows/build_osx_arm.yml/badge.svg?branch=master)](https://github.com/Sphereserver/Source-X/actions/workflows/build_osx_arm.yml) | [![Build status: MacOS ARM](https://github.com/Sphereserver/Source-X/actions/workflows/build_osx_arm.yml/badge.svg?branch=dev)](https://github.com/Sphereserver/Source-X/actions/workflows/build_osx_arm.yml) | +| [![Build status: Windows x86_64](https://github.com/Sphereserver/Source-X/actions/workflows/build_win_x86_64.yml/badge.svg?branch=master)](https://github.com/Sphereserver/Source-X/actions/workflows/build_win_x86_64.yml) [![Build status: Windows x86](https://github.com/Sphereserver/Source-X/actions/workflows/build_win_x86.yml/badge.svg?branch=master)](https://github.com/Sphereserver/Source-X/actions/workflows/build_win_x86.yml) | [![Build status: Windows x86_64](https://github.com/Sphereserver/Source-X/actions/workflows/build_win_x86_64.yml/badge.svg?branch=dev)](https://github.com/Sphereserver/Source-X/actions/workflows/build_win_x86_64.yml) [![Build status: Windows x86](https://github.com/Sphereserver/Source-X/actions/workflows/build_win_x86.yml/badge.svg?branch=dev)](https://github.com/Sphereserver/Source-X/actions/workflows/build_win_x86.yml)| +| [![Build status: Linux x86_64](https://github.com/Sphereserver/Source-X/actions/workflows/build_linux_x86_64.yml/badge.svg?branch=master)](https://github.com/Sphereserver/Source-X/actions/workflows/build_linux_x86_64.yml) [![Build status: Linux x86](https://github.com/Sphereserver/Source-X/actions/workflows/build_linux_x86.yml/badge.svg?branch=master)](https://github.com/Sphereserver/Source-X/actions/workflows/build_linux_x86.yml) | [![Build status: Linux x86_64](https://github.com/Sphereserver/Source-X/actions/workflows/build_linux_x86_64.yml/badge.svg?branch=dev)](https://github.com/Sphereserver/Source-X/actions/workflows/build_linux_x86_64.yml) [![Build status: Linux x86](https://github.com/Sphereserver/Source-X/actions/workflows/build_linux_x86.yml/badge.svg?branch=dev)](https://github.com/Sphereserver/Source-X/actions/workflows/build_linux_x86.yml) | +| [![Build status: MacOS x86_64](https://github.com/Sphereserver/Source-X/actions/workflows/build_osx_x86_64.yml/badge.svg?branch=master)](https://github.com/Sphereserver/Source-X/actions/workflows/build_osx_x86_64.yml) [![Build status: MacOS ARM](https://github.com/Sphereserver/Source-X/actions/workflows/build_osx_arm.yml/badge.svg?branch=master)](https://github.com/Sphereserver/Source-X/actions/workflows/build_osx_arm.yml) | [![Build status: MacOS x86_64](https://github.com/Sphereserver/Source-X/actions/workflows/build_osx_x86_64.yml/badge.svg?branch=dev)](https://github.com/Sphereserver/Source-X/actions/workflows/build_osx_x86_64.yml) [![Build status: MacOS ARM](https://github.com/Sphereserver/Source-X/actions/workflows/build_osx_arm.yml/badge.svg?branch=dev)](https://github.com/Sphereserver/Source-X/actions/workflows/build_osx_arm.yml) | **Click the badges or follow the links:** @@ -74,67 +71,63 @@ Most notable changes (right now) are: ### Required libraries (Windows) -+ `libmariadb.dll` (MariaDB Client v10.*package), found in lib/bin/*cpu_architecture*/mariadb/libmariadb.dll ++ `libmariadb.dll` (MariaDB Client v10.*package), found in `lib/bin/*cpu_architecture*/mariadb/libmariadb.dll`
### Required libraries (Linux) + MariaDB Client library. Get it from the following sources. -
- -#### From MariaDB website - -See - -#### Ubuntu and Debian repositories - -Ubuntu: Enable "universe" repository: `sudo add-apt-repository universe` -Install MariaDB client: `sudo apt-get install mariadb-client` or `sudo apt-get install libmariadb3` (depends on the OS version) - -#### CentOS - Red Hat Enterprise Linux - Fedora repositories - -Then install MariaDB client via yum (CentOS or RH) or dnf (Fedora): `mariadb-connector-c` -
+ + From MariaDB website + See + + Ubuntu and Debian repositories + Ubuntu: Enable "universe" repository: `sudo add-apt-repository universe` + Install MariaDB client: `sudo apt-get install mariadb-client` or `sudo apt-get install libmariadb3` (depends on the OS version) + + CentOS - Red Hat Enterprise Linux - Fedora repositories + Then install MariaDB client via yum (CentOS or RH) or dnf (Fedora): `mariadb-connector-c` ### Required libraries (MacOS) + Install MariaDB Client library via `brew install mariadb-connector-c` -## Building +## Building the server from the source ### Generating the project files -The compilation of the code is possible only using recent compilers, since C++20 features are used: the newer the compiler, the better. Oldest compiler versions supporting C++20: Visual Studio 2019 version 16.11, GCC 8, MinGW distributions using GCC 8, Clang version 10.
-You need to build Makefiles or Ninja files (and project files if you wish) with CMake for both Linux (GCC) and Windows (MSVC and MinGW).
-Both 32 and 64 bits compilation are supported.
-No pre-built project files included.
-Does CMake give you an error? Ensure that you have Git installed, and if you are on Windows ensure also that the Git executable was added to the PATH environmental variable +Only recent compilers are supported, since Sphere uses C++20 features: the newer the compiler, the better. Oldest compiler versions supporting C++20: Visual Studio 2019 version 16.11, GCC 8, MinGW distributions using GCC 8, Clang version 10. +No pre-built project files are included. You need to build Visual Studio solution (.sln), Makefiles or Ninja Build files (or project files for other IDE or build systems) with CMake. +Below there's is a small guide. +You can use CMake GUI (graphical interface) or its CLI (command line interface). +To pass a flag to using the CLI, just prepend `-D` to the name of the variable, then assign the value with the equal sign, eg: `-DFOO=TRUE`. + +Before starting: does CMake give you an error? Ensure that you have Git installed, and if you are on Windows ensure also that the Git executable was added to the PATH environmental variable (you'll need to add it manually if you are using Git Desktop, - here's a quick guide).
- -#### Toolchains and custom CMake variables - -When generating project files, if you don't specify a toolchain, the CMake script will pick the native one as default.
-How to set a toolchain: - -+ Via CMake GUI: when configuring for the first time the project, choose "Specify toolchain file for cross-compiling", then on the next step you'll be allowed to select the toolchain file -+ Via CMake CLI (command line interface): pass the parameter `-DCMAKE_TOOLCHAIN_FILE="..."` - When using Makefiles or Ninja, you can specify a build type by setting (also this via GUI or CLI) `CMAKE_BUILD_TYPE="build"`, where build is **Nightly**, **Debug** or **Release**. If the build type - was not set, by default the makefiles for all of the three build types are generated.
-
- -You can also add other compiler flags, like optimization flags, with the custom variables C_FLAGS_EXTRA and CXX_FLAGS_EXTRA.
- -Example of CMake CLI additional parameters:
- -```bash --DC_FLAGS_EXTRA="-mtune=native" -DCXX_FLAGS_EXTRA="-mtune=native" -``` - -(Use the -mtune=native flag only if you are compiling on the same machine on which you will execute Sphere!) - -Example to build makefiles on Linux for a 64 bits Nightly version, inside the "build" directory (run it inside the project's root folder):
- + here's a quick guide). + ++ Select a **Generator** + Tells CMake which kind of project file to generate (Visual Studio, makefile, ninja build file...) + + GUI: it's the first thing CMake will ask you (well, after Sphere source directory) + + CLI: use -G flag, example: `-G "Visual Studio 17 2022"` or `-G Ninja`. + ++ Select a **Toolchain** + When generating project files, the easiest way is to use the provided OS-specific CMake toolchain file to automatically pass the right options to the selected compiler. + You can find them in the `cmake/toolchains/` folder. + If you don't specify a toolchain, CMake will pick the native one as default. + How to set a toolchain: + + Via CMake GUI: when configuring for the first time the project, choose "Specify toolchain file for cross-compiling", then on the next step you'll be allowed to select the toolchain file. + + Via CMake CLI (command line interface): pass the parameter `-DCMAKE_TOOLCHAIN_FILE="..."` + ++ Build **Configuration** (type) + When using Makefiles or Ninja, you can specify a build type by setting (also this via GUI or CLI) `CMAKE_BUILD_TYPE="build"`, where build is **Nightly**, **Debug** or **Release**. If the build type was not set, by default the makefiles for all of the three build types are generated. + **Debug** build is expected to be slow and it's to be used, you guessed it, for debugging purposes (best coupled with a debugger or with sanitizers enabled, more on them right below), so don't use it for a live shard! + +
+Other useful CMake flags: + ++ You can add other compiler flags with the custom variables `C_FLAGS_EXTRA` and `CXX_FLAGS_EXTRA`. ++ Enable Sanitizers: `USE_ASAN[=ON]`, `USE_UBSAN`, `USE_LSAN`, etc. ++ `CROSSCOMPILING_ARCH`: set this to TRUE to tell the compiler you are building binary files for a different architecture (not from x86_64 to x86, but for example from x86 to ARM). + +Example to build makefiles on Linux for a 64 bits Nightly version, inside the "build" directory (run the command inside the project's root folder): ```bash mkdir build cmake -DCMAKE_TOOLCHAIN_FILE=cmake/toolchains/Linux-GNU-x86_64.cmake -G "Unix Makefiles" -DCMAKE_BUILD_TYPE="Nightly" -B ./build -S ./ @@ -146,21 +139,18 @@ cmake -DCMAKE_TOOLCHAIN_FILE=cmake/toolchains/Linux-GNU-x86_64.cmake -G "Unix Ma Building will require more packages than the ones needed to run Sphere. -##### Ubuntu and Debian - ++ Ubuntu and Debian Install these additional packages: + + Build tools (other than the compiler): `sudo apt-get install git cmake`. + + MariaDB client: `sudo apt-get install libmariadb-dev` and `libmariadb3` or `mariadb-client` (depends on the OS version) + If you are on a 64 bits architecture but you want to compile (or execute) a 32 bits binary, you will need to + install MariaDB packages adding the postfix `:i386` to each package name. -+ `sudo apt-get install git cmake` -+ MariaDB client: `sudo apt-get install libmariadb-dev` and `libmariadb3` or `mariadb-client` (depends on the OS version) - -If you are on a 64 bits architecture but you want to compile (or execute) a 32 bits binary, you will need to - install MariaDB packages adding the postfix `:i386` to each package name. - -##### CentOS - Red Hat Enterprise Linux - Fedora - -Then install these additional packages via yum (CentOS or RH) or dnf (Fedora): `git gcc-c++ glibc-devel mariadb-connector-c mariadb-connector-c-devel`
-
If you are on a 64 bits architecture but you want to compile (or execute) a 32 bits binary, you will need to install the appropriate gcc package - and to install the MySQL packages adding the postfix `.i686` to each package name. ++ CentOS - Red Hat Enterprise Linux - Fedora + Install these additional packages via yum (CentOS or RH) or dnf (Fedora). + + Build tools (other than the compiler): `git cmake glibc-devel` + + MariaDB client: `mariadb-connector-c mariadb-connector-c-devel` + If you are on a 64 bits architecture but you want to compile (or execute) a 32 bits binary, you will need to install MariaDB packages adding the postfix `.i686` to each package name. #### Compiling on Linux @@ -168,10 +158,10 @@ Just run the `make` command inside the `build` folder. You can pass the -jX argu #### Address Sanitizer and Undefined Behaviour Sanitizer -You can enable Address Sanitizer (ASan) and Undefined Behaviour Sanitizer (UBSan) with the ENABLE_SANITIZERS checkbox via the GUI, or via the CLI flag `-DENABLE_SANITIZERS=true`.
-This is easier with GCC and Clang on Linux.
+You can enable Address Sanitizer (ASan) and Undefined Behaviour Sanitizer (UBSan) with the ENABLE_SANITIZERS checkbox via the GUI, or via the CLI flag `-DENABLE_SANITIZERS=true`. +This is easier with GCC and Clang on Linux. Since ASan redirects the error output to stderr, you can retrieve its output by launching sphere from cmd (Command Prompt) or shell with the following command: -`SphereSvrX64_nightly > Sphere_ASan_log.txt 2>&1` +`SphereSvrX64_nightly > Sphere_ASan_log.txt 2>&1`, or simply use the precise flag to redirect the errors to a log file. ## Coding Notes (add as you wish to standardize the coding for new contributors) @@ -186,9 +176,9 @@ Since ASan redirects the error output to stderr, you can retrieve its output by to be printed to or retrieved by scripts should always be signed. + Don't use "long" except if you know why do you actually need it. Always prefer "int" or "llong". Use fixed width variables only for values that need to fit a limited range. -+ For strings, use pointers:
- to "char" for strings that should always have ASCII encoding;
- to "tchar" for strings that may be ASCII or Unicode, depending from compilation settings (more info in "datatypes.h");
++ For strings, use pointers: + to "char" for strings that should always have ASCII encoding; + to "tchar" for strings that may be ASCII or Unicode, depending from compilation settings (more info in "datatypes.h"); to "wchar" for string that should always have Unicode encoding. ### Naming Conventions @@ -212,12 +202,14 @@ These are meant to be applied to new code and, if there's some old code not foll **Variables meant to hold characters (also strings):** + For char, wchar, tchar use respectively the prefixes "c", "wc", "tc". -+ When handling strings, "lpstr", "lpcstr", "lpwstr", "lpcwstr", "lptstr", "lpctstr" data types are preferred aliases.
- You'll find a lot of "psz" prefixes for strings: the reason is that in the past Sphere coders wanted to be consistent with Microsoft's Hungarian Notation.
++ When handling strings, "lpstr", "lpcstr", "lpwstr", "lpcwstr", "lptstr", "lpctstr" data types are preferred aliases. + You'll find a lot of "psz" prefixes for strings: the reason is that in the past Sphere coders wanted to be consistent with Microsoft's Hungarian Notation. The correct and up to date notation is "pc" for lpstr/lpcstr (which are respectively char*and const char*), "pwc" (wchar*and const wchar*), - "ptc" for lptstr/lpctstr (tchar*and const tchar*).
- Use the "s" or "ps" (if pointer) when using CString or std::string. Always prefer CString over std::string, unless in your case there are obvious advantages for using the latter.
+ "ptc" for lptstr/lpctstr (tchar*and const tchar*). + Use the "s" or "ps" (if pointer) when using CString or std::string. Always prefer CString over std::string, unless in your case there are obvious advantages for using the latter. + Examples: + + Class or Struct: "CChar". + Class internal variable, signed integer: "_iAmount". + Tchar pointer: "ptcName". @@ -226,24 +218,24 @@ Examples: ### Coding Style Conventions + Indent with **spaces** of size 4. -+ Use the Allman indentation style:
-while (x == y)
-{
-    something();
-    somethingelse();
++ Use the Allman indentation style: +while (x == y) +{ +    something(); +    somethingelse(); } -+ Even if a single statement follows the if/else/while... clauses, use the brackets:
-if (fTrue)
-{
-    g_Log.EventWarn("True!\n");
++ Even if a single statement follows the if/else/while... clauses, use the brackets: +if (fTrue) +{ +    g_Log.EventWarn("True!\n"); } ## Licensing -Copyright 2024 SphereServer development team.
+Copyright 2024 SphereServer development team. -Licensed under the Apache License, Version 2.0 (the "License").
-You may not use any file of this project except in compliance with the License.
+Licensed under the Apache License, Version 2.0 (the "License"). +You may not use any file of this project except in compliance with the License. You may obtain a copy of the License at From 72d9111a8b43d3db9702d28b64bc175e681b0157 Mon Sep 17 00:00:00 2001 From: cbnolok Date: Wed, 28 Aug 2024 19:37:09 +0200 Subject: [PATCH 12/86] FACTION fix, breaking change.it has been split in two different properties: Changed: since there was too much data to be stored in the FACTION/SLAYER property, so that it sometimes couldn't fit and caused issues, it has been split in two different propertie - FACTION/SLAYER_GROUP (expects a bitmask, max value of the usable flag: 0x800000), - FACTION/SLAYER_SPECIES (plain number, max value 255). SPECIES with index/value 1 are always considered to be SuperSlayers for their group. Added some security checks and constexpr. --- Changelog.txt | 11 +- src/common/CPointBase.cpp | 1 + src/common/CSVFile.h | 5 +- src/common/resource/CResourceQty.cpp | 1 - src/game/CBase.cpp | 44 ++- src/game/CBase.h | 8 +- src/game/CComponent.cpp | 4 +- src/game/CComponent.h | 4 +- src/game/chars/CChar.cpp | 2 +- src/game/chars/CChar.h | 2 +- src/game/chars/CCharFight.cpp | 133 ++++---- src/game/chars/CCharSkill.cpp | 2 +- src/game/chars/CCharSpell.cpp | 50 +-- src/game/clients/CClient.cpp | 6 +- src/game/clients/CClient.h | 2 +- src/game/clients/CClientTarg.cpp | 11 +- src/game/components/CCFaction.cpp | 317 ++++++------------ src/game/components/CCFaction.h | 247 +++++++------- src/game/components/CCItemDamageable.cpp | 4 +- src/game/components/CCItemDamageable.h | 8 +- src/game/components/CCPropsChar.cpp | 12 +- src/game/components/CCPropsChar.h | 2 +- src/game/components/CCPropsItem.cpp | 10 +- src/game/components/CCPropsItem.h | 2 +- src/game/components/CCPropsItemChar.cpp | 10 +- src/game/components/CCPropsItemChar.h | 2 +- src/game/components/CCPropsItemEquippable.cpp | 8 +- src/game/components/CCPropsItemEquippable.h | 4 +- src/game/components/CCPropsItemWeapon.cpp | 10 +- src/game/components/CCPropsItemWeapon.h | 6 +- .../components/CCPropsItemWeaponRanged.cpp | 6 +- src/game/components/CCPropsItemWeaponRanged.h | 6 +- src/game/game_macros.h | 2 +- src/game/items/CItem.cpp | 5 +- src/game/items/CItemBase.h | 8 +- src/game/items/CItemMultiCustom.cpp | 19 +- src/game/items/CItemMultiCustom.h | 5 +- src/game/spheresvr.cpp | 6 +- src/tables/CBaseBaseDef_props.tbl | 42 +-- 39 files changed, 469 insertions(+), 558 deletions(-) diff --git a/Changelog.txt b/Changelog.txt index 0ab9942ea..c784b2348 100644 --- a/Changelog.txt +++ b/Changelog.txt @@ -3859,5 +3859,12 @@ Added: 'H' shortcut for variables to get the value as hexadecimal. If you have a custom anim with default configuration, you don't need to set ANIM= 10-08-2024, Gladie -- Fixed: CAN_I_DAMAGEABLE not updating status bar (PR #1259, issues #1248, #1260). - +- Fixed: CAN_I_DAMAGEABLE not updating status bar (PR #1259, issues #1248, #1260). + +29-08-2024, Nolok + WARNING! POTENTIALLY BREAKING CHANGE! Scripts will need to be updated. +- Changed: since there was too much data to be stored in the FACTION/SLAYER property, so that it sometimes couldn't fit and caused issues, + it has been split in two different properties: + - FACTION/SLAYER_GROUP (expects a bitmask, max value of the usable flag: 0x800000), + - FACTION/SLAYER_SPECIES (plain number, max value 255). + SPECIES with index/value 1 are always considered to be SuperSlayers for their group. diff --git a/src/common/CPointBase.cpp b/src/common/CPointBase.cpp index 377aafaac..0c2f0a8ec 100644 --- a/src/common/CPointBase.cpp +++ b/src/common/CPointBase.cpp @@ -9,6 +9,7 @@ #include "CPointBase.h" #include +static_assert(sizeof(CPointBase) == sizeof(CPointMap), "CPointBase and CPointMap have to have the same size. Was a virtual method added?"); DIR_TYPE GetDirTurn( DIR_TYPE dir, int offset ) { diff --git a/src/common/CSVFile.h b/src/common/CSVFile.h index 8933cdf38..1d001a43e 100644 --- a/src/common/CSVFile.h +++ b/src/common/CSVFile.h @@ -29,9 +29,8 @@ public: virtual bool Open(lpctstr ptcFilename = nullptr, uint uiModeFlags = CSVFile(); ~CSVFile(); -private: - CSVFile(const CSVFile& copy); - CSVFile& operator=(const CSVFile& other); + CSVFile(const CSVFile& copy) = delete; + CSVFile& operator=(const CSVFile& other) = delete; private: int _GetColumnCount() const { return _iColumnCount; } public: int GetColumnCount() const; diff --git a/src/common/resource/CResourceQty.cpp b/src/common/resource/CResourceQty.cpp index c7336084b..203c842fc 100644 --- a/src/common/resource/CResourceQty.cpp +++ b/src/common/resource/CResourceQty.cpp @@ -114,7 +114,6 @@ CResourceQtyArray::CResourceQtyArray(lpctstr pszCmds) void CResourceQtyArray::setNoMergeOnLoad() { - ADDTOCALLSTACK("CResourceQtyArray::setNoMergeOnLoad"); m_mergeOnLoad = false; } diff --git a/src/game/CBase.cpp b/src/game/CBase.cpp index a4f9cd5f7..60c9a9587 100644 --- a/src/game/CBase.cpp +++ b/src/game/CBase.cpp @@ -44,9 +44,6 @@ CBaseBaseDef::CBaseBaseDef( CResourceID id ) : m_BaseResources.setNoMergeOnLoad(); } -CBaseBaseDef::~CBaseBaseDef() -{ -} void CBaseBaseDef::DelInstance() { @@ -56,9 +53,14 @@ void CBaseBaseDef::DelInstance() --_dwInstances; } -CCFaction CBaseBaseDef::GetFaction() +CCFaction const& CBaseBaseDef::GetFaction() const noexcept +{ + return _Faction; +} + +CCFaction & CBaseBaseDef::GetFaction() noexcept { - return _pFaction; + return _Faction; } lpctstr CBaseBaseDef::GetTypeName() const @@ -145,9 +147,14 @@ bool CBaseBaseDef::r_WriteVal( lpctstr ptcKey, CSString & sVal, CTextConsole * p sVal = GetResourceName(); break; - case OBC_FACTION: - case OBC_SLAYER: - sVal.FormatULLHex(_pFaction.GetFactionID()); + case OBC_FACTION_GROUP: + case OBC_SLAYER_GROUP: + sVal.FormatHex(num_alias_cast(_Faction.GetGroup())); + break; + + case OBC_FACTION_SPECIES: + case OBC_SLAYER_SPECIES: + sVal.FormatHex(num_alias_cast(_Faction.GetSpecies())); break; case OBC_ARMOR: @@ -326,11 +333,18 @@ bool CBaseBaseDef::r_LoadVal( CScript & s ) bool fQuoted = false; SetDefStr(s.GetKey(), s.GetArgStr( &fQuoted ), fQuoted); } - break; - case OBC_FACTION: - case OBC_SLAYER: - _pFaction.SetFactionID( static_cast(s.GetArgULLVal()) ); + return true; + + case OBC_FACTION_GROUP: + case OBC_SLAYER_GROUP: + _Faction.SetGroup(num_alias_cast(s.GetArgU32Val())); + return true; + + case OBC_FACTION_SPECIES: + case OBC_SLAYER_SPECIES: + _Faction.SetSpecies(num_alias_cast(s.GetArgU32Val())); return true; + //Set as number only case OBC_EXPANSION: case OBC_VELOCITY: @@ -349,6 +363,7 @@ bool CBaseBaseDef::r_LoadVal( CScript & s ) SetDefStr(sm_szLoadKeys[OBC_DESCRIPTION], GetDefStr(sm_szLoadKeys[OBC_SUBSECTION]), false, true, false); } return true; + case OBC_ARMOR: { int64 piVal[2]; @@ -360,6 +375,7 @@ bool CBaseBaseDef::r_LoadVal( CScript & s ) m_defenseRange = 0; } return true; + case OBC_DAM: { int64 piVal[2]; @@ -371,6 +387,7 @@ bool CBaseBaseDef::r_LoadVal( CScript & s ) m_attackRange = 0; } return true; + case OBC_BASEID: return false; case OBC_CAN: @@ -431,7 +448,8 @@ void CBaseBaseDef::CopyBasic( const CBaseBaseDef * pBase ) m_defenseBase = pBase->m_defenseBase; m_defenseRange = pBase->m_defenseRange; m_Can = pBase->m_Can; - _pFaction.SetFactionID(pBase->_pFaction.GetFactionID()); + _Faction.SetGroup(pBase->_Faction.GetGroup()); + _Faction.SetSpecies(pBase->_Faction.GetSpecies()); CEntityProps::Copy(pBase); } diff --git a/src/game/CBase.h b/src/game/CBase.h index 2a77f661c..1228fabbd 100644 --- a/src/game/CBase.h +++ b/src/game/CBase.h @@ -139,11 +139,13 @@ struct CBaseBaseDef : public CResourceLink, public CEntityProps uint64 m_Can; // Base attribute flags. CAN_C_GHOST, etc - CCFaction _pFaction; +private: + CCFaction _Faction; public: - CCFaction GetFaction(); + CCFaction const& GetFaction() const noexcept; + CCFaction &GetFaction() noexcept; /** * @brief Gets definition string. @@ -200,7 +202,7 @@ struct CBaseBaseDef : public CResourceLink, public CEntityProps public: CBaseBaseDef( CResourceID id ); - virtual ~CBaseBaseDef(); + virtual ~CBaseBaseDef() = default; CBaseBaseDef(const CBaseBaseDef& copy) = delete; CBaseBaseDef& operator=(const CBaseBaseDef& other) = delete; diff --git a/src/game/CComponent.cpp b/src/game/CComponent.cpp index a6f9e1b91..a59881201 100644 --- a/src/game/CComponent.cpp +++ b/src/game/CComponent.cpp @@ -2,12 +2,12 @@ #include "CComponent.h" #include "CObjBase.h" -CComponent::CComponent(COMP_TYPE type) : +CComponent::CComponent(COMP_TYPE type) noexcept : _iType(type) { } -COMP_TYPE CComponent::GetType() const +COMP_TYPE CComponent::GetType() const noexcept { return _iType; } diff --git a/src/game/CComponent.h b/src/game/CComponent.h index aaaa84e76..c822f97f7 100644 --- a/src/game/CComponent.h +++ b/src/game/CComponent.h @@ -39,11 +39,11 @@ class CComponent protected: - CComponent(COMP_TYPE type); + CComponent(COMP_TYPE type) noexcept; public: virtual ~CComponent() = default; - COMP_TYPE GetType() const; + COMP_TYPE GetType() const noexcept; /* Script's compatibility * All methods here are meant to be proccessed from CEntity so they may behave a little different diff --git a/src/game/chars/CChar.cpp b/src/game/chars/CChar.cpp index bbeea5c4f..7901f0c64 100644 --- a/src/game/chars/CChar.cpp +++ b/src/game/chars/CChar.cpp @@ -4664,7 +4664,7 @@ bool CChar::r_Verb( CScript &s, CTextConsole * pSrc ) // Execute command from sc return false; m_atMagery.m_iSpell = SPELL_Polymorph; - m_atMagery.m_iSummonID = (CREID_TYPE)(g_Cfg.ResourceGetIndexType(RES_CHARDEF, s.GetArgStr())); + m_atMagery.m_uiSummonID = (CREID_TYPE)(g_Cfg.ResourceGetIndexType(RES_CHARDEF, s.GetArgStr())); m_Act_UID = GetUID(); m_Act_Prv_UID = GetUID(); diff --git a/src/game/chars/CChar.h b/src/game/chars/CChar.h index 58b1b1dd2..13a2efaa8 100644 --- a/src/game/chars/CChar.h +++ b/src/game/chars/CChar.h @@ -226,7 +226,7 @@ class CChar : public CObjBase, public CContainer, public CTextConsole struct { SPELL_TYPE m_iSpell; // ACTARG1 = Currently casting spell. - CREID_TYPE m_iSummonID; // ACTARG2 = A sub arg of the skill. (summoned type ?) + CREID_TYPE m_uiSummonID; // ACTARG2 = A sub arg of the skill. (summoned type ?) } m_atMagery; // SKILL_ALCHEMY diff --git a/src/game/chars/CCharFight.cpp b/src/game/chars/CCharFight.cpp index a26ad8a39..956055486 100644 --- a/src/game/chars/CCharFight.cpp +++ b/src/game/chars/CCharFight.cpp @@ -110,7 +110,7 @@ bool CChar::CheckCrimeSeen( SKILL_TYPE SkillToSee, CChar * pCharMark, const CObj if (this == pChar) // Ignore the player himself. continue; if (pChar == pCharMark) // Attacked player should be ignored. - continue; + continue; if (pChar->IsPriv(PRIV_GM)) // GMs also should be ignored. continue; if ( ! pChar->CanSeeLOS( this, LOS_NB_WINDOWS )) // What if I was standing behind a window when I saw a crime? :) @@ -119,7 +119,7 @@ bool CChar::CheckCrimeSeen( SKILL_TYPE SkillToSee, CChar * pCharMark, const CObj const bool fYour = (pCharMark && ( pCharMark == pChar )); if (!g_Cfg.Calc_CrimeSeen(this, pChar, SkillToSee, fYour)) continue; - + tchar *z = Str_GetTemp(); if ( pItem && pAction ) { @@ -128,7 +128,7 @@ bool CChar::CheckCrimeSeen( SKILL_TYPE SkillToSee, CChar * pCharMark, const CObj else snprintf(z, Str_TempLength(), g_Cfg.GetDefaultMsg(DEFMSG_MSG_YOUNOTICE_1), GetName(), pAction, pItem->GetName()); } - + // They are not a criminal til someone calls the guards !!! if ( SkillToSee == SKILL_SNOOPING ) { @@ -145,7 +145,7 @@ bool CChar::CheckCrimeSeen( SKILL_TYPE SkillToSee, CChar * pCharMark, const CObj } fSeen = true; - + // Off chance of being a criminal. (hehe) if ( g_Rand.GetVal(100) < g_Cfg.m_iSnoopCriminal ) pChar->OnNoticeCrime( this, pCharMark ); @@ -571,7 +571,7 @@ int CChar::CalcArmorDefense() const break; case LAYER_SHIRT: //LAYER_SHIRT, LAYER_CHEST and LAYER_TUNIC get the 35% of AR from chest location. case LAYER_CHEST: - case LAYER_TUNIC: + case LAYER_TUNIC: iPercentArmorDefence = sm_ArmorLayers[3].m_iCoverage; break; case LAYER_ROBE: //35% from chest, 22% from legs and 14% from arms locations. @@ -619,7 +619,7 @@ int CChar::CalcArmorDefense() const // -1 = already dead / invalid target. // 0 = no damage. // INT32_MAX = killed. -int CChar::OnTakeDamage( int iDmg, CChar * pSrc, DAMAGE_TYPE uType, int iDmgPhysical, int iDmgFire, int iDmgCold, int iDmgPoison, int iDmgEnergy, SPELL_TYPE spell) +int CChar::OnTakeDamage( int iDmg, CChar * pSrc, DAMAGE_TYPE uiType, int iDmgPhysical, int iDmgFire, int iDmgCold, int iDmgPoison, int iDmgEnergy, SPELL_TYPE spell) { ADDTOCALLSTACK("CChar::OnTakeDamage"); if ( pSrc == nullptr ) @@ -628,7 +628,7 @@ int CChar::OnTakeDamage( int iDmg, CChar * pSrc, DAMAGE_TYPE uType, int iDmgPhys if ( IsStatFlag(STATF_DEAD) ) // already dead return -1; - if ( !(uType & DAMAGE_GOD) ) + if ( !(uiType & DAMAGE_GOD) ) { if ( IsStatFlag(STATF_INVUL|STATF_STONE) ) { @@ -636,11 +636,14 @@ int CChar::OnTakeDamage( int iDmg, CChar * pSrc, DAMAGE_TYPE uType, int iDmgPhys Effect( EFFECT_OBJ, ITEMID_FX_GLOW, this, 10, 16 ); return 0; } - if ( (uType & DAMAGE_FIRE) && Can(CAN_C_FIRE_IMMUNE) ) + + if ( (uiType & DAMAGE_FIRE) && Can(CAN_C_FIRE_IMMUNE) ) goto effect_bounce; + // I can't take damage from my pets, the only exception is for BRAIN_BERSERK pets //if ( pSrc->m_pNPC && (pSrc->NPC_PetGetOwner() == this) && (pSrc->m_pNPC->m_Brain != NPCBRAIN_BERSERK) ) //goto effect_bounce; + if ( m_pArea ) { if ( m_pArea->IsFlag(REGION_FLAG_SAFE) ) @@ -667,7 +670,7 @@ int CChar::OnTakeDamage( int iDmg, CChar * pSrc, DAMAGE_TYPE uType, int iDmgPhys // Make some notoriety checks // Don't reveal attacker if the damage has DAMAGE_NOREVEAL flag set (this is set by default for poison and spell damage) - if ( !OnAttackedBy(pSrc, false, !(uType & DAMAGE_NOREVEAL)) ) + if ( !OnAttackedBy(pSrc, false, !(uiType & DAMAGE_NOREVEAL)) ) return 0; // Apply Necromancy cursed effects @@ -681,7 +684,7 @@ int CChar::OnTakeDamage( int iDmg, CChar * pSrc, DAMAGE_TYPE uType, int iDmgPhys } CItem * pBloodOath = LayerFind(LAYER_SPELL_Blood_Oath); - if ( pBloodOath && pBloodOath->m_uidLink == pSrc->GetUID() && !(uType & DAMAGE_FIXED) && !g_Cfg.GetSpellDef(SPELL_Blood_Oath)->IsSpellType(SPELLFLAG_SCRIPTED)) // if DAMAGE_FIXED is set we are already receiving a reflected damage, so we must stop here to avoid an infinite loop. + if ( pBloodOath && pBloodOath->m_uidLink == pSrc->GetUID() && !(uiType & DAMAGE_FIXED) && !g_Cfg.GetSpellDef(SPELL_Blood_Oath)->IsSpellType(SPELLFLAG_SCRIPTED)) // if DAMAGE_FIXED is set we are already receiving a reflected damage, so we must stop here to avoid an infinite loop. { iDmg += iDmg / 10; pSrc->OnTakeDamage(iDmg * (100 - pBloodOath->m_itSpell.m_spelllevel) / 100, this, DAMAGE_MAGIC|DAMAGE_FIXED,0,0,0,0,0,SPELL_Blood_Oath); @@ -694,12 +697,12 @@ int CChar::OnTakeDamage( int iDmg, CChar * pSrc, DAMAGE_TYPE uType, int iDmgPhys const CCPropsChar* pBaseCCPChar = pCharDef->GetComponentProps(); // MAGICF_IGNOREAR bypasses defense completely - if ( (uType & DAMAGE_MAGIC) && IsSetMagicFlags(MAGICF_IGNOREAR) ) - uType |= DAMAGE_FIXED; - + if ( (uiType & DAMAGE_MAGIC) && IsSetMagicFlags(MAGICF_IGNOREAR) ) + uiType |= DAMAGE_FIXED; + bool fElemental = IsSetCombatFlags(COMBAT_ELEMENTAL_ENGINE); // Apply armor calculation - if ( !(uType & (DAMAGE_GOD|DAMAGE_FIXED)) ) + if ( !(uiType & (DAMAGE_GOD|DAMAGE_FIXED)) ) { if ( fElemental ) { @@ -724,7 +727,7 @@ int CChar::OnTakeDamage( int iDmg, CChar * pSrc, DAMAGE_TYPE uType, int iDmgPhys int iArMin = iArMax / 2; int iDef = g_Rand.GetVal2Fast( iArMin, (iArMax - iArMin) + 1 ); - if ( uType & DAMAGE_MAGIC ) // magical damage halves effectiveness of defense + if ( uiType & DAMAGE_MAGIC ) // magical damage halves effectiveness of defense iDef /= 2; iDmg -= iDef; @@ -733,7 +736,7 @@ int CChar::OnTakeDamage( int iDmg, CChar * pSrc, DAMAGE_TYPE uType, int iDmgPhys } } - CScriptTriggerArgs Args( iDmg, uType, (int64)(0) ); + CScriptTriggerArgs Args( iDmg, uiType, (int64)(0) ); Args.m_VarsLocal.SetNum("ItemDamageLayer", sm_ArmorDamageLayers[(size_t)g_Rand.Get16ValFast(ARRAY_COUNT(sm_ArmorDamageLayers))]); Args.m_VarsLocal.SetNum("ItemDamageChance", 25); Args.m_VarsLocal.SetNum("Spell", (int)spell); @@ -753,7 +756,7 @@ int CChar::OnTakeDamage( int iDmg, CChar * pSrc, DAMAGE_TYPE uType, int iDmgPhys if ( OnTrigger( CTRIG_GetHit, pSrc, &Args ) == TRIGRET_RET_TRUE ) return 0; iDmg = (int)(Args.m_iN1); - uType = (DAMAGE_TYPE)(Args.m_iN2); + uiType = (DAMAGE_TYPE)(Args.m_iN2); LAYER_TYPE iHitLayer = (LAYER_TYPE)(Args.m_VarsLocal.GetKeyNum("ItemDamageLayer")); pItemHit = LayerFind(iHitLayer); @@ -764,7 +767,7 @@ int CChar::OnTakeDamage( int iDmg, CChar * pSrc, DAMAGE_TYPE uType, int iDmgPhys if (pItemHit->OnTrigger(ITRIG_GetHit, pSrc, &Args) == TRIGRET_RET_TRUE) return 0; iDmg = (int)(Args.m_iN1); //Update damage amount and type again after @Hit trigger under item. - uType = (DAMAGE_TYPE)(Args.m_iN2); + uiType = (DAMAGE_TYPE)(Args.m_iN2); // We don't need to update iHitLayer as it's already called on item } } @@ -773,12 +776,12 @@ int CChar::OnTakeDamage( int iDmg, CChar * pSrc, DAMAGE_TYPE uType, int iDmgPhys if ( (iItemDamageChance > g_Rand.GetVal(100)) && !Can(CAN_C_NONHUMANOID) ) { if ( pItemHit ) - pItemHit->OnTakeDamage(iDmg, pSrc, uType); + pItemHit->OnTakeDamage(iDmg, pSrc, uiType); } CSpellDef* pSpellDef = nullptr; // Remove stuck/paralyze effect - if (!(uType & DAMAGE_NOUNPARALYZE)) + if (!(uiType & DAMAGE_NOUNPARALYZE)) { if (spell) pSpellDef = g_Cfg.GetSpellDef(spell); @@ -804,7 +807,7 @@ int CChar::OnTakeDamage( int iDmg, CChar * pSrc, DAMAGE_TYPE uType, int iDmgPhys if (IsSetCombatFlags(COMBAT_SLAYER)) { CItem *pWeapon = nullptr; - if (uType & DAMAGE_MAGIC) // If the damage is magic, we are probably using a spell or a weapon that causes also magical damage. + if (uiType & DAMAGE_MAGIC) // If the damage is magic, we are probably using a spell or a weapon that causes also magical damage. { pWeapon = pSrc->GetSpellbookLayer(); // Search for an equipped spellbook if ( !pWeapon ) //No spellbook, so it's a weapon causing magical damage. @@ -821,18 +824,18 @@ int CChar::OnTakeDamage( int iDmg, CChar * pSrc, DAMAGE_TYPE uType, int iDmgPhys if (pWeapon) { pSlayer = pWeapon->GetSlayer(); - if (pSlayer && pSlayer->GetFactionID() != FACTION_NONE) + if (pSlayer && !pSlayer->IsNone()) { if (m_pNPC) // I'm an NPC attacked (Should the attacker be a player to get the bonus?). { - if (pFaction && pFaction->GetFactionID() != FACTION_NONE) + if (pFaction && !pFaction->IsNone()) { iDmgBonus = pSlayer->GetSlayerDamageBonus(pFaction); } } else if (m_pPlayer && pSrc->m_pNPC) // Wielding a slayer type against its opposite will cause the attacker to take more damage { - if (pFaction && pFaction->GetFactionID() != FACTION_NONE) + if (pFaction && !pFaction->IsNone()) { iDmgBonus = pSlayer->GetSlayerDamagePenalty(pFaction); } @@ -845,18 +848,18 @@ int CChar::OnTakeDamage( int iDmg, CChar * pSrc, DAMAGE_TYPE uType, int iDmgPhys if (pTalisman) { pSlayer = pTalisman->GetSlayer(); - if (pSlayer && pSlayer->GetFactionID() != FACTION_NONE) + if (pSlayer && pSlayer->IsNone()) { if (m_pNPC) // I'm an NPC attacked (Should the attacker be a player to get the bonus?). { - if (pFaction && pFaction->GetFactionID() != FACTION_NONE) + if (pFaction && pFaction->IsNone()) { iDmgBonus = pSlayer->GetSlayerDamageBonus(pFaction); } } else if (m_pPlayer && pSrc->m_pNPC) // Wielding a slayer type against its opposite will cause the attacker to take more damage { - if (pFaction && pFaction->GetFactionID() != FACTION_NONE) + if (pFaction && pFaction->IsNone()) { iDmgBonus = pSlayer->GetSlayerDamagePenalty(pFaction); } @@ -869,9 +872,9 @@ int CChar::OnTakeDamage( int iDmg, CChar * pSrc, DAMAGE_TYPE uType, int iDmgPhys iDmg *= iDmgBonus; } } - + // Disturb magic spells (only players can be disturbed if NpCCanFizzleOnHit is false in sphere.ini) - if ( (m_pPlayer || g_Cfg.m_fNPCCanFizzleOnHit) && (pSrc != this) && !(uType & DAMAGE_NODISTURB) && g_Cfg.IsSkillFlag(Skill_GetActive(), SKF_MAGIC) ) + if ( (m_pPlayer || g_Cfg.m_fNPCCanFizzleOnHit) && (pSrc != this) && !(uiType & DAMAGE_NODISTURB) && g_Cfg.IsSkillFlag(Skill_GetActive(), SKF_MAGIC) ) { // Check if my spell can be interrupted int iDisturbChance = 0; @@ -935,16 +938,16 @@ int CChar::OnTakeDamage( int iDmg, CChar * pSrc, DAMAGE_TYPE uType, int iDmgPhys } // A physical blow of some sort. - if (uType & (DAMAGE_HIT_BLUNT|DAMAGE_HIT_PIERCE|DAMAGE_HIT_SLASH)) + if (uiType & (DAMAGE_HIT_BLUNT|DAMAGE_HIT_PIERCE|DAMAGE_HIT_SLASH)) { // Check if Reactive Armor will reflect some damage back. // Preventing recurrent reflection with DAMAGE_REACTIVE. - if ( IsStatFlag(STATF_REACTIVE) && !((uType & DAMAGE_GOD) || (uType & DAMAGE_REACTIVE)) ) + if ( IsStatFlag(STATF_REACTIVE) && !((uiType & DAMAGE_GOD) || (uiType & DAMAGE_REACTIVE)) ) { if (GetTopDist3D(pSrc) <= 2) { CItem* pReactive = LayerFind(LAYER_SPELL_Reactive); - + if (pReactive) { int iReactiveDamage = (iDmg * pReactive->m_itSpell.m_PolyStr) / 100; @@ -962,7 +965,7 @@ int CChar::OnTakeDamage( int iDmg, CChar * pSrc, DAMAGE_TYPE uType, int iDmgPhys } // Check if REFLECTPHYSICALDAM will reflect some damage back. // Preventing recurrent reflection with DAMAGE_REACTIVE. - if (!(uType & DAMAGE_REACTIVE)) + if (!(uiType & DAMAGE_REACTIVE)) { int iReflectPhysical = (ushort)std::min(GetPropNum(pCCPChar, PROPCH_REFLECTPHYSICALDAM, pBaseCCPChar),250); //Capped to 250 @@ -972,10 +975,10 @@ int CChar::OnTakeDamage( int iDmg, CChar * pSrc, DAMAGE_TYPE uType, int iDmgPhys pSrc->OnTakeDamage(iReflectPhysicalDam, this, (DAMAGE_TYPE)(DAMAGE_FIXED | DAMAGE_REACTIVE), iDmgPhysical, iDmgFire, iDmgCold, iDmgPoison, iDmgEnergy); } } - + } } - + if (iDmg <= 0) return 0; @@ -993,7 +996,7 @@ int CChar::OnTakeDamage( int iDmg, CChar * pSrc, DAMAGE_TYPE uType, int iDmgPhys pSrc->m_pClient->addShowDamage( iDmg, (dword)(GetUID()) ); else { - CChar * pSrcOwner = pSrc->GetOwner(); + CChar * pSrcOwner = pSrc->GetOwner(); if ( pSrcOwner != nullptr && pSrcOwner != this ) //If my pet damages somebody display the pop-up damage unless it's damaging me because i already received the pop-up damage on before. { if ( pSrcOwner->IsClientActive() ) @@ -1020,7 +1023,7 @@ void CChar::OnTakeDamageInflictArea(int iDmg, CChar* pSrc, DAMAGE_TYPE uType, in ADDTOCALLSTACK("CChar::OnTakeDamageInflictArea"); bool fMakeSound = false; - + int iDistance = 5; if (IsAosFlagEnabled(FEATURE_AOS_DAMAGE)) iDistance=10; // 5 for ML and 10 for aos @@ -1046,7 +1049,7 @@ void CChar::OnTakeDamageInflictArea(int iDmg, CChar* pSrc, DAMAGE_TYPE uType, in continue; /* On servUo they modify the damage depending of the distance with this formula - There no info about this on UO Wiki + There no info about this on UO Wiki damage *= ( 11 - from.GetDistanceToSqrt( m ) ) / 10; */ pChar->OnTakeDamage(iDmg, pSrc, uType, iDmgPhysical, iDmgFire, iDmgCold, iDmgPoison, iDmgEnergy); @@ -1184,7 +1187,7 @@ int CChar::Fight_CalcDamage( const CItem * pWeapon, bool bNoRandom, bool bGetMax } } - if ( m_pPlayer || IsSetCombatFlags(COMBAT_NPC_BONUSDAMAGE)) + if ( m_pPlayer || IsSetCombatFlags(COMBAT_NPC_BONUSDAMAGE)) { int iIncreaseDam = (int)GetPropNum(COMP_PROPS_CHAR, PROPCH_INCREASEDAM, true); int iDmgBonus = maximum(-100, minimum(iIncreaseDam, 100)); // Damage Increase is capped at +-100% @@ -1297,7 +1300,7 @@ void CChar::Fight_ClearAll() Skill_Start(SKILL_NONE); m_Fight_Targ_UID.InitUID(); } - + Attacker_Clear(); m_atFight.m_iWarSwingState = WAR_SWING_EQUIPPING; m_atFight.m_iRecoilDelay = 0; @@ -1369,7 +1372,7 @@ bool CChar::Fight_Attack( CChar *pCharTarg, bool fToldByMaster ) Attacker_Delete(pCharTarg, true, ATTACKER_CLEAR_DISTANCE); Skill_Start(SKILL_NONE); return false; - } + } int threat = 0; if (fToldByMaster) @@ -1387,7 +1390,7 @@ bool CChar::Fight_Attack( CChar *pCharTarg, bool fToldByMaster ) if ( OnTrigger(CTRIG_Attack, pTarget, &Args) == TRIGRET_RET_TRUE ) return false; threat = (int)Args.m_iN1; - ignored = (bool)Args.m_iN2; + ignored = (bool)Args.m_iN2; } Attacker_SetIgnore(pTarget, ignored); @@ -1449,7 +1452,7 @@ void CChar::Fight_HitTry() CChar *pCharTarg = m_Fight_Targ_UID.CharFind(); /* - We still need to check if player is hidden/invisible but do not need to make anything if the attacker is player, + We still need to check if player is hidden/invisible but do not need to make anything if the attacker is player, So we only check Statf_Dead,stone,insub and invul for players to avoid continue attack the not attackable targets. */ if ( !pCharTarg || (pCharTarg && pCharTarg->IsStatFlag(STATF_DEAD|STATF_STONE|STATF_INSUBSTANTIAL|STATF_INVUL)) || (pCharTarg->IsStatFlag(STATF_HIDDEN|STATF_INVISIBLE) && m_pNPC) ) @@ -1473,7 +1476,7 @@ void CChar::Fight_HitTry() } return; } - + bool fIH_ShouldInstaHit = false, fIH_LastHitTag_Newer = false; int64 iIH_LastHitTag_FullHit = 0; // Time required to perform a normal hit, without the PreHit delay reduction. if (m_atFight.m_iWarSwingState == WAR_SWING_EQUIPPING) @@ -1618,7 +1621,7 @@ void CChar::Fight_SetDefaultSwingDelays() m_atFight.m_iRecoilDelay = 0; // We don't have an actual recoil: the hit animation has the duration of the delay between hits, so the char is always doing a smooth, slow attack animation m_atFight.m_iSwingAnimationDelay = iAttackSpeed; } - else + else { m_atFight.m_iRecoilDelay = (iAttackSpeed - kiMinSwingAnimationDelay); m_atFight.m_iSwingAnimationDelay = kiMinSwingAnimationDelay; @@ -1639,7 +1642,7 @@ WAR_SWING_TYPE CChar::Fight_CanHit(CChar * pCharSrc, bool fSwingNoRange) // WAR_SWING_EQUIPPING = recoiling weapon / swing made // WAR_SWING_READY = Ready to hit, will switch to WAR_SWING_SWINGING ASAP. // WAR_SWING_SWINGING = taking my swing now - + // We can't hit them. Char deleted? Target deleted? Am I dead or stoned? or Is target Dead, stone, invul, insub or slept? if (IsDisconnected() || pCharSrc->IsDisconnected() || IsStatFlag(STATF_DEAD | STATF_STONE) || (pCharSrc->IsStatFlag(STATF_DEAD | STATF_STONE | STATF_INVUL | STATF_INSUBSTANTIAL)) || (pCharSrc->IsSleeping())) { @@ -1657,7 +1660,7 @@ WAR_SWING_TYPE CChar::Fight_CanHit(CChar * pCharSrc, bool fSwingNoRange) // Ignore the distance and the line of sight if fSwingNoRange is true, but only if i'm starting the swing. To land the hit i need to be in range. if (!fSwingNoRange || - (IsSetCombatFlags(COMBAT_ANIM_HIT_SMOOTH) && (m_atFight.m_iWarSwingState == WAR_SWING_SWINGING)) || + (IsSetCombatFlags(COMBAT_ANIM_HIT_SMOOTH) && (m_atFight.m_iWarSwingState == WAR_SWING_SWINGING)) || (!IsSetCombatFlags(COMBAT_ANIM_HIT_SMOOTH) && (m_atFight.m_iWarSwingState == WAR_SWING_READY))) { int dist = GetTopDist3D(pCharSrc); @@ -1788,8 +1791,8 @@ WAR_SWING_TYPE CChar::Fight_Hit( CChar * pCharTarg ) { return iStageToSuspend; } - } - + } + CItem *pAmmo = nullptr; const SKILL_TYPE skill = Skill_GetActive(); const int dist = GetTopDist3D(pCharTarg); @@ -1813,8 +1816,8 @@ WAR_SWING_TYPE CChar::Fight_Hit( CChar * pCharTarg ) if ( pWeapon ) { const CResourceID ridAmmo(pWeapon->Weapon_GetRangedAmmoRes()); - - if (ridAmmo.IsValidUID() && ridAmmo.GetObjUID() > 0 ) + + if (ridAmmo.IsValidUID() && ridAmmo.GetObjUID() > 0 ) { pAmmo = pWeapon->Weapon_FindRangedAmmo(ridAmmo); if ( !pAmmo && m_pPlayer ) @@ -1850,7 +1853,7 @@ WAR_SWING_TYPE CChar::Fight_Hit( CChar * pCharTarg ) return swingTypeHold; return WAR_SWING_EQUIPPING; } - } + } } else { @@ -1938,13 +1941,13 @@ WAR_SWING_TYPE CChar::Fight_Hit( CChar * pCharTarg ) // Now that i have waited the recoil time, start the hit animation and wait for it to end /* - // If COMBAT_ANIM_SMOOTH is set we can't set m_iSwingAnimationDelay as the timeout value because otherwise + // If COMBAT_ANIM_SMOOTH is set we can't set m_iSwingAnimationDelay as the timeout value because otherwise there will be a delay between the end of the animation and the damage display. This is very noticeable when the m_iSwingAnimationDelay property is near the next digit. (If m_iSwingAnimationDelay is 3.8 the iSwingAnimationDelayInSeconds will be 3 and the damage will be displayed around a 0.8 second later! */ if (!IsSetCombatFlags(COMBAT_ANIM_HIT_SMOOTH)) _SetTimeoutD(m_atFight.m_iSwingAnimationDelay); - else + else _SetTimeoutD(iSwingAnimationDelayInSeconds * TENTHS_PER_SEC); return WAR_SWING_SWINGING; } @@ -2003,7 +2006,7 @@ WAR_SWING_TYPE CChar::Fight_Hit( CChar * pCharTarg ) SOUND_TYPE iSound = SOUND_NONE; if ( pWeapon ) - iSound = pWeapon->Weapon_GetSoundMiss(); + iSound = pWeapon->Weapon_GetSoundMiss(); if ( iSound == SOUND_NONE) { if ( g_Cfg.IsSkillFlag(skill, SKF_RANGED) ) @@ -2037,7 +2040,7 @@ WAR_SWING_TYPE CChar::Fight_Hit( CChar * pCharTarg ) // If Effect property is defined on the Parrying skill use it instead of the hardcoded value of 100. if (!pSkillDef->m_vcEffect.m_aiValues.empty()) iParryReduction = pSkillDef->m_vcEffect.GetLinear(pCharTarg->Skill_GetAdjusted(ParrySkill)); - + /* ARGN1 = Percent of damage that will be reduced. ARGN2 = Damage type. @@ -2088,7 +2091,7 @@ WAR_SWING_TYPE CChar::Fight_Hit( CChar * pCharTarg ) } } - + CScriptTriggerArgs Args(iDmg, iDmgType, pWeapon); Args.m_VarsLocal.SetNum("ItemDamageChance", 25); @@ -2170,7 +2173,7 @@ WAR_SWING_TYPE CChar::Fight_Hit( CChar * pCharTarg ) if ( pWeapon ) { // Check if the weapon is poisoned - if ( !IsSetCombatFlags(COMBAT_NOPOISONHIT) && pWeapon->m_itWeapon.m_poison_skill && + if ( !IsSetCombatFlags(COMBAT_NOPOISONHIT) && pWeapon->m_itWeapon.m_poison_skill && (pWeapon->m_itWeapon.m_poison_skill > g_Rand.GetVal(100) || pWeapon->m_itWeapon.m_poison_skill < 10)) { byte iPoisonDeliver = (byte)(iPoison); @@ -2268,14 +2271,14 @@ WAR_SWING_TYPE CChar::Fight_Hit( CChar * pCharTarg ) if (pWeapon) { - + if (GetPropNum(pCCPChar, PROPCH_HITAREAPHYSICAL, pBaseCCPChar) > g_Rand.GetVal(100)) pCharTarg->OnTakeDamageInflictArea(iDmg / 2, this, DAMAGE_HIT_BLUNT, 100, 0, 0, 0, 0, static_cast(0x32), static_cast(0x10E)); bool fElemental = IsSetCombatFlags(COMBAT_ELEMENTAL_ENGINE); if (fElemental) { - + if (GetPropNum(pCCPChar, PROPCH_HITAREAFIRE, pBaseCCPChar) > g_Rand.GetVal(100)) pCharTarg->OnTakeDamageInflictArea(iDmg / 2, this, DAMAGE_FIRE, 0, 100, 0, 0, 0, static_cast(0x488), static_cast(0x11D)); @@ -2287,21 +2290,21 @@ WAR_SWING_TYPE CChar::Fight_Hit( CChar * pCharTarg ) if (GetPropNum(pCCPChar, PROPCH_HITAREAENERGY, pBaseCCPChar) > g_Rand.GetVal(100)) pCharTarg->OnTakeDamageInflictArea(iDmg / 2, this, DAMAGE_ENERGY, 0, 0, 0, 0, 100, static_cast(0x78), static_cast(0x1F1)); - + } if (GetPropNum(pCCPChar, PROPCH_HITDISPEL, pBaseCCPChar) > g_Rand.GetVal(100)) pCharTarg->OnSpellEffect(SPELL_Dispel, this, Skill_GetAdjusted(SKILL_MAGERY), pWeapon); - + if (GetPropNum(pCCPChar, PROPCH_HITFIREBALL, pBaseCCPChar) > g_Rand.GetVal(100)) pCharTarg->OnSpellEffect(SPELL_Fireball, this, Skill_GetAdjusted(SKILL_MAGERY), pWeapon); - + if (GetPropNum(pCCPChar, PROPCH_HITHARM, pBaseCCPChar) > g_Rand.GetVal(100)) pCharTarg->OnSpellEffect(SPELL_Harm, this, Skill_GetAdjusted(SKILL_MAGERY), pWeapon); - + if (GetPropNum(pCCPChar, PROPCH_HITLIGHTNING, pBaseCCPChar) > g_Rand.GetVal(100)) pCharTarg->OnSpellEffect(SPELL_Lightning, this, Skill_GetAdjusted(SKILL_MAGERY), pWeapon); - + if (GetPropNum(pCCPChar, PROPCH_HITMAGICARROW, pBaseCCPChar) > g_Rand.GetVal(100)) pCharTarg->OnSpellEffect(SPELL_Magic_Arrow, this, Skill_GetAdjusted(SKILL_MAGERY), pWeapon); } diff --git a/src/game/chars/CCharSkill.cpp b/src/game/chars/CCharSkill.cpp index 158333da9..e14f6531f 100644 --- a/src/game/chars/CCharSkill.cpp +++ b/src/game/chars/CCharSkill.cpp @@ -2983,7 +2983,7 @@ int CChar::Skill_Fighting( SKTRIG_TYPE stage ) resetting both the RecoilDelay and the SwingAnimationDelay will also cause the ID of the summoned creatured to be resetted. This only happens when the creature to be summoned is chosen on the default "summon menu". */ - if ( !m_atMagery.m_iSummonID ) + if ( !m_atMagery.m_uiSummonID ) { m_atFight.m_iRecoilDelay = 0; m_atFight.m_iSwingAnimationDelay = 0; diff --git a/src/game/chars/CCharSpell.cpp b/src/game/chars/CCharSpell.cpp index 9b7aed598..b972ae6b1 100644 --- a/src/game/chars/CCharSpell.cpp +++ b/src/game/chars/CCharSpell.cpp @@ -1016,7 +1016,7 @@ void CChar::Spell_Effect_Add( CItem * pSpell ) iBuffIcon = BI_POLYMORPH; break; case SPELL_Lich_Form: - m_atMagery.m_iSummonID = CREID_LICH; + m_atMagery.m_uiSummonID = CREID_LICH; Stats_AddRegenVal(STAT_INT, + pSpell->m_itSpell.m_PolyStr); // RegenManaVal Stats_AddRegenVal(STAT_STR, - pSpell->m_itSpell.m_PolyDex); // RegenHitsVal ModPropNum(pCCPChar, PROPCH_RESFIRE, - pSpell->m_itSpell.m_spellcharges, pBaseCCPChar); @@ -1025,7 +1025,7 @@ void CChar::Spell_Effect_Add( CItem * pSpell ) iBuffIcon = BI_LICHFORM; break; case SPELL_Wraith_Form: - m_atMagery.m_iSummonID = CREID_SPECTRE; + m_atMagery.m_uiSummonID = CREID_SPECTRE; iBuffIcon = BI_WRAITHFORM; pSpell->m_itSpell.m_PolyStr = 15; pSpell->m_itSpell.m_PolyDex = 5; @@ -1035,12 +1035,12 @@ void CChar::Spell_Effect_Add( CItem * pSpell ) ModPropNum(pCCPChar, PROPCH_RESENERGY, - pSpell->m_itSpell.m_spellcharges, pBaseCCPChar); break; case SPELL_Horrific_Beast: - m_atMagery.m_iSummonID = CREID_HORRIFIC_BEAST; + m_atMagery.m_uiSummonID = CREID_HORRIFIC_BEAST; Stats_AddRegenVal(STAT_STR, + pSpell->m_itSpell.m_spellcharges); iBuffIcon = BI_HORRIFICBEAST; break; case SPELL_Vampiric_Embrace: - m_atMagery.m_iSummonID = CREID_VAMPIRE_BAT; + m_atMagery.m_uiSummonID = CREID_VAMPIRE_BAT; ModPropNum(pCCPChar, PROPCH_HITLEECHLIFE, + pSpell->m_itSpell.m_PolyStr, pBaseCCPChar); // +Hit Leech Life Stats_AddRegenVal(STAT_DEX, + pSpell->m_itSpell.m_PolyDex); // +RegenStamVal Stats_AddRegenVal(STAT_INT, + pSpell->m_itSpell.m_spellcharges); // RegenManaVal @@ -1048,11 +1048,11 @@ void CChar::Spell_Effect_Add( CItem * pSpell ) iBuffIcon = BI_VAMPIRICEMBRACE; break; case SPELL_Stone_Form: - m_atMagery.m_iSummonID = CREID_STONE_FORM; + m_atMagery.m_uiSummonID = CREID_STONE_FORM; iBuffIcon = BI_STONEFORM; break; case SPELL_Reaper_Form: - m_atMagery.m_iSummonID = CREID_STONE_FORM; + m_atMagery.m_uiSummonID = CREID_STONE_FORM; iBuffIcon = BI_REAPERFORM; break; default: @@ -1060,7 +1060,7 @@ void CChar::Spell_Effect_Add( CItem * pSpell ) } const ushort SPELL_MAX_POLY_STAT = (ushort)(g_Cfg.m_iMaxPolyStats); - SetID(m_atMagery.m_iSummonID); + SetID(m_atMagery.m_uiSummonID); const CCharBase * pCharDef = Char_GetDef(); ASSERT(pCharDef); @@ -2505,7 +2505,7 @@ CChar * CChar::Spell_Summon_Try(SPELL_TYPE spell, CPointMap ptTarg, CREID_TYPE u if (uiCreature)//if iC1 is set that means we are overriding the default summoned creature. { - m_atMagery.m_iSummonID = uiCreature; + m_atMagery.m_uiSummonID = uiCreature; } else { @@ -2516,46 +2516,46 @@ CChar * CChar::Spell_Summon_Try(SPELL_TYPE spell, CPointMap ptTarg, CREID_TYPE u case SPELL_Summon: break; case SPELL_Blade_Spirit: - m_atMagery.m_iSummonID = CREID_BLADE_SPIRIT; + m_atMagery.m_uiSummonID = CREID_BLADE_SPIRIT; break; case SPELL_Vortex: - m_atMagery.m_iSummonID = CREID_ENERGY_VORTEX; + m_atMagery.m_uiSummonID = CREID_ENERGY_VORTEX; break; case SPELL_Air_Elem: - m_atMagery.m_iSummonID = CREID_AIR_ELEM; + m_atMagery.m_uiSummonID = CREID_AIR_ELEM; break; case SPELL_Daemon: - m_atMagery.m_iSummonID = CREID_DEMON; + m_atMagery.m_uiSummonID = CREID_DEMON; break; case SPELL_Earth_Elem: - m_atMagery.m_iSummonID = CREID_EARTH_ELEM; + m_atMagery.m_uiSummonID = CREID_EARTH_ELEM; break; case SPELL_Fire_Elem: - m_atMagery.m_iSummonID = CREID_FIRE_ELEM; + m_atMagery.m_uiSummonID = CREID_FIRE_ELEM; break; case SPELL_Water_Elem: - m_atMagery.m_iSummonID = CREID_WATER_ELEM; + m_atMagery.m_uiSummonID = CREID_WATER_ELEM; break; case SPELL_Vengeful_Spirit: - m_atMagery.m_iSummonID = CREID_REVENANT; + m_atMagery.m_uiSummonID = CREID_REVENANT; break; case SPELL_Rising_Colossus: - m_atMagery.m_iSummonID = CREID_RISING_COLOSSUS; + m_atMagery.m_uiSummonID = CREID_RISING_COLOSSUS; break; case SPELL_Summon_Undead: //Sphere custom spell. switch (g_Rand.GetVal(15)) { case 1: - m_atMagery.m_iSummonID = CREID_LICH; + m_atMagery.m_uiSummonID = CREID_LICH; break; case 3: case 5: case 7: case 9: - m_atMagery.m_iSummonID = CREID_SKELETON; + m_atMagery.m_uiSummonID = CREID_SKELETON; break; default: - m_atMagery.m_iSummonID = CREID_ZOMBIE; + m_atMagery.m_uiSummonID = CREID_ZOMBIE; break; } break; @@ -2569,15 +2569,15 @@ CChar * CChar::Spell_Summon_Try(SPELL_TYPE spell, CPointMap ptTarg, CREID_TYPE u } if (IsPriv(PRIV_GM)) { - m_atMagery.m_iSummonID = pCorpse->m_itCorpse.m_BaseID; + m_atMagery.m_uiSummonID = pCorpse->m_itCorpse.m_BaseID; } else if (CCharBase::IsPlayableID(pCorpse->GetCorpseType())) // Must be a human corpse ? { - m_atMagery.m_iSummonID = CREID_ZOMBIE; + m_atMagery.m_uiSummonID = CREID_ZOMBIE; } else { - m_atMagery.m_iSummonID = pCorpse->GetCorpseType(); + m_atMagery.m_uiSummonID = pCorpse->GetCorpseType(); } if (!pCorpse->IsTopLevel()) { @@ -2586,12 +2586,12 @@ CChar * CChar::Spell_Summon_Try(SPELL_TYPE spell, CPointMap ptTarg, CREID_TYPE u break; } default: - m_atMagery.m_iSummonID = CREID_INVALID; + m_atMagery.m_uiSummonID = CREID_INVALID; break; } } - CChar* pChar = CChar::CreateBasic(m_atMagery.m_iSummonID); + CChar* pChar = CChar::CreateBasic(m_atMagery.m_uiSummonID); if (pChar == nullptr) return nullptr; diff --git a/src/game/clients/CClient.cpp b/src/game/clients/CClient.cpp index d19e1fade..46c6f4df1 100644 --- a/src/game/clients/CClient.cpp +++ b/src/game/clients/CClient.cpp @@ -1541,7 +1541,7 @@ bool CClient::r_Verb( CScript & s, CTextConsole * pSrc ) // Execute command from if ( pSpellDef->IsSpellType(SPELLFLAG_TARG_OBJ|SPELLFLAG_TARG_XYZ) ) { m_tmSkillMagery.m_iSpell = SPELL_Summon; - m_tmSkillMagery.m_iSummonID = (CREID_TYPE)(g_Cfg.ResourceGetIndexType(RES_CHARDEF, s.GetArgStr())); + m_tmSkillMagery.m_uiSummonID = (CREID_TYPE)(g_Cfg.ResourceGetIndexType(RES_CHARDEF, s.GetArgStr())); lpctstr pPrompt = g_Cfg.GetDefaultMsg(DEFMSG_SELECT_MAGIC_TARGET); if ( !pSpellDef->m_sTargetPrompt.IsEmpty() ) @@ -1557,7 +1557,7 @@ bool CClient::r_Verb( CScript & s, CTextConsole * pSrc ) // Execute command from else { m_pChar->m_atMagery.m_iSpell = SPELL_Summon; - m_pChar->m_atMagery.m_iSummonID = (CREID_TYPE)(g_Cfg.ResourceGetIndexType(RES_CHARDEF, s.GetArgStr())); + m_pChar->m_atMagery.m_uiSummonID = (CREID_TYPE)(g_Cfg.ResourceGetIndexType(RES_CHARDEF, s.GetArgStr())); if ( IsSetMagicFlags(MAGICF_PRECAST) && !pSpellDef->IsSpellType(SPELLFLAG_NOPRECAST) ) { @@ -1566,7 +1566,7 @@ bool CClient::r_Verb( CScript & s, CTextConsole * pSrc ) // Execute command from } else { - int skill; + int skill = SKILL_NONE; if ( !pSpellDef->GetPrimarySkill(&skill, nullptr) ) return false; diff --git a/src/game/clients/CClient.h b/src/game/clients/CClient.h index 092ff56b7..e4f9baf26 100644 --- a/src/game/clients/CClient.h +++ b/src/game/clients/CClient.h @@ -211,7 +211,7 @@ class CClient : public CSObjListRec, public CScriptObj, public CChatChanMember, struct { SPELL_TYPE m_iSpell; // targetting what spell ? - CREID_TYPE m_iSummonID; + CREID_TYPE m_uiSummonID; } m_tmSkillMagery; // CLIMODE_TARG_USE_ITEM diff --git a/src/game/clients/CClientTarg.cpp b/src/game/clients/CClientTarg.cpp index cdf48ffcb..05c2730d0 100644 --- a/src/game/clients/CClientTarg.cpp +++ b/src/game/clients/CClientTarg.cpp @@ -37,12 +37,15 @@ bool CClient::OnTarg_Obj_Set( CObjBase * pObj ) { const CItem * pItem = static_cast (pObj); if ( pItem->GetAmount() > 1 ) - snprintf(pszLogMsg, Str_TempLength(), "'%s' commands uid=0%x (%s) [amount=%u] to '%s'", GetName(), (dword)(pObj->GetUID()), pObj->GetName(), pItem->GetAmount(), static_cast(m_Targ_Text)); + snprintf(pszLogMsg, Str_TempLength(), "'%s' commands uid=0%x (%s) [amount=%u] to '%s'", + GetName(), (dword)(pObj->GetUID()), pObj->GetName(), pItem->GetAmount(), static_cast(m_Targ_Text)); else - snprintf(pszLogMsg, Str_TempLength(), "'%s' commands uid=0%x (%s) to '%s'", GetName(), (dword)(pObj->GetUID()), pObj->GetName(), static_cast(m_Targ_Text)); + snprintf(pszLogMsg, Str_TempLength(), "'%s' commands uid=0%x (%s) to '%s'", GetName(), + (dword)(pObj->GetUID()), pObj->GetName(), static_cast(m_Targ_Text)); } else - snprintf(pszLogMsg, Str_TempLength(), "'%s' commands uid=0%x (%s) to '%s'", GetName(), (dword)(pObj->GetUID()), pObj->GetName(), static_cast(m_Targ_Text)); + snprintf(pszLogMsg, Str_TempLength(), "'%s' commands uid=0%x (%s) to '%s'", GetName(), + (dword)(pObj->GetUID()), pObj->GetName(), static_cast(m_Targ_Text)); // Check priv level for the new verb. if ( ! g_Cfg.CanUsePrivVerb( pObj, m_Targ_Text, this )) @@ -1486,7 +1489,7 @@ bool CClient::OnTarg_Skill_Magery( CObjBase * pObj, const CPointMap & pt ) } m_pChar->m_atMagery.m_iSpell = m_tmSkillMagery.m_iSpell; - m_pChar->m_atMagery.m_iSummonID = m_tmSkillMagery.m_iSummonID; + m_pChar->m_atMagery.m_uiSummonID = m_tmSkillMagery.m_uiSummonID; m_pChar->m_Act_Prv_UID = m_Targ_Prv_UID; // Source (wand or you?) m_pChar->m_Act_UID = pObj ? pObj->GetUID() : CUID(UID_PLAIN_CLEAR); diff --git a/src/game/components/CCFaction.cpp b/src/game/components/CCFaction.cpp index 8e9954832..3775d477f 100644 --- a/src/game/components/CCFaction.cpp +++ b/src/game/components/CCFaction.cpp @@ -7,18 +7,47 @@ #include "../items/CItem.h" -CFactionDef::CFactionDef() : _iFaction(FACTION_NONE) +CFactionDef::CFactionDef() noexcept : + _uiFactionData(0) { } -NPC_FACTION CFactionDef::GetFactionID() const +bool CFactionDef::IsNone() const noexcept { - return _iFaction; + return (!_uiFactionData || (GetGroup() == Group::NONE) || (GetSpecies() == Species::NONE)); } -void CFactionDef::SetFactionID(NPC_FACTION faction) +CFactionDef::Group CFactionDef::GetGroup() const noexcept { - _iFaction = faction; + const auto masked_shifted = (_uiFactionData & _kuiGroupMask) >> _kuiGroupReservedBytes; + return num_alias_cast(masked_shifted); +} + +bool CFactionDef::SetGroup(CFactionDef::Group group) noexcept +{ + const auto group_numeric = num_alias_cast(group); + if (group_numeric > _kuiGroupMaxVal) + return false; + + const auto masked_shifted = (group_numeric & _kuiGroupMaxVal) << _kuiGroupReservedBytes; + _uiFactionData = (_uiFactionData & ~_kuiSpeciesMask) | num_alias_cast(masked_shifted); + return true; +} + +CFactionDef::Species CFactionDef::GetSpecies() const noexcept +{ + return num_alias_cast(_uiFactionData & _kuiSpeciesMask); +} + +bool CFactionDef::SetSpecies(CFactionDef::Species species) noexcept +{ + const auto species_numeric = num_alias_cast(species); + if (species_numeric > _kuiSpeciesMaxVal) + return false; + + const auto masked = species_numeric & _kuiSpeciesMask; + _uiFactionData = (_uiFactionData & ~_kuiSpeciesMask) | masked; + return true; } //--- @@ -26,19 +55,22 @@ void CFactionDef::SetFactionID(NPC_FACTION faction) bool CCFaction::IsOppositeGroup(const CCFaction *target) const { ADDTOCALLSTACK("CCFaction::IsOppositeGroup"); - if (IsGroupElemental() && target->IsGroupAbyss()) + const auto myGroup = GetGroup(); + const auto targGroup = target->GetGroup(); + + if ((myGroup == Group::ELEMENTAL) && (targGroup == Group::ABYSS)) return true; - else if (IsGroupAbyss() && (target->IsGroupElemental() || target->IsGroupFey())) + else if ((myGroup == Group::ABYSS) && ((targGroup == Group::FEY) || (targGroup == Group::ELEMENTAL))) return true; - else if (IsGroupFey() && target->IsGroupAbyss()) + else if ((myGroup == Group::FEY) && (targGroup == Group::ABYSS)) return true; - else if (IsGroupReptilian() && target->IsGroupArachnid()) + else if ((myGroup == Group::REPTILIAN) && (targGroup == Group::ARACHNID)) return true; - else if (IsGroupArachnid() && target->IsGroupReptilian()) + else if ((myGroup == Group::ARACHNID) && (targGroup == Group::REPTILIAN)) return true; - else if (IsGroupHumanoid() && target->IsGroupUndead()) + else if ((myGroup == Group::HUMANOID) && (targGroup == Group::UNDEAD)) return true; - else if (IsGroupUndead() && target->IsGroupHumanoid()) + else if ((myGroup == Group::UNDEAD) && (targGroup == Group::HUMANOID)) return true; return false; } @@ -46,20 +78,22 @@ bool CCFaction::IsOppositeGroup(const CCFaction *target) const bool CCFaction::IsOppositeSuperSlayer(const CCFaction *target) const { ADDTOCALLSTACK("CCFaction::IsOppositeSuperSlayer"); - const NPC_FACTION targFaction = target->GetFactionID(); - if ((IsGroupFey()) && (targFaction & FACTION_FEY)) + const auto myGroup = GetGroup(); + const auto targGroup = target->GetGroup(); + const auto targSpecies = target->GetSpecies(); + if ((myGroup == Group::FEY) && (targGroup == Group::FEY) && (targSpecies == Species::FEY_SSLAYER)) return true; - else if ((IsGroupElemental()) && (targFaction & FACTION_ELEMENTAL)) + else if ((myGroup == Group::ELEMENTAL) && (targGroup == Group::ELEMENTAL) && (targSpecies == Species::ELEMENTAL_SSLAYER)) return true; - else if ((IsGroupAbyss()) && (targFaction & FACTION_DEMON)) + else if ((myGroup == Group::ABYSS) && (targGroup == Group::ELEMENTAL) && (targSpecies == Species::DEMON_SSLAYER)) return true; - else if ((IsGroupHumanoid()) && (targFaction & FACTION_REPOND)) + else if ((myGroup == Group::HUMANOID) && (targGroup == Group::HUMANOID) && (targSpecies == Species::REPOND_SSLAYER)) return true; - else if ((IsGroupUndead()) && (targFaction & FACTION_UNDEAD)) + else if ((myGroup == Group::UNDEAD) && (targGroup == Group::UNDEAD) && (targSpecies == Species::UNDEAD_SSLAYER)) return true; - else if ((IsGroupArachnid()) && (targFaction & FACTION_ARACHNID)) + else if ((myGroup == Group::ARACHNID) && (targGroup == Group::ARACHNID) && (targSpecies == Species::ARACHNID_SSLAYER)) return true; - else if ((IsGroupReptilian()) && (targFaction & FACTION_REPTILE)) + else if ((myGroup == Group::REPTILIAN) && (targGroup == Group::REPTILIAN) && (targSpecies == Species::REPTILE_SSLAYER)) return true; return false; } @@ -67,116 +101,49 @@ bool CCFaction::IsOppositeSuperSlayer(const CCFaction *target) const bool CCFaction::IsOppositeLesserSlayer(const CCFaction *target) const { ADDTOCALLSTACK("CCFaction::IsOppositeLesserSlayer"); - // Start Elemental Lesser Slayers - const NPC_FACTION myFaction = GetFactionID(); - const NPC_FACTION targFaction = target->GetFactionID(); - if ((myFaction & FACTION_AIR_ELEMENTAL) && (targFaction & FACTION_AIR_ELEMENTAL)) - return true; - else if ((myFaction & FACTION_BLOOD_ELEMENTAL) && (targFaction & FACTION_BLOOD_ELEMENTAL)) - return true; - else if ((myFaction & FACTION_EARTH_ELEMENTAL) && (targFaction & FACTION_EARTH_ELEMENTAL)) - return true; - else if ((myFaction & FACTION_FIRE_ELEMENTAL) && (targFaction & FACTION_FIRE_ELEMENTAL)) - return true; - else if ((myFaction & FACTION_POISON_ELEMENTAL) && (targFaction & FACTION_POISON_ELEMENTAL)) - return true; - else if ((myFaction & FACTION_SNOW_ELEMENTAL) && (targFaction & FACTION_SNOW_ELEMENTAL)) - return true; - else if ((myFaction & FACTION_WATER_ELEMENTAL) && (targFaction & FACTION_WATER_ELEMENTAL)) - return true; - // Abyss Lesser Slayers - else if ((myFaction & FACTION_GARGOYLE) && (targFaction & FACTION_GARGOYLE)) - return true; - - // Humanoid Lesser Slayers - else if ((myFaction & FACTION_GOBLIN) && (targFaction & FACTION_GOBLIN)) - return true; - else if ((myFaction & FACTION_VERMIN) && (targFaction & FACTION_VERMIN)) - return true; - else if ((myFaction & FACTION_OGRE) && (targFaction & FACTION_OGRE)) - return true; - else if ((myFaction & FACTION_ORC) && (targFaction & FACTION_ORC)) - return true; - else if ((myFaction & FACTION_TROLL) && (targFaction & FACTION_TROLL)) - return true; - - // Undead Lesser Slayers - else if ((myFaction & FACTION_MAGE) && (targFaction & FACTION_MAGE)) - return true; - - // Arachnid Lesser Slayers - else if ((myFaction & FACTION_SCORPION) && (targFaction & FACTION_SCORPION)) - return true; - else if ((myFaction & FACTION_SPIDER) && (targFaction & FACTION_SPIDER)) - return true; - else if ((myFaction & FACTION_TERATHAN) && (targFaction & FACTION_TERATHAN)) - return true; - - // Reptilian Lesser Slayers - else if ((myFaction & FACTION_DRAGON) && (targFaction & FACTION_DRAGON)) - return true; - else if ((myFaction & FACTION_OPHIDIAN) && (targFaction & FACTION_OPHIDIAN)) - return true; - else if ((myFaction & FACTION_SNAKE) && (targFaction & FACTION_SNAKE)) - return true; - else if ((myFaction & FACTION_LIZARDMAN) && (targFaction & FACTION_LIZARDMAN)) - return true; - - // Old ML's Lesser Slayers - else if ((myFaction & FACTION_BAT) && (targFaction & FACTION_BAT)) - return true; - else if ((myFaction & FACTION_BEAR) && (targFaction & FACTION_BEAR)) - return true; - else if ((myFaction & FACTION_BEETLE) && (targFaction & FACTION_BEETLE)) - return true; - else if ((myFaction & FACTION_BIRD) && (targFaction & FACTION_BIRD)) - return true; - - // Standalone Lesser Slayers - else if ((myFaction & FACTION_BOVINE) && (targFaction & FACTION_BOVINE)) - return true; - else if ((myFaction & FACTION_FLAME) && (targFaction & FACTION_FLAME)) - return true; - else if ((myFaction & FACTION_ICE) && (targFaction & FACTION_ICE)) - return true; - else if ((myFaction & FACTION_WOLF) && (targFaction & FACTION_WOLF)) - return true; + // Do i belong to the same group? + if (!( + num_alias_cast(GetGroup()) & + num_alias_cast(target->GetGroup())) + ) + return false; - return false; + // Same species? + return (GetSpecies() == target->GetSpecies()); } enum CHF_TYPE : int { - CHF_FACTION, - CHF_SLAYER, - CHF_FACTIONGROUP, - CHF_SLAYERGROUP, + CHF_FACTION_GROUP, + CHF_FACTION_SPECIES, + CHF_SLAYER_GROUP, + CHF_SLAYER_SPECIES, CHF_QTY }; lpctstr const CCFaction::sm_szLoadKeys[CHF_QTY + 1] = { - "FACTION", - "SLAYER", - "FACTIONGROUP", - "SLAYERGROUP", + "FACTION_GROUP", + "FACTION_SPECIES", + "SLAYER_GROUP", + "SLAYER_SPECIES", nullptr }; -CCFaction::CCFaction() : CFactionDef(), CComponent(COMP_FACTION) +CCFaction::CCFaction() noexcept : + CFactionDef(), CComponent(COMP_FACTION) { - //ADDTOCALLSTACK_DEBUG("CCFaction::CCFaction(FACTION_TYPE)"); } -CCFaction::CCFaction(CCFaction *copy) : CFactionDef(), CComponent(COMP_FACTION) +CCFaction::CCFaction(CCFaction *copy) noexcept : + CFactionDef(), CComponent(COMP_FACTION) { - //ADDTOCALLSTACK_DEBUG("CCFaction::CCFaction(CCFaction*)"); Copy(copy); } -bool CCFaction::CanSubscribe(const CItem* pItem) // static +bool CCFaction::CanSubscribe(const CItem* pItem) noexcept // static { return pItem->IsTypeEquippable(); } @@ -192,10 +159,17 @@ bool CCFaction::r_LoadVal(CScript & s) CHF_TYPE iKeyNum = (CHF_TYPE)FindTableSorted(s.GetKey(), sm_szLoadKeys, ARRAY_COUNT(sm_szLoadKeys) - 1); switch (iKeyNum) { - case CHF_FACTION: - case CHF_SLAYER: + case CHF_FACTION_GROUP: + case CHF_SLAYER_GROUP: + { + SetGroup(num_alias_cast(s.GetArgU32Val())); + return true; + } + + case CHF_FACTION_SPECIES: + case CHF_SLAYER_SPECIES: { - SetFactionID(static_cast(s.GetArgLLVal())); + SetSpecies(num_alias_cast(s.GetArgU32Val())); return true; } } @@ -221,16 +195,16 @@ bool CCFaction::r_WriteVal(lpctstr ptcKey, CSString & s, CTextConsole * pSrc) UnreferencedParameter(pSrc); switch (iKeyNum) { - case CHF_SLAYER: - case CHF_FACTION: + case CHF_FACTION_GROUP: + case CHF_SLAYER_GROUP: { - s.FormatLLHex(GetFactionID()); + s.FormatHex(num_alias_cast(GetGroup())); return true; } - case CHF_SLAYERGROUP: - case CHF_FACTIONGROUP: + case CHF_FACTION_SPECIES: + case CHF_SLAYER_SPECIES: { - s.FormatHex(GetGroupID()); + s.FormatHex(num_alias_cast(GetSpecies())); return true; } default: @@ -242,8 +216,10 @@ bool CCFaction::r_WriteVal(lpctstr ptcKey, CSString & s, CTextConsole * pSrc) void CCFaction::r_Write(CScript & s) { ADDTOCALLSTACK("CCFaction::r_Write"); - if (GetFactionID() != FACTION_NONE){ - s.WriteKeyHex("FACTION", GetFactionID()); // Same value stored with different names for CChars and CItems. + if (_uiFactionData != 0) + { + s.WriteKeyHex("FACTION_GROUP", num_alias_cast(GetGroup())); + s.WriteKeyHex("FACTION_SPECIES", num_alias_cast(GetSpecies())); } } @@ -264,113 +240,21 @@ bool CCFaction::r_Verb(CScript & s, CTextConsole * pSrc) void CCFaction::Copy(const CComponent * target) { ADDTOCALLSTACK("CCFaction::Copy"); - const CCFaction *pTarget = static_cast(target); - if (pTarget) - { - _iFaction = pTarget->GetFactionID(); - } -} - -NPC_GROUP CCFaction::GetGroupID() const -{ - ADDTOCALLSTACK("CCFaction::GetGroupID"); - if (IsGroupElemental()) - return NPCGROUP_ELEMENTAL; - else if (IsGroupAbyss()) - return NPCGROUP_ABYSS; - else if (IsGroupFey()) - return NPCGROUP_FEY; - else if (IsGroupHumanoid()) - return NPCGROUP_HUMANOID; - else if (IsGroupUndead()) - return NPCGROUP_UNDEAD; - else if (IsGroupArachnid()) - return NPCGROUP_ARACHNID; - else if (IsGroupReptilian()) - return NPCGROUP_REPTILIAN; - else - return NPCGROUP_NONE; -} - -NPC_FACTION CCFaction::GetFactionID() const -{ - ADDTOCALLSTACK_DEBUG("CCFaction::GetFactionID"); - return _iFaction; -} - -void CCFaction::SetFactionID(NPC_FACTION faction) -{ - ADDTOCALLSTACK_DEBUG("CCFaction::SetFactionID"); - ASSERT(faction < FACTION_QTY); - ASSERT(faction >= 0); - _iFaction = faction; -} - -bool CCFaction::IsGroupElemental() const -{ - //ADDTOCALLSTACK_DEBUG("CCFaction::IsGroupElemental"); - return ((_iFaction >= FACTION_ELEMENTAL) && (_iFaction < FACTION_ELEMENTAL_QTY)); -} - -bool CCFaction::IsGroupFey() const -{ - //ADDTOCALLSTACK_DEBUG("CCFaction::IsGroupFey"); - return (_iFaction == FACTION_FEY); -} - -bool CCFaction::IsGroupAbyss() const -{ - //ADDTOCALLSTACK_DEBUG("CCFaction::IsGroupAbyss"); - return ((_iFaction >= FACTION_DEMON) && (_iFaction < FACTION_ABYSS_QTY)); -} - -bool CCFaction::IsGroupHumanoid() const -{ - //ADDTOCALLSTACK_DEBUG("CCFaction::IsGroupHumanoid"); - return ((_iFaction >= FACTION_REPOND) && (_iFaction < FACTION_HUMANOID_QTY)); -} - -bool CCFaction::IsGroupUndead() const -{ - //ADDTOCALLSTACK_DEBUG("CCFaction::IsGroupUndead"); - return ((_iFaction >= FACTION_UNDEAD) && (_iFaction < FACTION_UNDEAD_QTY)); -} - -bool CCFaction::IsGroupArachnid() const -{ - //ADDTOCALLSTACK_DEBUG("CCFaction::IsGroupArachnid"); - return ((_iFaction >= FACTION_ARACHNID) && (_iFaction < FACTION_ARACHNID_QTY)); -} - -bool CCFaction::IsGroupReptilian() const -{ - //ADDTOCALLSTACK_DEBUG("CCFaction::IsGroupReptilian"); - return ((_iFaction >= FACTION_REPTILE) && (_iFaction < FACTION_REPTILIAN_QTY)); + const CCFaction *pTarget = dynamic_cast(target); + ASSERT(pTarget); + _uiFactionData = pTarget->_uiFactionData; } bool CCFaction::IsSuperSlayer() const { ADDTOCALLSTACK_DEBUG("CCFaction::IsSuperSlayer"); - switch (_iFaction) - { - case FACTION_FEY: - case FACTION_ELEMENTAL: - case FACTION_DEMON: - case FACTION_REPOND: - case FACTION_UNDEAD: - case FACTION_ARACHNID: - case FACTION_REPTILE: - return true; - } - return false; + return (GetGroup() != Group::NONE && (_kuiSuperSlayerSpeciesIndex == num_alias_cast(GetSpecies()))); } bool CCFaction::IsLesserSlayer() const { ADDTOCALLSTACK_DEBUG("CCFaction::IsLesserSlayer"); - if ((_iFaction > FACTION_NONE) && (_iFaction < FACTION_QTY) && (!IsSuperSlayer())) - return true; - return false; + return ((GetGroup() != Group::NONE) && (GetSpecies() != Species::NONE) && !IsSuperSlayer()); } int CCFaction::GetSlayerDamageBonus(const CCFaction *target) const @@ -391,3 +275,4 @@ int CCFaction::GetSlayerDamagePenalty(const CCFaction * target) const return 1; } + diff --git a/src/game/components/CCFaction.h b/src/game/components/CCFaction.h index c9084f89f..794d18931 100644 --- a/src/game/components/CCFaction.h +++ b/src/game/components/CCFaction.h @@ -8,6 +8,8 @@ #include "../CComponent.h" + +class CChar; class CItem; @@ -33,116 +35,135 @@ class CItem; #define DAMAGE_SLAYER_SUPER 2 // Super Slayer does x2 damage. #define DAMAGE_SLAYER_OPPOSITE 2 // Opposite Slayer does x2 damage. -/* - Groups of NPC_FACTION -*/ -enum NPC_GROUP -{ - NPCGROUP_NONE = 0, - NPCGROUP_FEY = 0x1, - NPCGROUP_ELEMENTAL = 0x2, - NPCGROUP_ABYSS = 0x4, - NPCGROUP_HUMANOID = 0x8, - NPCGROUP_UNDEAD = 0x10, - NPCGROUP_ARACHNID = 0x20, - NPCGROUP_REPTILIAN = 0x40, - NPCGROUP_QTY -}; -/* - Faction IDs -*/ -enum NPC_FACTION : llong -{ - FACTION_NONE = 0, - // Fey Group (opposed to Abyss Group) - FACTION_FEY = 0x1, // SuperSlayer - - // Elemental Group (opposed to Abyss Group) - FACTION_ELEMENTAL = 0x2, // SuperSlayer - FACTION_AIR_ELEMENTAL = 0x4, - FACTION_BLOOD_ELEMENTAL = 0x8, - FACTION_EARTH_ELEMENTAL = 0x10, - FACTION_FIRE_ELEMENTAL = 0x20, - FACTION_POISON_ELEMENTAL = 0x40, - FACTION_SNOW_ELEMENTAL = 0x90, - FACTION_WATER_ELEMENTAL = 0x100, - FACTION_ELEMENTAL_QTY, - - // Abyss Group (opposed to Elemental and Fey Groups) - FACTION_DEMON = 0x200, // SuperSlayer - FACTION_GARGOYLE = 0x400, - FACTION_ABYSS_QTY, - - // Humanoid Group (opposed to Undead Group) - FACTION_REPOND = 0x800, // SuperSlayer - FACTION_GOBLIN = 0x1000, - FACTION_VERMIN = 0x2000, - FACTION_OGRE = 0x4000, - FACTION_ORC = 0x8000, - FACTION_TROLL = 0x10000, - FACTION_HUMANOID_QTY, - - // Undead Group (opposed to Humanoid Group) - FACTION_UNDEAD = 0x20000, // SuperSlayer - FACTION_MAGE = 0x40000, - FACTION_UNDEAD_QTY, - - // Arachnid Group (opposed to Reptilian Group) - FACTION_ARACHNID = 0x80000, // SuperSlayer - FACTION_SCORPION = 0x100000, - FACTION_SPIDER = 0x200000, - FACTION_TERATHAN = 0x400000, - FACTION_ARACHNID_QTY, - - // Reptile Group (opposed to Arachnid) - FACTION_REPTILE = 0x800000, // SuperSlayer - FACTION_DRAGON = 0x1000000, - FACTION_OPHIDIAN = 0x2000000, - FACTION_SNAKE = 0x4000000, - FACTION_LIZARDMAN = 0x8000000, - FACTION_REPTILIAN_QTY, - - // Old Mondain’s Legacy Slayers - FACTION_BAT = 0x10000000, - FACTION_BEAR = 0x20000000, - FACTION_BEETLE = 0x40000000, - FACTION_BIRD = 0x80000000, - - // Standalone Slayers - FACTION_BOVINE = 0x100000000, - FACTION_FLAME = 0x200000000, - FACTION_ICE = 0x400000000, - FACTION_WOLF = 0x800000000, - FACTION_QTY -}; - -class CChar; /* This class is used to store FACTION for NPCs and SLAYER for items Initially involved in the Slayer system it handles Super Slayer, Lesser Slayer and Opposites to increase damage dealt/received */ - class CFactionDef { protected: - NPC_FACTION _iFaction; + uint32 _uiFactionData; + +public: + enum class Group : uint32 + { + NONE = 0, + FEY = 0x1, + ELEMENTAL = 0x2, + ABYSS = 0x4, + HUMANOID = 0x8, + UNDEAD = 0x10, + ARACHNID = 0x20, + REPTILIAN = 0x40, + QTY + // MAX = 0x800000 + }; + // Lowest two bytes are used to store the species as a plain number. + static constexpr uint32 _kuiGroupMask = 0xFFFF'FF00; + static constexpr uint32 _kuiGroupReservedBytes = 8; + static constexpr uint32 _kuiGroupMaxVal = (_kuiGroupMask >> _kuiGroupReservedBytes); + + // TODO: move the values to scripts, we don't need to know here what's the number for a given species. + // Only interested in superslayers (which num is always 1 btw) + static constexpr uint32 _kuiSuperSlayerSpeciesIndex = 1; + enum class Species : uint32 + { + NONE = 0, + // MAX = 255 + // Super Slayers always have species ID 1. + + // Fey Group (opposed to Abyss Group) + FEY_SSLAYER = _kuiSuperSlayerSpeciesIndex, // SuperSlayer + + // Elemental Group (opposed to Abyss Group) + ELEMENTAL_SSLAYER = _kuiSuperSlayerSpeciesIndex, // SuperSlayer + AIR_ELEMENTAL, + BLOOD_ELEMENTAL, + EARTH_ELEMENTAL, + FIRE_ELEMENTAL, + POISON_ELEMENTAL, + SNOW_ELEMENTAL, + WATER_ELEMENTAL, + ELEMENTAL_QTY, + + // Abyss Group (opposed to Elemental and Fey Groups) + DEMON_SSLAYER = _kuiSuperSlayerSpeciesIndex, // SuperSlayer + GARGOYLE, + ABYSS_QTY, + + // Humanoid Group (opposed to Undead Group) + REPOND_SSLAYER = _kuiSuperSlayerSpeciesIndex, // SuperSlayer + GOBLIN, + VERMIN, + OGRE, + ORC, + TROLL, + HUMANOID_QTY, + + // Undead Group (opposed to Humanoid Group) + UNDEAD_SSLAYER = _kuiSuperSlayerSpeciesIndex, // SuperSlayer + MAGE, + UNDEAD_QTY, + + // Arachnid Group (opposed to Reptilian Group) + ARACHNID_SSLAYER = _kuiSuperSlayerSpeciesIndex, // SuperSlayer + SCORPION, + SPIDER, + TERATHAN, + ARACHNID_QTY, + + // Reptile Group (opposed to Arachnid) + REPTILE_SSLAYER = _kuiSuperSlayerSpeciesIndex, // SuperSlayer + DRAGON, + OPHIDIAN, + SNAKE, + LIZARDMAN, + REPTILIAN_QTY, + + // Old Mondain’s Legacy Slayers + BAT_SSLAYER = _kuiSuperSlayerSpeciesIndex, + BEAR, + BEETLE, + BIRD, + //ANIMAL_QTY, // This is not a real slayer group, but we might add ANIMAL_QTY for convenience + + // Standalone Slayers + BOVINE_SSLAYER = _kuiSuperSlayerSpeciesIndex, + FLAME, + ICE, + WOLF + //STANDALONE_QTY + }; + // The upper 6 bytes are used to store the family/group as a bitmask. + static constexpr uint32 _kuiSpeciesMask = 0x0000'00FF; + //static constexpr uint32 _kuiSpeciesReservedBytes = 24; + static constexpr uint32 _kuiSpeciesMaxVal = _kuiSpeciesMask; // 255 + + public: - CFactionDef(); - NPC_FACTION GetFactionID() const; - void SetFactionID(NPC_FACTION faction); + CFactionDef() noexcept; + ~CFactionDef() noexcept = default; + + bool IsNone() const noexcept; + Group GetGroup() const noexcept; + bool SetGroup (Group faction) noexcept; + Species GetSpecies() const noexcept; + bool SetSpecies(Species species) noexcept; }; + class CCFaction : public CFactionDef, public CComponent { static lpctstr const sm_szLoadKeys[]; public: - CCFaction(); - CCFaction(CCFaction *copy); + CCFaction() noexcept; + CCFaction(CCFaction *copy) noexcept; virtual ~CCFaction() override = default; - static bool CanSubscribe(const CItem* pItem); + + static bool CanSubscribe(const CItem* pItem) noexcept; virtual void Delete(bool fForced = false) override; virtual bool r_LoadVal(CScript & s) override; virtual bool r_WriteVal(lpctstr ptcKey, CSString & s, CTextConsole * pSrc = nullptr) override; @@ -152,48 +173,6 @@ class CCFaction : public CFactionDef, public CComponent virtual void Copy(const CComponent *target) override; bool r_Load(CScript & s); // Load a character from Script virtual CCRET_TYPE OnTickComponent() override; - /* - Sets the Group to the specified type. - */ - void SetFactionID(NPC_FACTION group); - /* - Return true if I'm in the 'Elemental' group. - */ - bool IsGroupElemental() const; - /* - Return true if I'm in the 'Fey' group. - */ - bool IsGroupFey() const; - /* - Return true if I'm in the 'Abyss' group. - */ - bool IsGroupAbyss() const; - /* - Return true if I'm in the 'Humaoind' group. - */ - bool IsGroupHumanoid() const; - /* - Return true if I'm in the 'Undead' group. - */ - bool IsGroupUndead() const; - /* - Return true if I'm in the 'Arachnid' group. - */ - bool IsGroupArachnid() const; - /* - Return true if I'm in the 'Reptilian' group. - */ - bool IsGroupReptilian() const; - - /* - Checks for an specific Group and returns it I fit in anyone or FACTION_QTY if not. - */ - NPC_GROUP GetGroupID() const; - - /* - Checks for an specific Faction and returns it I fit in anyone or FACTION_QTY if not. - */ - NPC_FACTION GetFactionID() const; /* Checks my group and the target's one and return true if we are enemies. diff --git a/src/game/components/CCItemDamageable.cpp b/src/game/components/CCItemDamageable.cpp index cd20d1229..8b89325c8 100644 --- a/src/game/components/CCItemDamageable.cpp +++ b/src/game/components/CCItemDamageable.cpp @@ -18,12 +18,12 @@ CCItemDamageable::CCItemDamageable(CItem * pLink) : CComponent(COMP_ITEMDAMAGEAB _fNeedUpdate = true; } -CItem * CCItemDamageable::GetLink() const +CItem * CCItemDamageable::GetLink() const noexcept { return _pLink; } -bool CCItemDamageable::CanSubscribe(const CItem* pItem) // static +bool CCItemDamageable::CanSubscribe(const CItem* pItem) noexcept // static { return pItem->Can(CAN_I_DAMAGEABLE); } diff --git a/src/game/components/CCItemDamageable.h b/src/game/components/CCItemDamageable.h index 44e1e5432..9c90bcf68 100644 --- a/src/game/components/CCItemDamageable.h +++ b/src/game/components/CCItemDamageable.h @@ -20,13 +20,13 @@ class CCItemDamageable : public CComponent word _iMaxHits; int64 _iTimeLastUpdate; bool _fNeedUpdate; - + public: CCItemDamageable(CItem *pLink); virtual ~CCItemDamageable() override = default; - static bool CanSubscribe(const CItem* pItem); + static bool CanSubscribe(const CItem* pItem) noexcept; - CItem *GetLink() const; + CItem *GetLink() const noexcept; void SetCurHits(word iCurHits); void SetMaxHits(word iMaxHits); @@ -43,4 +43,4 @@ class CCItemDamageable : public CComponent virtual void Copy(const CComponent *target) override; virtual CCRET_TYPE OnTickComponent() override; }; -#endif //_INC_CCITEMDAMAGEABLE_H \ No newline at end of file +#endif //_INC_CCITEMDAMAGEABLE_H diff --git a/src/game/components/CCPropsChar.cpp b/src/game/components/CCPropsChar.cpp index 159f3a6ff..aadc5429b 100644 --- a/src/game/components/CCPropsChar.cpp +++ b/src/game/components/CCPropsChar.cpp @@ -30,7 +30,7 @@ CCPropsChar::CCPropsChar() : CComponentProps(COMP_PROPS_CHAR) // If a CItem: subscribed in CItemBase::SetType and CItem::SetType // If a CChar: subscribed in CCharBase::CCharBase and CChar::CChar /* -bool CCPropsChar::CanSubscribe(const CObjBase* pObj) // static +bool CCPropsChar::CanSubscribe(const CObjBase* pObj) noexcept // static { return (pObj->IsItem() || pObj->IsChar()); } @@ -170,7 +170,7 @@ void CCPropsChar::SetPropertyNum(PropertyIndex_t iPropIndex, PropertyValNum_t iV pChar->UpdateStatsFlag(); break; } - + default: //pLinkedObj->UpdatePropertyFlag(); break; @@ -227,7 +227,7 @@ bool CCPropsChar::FindLoadPropVal(CScript & s, CObjBase* pLinkedObj, RESDISPLAY_ return true; } } - + if (!fPropStr && (*s.GetArgRaw() == '\0')) { DeletePropertyNum(fPropStr); @@ -273,17 +273,17 @@ void CCPropsChar::AddPropsTooltipData(CObjBase* pLinkedObj) UnreferencedParameter(pLinkedObj); /* Tooltips for "dynamic" properties (stored in the BaseConts: _mPropsNum and _mPropsStr) */ - + /* // Numeric properties for (const BaseContNumPair_t& propPair : _mPropsNum) { PropertyIndex_t prop = propPair.first; PropertyValNum_t iVal = propPair.second; - + if (iVal == 0) continue; - + switch (prop) { default: // unimplemented diff --git a/src/game/components/CCPropsChar.h b/src/game/components/CCPropsChar.h index 22b2d680d..22fd59ffb 100644 --- a/src/game/components/CCPropsChar.h +++ b/src/game/components/CCPropsChar.h @@ -28,7 +28,7 @@ class CCPropsChar : public CComponentProps CCPropsChar(); virtual ~CCPropsChar() = default; - //static bool CanSubscribe(const CObjBase* pObj); + //static bool CanSubscribe(const CObjBase* pObj) noexcept; static bool IgnoreElementalProperty(PropertyIndex_t iPropIndex); virtual lpctstr GetName() const override { diff --git a/src/game/components/CCPropsItem.cpp b/src/game/components/CCPropsItem.cpp index 94069323f..b37b1e186 100644 --- a/src/game/components/CCPropsItem.cpp +++ b/src/game/components/CCPropsItem.cpp @@ -29,7 +29,7 @@ CCPropsItem::CCPropsItem() : CComponentProps(COMP_PROPS_ITEM) // If a CItem: subscribed in CItemBase::SetType and CItem::SetType // If a CChar: subscribed in CCharBase::CCharBase and CChar::CChar /* -bool CCPropsItem::CanSubscribe(const CObjBase* pObj) // static +bool CCPropsItem::CanSubscribe(const CObjBase* pObj) noexcept // static { return (pObj->IsItem() || pObj->IsChar()); } @@ -179,16 +179,16 @@ void CCPropsItem::AddPropsTooltipData(CObjBase* pLinkedObj) #define ADDTSTR(tooltipID) TOOLTIP_APPEND(new CClientTooltip(tooltipID, ptcVal)) /* Tooltips for "dynamic" properties (stored in the BaseConts: _mPropsNum and _mPropsStr) */ - + // Numeric properties for (const BaseContNumPair_t& propPair : _mPropsNum) { PropertyIndex_t prop = propPair.first; PropertyValNum_t iVal = propPair.second; - + if (iVal == 0) continue; - + if (pLinkedObj->IsItem()) { // Show tooltips for these props only if the linked obj is an item @@ -209,7 +209,7 @@ void CCPropsItem::AddPropsTooltipData(CObjBase* pLinkedObj) } // End of Numeric properties -/* +/* // String properties for (const BaseContStrPair_t& propPair : _mPropsStr) { diff --git a/src/game/components/CCPropsItem.h b/src/game/components/CCPropsItem.h index 60bae8d01..a252a2324 100644 --- a/src/game/components/CCPropsItem.h +++ b/src/game/components/CCPropsItem.h @@ -28,7 +28,7 @@ class CCPropsItem : public CComponentProps CCPropsItem(); virtual ~CCPropsItem() = default; - //static bool CanSubscribe(const CObjBase* pObj); + //static bool CanSubscribe(const CObjBase* pObj) noexcept; virtual lpctstr GetName() const override { return "Item"; diff --git a/src/game/components/CCPropsItemChar.cpp b/src/game/components/CCPropsItemChar.cpp index cf946a678..f62b155dc 100644 --- a/src/game/components/CCPropsItemChar.cpp +++ b/src/game/components/CCPropsItemChar.cpp @@ -31,7 +31,7 @@ CCPropsItemChar::CCPropsItemChar() : CComponentProps(COMP_PROPS_ITEMCHAR) // If a CItem: subscribed in CItemBase::SetType and CItem::SetType // If a CChar: subscribed in CCharBase::CCharBase and CChar::CChar /* -bool CCPropsItemChar::CanSubscribe(const CObjBase* pObj) // static +bool CCPropsItemChar::CanSubscribe(const CObjBase* pObj) noexcept // static { return (pObj->IsItem() || pObj->IsChar()); } @@ -214,16 +214,16 @@ void CCPropsItemChar::AddPropsTooltipData(CObjBase* pLinkedObj) #define ADDTSTR(tooltipID) TOOLTIP_APPEND(new CClientTooltip(tooltipID, ptcVal)) /* Tooltips for "dynamic" properties (stored in the BaseConts: _mPropsNum and _mPropsStr) */ - + // Numeric properties for (const BaseContNumPair_t& propPair : _mPropsNum) { PropertyIndex_t prop = propPair.first; PropertyValNum_t iVal = propPair.second; - + if (iVal == 0) continue; - + if (pLinkedObj->IsItem()) { // Show tooltips for these props only if the linked obj is an item @@ -238,7 +238,7 @@ void CCPropsItemChar::AddPropsTooltipData(CObjBase* pLinkedObj) } // End of Numeric properties -/* +/* // String properties for (const BaseContStrPair_t& propPair : _mPropsStr) { diff --git a/src/game/components/CCPropsItemChar.h b/src/game/components/CCPropsItemChar.h index 645e05d8b..8597f4375 100644 --- a/src/game/components/CCPropsItemChar.h +++ b/src/game/components/CCPropsItemChar.h @@ -28,7 +28,7 @@ class CCPropsItemChar : public CComponentProps CCPropsItemChar(); virtual ~CCPropsItemChar() = default; - //static bool CanSubscribe(const CObjBase* pObj); + //static bool CanSubscribe(const CObjBase* pObj) noexcept; virtual lpctstr GetName() const override { return "ItemChar"; diff --git a/src/game/components/CCPropsItemEquippable.cpp b/src/game/components/CCPropsItemEquippable.cpp index 37dba2b27..717832916 100644 --- a/src/game/components/CCPropsItemEquippable.cpp +++ b/src/game/components/CCPropsItemEquippable.cpp @@ -27,12 +27,12 @@ CCPropsItemEquippable::CCPropsItemEquippable() : CComponentProps(COMP_PROPS_ITEM { } -bool CCPropsItemEquippable::CanSubscribe(const CItemBase* pItemBase) // static +bool CCPropsItemEquippable::CanSubscribe(const CItemBase* pItemBase) noexcept // static { return pItemBase->IsTypeEquippable(); } -bool CCPropsItemEquippable::CanSubscribe(const CItem* pItem) // static +bool CCPropsItemEquippable::CanSubscribe(const CItem* pItem) noexcept // static { return pItem->IsTypeEquippable(); } @@ -56,7 +56,7 @@ bool CCPropsItemEquippable::IsPropertyStr(PropertyIndex_t iPropIndex) const } -/* The idea is: +/* The idea is: - Changed: Elemental damages and resistances (RESFIRE, DAMFIRE...) are now loaded only if COMBAT_ELEMENTAL_ENGINE is on, otherwise those keywords will be IGNORED. Bear in mind that if you have created equippable items when that flag was off and you decide to turn it on later, you'll need to RECREATE all of those ITEMS in order to make them load the elemental properties. We'll use this method when we have figured how to avoid possible bugs when equipping and unequipping items and switching COMBAT_ELEMENTAL_ENGINE on and off. @@ -312,7 +312,7 @@ void CCPropsItemEquippable::AddPropsTooltipData(CObjBase* pLinkedObj) ADDTNUM(1113593); // Fire Eater ~1_Val~% break; case PROPIEQUIP_EATERKINETIC: // Unimplemented - if (IsSetCombatFlags(COMBAT_ELEMENTAL_ENGINE)) + if (IsSetCombatFlags(COMBAT_ELEMENTAL_ENGINE)) ADDTNUM(1113597); // Kinetic Eater ~1_Val~% break; case PROPIEQUIP_EATERPOISON: // Unimplemented diff --git a/src/game/components/CCPropsItemEquippable.h b/src/game/components/CCPropsItemEquippable.h index 83defb0fd..b12c61c56 100644 --- a/src/game/components/CCPropsItemEquippable.h +++ b/src/game/components/CCPropsItemEquippable.h @@ -32,8 +32,8 @@ class CCPropsItemEquippable : public CComponentProps CCPropsItemEquippable(); virtual ~CCPropsItemEquippable() = default; - static bool CanSubscribe(const CItemBase* pItemBase); - static bool CanSubscribe(const CItem* pItem); + static bool CanSubscribe(const CItemBase* pItemBase) noexcept; + static bool CanSubscribe(const CItem* pItem) noexcept; static bool IgnoreElementalProperty(PropertyIndex_t iPropIndex); diff --git a/src/game/components/CCPropsItemWeapon.cpp b/src/game/components/CCPropsItemWeapon.cpp index a3cb0af51..20242746c 100644 --- a/src/game/components/CCPropsItemWeapon.cpp +++ b/src/game/components/CCPropsItemWeapon.cpp @@ -29,19 +29,19 @@ CCPropsItemWeapon::CCPropsItemWeapon() : CComponentProps(COMP_PROPS_ITEMWEAPON) _uiRange = 0; } -static bool CanSubscribeTypeIW(IT_TYPE type) +static bool CanSubscribeTypeIW(IT_TYPE type) noexcept { return (type == IT_WEAPON_AXE || type == IT_WEAPON_BOW || type == IT_WEAPON_FENCE || type == IT_WEAPON_MACE_CROOK || type == IT_WEAPON_MACE_PICK || type == IT_WEAPON_MACE_SHARP || type == IT_WEAPON_MACE_SMITH || type == IT_WEAPON_MACE_STAFF || type == IT_WEAPON_SWORD || type == IT_WEAPON_THROWING || type == IT_WEAPON_WHIP || type == IT_WEAPON_XBOW || type == IT_FISH_POLE || type == IT_MUSICAL); } -bool CCPropsItemWeapon::CanSubscribe(const CItemBase* pItemBase) // static +bool CCPropsItemWeapon::CanSubscribe(const CItemBase* pItemBase) noexcept // static { return CanSubscribeTypeIW(pItemBase->GetType()); } -bool CCPropsItemWeapon::CanSubscribe(const CItem* pItem) // static +bool CCPropsItemWeapon::CanSubscribe(const CItem* pItem) noexcept // static { return CanSubscribeTypeIW(pItem->GetType()); } @@ -125,7 +125,7 @@ bool CCPropsItemWeapon::GetPropertyStrPtr(PropertyIndex_t iPropIndex, CSString* void CCPropsItemWeapon::SetPropertyNum(PropertyIndex_t iPropIndex, PropertyValNum_t iVal, CObjBase* pLinkedObj, RESDISPLAY_VERSION iLimitToExpansion, bool fDeleteZero) { ADDTOCALLSTACK("CCPropsItemWeapon::SetPropertyNum"); - + switch (iPropIndex) { case PROPIWEAP_RANGEH: @@ -175,7 +175,7 @@ void CCPropsItemWeapon::SetPropertyStr(PropertyIndex_t iPropIndex, lpctstr ptcVa _uiRange = CBaseBaseDef::ConvertRangeStr(ptcVal); break; } - + default: ASSERT(IsPropertyStr(iPropIndex)); ASSERT((iLimitToExpansion >= RDS_PRET2A) && (iLimitToExpansion < RDS_QTY)); diff --git a/src/game/components/CCPropsItemWeapon.h b/src/game/components/CCPropsItemWeapon.h index 1a9f014f6..c28a68a0a 100644 --- a/src/game/components/CCPropsItemWeapon.h +++ b/src/game/components/CCPropsItemWeapon.h @@ -32,8 +32,8 @@ class CCPropsItemWeapon : public CComponentProps CCPropsItemWeapon(); virtual ~CCPropsItemWeapon() = default; - static bool CanSubscribe(const CItemBase* pItemBase); - static bool CanSubscribe(const CItem* pItem); + static bool CanSubscribe(const CItemBase* pItemBase) noexcept; + static bool CanSubscribe(const CItem* pItem) noexcept; virtual lpctstr GetName() const override { @@ -67,4 +67,4 @@ class CCPropsItemWeapon : public CComponentProps }; -#endif //_INC_CCPROPSITEMWEAPON_H \ No newline at end of file +#endif //_INC_CCPROPSITEMWEAPON_H diff --git a/src/game/components/CCPropsItemWeaponRanged.cpp b/src/game/components/CCPropsItemWeaponRanged.cpp index 5a6308aa3..03ddc02f7 100644 --- a/src/game/components/CCPropsItemWeaponRanged.cpp +++ b/src/game/components/CCPropsItemWeaponRanged.cpp @@ -26,17 +26,17 @@ CCPropsItemWeaponRanged::CCPropsItemWeaponRanged() : CComponentProps(COMP_PROPS_ { } -static bool CanSubscribeTypeIWR(IT_TYPE type) +static bool CanSubscribeTypeIWR(IT_TYPE type) noexcept { return (type == IT_WEAPON_BOW || type == IT_WEAPON_XBOW); } -bool CCPropsItemWeaponRanged::CanSubscribe(const CItemBase* pItemBase) // static +bool CCPropsItemWeaponRanged::CanSubscribe(const CItemBase* pItemBase) noexcept // static { return CanSubscribeTypeIWR(pItemBase->GetType()); } -bool CCPropsItemWeaponRanged::CanSubscribe(const CItem* pItem) // static +bool CCPropsItemWeaponRanged::CanSubscribe(const CItem* pItem) noexcept // static { return CanSubscribeTypeIWR(pItem->GetType()); } diff --git a/src/game/components/CCPropsItemWeaponRanged.h b/src/game/components/CCPropsItemWeaponRanged.h index 7c1751ebe..83e5f6857 100644 --- a/src/game/components/CCPropsItemWeaponRanged.h +++ b/src/game/components/CCPropsItemWeaponRanged.h @@ -30,8 +30,8 @@ class CCPropsItemWeaponRanged : public CComponentProps CCPropsItemWeaponRanged(); virtual ~CCPropsItemWeaponRanged() = default; - static bool CanSubscribe(const CItemBase* pItemBase); - static bool CanSubscribe(const CItem* pItem); + static bool CanSubscribe(const CItemBase* pItemBase) noexcept; + static bool CanSubscribe(const CItem* pItem) noexcept; virtual lpctstr GetName() const override { @@ -63,4 +63,4 @@ class CCPropsItemWeaponRanged : public CComponentProps }; -#endif //_INC_CCPROPSITEMWEAPONRANGED_H \ No newline at end of file +#endif //_INC_CCPROPSITEMWEAPONRANGED_H diff --git a/src/game/game_macros.h b/src/game/game_macros.h index f3173b26a..b429e2343 100644 --- a/src/game/game_macros.h +++ b/src/game/game_macros.h @@ -70,7 +70,7 @@ #define DAMAGE_THROWN 0x40000 // Damage flag for the throw NPCs action (not the throwing skill!). #define DAMAGE_REACTIVE 0x80000 // Damage reflected by Reactive Armor spell. -typedef dword DAMAGE_TYPE; // describe a type of damage. +typedef uint DAMAGE_TYPE; // describe a type of damage. //--Spellflags diff --git a/src/game/items/CItem.cpp b/src/game/items/CItem.cpp index 7b9f14883..797543052 100644 --- a/src/game/items/CItem.cpp +++ b/src/game/items/CItem.cpp @@ -1234,7 +1234,8 @@ int CItem::FixWeirdness() // unreasonably long for a top level item ? if (_GetTimerSAdjusted() > 90ll * 24 * 60 * 60) { - g_Log.EventWarn("FixWeirdness on Item (UID=0%x [%s]): timer unreasonably long (> 90 days) on a top level object.\n", GetUID().GetObjUID(), GetName()); + g_Log.EventWarn("FixWeirdness on Item (UID=0%x [%s]): timer unreasonably long (> 90 days) on a top level object. Setting to 1 hour.\n", + GetUID().GetObjUID(), GetName()); _SetTimeoutS(60 * 60); } } @@ -3921,7 +3922,7 @@ bool CItem::SetType(IT_TYPE type, bool fPreCheck) else if (!pComp) { CItemBase* pItemDef = Item_GetDef(); - SubscribeComponent(new CCFaction(pItemDef->_pFaction)); + SubscribeComponent(new CCFaction(pItemDef->GetFaction())); } return true; diff --git a/src/game/items/CItemBase.h b/src/game/items/CItemBase.h index 086548311..2c5b33aa6 100644 --- a/src/game/items/CItemBase.h +++ b/src/game/items/CItemBase.h @@ -265,11 +265,11 @@ class CItemBase : public CBaseBaseDef static CREID_TYPE FindCharTrack( ITEMID_TYPE trackID ); - IT_TYPE GetType() const + IT_TYPE GetType() const noexcept { return m_type; } - bool IsType( IT_TYPE type ) const + bool IsType( IT_TYPE type ) const noexcept { return ( type == m_type ); } @@ -277,7 +277,7 @@ class CItemBase : public CBaseBaseDef virtual void SetTypeName( lpctstr pszName ) override; - LAYER_TYPE GetEquipLayer() const + LAYER_TYPE GetEquipLayer() const noexcept { // Is this item really equippable ? return (LAYER_TYPE)m_layer; @@ -378,7 +378,7 @@ class CItemBaseDupe : public CResourceDef static CItemBaseDupe* GetDupeRef(ITEMID_TYPE id); virtual void UnLink() override; - CItemBase* GetItemDef() const; + CItemBase* GetItemDef() const; inline uint64 GetTFlags() const noexcept { diff --git a/src/game/items/CItemMultiCustom.cpp b/src/game/items/CItemMultiCustom.cpp index ef9a9a33a..6955f89c9 100644 --- a/src/game/items/CItemMultiCustom.cpp +++ b/src/game/items/CItemMultiCustom.cpp @@ -1932,7 +1932,7 @@ bool CItemMultiCustom::LoadValidItems() if (!sm_mapValidItems.empty()) // already loaded? return true; - static const char * sm_szItemFiles[][32] = + static constexpr const char * sm_szItemFiles[][32] = { // list of files containing valid items { "doors.txt", "Piece1", "Piece2", "Piece3", "Piece4", "Piece5", "Piece6", "Piece7", "Piece8", nullptr }, @@ -1975,7 +1975,14 @@ bool CItemMultiCustom::LoadValidItems() const std::string& strCurRow = csvDataRow[sm_szItemFiles[i][ii]]; if (strCurRow.empty() || !IsDigit(strCurRow[0])) continue; - ITEMID_TYPE itemid = (ITEMID_TYPE)std::stoul(strCurRow, nullptr, 10); + + auto iconv = Str_ToU(strCurRow.c_str(), 10); + if (iconv.has_value()) + { + g_Log.EventWarn("Invalid number in file '%s', row=%d. Skipping.\n", sm_szItemFiles[i][0], curCSV.GetCurrentRow()); + continue; + } + ITEMID_TYPE itemid = (ITEMID_TYPE)*iconv; if (itemid <= 0 || itemid >= ITEMID_MULTI) continue; @@ -1993,7 +2000,13 @@ bool CItemMultiCustom::LoadValidItems() DEBUG_WARN(("No FeatureMask in file '%s', row=%d.\n", sm_szItemFiles[i][0], curCSV.GetCurrentRow())); continue; } - sm_mapValidItems[itemid] = (uint)std::stoul(strFeatureMask, nullptr, 10); + iconv = Str_ToU(strCurRow.c_str(), 10); + if (iconv.has_value()) + { + g_Log.EventWarn("Invalid FeatureMask number in file '%s', row=%d. Skipping.\n", sm_szItemFiles[i][0], curCSV.GetCurrentRow()); + continue; + } + sm_mapValidItems[itemid] = *iconv; } } diff --git a/src/game/items/CItemMultiCustom.h b/src/game/items/CItemMultiCustom.h index 169345ed5..313fb0afa 100644 --- a/src/game/items/CItemMultiCustom.h +++ b/src/game/items/CItemMultiCustom.h @@ -90,9 +90,8 @@ class CItemMultiCustom : public CItemMulti CItemMultiCustom(ITEMID_TYPE id, CItemBase * pItemDef); virtual ~CItemMultiCustom(); -private: - CItemMultiCustom(const CItemMultiCustom& copy); - CItemMultiCustom& operator=(const CItemMultiCustom& other); + CItemMultiCustom(const CItemMultiCustom& copy) = delete; + CItemMultiCustom& operator=(const CItemMultiCustom& other) = delete; public: void BeginCustomize(CClient* pClientSrc, bool continueCustomize = false); diff --git a/src/game/spheresvr.cpp b/src/game/spheresvr.cpp index 070ead4b5..9843543fe 100644 --- a/src/game/spheresvr.cpp +++ b/src/game/spheresvr.cpp @@ -141,9 +141,9 @@ LinuxEv g_NetworkEvent; CLog g_Log; // Config data from sphere.ini is needed from the beginning. -CServerConfig g_Cfg; -CServer g_Serv; // current state, stuff not saved. -CAccounts g_Accounts; // All the player accounts. name sorted CAccount +CServerConfig g_Cfg; +CServer g_Serv; // current state, stuff not saved. +CAccounts g_Accounts; // All the player accounts. name sorted CAccount // Game servers stuff. CWorld g_World; // the world. (we save this stuff) diff --git a/src/tables/CBaseBaseDef_props.tbl b/src/tables/CBaseBaseDef_props.tbl index 6e5279f25..80402ee19 100644 --- a/src/tables/CBaseBaseDef_props.tbl +++ b/src/tables/CBaseBaseDef_props.tbl @@ -4,30 +4,32 @@ // Prefix: OBC_ // -ADD(ABILITYPRIMARY, "ABILITYPRIMARY") -ADD(ABILITYSECONDARY, "ABILITYSECONDARY") -ADD(ARMOR, "ARMOR") -ADD(BASEID, "BASEID") +ADD(ABILITYPRIMARY, "ABILITYPRIMARY") +ADD(ABILITYSECONDARY, "ABILITYSECONDARY") +ADD(ARMOR, "ARMOR") +ADD(BASEID, "BASEID") ADD(CAN, "CAN") -ADD(CATEGORY, "CATEGORY") +ADD(CATEGORY, "CATEGORY") ADD(DAM, "DAM") ADD(DEFNAME, "DEFNAME") -ADD(DEFNAME2, "DEFNAME2") +ADD(DEFNAME2, "DEFNAME2") ADD(DESCRIPTION, "DESCRIPTION") -ADD(EXPANSION, "EXPANSION") -ADD(FACTION, "FACTION") -ADD(HASCOMPONENTPROPS, "HASCOMPONENTPROPS") -ADD(HEIGHT, "HEIGHT") -ADD(INSTANCES, "INSTANCES") -ADD(ISTEVENT, "ISTEVENT") -ADD(NAME, "NAME") +ADD(EXPANSION, "EXPANSION") +ADD(FACTION_GROUP, "FACTION_GROUP") +ADD(FACTION_SPECIES, "FACTION_SPECIES") +ADD(HASCOMPONENTPROPS, "HASCOMPONENTPROPS") +ADD(HEIGHT, "HEIGHT") +ADD(INSTANCES, "INSTANCES") +ADD(ISTEVENT, "ISTEVENT") +ADD(NAME, "NAME") ADD(NAMELOC, "NAMELOC") -ADD(RESDISPDNHUE, "RESDISPDNHUE") -ADD(RESLEVEL, "RESLEVEL") -ADD(RESOURCES, "RESOURCES") -ADD(SLAYER, "SLAYER") -ADD(SUBSECTION, "SUBSECTION") +ADD(RESDISPDNHUE, "RESDISPDNHUE") +ADD(RESLEVEL, "RESLEVEL") +ADD(RESOURCES, "RESOURCES") +ADD(SLAYER_GROUP, "SLAYER_GROUP") +ADD(SLAYER_SPECIES, "SLAYER_SPECIES") +ADD(SUBSECTION, "SUBSECTION") ADD(TAG, "TAG") -ADD(TAG0, "TAG0") +ADD(TAG0, "TAG0") ADD(TEVENTS, "TEVENTS") -ADD(VELOCITY, "VELOCITY") // TODO: remove? +ADD(VELOCITY, "VELOCITY") // TODO: remove? From ad1e36fabb7252a8dbf9d0f20a4da6b62503dbe0 Mon Sep 17 00:00:00 2001 From: cbnolok Date: Fri, 30 Aug 2024 16:29:57 +0200 Subject: [PATCH 13/86] Changed: enabled resource/defname redefinition warning also for non-debug builds. Fixed: gump tooltips not showing. Also, small refactoring of dialog parsing code. Fixed: CUOMobtypes not parsing correctly strings with comments, bug introduced with a recent refactor commit. Fixed: CGlobalChatChanMember name could be corrupted/overwritten since it was using a temporary string instead of a properly owned one. Fixed: undefined behavior warning in CScriptObj.cpp. Added more stypecast functions and a couple of fixes there. Added more noexcept specifiers. --- src/common/CScriptObj.cpp | 7 +- src/common/assertion.h | 4 +- src/common/basic_threading.h | 2 + src/common/resource/CResourceDef.cpp | 6 +- src/common/resource/sections/CDialogDef.cpp | 156 +++++++++++--------- src/common/sphere_library/stypecast.h | 142 +++++++++++++++--- src/game/CObjBase.cpp | 6 +- src/game/CObjBase.h | 6 +- src/game/CWorld.cpp | 2 +- src/game/CWorld.h | 2 +- src/game/chars/CChar.cpp | 2 +- src/game/clients/CChat.cpp | 11 +- src/game/clients/CChat.h | 2 +- src/game/clients/CChatChanMember.cpp | 17 +-- src/game/clients/CChatChanMember.h | 20 +-- src/game/clients/CGlobalChatChanMember.cpp | 14 +- src/game/clients/CGlobalChatChanMember.h | 14 +- src/game/items/CItem.cpp | 4 +- src/game/items/CItem.h | 4 +- src/game/uo_files/CUOMobtypes.cpp | 18 +-- 20 files changed, 288 insertions(+), 151 deletions(-) diff --git a/src/common/CScriptObj.cpp b/src/common/CScriptObj.cpp index 0836fdc77..9731e86f3 100644 --- a/src/common/CScriptObj.cpp +++ b/src/common/CScriptObj.cpp @@ -2650,12 +2650,14 @@ TRIGRET_TYPE CScriptObj::OnTriggerLoopGeneric(CScript& s, int iType, CTextConsol dword dwUID = 0; dword dwFound = 0; - while (dwCount--) + while (dwCount) { // Check the current UID to test is within our range if (++dwUID >= dwTotal) break; + dwCount -= 1; + // Acquire the object with this UID and check it exists CObjBase* pObj = g_World.FindUID(dwUID); if (pObj == nullptr) @@ -2752,7 +2754,8 @@ TRIGRET_TYPE CScriptObj::OnTriggerLoopForCharSpecial(CScript& s, SK_TYPE iCmd, C } else { - g_Log.EventError("FORCHAR[layer/memorytype] called on char 0%" PRIx32 " (%s) without arguments.\n", (dword)(pCharThis->GetUID()), pCharThis->GetName()); + g_Log.EventError("FORCHAR[layer/memorytype] called on char 0%" PRIx32 " (%s) without arguments.\n", + (dword)(pCharThis->GetUID()), pCharThis->GetName()); iRet = OnTriggerRun(s, TRIGRUN_SECTION_FALSE, pSrc, pArgs, pResult); } } diff --git a/src/common/assertion.h b/src/common/assertion.h index dd30c68d1..984ca1e48 100644 --- a/src/common/assertion.h +++ b/src/common/assertion.h @@ -15,13 +15,13 @@ extern void Assert_Fail(const char * pExp, const char *pFile, long long llLine); #include #define ASSERT(exp) assert(exp) #elif defined(_NIGHTLY) || defined(_DEBUG) - #define ASSERT(exp) if ( !(exp) ) Assert_Fail(#exp, __FILE__, __LINE__) + #define ASSERT(exp) [[unlikely]] if ( !(exp) ) Assert_Fail(#exp, __FILE__, __LINE__) #else #define ASSERT(exp) (void)0 #endif #if defined(_DEBUG) || defined(STATIC_ANALYSIS) - #define DEBUG_ASSERT(exp) if ( !(exp) ) Assert_Fail(#exp, __FILE__, __LINE__) + #define DEBUG_ASSERT(exp) [[unlikely]] if ( !(exp) ) Assert_Fail(#exp, __FILE__, __LINE__) #else #define DEBUG_ASSERT(exp) (void)0 #endif diff --git a/src/common/basic_threading.h b/src/common/basic_threading.h index d5c7193fc..79290e82a 100644 --- a/src/common/basic_threading.h +++ b/src/common/basic_threading.h @@ -40,10 +40,12 @@ // A single macro to lock the class mutex and return the value in a thread-safe way. // Do not use to return references! (It will return the address of the local-scoped, temporary variable _MT_RETURN_val) #define MT_SHARED_LOCK_RETURN(x) \ + /* Creating and locking a mutex might THROW std::system_error ! */ \ {MT_SHARED_LOCK_SET; \ MT_RETURN(x);} #define MT_UNIQUE_LOCK_RETURN(x) \ + /* Creating and locking a mutex might THROW std::system_error ! */ \ {MT_UNIQUE_LOCK_SET; \ MT_RETURN(x);} diff --git a/src/common/resource/CResourceDef.cpp b/src/common/resource/CResourceDef.cpp index 23fa784a4..29f066b51 100644 --- a/src/common/resource/CResourceDef.cpp +++ b/src/common/resource/CResourceDef.cpp @@ -46,9 +46,11 @@ bool CResourceDef::SetResourceName( lpctstr pszName ) const int iKeyIndex = (int)ResGetIndex(dwKeyVal); if ( iKeyIndex == iResIndex) - DEBUG_WARN(( "DEFNAME=%s: redefinition with a strange type mismatch? (0%" PRIx32 "!=0%" PRIx32 ")\n", pszName, dwKeyVal, dwResPrivateUID )); + g_Log.EventWarn( "DEFNAME=%s: redefinition with a strange type mismatch? (0%" PRIx32 "!=0%" PRIx32 ")\n", + pszName, dwKeyVal, dwResPrivateUID ); else - DEBUG_WARN(( "DEFNAME=%s: redefinition (0%x!=0%x)\n", pszName, iKeyIndex, iResIndex )); + g_Log.EventWarn("DEFNAME=%s: redefinition (0%x!=0%x)\n", + pszName, iKeyIndex, iResIndex); pVarKeyNum = g_Exp.m_VarResDefs.SetNum( pszName, dwResPrivateUID ); } diff --git a/src/common/resource/sections/CDialogDef.cpp b/src/common/resource/sections/CDialogDef.cpp index b0a4f90db..0a6fceb81 100644 --- a/src/common/resource/sections/CDialogDef.cpp +++ b/src/common/resource/sections/CDialogDef.cpp @@ -32,6 +32,8 @@ enum GUMPCTL_TYPE // controls we can put in a gump. GUMPCTL_GUMPPICTILED, // x, y, gumpID, w, h, hue=color GUMPCTL_HTMLGUMP, // 7 = x,y,sx,sy, 0 0 0 + GUMPCTL_ITEMPROPERTY, // 1 = uid of the item in question. + // Not really controls but more attributes. GUMPCTL_NOCLOSE, // 0 = The gump cannot be closed by right clicking. GUMPCTL_NODISPOSE, // 0 = The gump cannot be closed by gump-closing macro. @@ -49,7 +51,6 @@ enum GUMPCTL_TYPE // controls we can put in a gump. GUMPCTL_TILEPICHUE, // NEW: x,y,item,color GUMPCTL_TOOLTIP, // From SE client. tooltip cliloc(1003000) - GUMPCTL_ITEMPROPERTY, // 1 = uid of the item in question. GUMPCTL_XMFHTMLGUMP, // 7 = x,y,sx,sy, cliloc(1003000) hasBack canScroll GUMPCTL_XMFHTMLGUMPCOLOR, // NEW: x,y,w,h ??? @@ -80,6 +81,8 @@ lpctstr const CDialogDef::sm_szLoadKeys[GUMPCTL_QTY+1] = "GUMPPICTILED", "HTMLGUMP", + "ITEMPROPERTY", + "NOCLOSE", "NODISPOSE", "NOMOVE", @@ -96,7 +99,6 @@ lpctstr const CDialogDef::sm_szLoadKeys[GUMPCTL_QTY+1] = "TILEPICHUE", "TOOLTIP", - "ITEMPROPERTY", "XMFHTMLGUMP", "XMFHTMLGUMPCOLOR", @@ -106,39 +108,21 @@ lpctstr const CDialogDef::sm_szLoadKeys[GUMPCTL_QTY+1] = }; -uint CDialogDef::GumpAddText( lpctstr pszText ) +uint CDialogDef::GumpAddText( lpctstr ptcText ) { ADDTOCALLSTACK("CDialogDef::GumpAddText"); - m_sText.emplace_back(pszText); + m_sText.emplace_back(ptcText); return uint(m_sText.size() - 1); } -#define SKIP_ALL( args ) SKIP_SEPARATORS( args ); GETNONWHITESPACE( args ); -#define GET_ABSOLUTE( c ) SKIP_ALL( pszArgs ); int c = Exp_GetSingle( pszArgs ); - -#define GET_EVAL( c ) SKIP_ALL( pszArgs ); int c = Exp_GetVal( pszArgs ); - -#define GET_RELATIVE( c, base ) \ - SKIP_ALL( pszArgs ); int c; \ - if ( *pszArgs == '-' && IsSpace(pszArgs[1])) \ - c = base, ++pszArgs; \ - else if ( *pszArgs == '+' ) \ - c = base + Exp_GetSingle( ++pszArgs ); \ - else if ( *pszArgs == '-' ) \ - c = base - Exp_GetSingle( ++pszArgs ); \ - else if ( *pszArgs == '*' ) \ - base = c = base + Exp_GetSingle( ++pszArgs ); \ - else \ - c = Exp_GetSingle( pszArgs ); - bool CDialogDef::r_Verb( CScript & s, CTextConsole * pSrc ) // some command on this object as a target { ADDTOCALLSTACK("CDialogDef::r_Verb"); EXC_TRY("Verb"); + // The first part of the key is GUMPCTL_TYPE lpctstr ptcKey = s.GetKey(); - const int index = FindTableSorted( ptcKey, sm_szLoadKeys, ARRAY_COUNT(sm_szLoadKeys)-1 ); if ( index < 0 ) { @@ -157,7 +141,35 @@ bool CDialogDef::r_Verb( CScript & s, CTextConsole * pSrc ) // some command on t return m_pObj->r_Verb(s, pSrc); } - lpctstr pszArgs = s.GetArgStr(); + lptstr ptcArgs = s.GetArgStr(); + //g_Log.EventDebug("Dialog index %d, KEY %s ARG %s.\n", index, ptcKey, ptcArgs); + + const auto _SkipAll = [](lptstr& ptcArgs) noexcept -> void + { + SKIP_SEPARATORS(ptcArgs); + GETNONWHITESPACE(ptcArgs); + }; + + const auto _CalcRelative = [](lptstr& ptcArgs, int iCoordBase) -> int + { + int c; + if ( *ptcArgs == '-' && IsSpace(ptcArgs[1])) + c = iCoordBase, ++ptcArgs; + else if ( *ptcArgs == '+' ) + c = iCoordBase + Exp_GetSingle( ++ptcArgs ); + else if ( *ptcArgs == '-' ) + c = iCoordBase - Exp_GetSingle( ++ptcArgs ); + else if ( *ptcArgs == '*' ) + iCoordBase = c = iCoordBase + Exp_GetSingle( ++ptcArgs ); + else + c = Exp_GetSingle( ptcArgs ); + return c; + }; + +# define GET_ABSOLUTE(c) _SkipAll(ptcArgs); int c = Exp_GetSingle(ptcArgs); +# define GET_EVAL(c) _SkipAll(ptcArgs); int c = Exp_GetVal(ptcArgs); +# define GET_RELATIVE(c, base) _SkipAll(ptcArgs); int c = _CalcRelative(ptcArgs, base); + switch( index ) { case GUMPCTL_PAGE: @@ -217,9 +229,9 @@ bool CDialogDef::r_Verb( CScript & s, CTextConsole * pSrc ) // some command on t GET_RELATIVE( x, m_iOriginX ); GET_RELATIVE( y, m_iOriginY ); GET_ABSOLUTE( id ); - SKIP_ALL( pszArgs ); + _SkipAll( ptcArgs ); - m_sControls.emplace_back(false).Format( "gumppic %d %d %d%s%s", x, y, id, *pszArgs ? " hue=" : "", *pszArgs ? pszArgs : "" ); + m_sControls.emplace_back(false).Format( "gumppic %d %d %d%s%s", x, y, id, *ptcArgs ? " hue=" : "", *ptcArgs ? ptcArgs : "" ); return true; } @@ -267,13 +279,13 @@ bool CDialogDef::r_Verb( CScript & s, CTextConsole * pSrc ) // some command on t GET_RELATIVE( x, m_iOriginX ); GET_RELATIVE( y, m_iOriginY ); GET_ABSOLUTE( id ); - SKIP_ALL( pszArgs ); + _SkipAll( ptcArgs ); // TilePic don't use args, TilePicHue yes :) if ( index == GUMPCTL_TILEPIC ) m_sControls.emplace_back(false).Format( "tilepic %d %d %d", x, y, id ); else - m_sControls.emplace_back(false).Format( "tilepichue %d %d %d%s%s", x, y, id, *pszArgs ? " " : "", *pszArgs ? pszArgs : "" ); + m_sControls.emplace_back(false).Format( "tilepichue %d %d %d%s%s", x, y, id, *ptcArgs ? " " : "", *ptcArgs ? ptcArgs : "" ); return true; } @@ -283,12 +295,12 @@ bool CDialogDef::r_Verb( CScript & s, CTextConsole * pSrc ) // some command on t GET_RELATIVE( x, m_iOriginX ); GET_RELATIVE( y, m_iOriginY ); GET_ABSOLUTE( hue ); - SKIP_ALL( pszArgs ) - if ( *pszArgs == '.' ) - ++pszArgs; + _SkipAll( ptcArgs ); + if ( *ptcArgs == '.' ) + ++ptcArgs; - uint iText = GumpAddText( *pszArgs ? pszArgs : "" ); - m_sControls.emplace_back(false).Format( "text %d %d %d %u", x, y, hue, iText ); + const uint uiText = GumpAddText( *ptcArgs ? ptcArgs : "" ); + m_sControls.emplace_back(false).Format( "text %d %d %d %u", x, y, hue, uiText ); return true; } @@ -299,11 +311,12 @@ bool CDialogDef::r_Verb( CScript & s, CTextConsole * pSrc ) // some command on t GET_ABSOLUTE( w ); GET_ABSOLUTE( h ); GET_ABSOLUTE( hue ); - SKIP_ALL( pszArgs ) - if ( *pszArgs == '.' ) pszArgs++; + _SkipAll( ptcArgs ); + if ( *ptcArgs == '.' ) + ptcArgs += 1; - uint iText = GumpAddText( *pszArgs ? pszArgs : "" ); - m_sControls.emplace_back(false).Format( "croppedtext %d %d %d %d %d %u", x, y, w, h, hue, iText ); + const uint uiText = GumpAddText( *ptcArgs ? ptcArgs : "" ); + m_sControls.emplace_back(false).Format( "croppedtext %d %d %d %d %d %u", x, y, w, h, hue, uiText ); return true; } @@ -315,10 +328,10 @@ bool CDialogDef::r_Verb( CScript & s, CTextConsole * pSrc ) // some command on t GET_ABSOLUTE( h ); GET_ABSOLUTE( bck ); GET_ABSOLUTE( options ); - SKIP_ALL( pszArgs ) + _SkipAll( ptcArgs ); - uint iText = GumpAddText( *pszArgs ? pszArgs : "" ); - m_sControls.emplace_back(false).Format( "htmlgump %d %d %d %d %u %d %d", x, y, w, h, iText, bck, options ); + const uint uiText = GumpAddText( *ptcArgs ? ptcArgs : "" ); + m_sControls.emplace_back(false).Format( "htmlgump %d %d %d %d %u %d %d", x, y, w, h, uiText, bck, options ); return true; } @@ -330,10 +343,10 @@ bool CDialogDef::r_Verb( CScript & s, CTextConsole * pSrc ) // some command on t GET_ABSOLUTE( h ); GET_ABSOLUTE( hue ); GET_ABSOLUTE( id ); - SKIP_ALL( pszArgs ) + _SkipAll( ptcArgs ); - uint iText = GumpAddText( *pszArgs ? pszArgs : "" ); - m_sControls.emplace_back(false).Format( "textentry %d %d %d %d %d %d %u", x, y, w, h, hue, id, iText ); + const uint uiText = GumpAddText( *ptcArgs ? ptcArgs : "" ); + m_sControls.emplace_back(false).Format( "textentry %d %d %d %d %d %d %u", x, y, w, h, hue, id, uiText ); return true; } @@ -346,10 +359,10 @@ bool CDialogDef::r_Verb( CScript & s, CTextConsole * pSrc ) // some command on t GET_ABSOLUTE( hue ); GET_ABSOLUTE( id ); GET_ABSOLUTE( charLimit ); - SKIP_ALL( pszArgs ) + _SkipAll( ptcArgs ); - uint iText = GumpAddText( *pszArgs ? pszArgs : "" ); - m_sControls.emplace_back(false).Format( "textentrylimited %d %d %d %d %d %d %u %d", x, y, w, h, hue, id, iText, charLimit ); + const uint uiText = GumpAddText( *ptcArgs ? ptcArgs : "" ); + m_sControls.emplace_back(false).Format( "textentrylimited %d %d %d %d %d %d %u %d", x, y, w, h, hue, id, uiText, charLimit ); return true; } @@ -381,12 +394,17 @@ bool CDialogDef::r_Verb( CScript & s, CTextConsole * pSrc ) // some command on t case GUMPCTL_TOOLTIP: { - // The client expects this to be sent as a string in decimal notation. - std::optional conv = Str_ToU(pszArgs); + tchar* pptcArgs[2]; + const int iArgs = Str_ParseCmds(ptcArgs, pptcArgs, ARRAY_COUNT(pptcArgs)); + if (iArgs < 2) + return false; + + // The client expects this to be sent as a string in decimal notation. Ensure that. + std::optional conv = Str_ToU(pptcArgs[0]); if (!conv.has_value()) return false; - m_sControls.emplace_back(false).Format( "tooltip %u", conv.value() ); + m_sControls.emplace_back(false).Format( "tooltip %u %s", conv.value(), pptcArgs[1] ); return true; } @@ -408,21 +426,21 @@ bool CDialogDef::r_Verb( CScript & s, CTextConsole * pSrc ) // some command on t // m_iOriginX = x; // m_iOriginY = y; - SKIP_ALL( pszArgs ); - if ( *pszArgs == '-' && (IsSpace( pszArgs[1] ) || !pszArgs[1]) ) - ++pszArgs; - else if ( *pszArgs == '*' ) - m_iOriginX += Exp_GetSingle( ++pszArgs ); + _SkipAll( ptcArgs ); + if ( *ptcArgs == '-' && (IsSpace( ptcArgs[1] ) || !ptcArgs[1]) ) + ++ptcArgs; + else if ( *ptcArgs == '*' ) + m_iOriginX += Exp_GetSingle( ++ptcArgs ); else - m_iOriginX = Exp_GetSingle( pszArgs ); + m_iOriginX = Exp_GetSingle( ptcArgs ); - SKIP_ALL( pszArgs ); - if ( *pszArgs == '-' && (IsSpace( pszArgs[1] ) || !pszArgs[1]) ) - ++pszArgs; - else if ( *pszArgs == '*' ) - m_iOriginY += Exp_GetSingle( ++pszArgs ); + _SkipAll( ptcArgs ); + if ( *ptcArgs == '-' && (IsSpace( ptcArgs[1] ) || !ptcArgs[1]) ) + ++ptcArgs; + else if ( *ptcArgs == '*' ) + m_iOriginY += Exp_GetSingle( ++ptcArgs ); else - m_iOriginY = Exp_GetSingle( pszArgs ); + m_iOriginY = Exp_GetSingle( ptcArgs ); return true; } @@ -447,12 +465,12 @@ bool CDialogDef::r_Verb( CScript & s, CTextConsole * pSrc ) // some command on t GET_ABSOLUTE( cliloc ); GET_ABSOLUTE( hasBack ); GET_ABSOLUTE( canScroll ); - //SKIP_ALL( pszArgs ) + //_SkipAll( ptcArgs ) if ( index == GUMPCTL_XMFHTMLGUMP ) // xmfhtmlgump doesn't use color - m_sControls.emplace_back(false).Format( "xmfhtmlgump %d %d %d %d %d %d %d" , x, y, sX, sY, cliloc, hasBack, canScroll ); + m_sControls.emplace_back(false).Format( "xmfhtmlgump %d %d %d %d %d %d %d", x, y, sX, sY, cliloc, hasBack, canScroll ); else - m_sControls.emplace_back(false).Format( "xmfhtmlgumpcolor %d %d %d %d %d %d %d%s%s", x, y, sX, sY, cliloc, hasBack, canScroll, *pszArgs ? " " : "", *pszArgs ? pszArgs : "" ); + m_sControls.emplace_back(false).Format( "xmfhtmlgumpcolor %d %d %d %d %d %d %d%s%s", x, y, sX, sY, cliloc, hasBack, canScroll, *ptcArgs ? " " : "", *ptcArgs ? ptcArgs : "" ); return true; } @@ -466,9 +484,9 @@ bool CDialogDef::r_Verb( CScript & s, CTextConsole * pSrc ) // some command on t GET_ABSOLUTE(canScroll); GET_ABSOLUTE(color); GET_ABSOLUTE(cliloc); - SKIP_ALL(pszArgs); + _SkipAll(ptcArgs); - m_sControls.emplace_back(false).Format("xmfhtmltok %d %d %d %d %d %d %d %d %s", x, y, sX, sY, hasBack, canScroll, color, cliloc, *pszArgs ? pszArgs : ""); + m_sControls.emplace_back(false).Format("xmfhtmltok %d %d %d %d %d %d %d %d %s", x, y, sX, sY, hasBack, canScroll, color, cliloc, *ptcArgs ? ptcArgs : ""); return true; } @@ -476,10 +494,14 @@ bool CDialogDef::r_Verb( CScript & s, CTextConsole * pSrc ) // some command on t break; } - m_sControls.emplace_back(false).Format("%s %s", ptcKey, pszArgs); + m_sControls.emplace_back(false).Format("%s %s", ptcKey, ptcArgs); return true; EXC_CATCH; +# undef GET_ABSOLUTE +# undef GET_EVAL +# undef GET_RELATIVE + EXC_DEBUG_START; EXC_ADD_SCRIPTSRC; EXC_DEBUG_END; diff --git a/src/common/sphere_library/stypecast.h b/src/common/sphere_library/stypecast.h index bce210d15..f36b0e040 100644 --- a/src/common/sphere_library/stypecast.h +++ b/src/common/sphere_library/stypecast.h @@ -1,7 +1,7 @@ #ifndef _INC_STYPECAST_H #define _INC_STYPECAST_H -#include +#include #include #include @@ -75,7 +75,7 @@ template [[nodiscard]] inline auto n64_narrow32_checked(const T a) { - ASSERT(a < std::numeric_limits::max()); + ASSERT(a <= std::numeric_limits::max()); return n64_narrow32(a); } @@ -88,7 +88,7 @@ constexpr auto n64_narrow16(const T a) noexcept static_assert(std::is_integral_v || (std::is_floating_point_v && std::is_signed_v), "Unsigned floating point numbers are unsupported by the language standard"); static_assert(sizeof(T) == 8, "Input variable is not a 64 bit number."); - // Since the narrowing can be implementation specific, here we decide that we take only the lower 32 bytes and discard the upper ones. + // Since the narrowing can be implementation specific, here we decide that we take only the lower 16 bytes and discard the upper ones. constexpr uint64 umask = 0x0000'0000'0000'FFFF; if constexpr (std::is_signed_v) { @@ -105,10 +105,37 @@ template [[nodiscard]] inline auto n64_narrow16_checked(const T a) { - ASSERT(a < std::numeric_limits::max()); + ASSERT(a <= std::numeric_limits::max()); return n64_narrow16(a); } +// Narrow a 64 bits number to a 8 bits number, discarding any upper exceeding bytes. +template +[[nodiscard]] +constexpr auto n64_narrow8(const T a) noexcept +{ + static_assert(std::is_arithmetic_v, "Input variable is not an arithmetic type"); + static_assert(std::is_floating_point_v == false, "Corresponding 8-bit floating point type does not exist?"); + static_assert(std::is_integral_v || (std::is_floating_point_v && std::is_signed_v), "Unsigned floating point numbers are unsupported by the language standard"); + static_assert(sizeof(T) == 8, "Input variable is not a 64 bit number."); + + // Since the narrowing can be implementation specific, here we decide that we take only the lower 8 bytes and discard the upper ones. + constexpr uint64 umask = 0x0000'0000'0000'00FF; + if constexpr (std::is_signed_v) + return static_cast(a & umask); + else + return static_cast(a & umask); +} + +// Narrow a 64 bits number to a 8 bits number and ASSERT (because you're reasonably sure but not absolutely certain) that it won't overflow. +template +[[nodiscard]] inline +auto n64_narrow8_checked(const T a) +{ + ASSERT(a <= std::numeric_limits::max()); + return n64_narrow8(a); +} + // Narrow a 32 bits number to a 16 bits number, discarding any upper exceeding bytes. template [[nodiscard]] @@ -135,7 +162,7 @@ template [[nodiscard]] inline auto n32_narrow16_checked(const T a) { - ASSERT(a < std::numeric_limits::max()); + ASSERT(a <= std::numeric_limits::max()); return n32_narrow16(a); } @@ -160,7 +187,7 @@ template [[nodiscard]] inline auto n32_narrow8_checked(const T a) { - ASSERT(a < std::numeric_limits::max()); + ASSERT(a <= std::numeric_limits::max()); return n32_narrow8(a); } @@ -186,7 +213,7 @@ template [[nodiscard]] inline auto n16_narrow8_checked(const T a) { - ASSERT(a < std::numeric_limits::max()); + ASSERT(a <= std::numeric_limits::max()); return n16_narrow8(a); } @@ -201,14 +228,12 @@ constexpr uint32 usize_narrow32(const size_t a) noexcept else return a; */ -#if SIZE_MAX == ULLONG_MAX - // ptr size is 8 -> 64 bits +#if SIZE_MAX == UINT64_MAX return n64_narrow32(a); -#elif SIZE_MAX == UINT_MAX - // ptr size is 4 -> 32 bits +#elif SIZE_MAX == UINT32_MAX return a; #else -# error "Pointer size is neither 8 nor 4?" +# error "size_t is neither 8 nor 4 bytes?" #endif } @@ -216,12 +241,12 @@ constexpr uint32 usize_narrow32(const size_t a) noexcept [[nodiscard]] inline uint32 usize_narrow32_checked(const size_t a) { - ASSERT(a < std::numeric_limits::max()); + ASSERT(a <= std::numeric_limits::max()); return usize_narrow32(a); } -// Unsigned (and size_t) to signed. +/* Unsigned (and size_t) to signed, checked. */ // Convert an 8 bits unsigned value to signed and ASSERT (because you're reasonably sure but not absolutely certain) that it will fit into its signed datatype counterpart (unsigned variables can store greater values than signed ones). [[nodiscard]] inline @@ -241,6 +266,22 @@ int16 i16_from_u16_checked(const uint16 a) // not clamping/capping } template int16 i16_from_u16_checked(T) = delete; +[[nodiscard]] inline +int16 i16_from_u32_checked(const uint32 a) // not clamping/capping +{ + ASSERT(a <= (uint32_t)std::numeric_limits::max()); + return static_cast(a); +} +template int16 i16_from_u32_checked(T) = delete; + +[[nodiscard]] inline +int16 i16_from_u64_checked(const uint64 a) // not clamping/capping +{ + ASSERT(a <= (uint64_t)std::numeric_limits::max()); + return static_cast(a); +} +template int16 i16_from_u64_checked(T) = delete; + // Convert a 32 bits unsigned value to signed and ASSERT (because you're reasonably sure but not absolutely certain) that it will fit into its signed datatype counterpart (unsigned variables can store greater values than signed ones). [[nodiscard]] inline int32 i32_from_u32_checked(const uint32 a) // not clamping/capping @@ -250,6 +291,14 @@ int32 i32_from_u32_checked(const uint32 a) // not clamping/capping } template int32 i32_from_u32_checked(T) = delete; +[[nodiscard]] inline +int32 i32_from_u64_checked(const uint64 a) // not clamping/capping +{ + ASSERT(a <= (uint64_t)std::numeric_limits::max()); + return static_cast(a); +} +template int32 i32_from_u64_checked(T) = delete; + // Convert a 64 bits unsigned value to signed and ASSERT (because you're reasonably sure but not absolutely certain) that it will fit into its signed datatype counterpart (unsigned variables can store greater values than signed ones). [[nodiscard]] inline int64 i64_from_u64_checked(const uint64 a) // not clamping/capping @@ -260,6 +309,65 @@ int64 i64_from_u64_checked(const uint64 a) // not clamping/capping template int64 i64_from_u64_checked(T) = delete; +// size_t conversions + +[[nodiscard]] inline +int8 i8_from_usize_checked(const size_t a) // not clamping/capping +{ +#if SIZE_MAX == UINT64_MAX + return n64_narrow8_checked(a); +#elif SIZE_MAX == UINT32_MAX + return n32_narrow8_checked(a); +#else +# error "size_t is neither 8 nor 4 bytes?" +#endif +} +template int8 i8_from_usize_checked(T) = delete; + + +[[nodiscard]] inline +int16 i16_from_usize_checked(const size_t a) // not clamping/capping +{ +#if SIZE_MAX == UINT64_MAX + return n64_narrow16_checked(a); +#elif SIZE_MAX == UINT32_MAX + return n32_narrow16_checked(a); +#else +# error "size_t is neither 8 nor 4 bytes?" +#endif +} +template int16 i16_from_usize_checked(T) = delete; + +[[nodiscard]] inline +int32 i32_from_usize_checked(const size_t a) // not clamping/capping +{ +#if SIZE_MAX == UINT64_MAX + return n64_narrow32_checked(a); +#elif SIZE_MAX == UINT32_MAX + return i32_from_u32_checked(a); +#else +# error "size_t is neither 8 nor 4 bytes?" +#endif +} +template int32 i32_from_usize_checked(T) = delete; + +[[nodiscard]] inline +int64 i64_from_usize_checked(const size_t a) // not clamping/capping +{ +#if SIZE_MAX == UINT64_MAX + return i64_from_u64_checked(a); +#elif SIZE_MAX == UINT32_MAX + return static_cast(a); // For sure it will fit +#else +# error "size_t is neither 8 nor 4 bytes?" +#endif +} +template int64 i64_from_usize_checked(T) = delete; + + +/* Unsigned (and size_t) to signed, clamping. */ + + [[nodiscard]] constexpr int8 i8_from_u8_clamping(const uint8 a) noexcept { @@ -269,19 +377,19 @@ int8 i8_from_u8_clamping(const uint8 a) noexcept [[nodiscard]] constexpr int16 i16_from_u16_clamping(const uint16 a) noexcept { - return (a > (uint16_t)std::numeric_limits::max()) ? (uint16_t)std::numeric_limits::max() : (int16_t)a; + return (a > (uint16_t)std::numeric_limits::max()) ? std::numeric_limits::max() : (int16_t)a; } [[nodiscard]] constexpr int32 i32_from_u32_clamping(const uint32 a) noexcept { - return (a > (uint32_t)std::numeric_limits::max()) ? (uint32_t)std::numeric_limits::max() : (int32_t)a; + return (a > (uint32_t)std::numeric_limits::max()) ? std::numeric_limits::max() : (int32_t)a; } [[nodiscard]] constexpr int64 i64_from_u64_clamping(const uint64 a) noexcept { - return (a > (uint64_t)std::numeric_limits::max()) ? (uint64_t)std::numeric_limits::max() : (int64_t)a; + return (a > (uint64_t)std::numeric_limits::max()) ? std::numeric_limits::max() : (int64_t)a; } [[nodiscard]] constexpr diff --git a/src/game/CObjBase.cpp b/src/game/CObjBase.cpp index d7c213b6a..818036c1c 100644 --- a/src/game/CObjBase.cpp +++ b/src/game/CObjBase.cpp @@ -274,18 +274,18 @@ CBaseBaseDef* CObjBase::Base_GetDef() const noexcept return (static_cast (m_BaseRef.GetRef())); } -bool CObjBase::IsContainer() const +bool CObjBase::IsContainer() const noexcept { // Simple test if object is a container. return (dynamic_cast (this) != nullptr); } -int64 CObjBase::GetTimeStampS() const +int64 CObjBase::GetTimeStampS() const noexcept { return m_iTimeStampS; } -void CObjBase::SetTimeStampS(int64 t_time) +void CObjBase::SetTimeStampS(int64 t_time) noexcept { m_iTimeStampS = t_time; } diff --git a/src/game/CObjBase.h b/src/game/CObjBase.h index 41b68084b..94d97e2ef 100644 --- a/src/game/CObjBase.h +++ b/src/game/CObjBase.h @@ -204,13 +204,13 @@ public: virtual bool IsDeleted() const override; * @brief Gets timestamp of the item (it's a property and not related at all with TIMER). * @return The timestamp. */ - int64 GetTimeStampS() const; + int64 GetTimeStampS() const noexcept; /** * @brief Sets time stamp. * @param t_time The time. */ - void SetTimeStampS(int64 t_time); + void SetTimeStampS(int64 t_time) noexcept; /* * @brief Add iDelta to this object's timer (if active) and its child objects. @@ -859,7 +859,7 @@ public: virtual bool IsDeleted() const override; * * @return true if container, false if not. */ - bool IsContainer() const; + bool IsContainer() const noexcept; /** * @fn virtual void CObjBase::Update(const CClient * pClientExclude = nullptr) = 0; diff --git a/src/game/CWorld.cpp b/src/game/CWorld.cpp index ed896a707..5abeb62ef 100644 --- a/src/game/CWorld.cpp +++ b/src/game/CWorld.cpp @@ -294,7 +294,7 @@ dword CWorldThread::GetUIDCount() const return (dword)_uiUIDObjArraySize; } -CObjBase *CWorldThread::FindUID(dword dwIndex) const +CObjBase *CWorldThread::FindUID(dword dwIndex) const noexcept { if ( !dwIndex || dwIndex >= GetUIDCount() ) return nullptr; diff --git a/src/game/CWorld.h b/src/game/CWorld.h index ab0544c29..fce63a5a5 100644 --- a/src/game/CWorld.h +++ b/src/game/CWorld.h @@ -81,7 +81,7 @@ class CWorldThread // UID Managenent #define UID_PLACE_HOLDER (reinterpret_cast(INTPTR_MAX)) dword GetUIDCount() const; - CObjBase * FindUID(dword dwIndex) const; + CObjBase * FindUID(dword dwIndex) const noexcept; void FreeUID(dword dwIndex); dword AllocUID( dword dwIndex, CObjBase * pObj ); diff --git a/src/game/chars/CChar.cpp b/src/game/chars/CChar.cpp index 7901f0c64..40626e0e0 100644 --- a/src/game/chars/CChar.cpp +++ b/src/game/chars/CChar.cpp @@ -1248,7 +1248,7 @@ bool CChar::DupeFrom(const CChar * pChar, bool fNewbieItems ) pItem->m_uidLink = myUID; //If the character being duped has an item which linked to himself, set the newly duped character link instead. else if (IsSetOF(OF_PetSlots) && pItem->IsMemoryTypes(MEMORY_IPET) && pTest3 == NPC_PetGetOwner()) { - const short iFollowerSlots = (short)GetDefNum("FOLLOWERSLOTS", true, 1); + const short iFollowerSlots = n64_narrow16(GetDefNum("FOLLOWERSLOTS", true, 1)); //If we have reached the maximum follower slots we remove the ownership of the pet by clearing the memory flag instead of using NPC_PetClearOwners(). if (!pTest3->FollowersUpdate(this, maximum(0, iFollowerSlots))) Memory_ClearTypes(MEMORY_IPET); diff --git a/src/game/clients/CChat.cpp b/src/game/clients/CChat.cpp index cc60350ce..b9aec96dd 100644 --- a/src/game/clients/CChat.cpp +++ b/src/game/clients/CChat.cpp @@ -6,6 +6,9 @@ #include "CChatChanMember.h" #include "CClient.h" + +lpctstr CChat::m_sClassName = "CChat"; + bool CChat::CreateChannel(lpctstr pszName, lpctstr pszPassword, CChatChanMember* pMember) { ADDTOCALLSTACK("CChat::CreateChannel"); @@ -377,7 +380,7 @@ void CChat::Action(CClient* pClient, const nachar* pszText, int len, CLanguageID } } -void CChat::QuitChat(CChatChanMember* pClient) +void CChat::QuitChat(CChatChanMember* pClient) noexcept { ADDTOCALLSTACK("CChat::QuitChat"); // Remove from old channel (if any) @@ -387,7 +390,11 @@ void CChat::QuitChat(CChatChanMember* pClient) CChatChannel* pCurrentChannel = pClient->GetChannel(); if (pCurrentChannel) + { + EXC_TRY("Removing channel member"); pCurrentChannel->RemoveMember(pClient); + EXC_CATCH; + } } void CChat::FormatName(CSString& sName, const CChatChanMember* pMember, bool fSystem) @@ -471,7 +478,7 @@ void CChat::BroadcastAddChannel(CChatChannel* pChannel) ClientIterator it; for (CClient* pClient = it.next(); pClient != nullptr; pClient = it.next()) - pClient->addChatSystemMessage(CHATCMD_AddChannel, pChannel->GetName(), pClient->m_fUseNewChatSystem ? nullptr : pChannel->GetPassword()); + pClient->addChatSystemMessage(CHATCMD_AddChannel, pChannel->GetName(), (pClient->m_fUseNewChatSystem ? nullptr : pChannel->GetPassword())); } void CChat::BroadcastRemoveChannel(CChatChannel* pChannel) diff --git a/src/game/clients/CChat.h b/src/game/clients/CChat.h index 3c62e96c3..0cfda724d 100644 --- a/src/game/clients/CChat.h +++ b/src/game/clients/CChat.h @@ -33,7 +33,7 @@ class CChat void Broadcast(CChatChanMember * pFrom, lpctstr pszText, CLanguageID lang = 0, bool fOverride = false); void BroadcastAddChannel(CChatChannel* pChannel); void BroadcastRemoveChannel(CChatChannel* pChannel); - void QuitChat(CChatChanMember * pClient); + void QuitChat(CChatChanMember * pClient) noexcept; bool IsChannel(const CChatChannel* pChannel) const; void JoinChannel(lpctstr pszChannel, lpctstr pszPassword, CChatChanMember* pMember = nullptr); diff --git a/src/game/clients/CChatChanMember.cpp b/src/game/clients/CChatChanMember.cpp index e310d0415..edc41a909 100644 --- a/src/game/clients/CChatChanMember.cpp +++ b/src/game/clients/CChatChanMember.cpp @@ -4,15 +4,12 @@ #include "CChatChanMember.h" #include "CClient.h" -CChatChanMember::CChatChanMember() +CChatChanMember::CChatChanMember() noexcept + :m_fChatActive(false), m_fReceiving(true), m_fAllowWhoIs(true), m_pChannel(nullptr) { - m_fChatActive = false; - m_pChannel = nullptr; - m_fReceiving = true; - m_fAllowWhoIs = true; } -CChatChanMember::~CChatChanMember() +CChatChanMember::~CChatChanMember() noexcept { if ( IsChatActive()) // Are we chatting currently ? { @@ -20,7 +17,7 @@ CChatChanMember::~CChatChanMember() } } -CChatChannel * CChatChanMember::GetChannel() const +CChatChannel * CChatChanMember::GetChannel() const noexcept { return m_pChannel; } @@ -30,7 +27,7 @@ void CChatChanMember::SetChannel(CChatChannel * pChannel) m_pChannel = pChannel; } -bool CChatChanMember::IsChatActive() const +bool CChatChanMember::IsChatActive() const noexcept { return m_fChatActive; } @@ -181,14 +178,14 @@ void CChatChanMember::ToggleWhoIs() SendChatMsg((GetWhoIs() == true) ? CHATMSG_ShowingName : CHATMSG_NotShowingName); } -CClient * CChatChanMember::GetClientActive() +CClient * CChatChanMember::GetClientActive() NOEXCEPT_NODEBUG { ADDTOCALLSTACK("CChatChanMember::GetClientActive"); DEBUG_ASSERT(dynamic_cast(this)); return static_cast ( this ); } -const CClient * CChatChanMember::GetClientActive() const +const CClient * CChatChanMember::GetClientActive() const NOEXCEPT_NODEBUG { ADDTOCALLSTACK("CChatChanMember::GetClientActive(const)"); DEBUG_ASSERT(dynamic_cast(this)); diff --git a/src/game/clients/CChatChanMember.h b/src/game/clients/CChatChanMember.h index 0fa06e911..46fcd0147 100644 --- a/src/game/clients/CChatChanMember.h +++ b/src/game/clients/CChatChanMember.h @@ -16,14 +16,15 @@ class CClient; class CChatChanMember { // This is a member of the CClient. -private: bool m_fChatActive; bool m_fReceiving; bool m_fAllowWhoIs; CChatChannel * m_pChannel; // I can only be a member of one chan at a time. + public: static const char *m_sClassName; CSObjArray m_IgnoredMembers; // Player's list of ignored members + private: friend class CChatChannel; friend class CChat; @@ -36,17 +37,16 @@ class CChatChanMember size_t FindIgnoringIndex( lpctstr pszName) const; public: - CChatChanMember(); - virtual ~CChatChanMember(); + CChatChanMember() noexcept; + virtual ~CChatChanMember() noexcept; -private: - CChatChanMember(const CChatChanMember& copy); - CChatChanMember& operator=(const CChatChanMember& other); + CChatChanMember(const CChatChanMember& copy) = delete; + CChatChanMember& operator=(const CChatChanMember& other) = delete; public: - CClient * GetClientActive(); - const CClient * GetClientActive() const; - bool IsChatActive() const; + CClient * GetClientActive() NOEXCEPT_NODEBUG; + const CClient * GetClientActive() const NOEXCEPT_NODEBUG; + bool IsChatActive() const noexcept; void SetReceiving(bool fOnOff); void addChatWindow(); void ToggleReceiving(); @@ -55,7 +55,7 @@ class CChatChanMember void ForbidWhoIs(); void ToggleWhoIs(); - CChatChannel * GetChannel() const; + CChatChannel * GetChannel() const noexcept; void SetChannel(CChatChannel * pChannel); void SendChatMsg( CHATMSG_TYPE iType, lpctstr pszName1 = nullptr, lpctstr pszName2 = nullptr, CLanguageID lang = 0 ); void RenameChannel(lpctstr pszName); diff --git a/src/game/clients/CGlobalChatChanMember.cpp b/src/game/clients/CGlobalChatChanMember.cpp index f39a84770..e06ec2663 100644 --- a/src/game/clients/CGlobalChatChanMember.cpp +++ b/src/game/clients/CGlobalChatChanMember.cpp @@ -3,24 +3,20 @@ #include "CClient.h" #include "CGlobalChatChanMember.h" -CGlobalChatChanMember::CGlobalChatChanMember() +CGlobalChatChanMember::CGlobalChatChanMember() noexcept : + m_fVisible(false) { - m_pszJID = Str_GetTemp(); - m_fVisible = false; } -CGlobalChatChanMember::~CGlobalChatChanMember() -{ -} void CGlobalChatChanMember::SetJID(lpctstr pszJID) { - m_pszJID = pszJID; + m_strJID = pszJID; } lpctstr CGlobalChatChanMember::GetJID() const { - return m_pszJID; + return m_strJID.GetBuffer(); } void CGlobalChatChanMember::SetVisible(bool fNewStatus) @@ -31,4 +27,4 @@ void CGlobalChatChanMember::SetVisible(bool fNewStatus) bool CGlobalChatChanMember::IsVisible() const { return m_fVisible; -} \ No newline at end of file +} diff --git a/src/game/clients/CGlobalChatChanMember.h b/src/game/clients/CGlobalChatChanMember.h index abe64e4c9..24d03f922 100644 --- a/src/game/clients/CGlobalChatChanMember.h +++ b/src/game/clients/CGlobalChatChanMember.h @@ -6,18 +6,21 @@ #ifndef _INC_CGLOBALCHATCHANMEMBER_H #define _INC_CGLOBALCHATCHANMEMBER_H +#include "../../common/sphere_library/CSString.h" + class CClient; + class CGlobalChatChanMember // This is member of CClient { public: static const char* m_sClassName; - CGlobalChatChanMember(); - virtual ~CGlobalChatChanMember(); + CGlobalChatChanMember() noexcept; + virtual ~CGlobalChatChanMember() noexcept = default; private: - lpctstr m_pszJID; // client Jabber ID + CSString m_strJID; // client Jabber ID bool m_fVisible; // client visibility status (online/offline) public: @@ -26,9 +29,8 @@ class CGlobalChatChanMember // This is member of CClient void SetVisible(bool fNewStatus); bool IsVisible() const; -private: - CGlobalChatChanMember(const CGlobalChatChanMember& copy); - CGlobalChatChanMember& operator=(const CGlobalChatChanMember& other); + CGlobalChatChanMember(const CGlobalChatChanMember& copy) = delete; + CGlobalChatChanMember& operator=(const CGlobalChatChanMember& other) = delete; }; #endif // _INC_CGLOBALCHATCHANMEMBER_H diff --git a/src/game/items/CItem.cpp b/src/game/items/CItem.cpp index 797543052..848a49920 100644 --- a/src/game/items/CItem.cpp +++ b/src/game/items/CItem.cpp @@ -2119,13 +2119,13 @@ void CItem::OnHear( lpctstr pszCmd, CChar * pSrc ) ASSERT(false); } -bool CItem::CanHear() const +bool CItem::CanHear() const noexcept { //ADDTOCALLSTACK("CItem::CanHear"); return IsType(IT_SHIP) || IsType(IT_COMM_CRYSTAL); } -CItemBase * CItem::Item_GetDef() const +CItemBase * CItem::Item_GetDef() const noexcept { return static_cast ( Base_GetDef() ); } diff --git a/src/game/items/CItem.h b/src/game/items/CItem.h index a30c15352..518098b7b 100644 --- a/src/game/items/CItem.h +++ b/src/game/items/CItem.h @@ -624,10 +624,10 @@ class CItem : public CObjBase void SetComponentOfMulti(const CUID& uidMulti); void SetLockDownOfMulti(const CUID& uidMulti); - bool CanHear() const; + bool CanHear() const noexcept; virtual void OnHear( lpctstr pszCmd, CChar * pSrc ); - CItemBase * Item_GetDef() const; + CItemBase * Item_GetDef() const noexcept; ITEMID_TYPE GetID() const; inline virtual word GetBaseID() const override { diff --git a/src/game/uo_files/CUOMobtypes.cpp b/src/game/uo_files/CUOMobtypes.cpp index 0d289b957..cffc0a61a 100644 --- a/src/game/uo_files/CUOMobtypes.cpp +++ b/src/game/uo_files/CUOMobtypes.cpp @@ -25,7 +25,7 @@ void CUOMobTypes::Load() _vMobTypesEntries.resize(CREID_QTY); for (size_t i = 0; i < _vMobTypesEntries.size(); ++i) { - _vMobTypesEntries[i] = CUOMobTypesEntry{MOBTE_QTY, 0}; + _vMobTypesEntries[i] = CUOMobTypesEntry{MOBTE_EQUIPMENT, 0}; } tchar* ptcTemp = Str_GetTemp(); @@ -41,11 +41,15 @@ void CUOMobTypes::Load() int iLineLength = (int)strnlen(ptcTemp, Str_TempLength()); iLineLength = Str_TrimEndWhitespace(ptcTemp, iLineLength); - if (iLineLength == 0 || ptcTemp[0] == '#') //Empty line or commented + //Empty line or commented + if (iLineLength == 0 || ptcTemp[0] == '#') + continue; + GETNONWHITESPACE(ptcTemp); + if (ptcTemp[0] == '#') continue; //Split the string - tchar* pptcSplitArray[3]; + tchar* pptcSplitArray[4]; // Bigger on purpose, put possible trailing garbage in the fourth element to keep clean the third. const int iQty = Str_ParseCmds(ptcTemp, pptcSplitArray, ARRAY_COUNT(pptcSplitArray), " \t#"); if (iQty < 3) { @@ -53,13 +57,6 @@ void CUOMobTypes::Load() continue; } - //if (!IsStrNumeric(pptcSplitArray[0])) - //{ - // g_Log.EventError("Mobtypes.txt: non numeric ID on line %" PRIuSIZE_T " \n", uiLineCount); - // continue; - //} - // const uint uiAnimIndex = (uint)std::stoul(pptcSplitArray[0]); - std::optional iconv = Str_ToU(pptcSplitArray[0], 10); if (!iconv.has_value()) { @@ -119,3 +116,4 @@ const CUOMobTypesEntry* CUOMobTypes::GetEntry(uint id) const ASSERT(id < _vMobTypesEntries.size()); return &(_vMobTypesEntries[id]); } + From dfd57ac7cb69ccb6fb876ad915a6ba5c9660dcdc Mon Sep 17 00:00:00 2001 From: cbnolok Date: Fri, 30 Aug 2024 17:00:18 +0200 Subject: [PATCH 14/86] Fix macos compilation error --- src/common/sphere_library/stypecast.h | 158 +++++++++++++------------- 1 file changed, 79 insertions(+), 79 deletions(-) diff --git a/src/common/sphere_library/stypecast.h b/src/common/sphere_library/stypecast.h index f36b0e040..346bcdb3b 100644 --- a/src/common/sphere_library/stypecast.h +++ b/src/common/sphere_library/stypecast.h @@ -6,6 +6,70 @@ #include +// Use this as a double check, to be sure at compile time that the two variables have the same size and sign. +template +[[nodiscard]] +constexpr Tout num_alias_cast(const Tin a) noexcept +{ + static_assert(std::is_arithmetic_v || std::is_enum_v, "Input variable is not a numeric type."); + static_assert(std::is_arithmetic_v || std::is_enum_v, "Output variable is not a numeric type."); + static_assert(sizeof(Tin) == sizeof(Tout), "Input and output types do not have the same size."); + static_assert(!(std::is_signed_v && std::is_unsigned_v), "Casting signed to unsigned."); + static_assert(!(std::is_signed_v && std::is_unsigned_v ), "Casting unsigned to signed."); + return static_cast(a); +} + + +/* Unsigned (and size_t) to signed, clamping. */ + +[[nodiscard]] constexpr +int8 i8_from_u8_clamping(const uint8 a) noexcept +{ + return (a > (uint8_t)std::numeric_limits::max()) ? std::numeric_limits::max() : (int8_t)a; +} + +[[nodiscard]] constexpr +int16 i16_from_u16_clamping(const uint16 a) noexcept +{ + return (a > (uint16_t)std::numeric_limits::max()) ? std::numeric_limits::max() : (int16_t)a; +} + +[[nodiscard]] constexpr +int32 i32_from_u32_clamping(const uint32 a) noexcept +{ + return (a > (uint32_t)std::numeric_limits::max()) ? std::numeric_limits::max() : (int32_t)a; +} + +[[nodiscard]] constexpr +int64 i64_from_u64_clamping(const uint64 a) noexcept +{ + return (a > (uint64_t)std::numeric_limits::max()) ? std::numeric_limits::max() : (int64_t)a; +} + +[[nodiscard]] constexpr +int32 i32_from_usize_clamping(const size_t a) noexcept +{ + return (a > (size_t)std::numeric_limits::max()) ? std::numeric_limits::max() : (int32_t)a; +} + +[[nodiscard]] constexpr +int64 i64_from_usize_clamping(const size_t a) noexcept +{ + return (a > (size_t)std::numeric_limits::max()) ? std::numeric_limits::max() : (int64_t)a; +} + +[[nodiscard]] constexpr +uint32 u32_from_usize_clamping(const size_t a) noexcept +{ + if constexpr (sizeof(size_t) == 8) + return (a > (size_t)std::numeric_limits::max()) ? std::numeric_limits::max() : (uint32_t)a; + else + return a; +} + + +/* Promotion and narrowing of numbers to a same sign greater/smaller data type */ + // Explicitly promote to a larger type or narrow to a smaller type, instead of inattentive raw casts. // Function prefixes: // - n: works regardless of the sign, it deduces and uses the right types automatically. @@ -246,7 +310,7 @@ uint32 usize_narrow32_checked(const size_t a) } -/* Unsigned (and size_t) to signed, checked. */ +/* Unsigned (and size_t) to signed, checked for overflows. */ // Convert an 8 bits unsigned value to signed and ASSERT (because you're reasonably sure but not absolutely certain) that it will fit into its signed datatype counterpart (unsigned variables can store greater values than signed ones). [[nodiscard]] inline @@ -255,7 +319,7 @@ int8 i8_from_u8_checked(const uint8 a) // not clamping/capping ASSERT(a <= (uint8_t)std::numeric_limits::max()); return static_cast(a); } -template int8 i8_from_u8_checked(T) = delete; +template int8 i8_from_u8_checked(T) = delete; // disable implicit type conversion for the input argument // Convert a 16 bits unsigned value to signed and ASSERT (because you're reasonably sure but not absolutely certain) that it will fit into its signed datatype counterpart (unsigned variables can store greater values than signed ones). [[nodiscard]] inline @@ -264,7 +328,7 @@ int16 i16_from_u16_checked(const uint16 a) // not clamping/capping ASSERT(a <= (uint16_t)std::numeric_limits::max()); return static_cast(a); } -template int16 i16_from_u16_checked(T) = delete; +template int16 i16_from_u16_checked(T) = delete; // disable implicit type conversion for the input argument [[nodiscard]] inline int16 i16_from_u32_checked(const uint32 a) // not clamping/capping @@ -272,7 +336,7 @@ int16 i16_from_u32_checked(const uint32 a) // not clamping/capping ASSERT(a <= (uint32_t)std::numeric_limits::max()); return static_cast(a); } -template int16 i16_from_u32_checked(T) = delete; +template int16 i16_from_u32_checked(T) = delete; // disable implicit type conversion for the input argument [[nodiscard]] inline int16 i16_from_u64_checked(const uint64 a) // not clamping/capping @@ -280,7 +344,7 @@ int16 i16_from_u64_checked(const uint64 a) // not clamping/capping ASSERT(a <= (uint64_t)std::numeric_limits::max()); return static_cast(a); } -template int16 i16_from_u64_checked(T) = delete; +template int16 i16_from_u64_checked(T) = delete; // disable implicit type conversion for the input argument // Convert a 32 bits unsigned value to signed and ASSERT (because you're reasonably sure but not absolutely certain) that it will fit into its signed datatype counterpart (unsigned variables can store greater values than signed ones). [[nodiscard]] inline @@ -289,7 +353,7 @@ int32 i32_from_u32_checked(const uint32 a) // not clamping/capping ASSERT(a <= (uint32_t)std::numeric_limits::max()); return static_cast(a); } -template int32 i32_from_u32_checked(T) = delete; +template int32 i32_from_u32_checked(T) = delete; // disable implicit type conversion for the input argument [[nodiscard]] inline int32 i32_from_u64_checked(const uint64 a) // not clamping/capping @@ -297,7 +361,7 @@ int32 i32_from_u64_checked(const uint64 a) // not clamping/capping ASSERT(a <= (uint64_t)std::numeric_limits::max()); return static_cast(a); } -template int32 i32_from_u64_checked(T) = delete; +template int32 i32_from_u64_checked(T) = delete; // disable implicit type conversion for the input argument // Convert a 64 bits unsigned value to signed and ASSERT (because you're reasonably sure but not absolutely certain) that it will fit into its signed datatype counterpart (unsigned variables can store greater values than signed ones). [[nodiscard]] inline @@ -306,8 +370,7 @@ int64 i64_from_u64_checked(const uint64 a) // not clamping/capping ASSERT(a <= (uint64_t)std::numeric_limits::max()); return static_cast(a); } -template int64 i64_from_u64_checked(T) = delete; - +template int64 i64_from_u64_checked(T) = delete; // disable implicit type conversion for the input argument // size_t conversions @@ -322,7 +385,7 @@ int8 i8_from_usize_checked(const size_t a) // not clamping/capping # error "size_t is neither 8 nor 4 bytes?" #endif } -template int8 i8_from_usize_checked(T) = delete; +template int8 i8_from_usize_checked(T) = delete; // disable implicit type conversion for the input argument [[nodiscard]] inline @@ -336,96 +399,33 @@ int16 i16_from_usize_checked(const size_t a) // not clamping/capping # error "size_t is neither 8 nor 4 bytes?" #endif } -template int16 i16_from_usize_checked(T) = delete; +template int16 i16_from_usize_checked(T) = delete; // disable implicit type conversion for the input argument [[nodiscard]] inline int32 i32_from_usize_checked(const size_t a) // not clamping/capping { #if SIZE_MAX == UINT64_MAX - return n64_narrow32_checked(a); + return i32_from_u32_clamping(n64_narrow32_checked(a)); #elif SIZE_MAX == UINT32_MAX - return i32_from_u32_checked(a); + return i32_from_u32_checked(num_alias_cast(a)); #else # error "size_t is neither 8 nor 4 bytes?" #endif } -template int32 i32_from_usize_checked(T) = delete; +template int32 i32_from_usize_checked(T) = delete; // disable implicit type conversion for the input argument [[nodiscard]] inline int64 i64_from_usize_checked(const size_t a) // not clamping/capping { #if SIZE_MAX == UINT64_MAX - return i64_from_u64_checked(a); + return i64_from_u64_checked(num_alias_cast(a)); #elif SIZE_MAX == UINT32_MAX return static_cast(a); // For sure it will fit #else # error "size_t is neither 8 nor 4 bytes?" #endif } -template int64 i64_from_usize_checked(T) = delete; - - -/* Unsigned (and size_t) to signed, clamping. */ - - -[[nodiscard]] constexpr -int8 i8_from_u8_clamping(const uint8 a) noexcept -{ - return (a > (uint8_t)std::numeric_limits::max()) ? std::numeric_limits::max() : (int8_t)a; -} - -[[nodiscard]] constexpr -int16 i16_from_u16_clamping(const uint16 a) noexcept -{ - return (a > (uint16_t)std::numeric_limits::max()) ? std::numeric_limits::max() : (int16_t)a; -} - -[[nodiscard]] constexpr -int32 i32_from_u32_clamping(const uint32 a) noexcept -{ - return (a > (uint32_t)std::numeric_limits::max()) ? std::numeric_limits::max() : (int32_t)a; -} - -[[nodiscard]] constexpr -int64 i64_from_u64_clamping(const uint64 a) noexcept -{ - return (a > (uint64_t)std::numeric_limits::max()) ? std::numeric_limits::max() : (int64_t)a; -} - -[[nodiscard]] constexpr -int32 i32_from_usize_clamping(const size_t a) noexcept -{ - return (a > (size_t)std::numeric_limits::max()) ? std::numeric_limits::max() : (int32_t)a; -} - -[[nodiscard]] constexpr -int64 i64_from_usize_clamping(const size_t a) noexcept -{ - return (a > (size_t)std::numeric_limits::max()) ? std::numeric_limits::max() : (int64_t)a; -} - -[[nodiscard]] constexpr -uint32 u32_from_usize_clamping(const size_t a) noexcept -{ - if constexpr (sizeof(size_t) == 8) - return (a > (size_t)std::numeric_limits::max()) ? std::numeric_limits::max() : (uint32_t)a; - else - return a; -} - - -// Use this as a double check, to be sure at compile time that the two variables have the same size and sign. -template -[[nodiscard]] -constexpr Tout num_alias_cast(const Tin a) noexcept -{ - static_assert(std::is_arithmetic_v || std::is_enum_v, "Input variable is not a numeric type."); - static_assert(std::is_arithmetic_v || std::is_enum_v, "Output variable is not a numeric type."); - static_assert(sizeof(Tin) == sizeof(Tout), "Input and output types do not have the same size."); - static_assert(!(std::is_signed_v && std::is_unsigned_v), "Casting signed to unsigned."); - static_assert(!(std::is_signed_v && std::is_unsigned_v ), "Casting unsigned to signed."); - return static_cast(a); -} +template int64 i64_from_usize_checked(T) = delete; // disable implicit type conversion for the input argument #endif // _INC_STYPECAST_H From 5ca9f8e5329b559a8a42140ae585199b26d58dad Mon Sep 17 00:00:00 2001 From: cbnolok Date: Sat, 31 Aug 2024 13:37:47 +0200 Subject: [PATCH 15/86] Added mutex lock retry macros Added: RETRY_LOCK_FOR_TASK*, used to retry mutex lock in the (rare) case it fails. This has to be used only for critical mutexes. Added: STDERR_LOG to log critical messages to stderr if standard CLog methods are failing or can't be used. Added: NOTHROW macro to specify functions that might throw an exception, as opposite to nothrow. Adapted some CLog and threading methods to actually be noexcept. Reordered common.h. --- src/common/CLog.cpp | 10 +- src/common/assertion.h | 8 +- src/common/basic_threading.h | 37 ++++- src/common/common.h | 179 +++++++++++++---------- src/common/sphere_library/CSObjCont.cpp | 4 +- src/common/sphere_library/CSObjCont.h | 2 +- src/common/sphere_library/CSObjContRec.h | 2 +- src/game/CContainer.cpp | 2 +- src/game/CContainer.h | 7 +- src/sphere/threads.cpp | 160 ++++++++++++-------- src/sphere/threads.h | 10 +- 11 files changed, 258 insertions(+), 163 deletions(-) diff --git a/src/common/CLog.cpp b/src/common/CLog.cpp index 582d6ec0b..922fd1323 100644 --- a/src/common/CLog.cpp +++ b/src/common/CLog.cpp @@ -215,17 +215,18 @@ bool CLog::OpenLog(lpctstr pszBaseDirName) // name set previously. int CLog::EventStr( dword dwMask, lpctstr pszMsg, ConsoleTextColor iLogColor) noexcept { - ADDTOCALLSTACK("CLog::EventStr"); // NOTE: This could be called in odd interrupt context so don't use dynamic stuff + if ( !IsLogged(dwMask) ) // I don't care about these. return 0; if ( !pszMsg || !*pszMsg ) return 0; - int iRet = 0; - + int iRet = 0; try { + ADDTOCALLSTACK("CLog::EventStr"); + ConsoleTextColor iLogTextColor = iLogColor; ConsoleTextColor iLogTypeColor = CTCOL_DEFAULT; @@ -241,7 +242,7 @@ int CLog::EventStr( dword dwMask, lpctstr pszMsg, ConsoleTextColor iLogColor) no pszLabel = "FATAL:"; iLogTypeColor = CTCOL_RED; break; - case LOGL_CRIT: // critical. + case LOGL_CRIT: // critical. pszLabel = "CRITICAL:"; iLogTypeColor = CTCOL_RED; break; @@ -342,6 +343,7 @@ int CLog::EventStr( dword dwMask, lpctstr pszMsg, ConsoleTextColor iLogColor) no // Not much we can do about this iRet = 0; GetCurrentProfileData().Count(PROFILE_STAT_FAULTS, 1); + STDERR_LOG("CLog::EventStr failed to print: '%s'.\n", pszMsg); } return iRet; diff --git a/src/common/assertion.h b/src/common/assertion.h index 984ca1e48..7e5f90b3f 100644 --- a/src/common/assertion.h +++ b/src/common/assertion.h @@ -1,15 +1,15 @@ #ifndef _INC_ASSERTION_H #define _INC_ASSERTION_H -#ifndef STATIC_ANALYSIS +#ifndef STATIC_ANALYSIS_ #if defined(__COVERITY__) - #define STATIC_ANALYSIS + #define STATIC_ANALYSIS_ #endif #endif extern void Assert_Fail(const char * pExp, const char *pFile, long long llLine); -#define PERSISTANT_ASSERT(exp) if ( !(exp) ) Assert_Fail(#exp, __FILE__, __LINE__) +#define PERSISTANT_ASSERT(exp) [[unlikely]] if ( !(exp) ) Assert_Fail(#exp, __FILE__, __LINE__) #if defined(STATIC_ANALYSIS) #include @@ -27,6 +27,6 @@ extern void Assert_Fail(const char * pExp, const char *pFile, long long llLine); #endif -#undef STATIC_ANALYSIS +#undef STATIC_ANALYSIS_ #endif // ! _INC_ASSERTION_H diff --git a/src/common/basic_threading.h b/src/common/basic_threading.h index 79290e82a..ce021319d 100644 --- a/src/common/basic_threading.h +++ b/src/common/basic_threading.h @@ -7,8 +7,9 @@ #define MT_ENGINES 0 // are we using/working on true multithreaded network/scripting engines? -#include -#include + +#include // As per standard, std::mutex has a noexcept constructor. +#include // As per standard, std::shared_mutex has NOT a noexcept contructor, nevertheless its implementations should actually not throw. // Name of the Class Mutex @@ -75,4 +76,36 @@ #endif +// Try acquiring a lock (try multiple times), to be used only for CRITICAL mutexes, that you pray will never fail (for an OS error) to be locked (not because they are already locked). If successiful, call func_, usually a lambda. If fails, program explodes (std::abort). + +#define RETRY_LOCK_ATTEMPTS_MAX 20 +#define RETRY_LOCK_FOR_TASK_IMPL_(lock_type_, mutex_name_, lock_name_, max_retries_, retval_, func_) \ + { \ + bool success_acquire_ = false; \ + for (uint spin_attempt_ = 0; spin_attempt_ < max_retries_; ++spin_attempt_) { \ + try { \ + lock_type_ > lock_name_ ((mutex_name_)); \ + retval_ = func_(); \ + success_acquire_ = true; \ + break; \ + } catch (const std::system_error& e_) { \ + STDERR_LOG("[File '%s', line %d, function '%s']. Failed to acquire lock on attempt %u. Exc msg: '%s'.\n", \ + __FILE__, __LINE__, __func__, spin_attempt_ + 1, e_.what()); \ + } \ + } \ + if (!success_acquire_) { \ + /*throw std::runtime_error("Failed to acquire lock after " #max_retries_ " attempts."); */ \ + /* That should never happen. */ \ + EXC_NOTIFY_DEBUGGER; \ + std::abort(); \ + } \ + } + +#define RETRY_SHARED_LOCK_FOR_TASK(mutex_name_, lock_name_, retval_, func_) \ + RETRY_LOCK_FOR_TASK_IMPL_(std::shared_lock, (mutex_name_), (lock_name_), RETRY_LOCK_ATTEMPTS_MAX, (retval_), (func_)) + +#define RETRY_UNIQUE_LOCK_FOR_TASK(mutex_name_, lock_name_, retval_, func_) \ + RETRY_LOCK_FOR_TASK_IMPL_(std::unique_lock, (mutex_name_), (lock_name_), RETRY_LOCK_ATTEMPTS_MAX, (retval_), (func_)) + + #endif // _INC_BASIC_THREADING_H diff --git a/src/common/common.h b/src/common/common.h index a9f037a06..1622fd78f 100644 --- a/src/common/common.h +++ b/src/common/common.h @@ -34,6 +34,8 @@ #include "sphere_library/stypecast.h" +/* Coding helpers */ + // Strings #define _STRINGIFY_AUX(x) #x #define STRINGIFY(x) _STRINGIFY_AUX(x) @@ -45,84 +47,15 @@ #define HAS_FLAGS_STRICT(var, flag) (((var) & (flag)) == flag) // Every one of the passed flags has to be set #define HAS_FLAGS_ANY(var, flag) (static_cast((var) & (flag))) // True if even only one of the passed flags are set -// Cpp attributes -#define FALLTHROUGH [[fallthrough]] -#define NODISCARD [[nodiscard]] -#ifdef _DEBUG - #define NOEXCEPT_NODEBUG -#else - #define NOEXCEPT_NODEBUG noexcept -#endif +/* Start of arithmetic code */ -/* - There is a problem with the UnreferencedParameter macro from mingw and sphereserver. - operator= is on many clases private and the UnreferencedParameter macro from mingw is (P)=(P), - so we have a compilation error here. -*/ -#undef UNREFERENCED_PARAMETER +//#define IsNegative(c) (((c) < 0) ? 1 : 0) template -inline constexpr void UnreferencedParameter(T const&) noexcept { - ; +constexpr bool IsNegative(T val) noexcept { + return (val < 0); } - -/* Sanitizers utility */ - -#if defined(_MSC_VER) - - #if defined(__SANITIZE_ADDRESS__) || defined(ADDRESS_SANITIZER) - #define NO_SANITIZE_ADDRESS __declspec(no_sanitize_address) - #else - #define NO_SANITIZE_ADDRESS - #endif - - // Not yet implemented on MSVC, as of 2022 ver. - #define NO_SANITIZE_UNDEFINED - -#elif defined(__clang__) - - #if defined(__SANITIZE_ADDRESS__) || defined(ADDRESS_SANITIZER) - #define NO_SANITIZE_ADDRESS __attribute__((no_sanitize_address)) - #else - #define NO_SANITIZE_ADDRESS - #endif - - //#if __has_feature(undefined_behavior_sanitizer) || defined(UNDEFINED_BEHAVIOR_SANITIZER) - // Clang doesn't have an attribute nor a pragma for this (yet?) - // #define NO_SANITIZE_UNDEFINED __attribute__((no_sanitize_undefined)) - //#else - #define NO_SANITIZE_UNDEFINED - //#endif - -#elif defined(__GNUC__) - - #if defined(__SANITIZE_ADDRESS__) || defined(ADDRESS_SANITIZER) - #define NO_SANITIZE_ADDRESS __attribute__((no_sanitize("address"))) - #else - #define NO_SANITIZE_ADDRESS - #endif - - // GCC still hasn't __SANITIZE_UNDEFINED__ ? - //#if defined(__SANITIZE_UNDEFINED__) || defined(UNDEFINED_BEHAVIOR_SANITIZER) - // #define NO_SANITIZE_UNDEFINED __attribute__((no_sanitize("undefined"))) - //#else - #define NO_SANITIZE_UNDEFINED - //#endif - -#else - - #define NO_SANITIZE_ADDRESS - #define NO_SANITIZE_UNDEFINED - -#endif - - -/* Start of arithmetic code */ - -#define IsNegative(c) (((c) < 0) ? 1 : 0) - - //-- Bitwise magic: combine numbers. // MAKEWORD: defined in minwindef.h (loaded by windows.h), so it's missing only on Linux. @@ -132,43 +65,43 @@ inline constexpr void UnreferencedParameter(T const&) noexcept { //#define IMulDiv(a,b,c) (((((int)(a)*(int)(b)) + (int)(c / 2)) / (int)(c)) - (IsNegative((int)(a)*(int)(b)))) -inline constexpr int IMulDiv(const int a, const int b, const int c) noexcept +constexpr int IMulDiv(const int a, const int b, const int c) noexcept { const int ab = a*b; return ((ab + (c/2)) / c) - IsNegative(ab); } -inline constexpr uint UIMulDiv(const uint a, const uint b, const uint c) noexcept +constexpr uint UIMulDiv(const uint a, const uint b, const uint c) noexcept { const int ab = a * b; return ((ab + (c / 2)) / c) - IsNegative(ab); } //#define IMulDivLL(a,b,c) (((((llong)(a)*(llong)(b)) + (llong)(c / 2)) / (llong)(c)) - (IsNegative((llong)(a)*(llong)(b)))) -inline constexpr llong IMulDivLL(const llong a, const llong b, const llong c) noexcept +constexpr llong IMulDivLL(const llong a, const llong b, const llong c) noexcept { const llong ab = a*b; return ((ab + (c/2)) / c) - IsNegative(ab); } -inline constexpr realtype IMulDivRT(const realtype a, const realtype b, const realtype c) noexcept +constexpr realtype IMulDivRT(const realtype a, const realtype b, const realtype c) noexcept { const realtype ab = a*b; return ((ab + (c/2)) / c) - IsNegative(ab); } //#define IMulDivDown(a,b,c) (((a)*(b))/(c)) -inline constexpr int IMulDivDown(const int a, const int b, const int c) noexcept +constexpr int IMulDivDown(const int a, const int b, const int c) noexcept { return (a*b)/c; } -inline constexpr llong IMulDivDownLL(const llong a, const llong b, const llong c) noexcept +constexpr llong IMulDivDownLL(const llong a, const llong b, const llong c) noexcept { return (a*b)/c; } //#define sign(n) (((n) < 0) ? -1 : (((n) > 0) ? 1 : 0)) template -inline constexpr T sign(const T n) noexcept +constexpr T sign(const T n) noexcept { static_assert(std::is_arithmetic::value, "Invalid data type."); return ( (n < 0) ? -1 : ((n > 0) ? 1 : 0) ); @@ -176,12 +109,45 @@ inline constexpr T sign(const T n) noexcept #define minimum(x,y) ((x)<(y)?(x):(y)) // NOT to be used with functions! Store the result of the function in a variable first, otherwise the function will be executed twice! #define maximum(x,y) ((x)>(y)?(x):(y)) // NOT to be used with functions! Store the result of the function in a variable first, otherwise the function will be executed twice! -#define medium(x,y,z) ((x)>(y)?(x):((z)<(y)?(z):(y))) // NOT to be used with functions! Store the result of the function in a variable first, otherwise the function will be executed twice! +#define medium(x,y,z) ((x)>(y)?(x):((z)<(y)?(z):(y))) // NOT to be used with functions! Store the result of the function in a variable first, otherwise the function will be executed twice! /* End of arithmetic code */ +/* Compiler/c++ language helpers */ + +//#include // already included by stypecast.h +#define ASSERT_NOT_NOEXCEPT_CONSTRUCTOR(_ClassType) \ + static_assert(!std::is_nothrow_constructible_v<_ClassType>, #_ClassType " constructor should not be noexcept!") + +// Function specifier, like noexcept. Use this to make us know that the function code was checked and we know it can throw an exception. +#define CANTHROW noexcept(false) + +// Cpp attributes +#define FALLTHROUGH [[fallthrough]] +#define NODISCARD [[nodiscard]] + +#ifdef _DEBUG + #define NOEXCEPT_NODEBUG +#else + #define NOEXCEPT_NODEBUG noexcept +#endif + +/* + There is a problem with the UnreferencedParameter macro from mingw and sphereserver. + operator= is on many clases private and the UnreferencedParameter macro from mingw is (P)=(P), + so we have a compilation error here. +*/ +#undef UNREFERENCED_PARAMETER +template +constexpr void UnreferencedParameter(T const&) noexcept { + ; +} + +// For unrecoverable/unloggable errors. Should be used almost *never*. +#define STDERR_LOG(...) fprintf(stderr, __VA_ARGS__); fflush(stderr) + // use to indicate that a function uses printf-style arguments, allowing GCC // to validate the format string and arguments: // a = 1-based index of format string @@ -199,4 +165,55 @@ inline constexpr T sign(const T n) noexcept #endif +/* Sanitizers utilities */ + +#if defined(_MSC_VER) + + #if defined(__SANITIZE_ADDRESS__) || defined(ADDRESS_SANITIZER) + #define NO_SANITIZE_ADDRESS __declspec(no_sanitize_address) + #else + #define NO_SANITIZE_ADDRESS + #endif + + // Not yet implemented on MSVC, as of 2022 ver. + #define NO_SANITIZE_UNDEFINED + +#elif defined(__clang__) + + #if defined(__SANITIZE_ADDRESS__) || defined(ADDRESS_SANITIZER) + #define NO_SANITIZE_ADDRESS __attribute__((no_sanitize_address)) + #else + #define NO_SANITIZE_ADDRESS + #endif + + //#if __has_feature(undefined_behavior_sanitizer) || defined(UNDEFINED_BEHAVIOR_SANITIZER) + // Clang doesn't have an attribute nor a pragma for this (yet?) + // #define NO_SANITIZE_UNDEFINED __attribute__((no_sanitize_undefined)) + //#else + #define NO_SANITIZE_UNDEFINED + //#endif + +#elif defined(__GNUC__) + + #if defined(__SANITIZE_ADDRESS__) || defined(ADDRESS_SANITIZER) + #define NO_SANITIZE_ADDRESS __attribute__((no_sanitize("address"))) + #else + #define NO_SANITIZE_ADDRESS + #endif + + // GCC still hasn't __SANITIZE_UNDEFINED__ ? + //#if defined(__SANITIZE_UNDEFINED__) || defined(UNDEFINED_BEHAVIOR_SANITIZER) + // #define NO_SANITIZE_UNDEFINED __attribute__((no_sanitize("undefined"))) + //#else + #define NO_SANITIZE_UNDEFINED + //#endif + +#else + + #define NO_SANITIZE_ADDRESS + #define NO_SANITIZE_UNDEFINED + +#endif + + #endif // _INC_COMMON_H diff --git a/src/common/sphere_library/CSObjCont.cpp b/src/common/sphere_library/CSObjCont.cpp index fa480a467..58e5614cd 100644 --- a/src/common/sphere_library/CSObjCont.cpp +++ b/src/common/sphere_library/CSObjCont.cpp @@ -4,7 +4,7 @@ #include -CSObjContRec::CSObjContRec() : +CSObjContRec::CSObjContRec() noexcept : m_pParent(nullptr) { } @@ -38,7 +38,7 @@ CSObjCont::~CSObjCont() // CSObjCont:: Modifiers. -void CSObjCont::ClearContainer(bool fClosingWorld) +void CSObjCont::ClearContainer(bool fClosingWorld) noexcept { if (_Contents.empty()) return; diff --git a/src/common/sphere_library/CSObjCont.h b/src/common/sphere_library/CSObjCont.h index 29e1fb91b..d007a41b6 100644 --- a/src/common/sphere_library/CSObjCont.h +++ b/src/common/sphere_library/CSObjCont.h @@ -171,7 +171,7 @@ class CSObjCont * @brief Remove all records of the CSObjCont. * @param fClosingWorld Am i closing world UIDs or just destroyng everything before shutdown? */ - void ClearContainer(bool fClosingWorld); + void ClearContainer(bool fClosingWorld) noexcept; /** * @brief Insert a record at head. diff --git a/src/common/sphere_library/CSObjContRec.h b/src/common/sphere_library/CSObjContRec.h index 2ada9d42e..48d01fd72 100644 --- a/src/common/sphere_library/CSObjContRec.h +++ b/src/common/sphere_library/CSObjContRec.h @@ -27,7 +27,7 @@ class CSObjContRec /** * @brief set references for parent, next and previous to nullptr. */ - CSObjContRec(); + CSObjContRec() noexcept; virtual ~CSObjContRec(); /** diff --git a/src/game/CContainer.cpp b/src/game/CContainer.cpp index a9b1b46c6..740efb8a7 100644 --- a/src/game/CContainer.cpp +++ b/src/game/CContainer.cpp @@ -11,7 +11,7 @@ #include "CContainer.h" -CContainer::CContainer() : +CContainer::CContainer() noexcept : m_totalweight(0) { } diff --git a/src/game/CContainer.h b/src/game/CContainer.h index 04fa7f68e..530d30ae1 100644 --- a/src/game/CContainer.h +++ b/src/game/CContainer.h @@ -19,12 +19,11 @@ class CContainer : public CSObjCont // This class contains a list of items but m { public: static const char *m_sClassName; - CContainer(); + CContainer() noexcept; virtual ~CContainer() = default; -private: - CContainer(const CContainer& copy); - CContainer& operator=(const CContainer& other); + CContainer(const CContainer& copy) = delete; + CContainer& operator=(const CContainer& other) = delete; public: int m_totalweight; // weight of all the items it has. (1/WEIGHT_UNITS pound) diff --git a/src/sphere/threads.cpp b/src/sphere/threads.cpp index 3f93148c4..96fef2987 100644 --- a/src/sphere/threads.cpp +++ b/src/sphere/threads.cpp @@ -3,8 +3,8 @@ #include #include +#include "../common/basic_threading.h" #include "../common/CException.h" -#include "../common/common.h" #include "../common/CLog.h" #include "../game/CServer.h" #include "ProfileTask.h" @@ -126,84 +126,128 @@ ThreadHolder& ThreadHolder::get() noexcept bool ThreadHolder::closing() noexcept { std::shared_lock lock(m_mutex); - return m_closing; + volatile auto ret = m_closing; + return ret; } -IThread* ThreadHolder::current() +IThread* ThreadHolder::current() noexcept { - // Do not use ASSERTs here, would cause recursion. + // Do not use ASSERTs here, would cause recursion + // RETRY_SHARED_LOCK_FOR_TASK is used to try to not make mutex lock fail and, if needed, + // handle failure while allowing this function to be noexcept. - std::shared_lock lock(m_mutex); + IThread* retval = nullptr; + RETRY_SHARED_LOCK_FOR_TASK(m_mutex, lock, retval, + ([this, &lock]() -> IThread* + { + if (m_closing) + return nullptr; - if (m_closing) - return nullptr; + const threadid_t tid = IThread::getCurrentThreadSystemId(); - const threadid_t tid = IThread::getCurrentThreadSystemId(); + if (m_spherethreadpairs_systemid_ptr.empty()) { + auto thread = static_cast(DummySphereThread::getInstance()); + if (!thread) { + // Should never happen. + EXC_NOTIFY_DEBUGGER; + std::abort(); + } - if (m_spherethreadpairs_systemid_ptr.empty()) { - auto thread = static_cast(DummySphereThread::getInstance()); - if (!thread) { - // Should never happen. - EXC_NOTIFY_DEBUGGER; - std::abort(); - } + thread->m_threadSystemId = tid; + lock.unlock(); + push(thread); + return thread; + } - thread->m_threadSystemId = tid; - lock.unlock(); - push(thread); - return thread; - } + spherethreadpair_t *found = nullptr; + for (auto &elem : m_spherethreadpairs_systemid_ptr) { + if (elem.first == tid) { + found = &elem; + break; + } + } + if (!found) { + //throw CSError(LOGL_FATAL, 0, "Thread handle not found in vector?"); + STDERR_LOG("Thread handle not found in vector?"); - spherethreadpair_t *found = nullptr; - for (auto &elem : m_spherethreadpairs_systemid_ptr) { - if (elem.first == tid) { - found = &elem; - break; - } - } - if (!found) { - throw CSError(LOGL_FATAL, 0, "Thread handle not found in vector?"); - } + // Should never happen. + EXC_NOTIFY_DEBUGGER; + std::abort(); + } + + auto thread = static_cast(found->second); - auto thread = static_cast(found->second); + ASSERT(thread->m_threadHolderId != -1); + SphereThreadData *tdata = &(m_threads[thread->m_threadHolderId]); + if (tdata->m_closed) + return nullptr; - ASSERT(thread->m_threadHolderId != -1); - SphereThreadData *tdata = &(m_threads[thread->m_threadHolderId]); - if (tdata->m_closed) - return nullptr; + // Uncomment it only for testing purposes, since this method is called very often and we don't need the additional overhead + //DEBUG_ASSERT( thread->isSameThread(thread->getId()) ); - // Uncomment it only for testing purposes, since this method is called very often and we don't need the additional overhead - //DEBUG_ASSERT( thread->isSameThread(thread->getId()) ); + return thread; + })); - return thread; + return retval; } -void ThreadHolder::push(IThread *thread) +void ThreadHolder::push(IThread *thread) noexcept { - auto sphere_thread = dynamic_cast(thread); - if (!sphere_thread) - throw CSError(LOGL_FATAL, 0, "IThread not being an AbstractSphereThread?"); + bool fExceptionThrown = false; + try + { + auto sphere_thread = dynamic_cast(thread); + if (!sphere_thread) + { + //throw CSError(LOGL_FATAL, 0, "IThread not being an AbstractSphereThread?"); + STDERR_LOG("IThread not being an AbstractSphereThread?"); + fExceptionThrown = true; + } - std::unique_lock lock(m_mutex); + std::unique_lock lock(m_mutex); - ASSERT(thread->m_threadSystemId != 0); - ASSERT(thread->m_threadHolderId == -1); + ASSERT(thread->m_threadSystemId != 0); + ASSERT(thread->m_threadHolderId == -1); - m_threads.emplace_back( SphereThreadData{ thread, false }); - thread->m_threadHolderId = m_threadCount + 1; + m_threads.emplace_back( SphereThreadData{ thread, false }); + thread->m_threadHolderId = m_threadCount + 1; #ifdef _DEBUG - auto it_thread = std::find_if( - m_spherethreadpairs_systemid_ptr.begin(), - m_spherethreadpairs_systemid_ptr.end(), - [sphere_thread](spherethreadpair_t const &elem) noexcept -> bool { return elem.second == sphere_thread; }); + auto it_thread = std::find_if( + m_spherethreadpairs_systemid_ptr.begin(), + m_spherethreadpairs_systemid_ptr.end(), + [sphere_thread](spherethreadpair_t const &elem) noexcept -> bool { return elem.second == sphere_thread; }); - // I don't want duplicates. - DEBUG_ASSERT(it_thread == m_spherethreadpairs_systemid_ptr.end()); + // I don't want duplicates. + DEBUG_ASSERT(it_thread == m_spherethreadpairs_systemid_ptr.end()); #endif - m_spherethreadpairs_systemid_ptr.emplace_back(sphere_thread->m_threadSystemId, sphere_thread); + m_spherethreadpairs_systemid_ptr.emplace_back(sphere_thread->m_threadSystemId, sphere_thread); - ++m_threadCount; + ++m_threadCount; + + } + catch (CAssert const& e) + { + fExceptionThrown = true; + STDERR_LOG("ASSERT failed.\n"); + } + catch (std::system_error const& e) + { + fExceptionThrown = true; + STDERR_LOG("Mutex cannot be acquired. Err: '%s'.\n", e.what()); + } + catch (...) + { + fExceptionThrown = true; + STDERR_LOG("Unknown exception thrown.\n"); + } + + if (fExceptionThrown) + { + // Should never happen. + EXC_NOTIFY_DEBUGGER; + std::abort(); + } } /* @@ -222,7 +266,7 @@ SphereThreadData* ThreadHolder::findThreadData(IThread* thread) noexcept } */ -void ThreadHolder::remove(IThread *thread) +void ThreadHolder::remove(IThread *thread) CANTHROW { if (!thread) throw CSError(LOGL_FATAL, 0, "thread == nullptr"); @@ -250,7 +294,7 @@ void ThreadHolder::remove(IThread *thread) m_spherethreadpairs_systemid_ptr.erase(it_thread); } -void ThreadHolder::markThreadsClosing() +void ThreadHolder::markThreadsClosing() CANTHROW { std::unique_lock lock(m_mutex); @@ -264,7 +308,7 @@ void ThreadHolder::markThreadsClosing() //printf("Marking threads as closing.\n"); } -IThread * ThreadHolder::getThreadAt(size_t at) +IThread * ThreadHolder::getThreadAt(size_t at) CANTHROW { std::shared_lock lock(m_mutex); diff --git a/src/sphere/threads.h b/src/sphere/threads.h index 87478d071..9b0871433 100644 --- a/src/sphere/threads.h +++ b/src/sphere/threads.h @@ -358,7 +358,7 @@ class ThreadHolder friend void atexit_handler(void); friend void Sphere_ExitServer(void); - void markThreadsClosing(); + void markThreadsClosing() CANTHROW; //SphereThreadData* findThreadData(IThread* thread) noexcept; @@ -369,13 +369,13 @@ class ThreadHolder bool closing() noexcept; // returns current working thread or DummySphereThread * if no IThread threads are running - IThread *current(); + IThread *current() noexcept; // records a thread to the list. Sould NOT be called, internal usage - void push(IThread *thread); + void push(IThread *thread) noexcept; // removes a thread from the list. Sould NOT be called, internal usage - void remove(IThread *thread); + void remove(IThread *thread) CANTHROW; // returns thread at i pos - IThread * getThreadAt(size_t at); + IThread * getThreadAt(size_t at) CANTHROW; // returns number of running threads. Sould NOT be called, unit tests usage inline size_t getActiveThreads() noexcept { return m_threadCount; } From ba4fcea4469b805aa0241c6770462f24e99be0a2 Mon Sep 17 00:00:00 2001 From: cbnolok Date: Tue, 3 Sep 2024 13:58:29 +0200 Subject: [PATCH 16/86] Moved FACTION/SLAYER code into a CComponentProps. Removed legacy/unused SLAYER* properties. Added log message when a new thread is created or a thread is being renamed. Added more methods for enum conversion in stypecast.h. Made more resilient to rare mutex locking errors the threads-managing code. Made more threads.h methods noexcept. Reordered CChar members to reduce memory usage. Added ensure_comptime() in common.h. Fixed Windows compilation error. --- cmake/toolchains/Windows-MSVC.cmake | 3 +- src/CMakeSources.cmake | 4 +- src/common/CException.cpp | 90 +++++- src/common/CException.h | 7 + src/common/CExpression.h | 2 +- src/common/basic_threading.h | 3 +- src/common/common.h | 53 +++- src/common/sphere_library/stypecast.h | 143 ++++++--- src/game/CBase.cpp | 31 -- src/game/CBase.h | 8 - src/game/CComponent.h | 1 - src/game/CComponentProps.h | 3 +- src/game/CObjBase.cpp | 13 - src/game/CObjBase.h | 7 - src/game/CServer.cpp | 2 +- src/game/CServer.h | 2 +- src/game/CWorldTicker.h | 3 +- src/game/chars/CChar.cpp | 21 +- src/game/chars/CChar.h | 50 ++-- src/game/chars/CCharBase.h | 25 +- src/game/chars/CCharFight.cpp | 80 +++-- src/game/chars/CCharSkill.cpp | 90 +++--- src/game/chars/CCharUse.cpp | 9 +- src/game/clients/CClientTarg.cpp | 8 +- src/game/components/CCFaction.cpp | 278 ------------------ src/game/components/CCPropsChar.cpp | 25 +- src/game/components/CCPropsChar.h | 14 + src/game/components/CCPropsItemEquippable.cpp | 24 ++ src/game/components/CCPropsItemEquippable.h | 13 + .../components/subcomponents/CFactionDef.cpp | 146 +++++++++ .../CFactionDef.h} | 79 +++-- src/game/items/CItem.cpp | 34 +-- src/game/items/CItem.h | 33 ++- src/game/items/CItemBase.h | 57 ++-- src/game/items/CItemMultiCustom.cpp | 10 +- src/network/send.cpp | 2 +- src/sphere/threads.cpp | 159 +++++++--- src/sphere/threads.h | 6 +- src/tables/CBaseBaseDef_props.tbl | 4 - src/tables/CCPropsChar_props.tbl | 4 +- src/tables/CCPropsItemEquippable_props.tbl | 2 + src/tables/CObjBase_props.tbl | 4 - 42 files changed, 840 insertions(+), 712 deletions(-) delete mode 100644 src/game/components/CCFaction.cpp create mode 100644 src/game/components/subcomponents/CFactionDef.cpp rename src/game/components/{CCFaction.h => subcomponents/CFactionDef.h} (77%) diff --git a/cmake/toolchains/Windows-MSVC.cmake b/cmake/toolchains/Windows-MSVC.cmake index 72bbab297..fc607c70a 100644 --- a/cmake/toolchains/Windows-MSVC.cmake +++ b/cmake/toolchains/Windows-MSVC.cmake @@ -97,8 +97,9 @@ function (toolchain_exe_stuff) # CMake's ${MSVC_VERSION} is equivalent to _MSC_VER # (according to https://cmake.org/cmake/help/latest/variable/MSVC_VERSION.html#variable:MSVC_VERSION) if (MSVC_VERSION GREATER_EQUAL 1914) - SET(cxx_compiler_flags_common ${cxx_compiler_flags_common} /Zc:__cplusplus) + SET(local_msvc_compat_options /Zc:__cplusplus) endif() + SET(cxx_compiler_flags_common ${cxx_compiler_flags_common} /Zc:preprocessor ${local_msvc_compat_options}) # Needed, otherwise throws a error... Regression? set(CMAKE_C_FLAGS_DEBUG_INIT "" INTERNAL) diff --git a/src/CMakeSources.cmake b/src/CMakeSources.cmake index 70f06ba74..056a8ac7a 100644 --- a/src/CMakeSources.cmake +++ b/src/CMakeSources.cmake @@ -454,10 +454,10 @@ src/game/clients/CParty.h SOURCE_GROUP (game\\clients FILES ${clients_SRCS}) SET (components_SRCS +src/game/components/subcomponents/CFactionDef.cpp +src/game/components/subcomponents/CFactionDef.h src/game/components/CCChampion.cpp src/game/components/CCChampion.h -src/game/components/CCFaction.cpp -src/game/components/CCFaction.h src/game/components/CCItemDamageable.cpp src/game/components/CCItemDamageable.h src/game/components/CCMultiMovable.cpp diff --git a/src/common/CException.cpp b/src/common/CException.cpp index 33a3971e1..e3ad57cd4 100644 --- a/src/common/CException.cpp +++ b/src/common/CException.cpp @@ -3,6 +3,7 @@ #ifndef _WIN32 #include +//#include // for pthread_exit #include #include @@ -47,6 +48,7 @@ void NotifyDebugger() #ifdef _MSC_VER __debugbreak(); #else + SetAbortImmediate(false); std::abort(); #endif #else @@ -57,6 +59,42 @@ void NotifyDebugger() } +// Is it unrecoverable? Should i exit cleanly or stop immediately? +// Set this just before calling abort. +static bool* _GetAbortImmediate() noexcept +{ + static bool _fIsAbortImmediate = true; + return &_fIsAbortImmediate; +} +void SetAbortImmediate(bool on) noexcept +{ + *_GetAbortImmediate() = on; +} +bool IsAbortImmediate() noexcept +{ + return *_GetAbortImmediate(); +} + +void RaiseRecoverableAbort() +{ + EXC_NOTIFY_DEBUGGER; + SetAbortImmediate(false); + std::abort(); +} +void RaiseImmediateAbort() +{ + EXC_NOTIFY_DEBUGGER; + SetAbortImmediate(true); + +//#if !defined(_WIN32) +// pthread_exit(EXIT_FAILURE); +#if defined(__GNUC__) || defined(__clang__) + __builtin_trap(); +#else + std::abort(); +#endif +} + #ifdef _WIN32 int CSError::GetSystemErrorMessage(dword dwError, lptstr lpszError, dword dwErrorBufLength) // static { @@ -235,7 +273,7 @@ void SetExceptionTranslator() } #ifndef _WIN32 -void _cdecl Signal_Hangup(int sig = 0) // If shutdown is initialized +void _cdecl Signal_Hangup(int sig = 0) noexcept // If shutdown is initialized { UnreferencedParameter(sig); @@ -254,11 +292,11 @@ void _cdecl Signal_Hangup(int sig = 0) // If shutdown is initialized g_Serv.SetExitFlag(SIGHUP); } -void _cdecl Signal_Terminate(int sig = 0) // If shutdown is initialized +void _cdecl Signal_Terminate(int sig = 0) noexcept // If shutdown is initialized { - sigset_t set; - g_Log.Event(LOGL_FATAL, "Server Unstable: %s\n", strsignal(sig)); + g_Log.Event(LOGL_FATAL, "Server Unstable: %s signal received\n", strsignal(sig)); + #ifdef THREAD_TRACK_CALLSTACK static bool _Signal_Terminate_stack_printed = false; if (!_Signal_Terminate_stack_printed) @@ -270,16 +308,42 @@ void _cdecl Signal_Terminate(int sig = 0) // If shutdown is initialized if (sig) { + if ((sig == SIGABRT) && IsAbortImmediate()) + { + // No clean ending. Abort right now. + STDERR_LOG("FATAL: Immediate abort requested."); + +#if defined(__GNUC__) || defined(__clang__) + __builtin_trap(); +#else + signal(SIGABRT, SIG_DFL); + raise(SIGABRT); +#endif + + return; + } + + sigset_t set; signal(sig, &Signal_Terminate); sigemptyset(&set); sigaddset(&set, sig); - sigprocmask(SIG_UNBLOCK, &set, nullptr); + //sigprocmask(SIG_UNBLOCK, &set, nullptr); + pthread_sigmask(SIG_UNBLOCK, &set, nullptr); } g_Serv.SetExitFlag(SIGABRT); - for (size_t i = 0; i < ThreadHolder::get().getActiveThreads(); ++i) - ThreadHolder::get().getThreadAt(i)->terminate(false); - //exit(EXIT_FAILURE); + + try + { + for (size_t i = 0; i < ThreadHolder::get().getActiveThreads(); ++i) + ThreadHolder::get().getThreadAt(i)->terminate(false); + } + catch (...) + { + RaiseImmediateAbort(); + } + + //exit(EXIT_FAILURE); // Having set the exit flag, all threads "should" terminate cleanly. } void _cdecl Signal_Break(int sig = 0) // signal handler attached when using secure mode @@ -292,13 +356,14 @@ void _cdecl Signal_Break(int sig = 0) // signal handler attached when using sec g_Log.Event(LOGL_FATAL, "Secure Mode prevents CTRL+C\n"); - sigset_t set; if (sig) { + sigset_t set; signal(sig, &Signal_Break); sigemptyset(&set); sigaddset(&set, sig); - sigprocmask(SIG_UNBLOCK, &set, nullptr); + //sigprocmask(SIG_UNBLOCK, &set, nullptr); + pthread_sigmask(SIG_UNBLOCK, &set, nullptr); } } @@ -307,7 +372,6 @@ void _cdecl Signal_Illegal_Instruction(int sig = 0) #ifdef THREAD_TRACK_CALLSTACK StackDebugInformation::freezeCallStack(true); #endif - sigset_t set; g_Log.Event(LOGL_FATAL, "%s\n", strsignal(sig)); #ifdef THREAD_TRACK_CALLSTACK @@ -316,10 +380,12 @@ void _cdecl Signal_Illegal_Instruction(int sig = 0) if (sig) { + sigset_t set; signal(sig, &Signal_Illegal_Instruction); sigemptyset(&set); sigaddset(&set, sig); - sigprocmask(SIG_UNBLOCK, &set, nullptr); + //sigprocmask(SIG_UNBLOCK, &set, nullptr); + pthread_sigmask(SIG_UNBLOCK, &set, nullptr); } #ifdef THREAD_TRACK_CALLSTACK diff --git a/src/common/CException.h b/src/common/CException.h index 83456ba54..3c9919a56 100644 --- a/src/common/CException.h +++ b/src/common/CException.h @@ -27,6 +27,13 @@ void SetExceptionTranslator(); void NotifyDebugger(); +void SetAbortImmediate(bool on) noexcept; +bool AbortImmediate() noexcept; + +void RaiseRecoverableAbort(); +void RaiseImmediateAbort(); + + // ------------------------------------------------------------------- // ------------------------------------------------------------------- diff --git a/src/common/CExpression.h b/src/common/CExpression.h index 2a1067d07..1ea81fc43 100644 --- a/src/common/CExpression.h +++ b/src/common/CExpression.h @@ -247,7 +247,7 @@ int64 ahextoi64( lpctstr pArgs ); // Convert decimal or (Sphere) hex string (sta #define Exp_GetRange( pa ) static_cast (g_Exp.GetRangeNumber( pa )) #define Exp_GetLLRange( pa ) g_Exp.GetRangeNumber( pa ) -#define Exp_GetCVal( pa ) static_cast (g_Exp.GetVal( pa )) +#define Exp_GetCVal( pa ) static_cast (g_Exp.GetVal( pa )) #define Exp_GetUCVal( pa ) static_cast (g_Exp.GetVal( pa )) #define Exp_GetSVal( pa ) static_cast (g_Exp.GetVal( pa )) #define Exp_GetUSVal( pa ) static_cast (g_Exp.GetVal( pa )) diff --git a/src/common/basic_threading.h b/src/common/basic_threading.h index ce021319d..c0df1bf06 100644 --- a/src/common/basic_threading.h +++ b/src/common/basic_threading.h @@ -96,8 +96,7 @@ if (!success_acquire_) { \ /*throw std::runtime_error("Failed to acquire lock after " #max_retries_ " attempts."); */ \ /* That should never happen. */ \ - EXC_NOTIFY_DEBUGGER; \ - std::abort(); \ + RaiseImmediateAbort(); \ } \ } diff --git a/src/common/common.h b/src/common/common.h index 1622fd78f..3101aa3ff 100644 --- a/src/common/common.h +++ b/src/common/common.h @@ -37,8 +37,8 @@ /* Coding helpers */ // Strings -#define _STRINGIFY_AUX(x) #x -#define STRINGIFY(x) _STRINGIFY_AUX(x) +#define STRINGIFY_IMPL_(x) #x +#define STRINGIFY(x) STRINGIFY_IMPL_(x) // Sizes #define ARRAY_COUNT(a) (sizeof(a)/sizeof((a)[0])) @@ -117,9 +117,44 @@ constexpr T sign(const T n) noexcept /* Compiler/c++ language helpers */ +// Ensure that a constexpr value or a generic expression is evaluated at compile time. +template +consteval T ensure_comptime(T&& val_) noexcept { + return val_; +} + +/* + There is a problem with the UnreferencedParameter macro from mingw and sphereserver. + operator= is on many clases private and the UnreferencedParameter macro from mingw is (P)=(P), + so we have a compilation error here. +*/ +#undef UNREFERENCED_PARAMETER +template +constexpr void UnreferencedParameter(T const&) noexcept { + ; +} + //#include // already included by stypecast.h -#define ASSERT_NOT_NOEXCEPT_CONSTRUCTOR(_ClassType) \ - static_assert(!std::is_nothrow_constructible_v<_ClassType>, #_ClassType " constructor should not be noexcept!") + +// Arguments: Class, arguments... +#define STATIC_ASSERT_NOEXCEPT_CONSTRUCTOR(_ClassType, ...) \ + static_assert( std::is_nothrow_constructible_v<_ClassType __VA_OPT__(,) __VA_ARGS__>, #_ClassType " constructor should be noexcept!") +#define STATIC_ASSERT_THROWING_CONSTRUCTOR(_ClassType, ...) \ + static_assert(!std::is_nothrow_constructible_v<_ClassType __VA_OPT__(,) __VA_ARGS__>, #_ClassType " constructor should *not* be noexcept!") + +// Arguments: function_name, arguments... +#define STATIC_ASSERT_NOEXCEPT_FREE_FUNCTION(_func, ...) \ + static_assert( std::is_nothrow_invocable_v, #_func " function should be noexcept!") +#define STATIC_ASSERT_THROWING_FREE_FUNCTION(_func, ...) \ + static_assert(!std::is_nothrow_invocable_v, #_func " function should be noexcept!") +// static_assert( noexcept(std::declval()()), #_func " should be noexcept"); + +// Arguments: Class, function_name, arguments... +#define STATIC_ASSERT_NOEXCEPT_MEMBER_FUNCTION(_ClassType, _func, ...) \ + static_assert( std::is_nothrow_invocable_v, #_func " function should be noexcept!") +#define STATIC_ASSERT_THROWING_MEMBER_FUNCTION(_ClassType, _func, ...) \ + static_assert(!std::is_nothrow_invocable_v, #_func " function should be noexcept!") + // Function specifier, like noexcept. Use this to make us know that the function code was checked and we know it can throw an exception. #define CANTHROW noexcept(false) @@ -134,16 +169,6 @@ constexpr T sign(const T n) noexcept #define NOEXCEPT_NODEBUG noexcept #endif -/* - There is a problem with the UnreferencedParameter macro from mingw and sphereserver. - operator= is on many clases private and the UnreferencedParameter macro from mingw is (P)=(P), - so we have a compilation error here. -*/ -#undef UNREFERENCED_PARAMETER -template -constexpr void UnreferencedParameter(T const&) noexcept { - ; -} // For unrecoverable/unloggable errors. Should be used almost *never*. #define STDERR_LOG(...) fprintf(stderr, __VA_ARGS__); fflush(stderr) diff --git a/src/common/sphere_library/stypecast.h b/src/common/sphere_library/stypecast.h index 346bcdb3b..a59d05601 100644 --- a/src/common/sphere_library/stypecast.h +++ b/src/common/sphere_library/stypecast.h @@ -80,9 +80,9 @@ uint32 u32_from_usize_clamping(const size_t a) noexcept // Promote to the corresponding 32 bits numeric type a smaller numeric variable. template [[nodiscard]] -constexpr auto n_promote32(const T a) noexcept +constexpr auto n_promote_n32(const T a) noexcept { - static_assert(std::is_arithmetic_v, "Input variable is not an arithmetic type."); + static_assert(std::is_arithmetic_v, "Input variable has not a arithmetic type."); static_assert(std::is_integral_v || (std::is_floating_point_v && std::is_signed_v), "Unsigned floating point numbers are unsupported by the language standard"); static_assert(sizeof(T) < 4, "Input variable is not smaller than a 32 bit number."); if constexpr (std::is_signed_v) @@ -95,12 +95,20 @@ constexpr auto n_promote32(const T a) noexcept return static_cast(a); } +template +[[nodiscard]] +constexpr auto enum_promote_n32(const T a) noexcept +{ + static_assert(std::is_enum_v, "Input variable is not an enum type."); + return n_promote_n32(static_cast>(a)); +} + // Promote to the corresponding 64 bits numeric type a smaller numeric variable. template [[nodiscard]] -constexpr auto n_promote64(const T a) noexcept +constexpr auto n_promote_n64(const T a) noexcept { - static_assert(std::is_arithmetic_v, "Input variable is not an arithmetic type."); + static_assert(std::is_arithmetic_v, "Input variable has not a arithmetic type."); static_assert(std::is_integral_v || (std::is_floating_point_v && std::is_signed_v), "Unsigned floating point numbers are unsupported by the language standard"); static_assert(sizeof(T) < 8, "Input variable is not smaller than a 64 bit number."); if constexpr (std::is_signed_v) @@ -113,12 +121,20 @@ constexpr auto n_promote64(const T a) noexcept return static_cast(a); } +template +[[nodiscard]] +constexpr auto enum_promote_n64(const T a) noexcept +{ + static_assert(std::is_enum_v, "Input variable is not an enum type."); + return n_promote_n64(static_cast>(a)); +} + // Narrow a 64 bits number to a 32 bits number, discarding any upper exceeding bytes. template [[nodiscard]] -constexpr auto n64_narrow32(const T a) noexcept +constexpr auto n64_narrow_n32(const T a) noexcept { - static_assert(std::is_arithmetic_v, "Input variable is not an arithmetic type."); + static_assert(std::is_arithmetic_v, "Input variable has not a arithmetic type."); static_assert(std::is_integral_v || (std::is_floating_point_v && std::is_signed_v), "Unsigned floating point numbers are unsupported by the language standard"); static_assert(sizeof(T) == 8, "Input variable is not a 64 bit number."); @@ -137,18 +153,27 @@ constexpr auto n64_narrow32(const T a) noexcept // Narrow a 64 bits number to a 32 bits number and ASSERT (because you're reasonably sure but not absolutely certain) that it won't overflow. template [[nodiscard]] inline -auto n64_narrow32_checked(const T a) +auto n64_narrow_n32_checked(const T a) { ASSERT(a <= std::numeric_limits::max()); - return n64_narrow32(a); + return n64_narrow_n32(a); } +template +[[nodiscard]] +constexpr auto enum64_narrow_n32_checked(const T a) noexcept +{ + static_assert(std::is_enum_v, "Input variable is not an enum type."); + return n64_narrow_n32_checked(static_cast>(a)); +} + + // Narrow a 64 bits number to a 16 bits number, discarding any upper exceeding bytes. template [[nodiscard]] -constexpr auto n64_narrow16(const T a) noexcept +constexpr auto n64_narrow_n16(const T a) noexcept { - static_assert(std::is_arithmetic_v, "Input variable is not an arithmetic type."); + static_assert(std::is_arithmetic_v, "Input variable has not a arithmetic type."); static_assert(std::is_integral_v || (std::is_floating_point_v && std::is_signed_v), "Unsigned floating point numbers are unsupported by the language standard"); static_assert(sizeof(T) == 8, "Input variable is not a 64 bit number."); @@ -167,18 +192,26 @@ constexpr auto n64_narrow16(const T a) noexcept // Narrow a 64 bits number to a 16 bits number and ASSERT (because you're reasonably sure but not absolutely certain) that it won't overflow. template [[nodiscard]] inline -auto n64_narrow16_checked(const T a) +auto n64_narrow_n16_checked(const T a) { ASSERT(a <= std::numeric_limits::max()); - return n64_narrow16(a); + return n64_narrow_n16(a); +} + +template +[[nodiscard]] +constexpr auto enum64_narrow_n16_checked(const T a) noexcept +{ + static_assert(std::is_enum_v, "Input variable is not an enum type."); + return n64_narrow_n16_checked(static_cast>(a)); } // Narrow a 64 bits number to a 8 bits number, discarding any upper exceeding bytes. template [[nodiscard]] -constexpr auto n64_narrow8(const T a) noexcept +constexpr auto n64_narrow_n8(const T a) noexcept { - static_assert(std::is_arithmetic_v, "Input variable is not an arithmetic type"); + static_assert(std::is_arithmetic_v, "Input variable has not a arithmetic type"); static_assert(std::is_floating_point_v == false, "Corresponding 8-bit floating point type does not exist?"); static_assert(std::is_integral_v || (std::is_floating_point_v && std::is_signed_v), "Unsigned floating point numbers are unsupported by the language standard"); static_assert(sizeof(T) == 8, "Input variable is not a 64 bit number."); @@ -194,18 +227,26 @@ constexpr auto n64_narrow8(const T a) noexcept // Narrow a 64 bits number to a 8 bits number and ASSERT (because you're reasonably sure but not absolutely certain) that it won't overflow. template [[nodiscard]] inline -auto n64_narrow8_checked(const T a) +auto n64_narrow_n8_checked(const T a) { ASSERT(a <= std::numeric_limits::max()); - return n64_narrow8(a); + return n64_narrow_n8(a); +} + +template +[[nodiscard]] +constexpr auto enum64_narrow_n8_checked(const T a) noexcept +{ + static_assert(std::is_enum_v, "Input variable is not an enum type."); + return n64_narrow_n8_checked(static_cast>(a)); } // Narrow a 32 bits number to a 16 bits number, discarding any upper exceeding bytes. template [[nodiscard]] -constexpr auto n32_narrow16(const T a) noexcept +constexpr auto n32_narrow_n16(const T a) noexcept { - static_assert(std::is_arithmetic_v, "Input variable is not an arithmetic type."); + static_assert(std::is_arithmetic_v, "Input variable has not a arithmetic type."); static_assert(std::is_integral_v || (std::is_floating_point_v && std::is_signed_v), "Unsigned floating point numbers are unsupported by the language standard"); static_assert(sizeof(T) == 4, "Input variable is not a 32 bit number."); @@ -224,18 +265,26 @@ constexpr auto n32_narrow16(const T a) noexcept // Narrow a 32 bits number to a 16 bits number and ASSERT (because you're reasonably sure but not absolutely certain) that it won't overflow. template [[nodiscard]] inline -auto n32_narrow16_checked(const T a) +auto n32_narrow_n16_checked(const T a) { ASSERT(a <= std::numeric_limits::max()); - return n32_narrow16(a); + return n32_narrow_n16(a); +} + +template +[[nodiscard]] +constexpr auto enum32_narrow_n16_checked(const T a) noexcept +{ + static_assert(std::is_enum_v, "Input variable is not an enum type."); + return n32_narrow_n16_checked(static_cast>(a)); } // Narrow a 32 bits number to a 8 bits number, discarding any upper exceeding bytes. template [[nodiscard]] -constexpr auto n32_narrow8(const T a) noexcept +constexpr auto n32_narrow_n8(const T a) noexcept { - static_assert(std::is_arithmetic_v, "Input variable is not an arithmetic type."); + static_assert(std::is_arithmetic_v, "Input variable has not a arithmetic type."); static_assert(sizeof(T) == 4, "Input variable is not a 32 bit number."); // Since the narrowing can be implementation specific, here we decide that we take only the lower 16 bytes and discard the upper ones. @@ -249,18 +298,26 @@ constexpr auto n32_narrow8(const T a) noexcept // Narrow a 32 bits number to an 8 bits number and ASSERT (because you're reasonably sure but not absolutely certain) that it won't overflow. template [[nodiscard]] inline -auto n32_narrow8_checked(const T a) +auto n32_narrow_n8_checked(const T a) { ASSERT(a <= std::numeric_limits::max()); - return n32_narrow8(a); + return n32_narrow_n8(a); +} + +template +[[nodiscard]] +constexpr auto enum32_narrow_n8_checked(const T a) noexcept +{ + static_assert(std::is_enum_v, "Input variable is not an enum type."); + return n32_narrow_n8_checked(static_cast>(a)); } // Narrow a 16 bits number to an 8 bits number, discarding any upper exceeding bytes. template [[nodiscard]] -constexpr auto n16_narrow8(const T a) noexcept +constexpr auto n16_narrow_n8(const T a) noexcept { - static_assert(std::is_arithmetic_v, "Input variable is not an arithmetic type."); + static_assert(std::is_arithmetic_v, "Input variable has not a arithmetic type."); static_assert(std::is_integral_v, "Only integral types are supported by this function."); static_assert(sizeof(T) == 2, "Input variable is not a 16 bit number."); @@ -275,25 +332,33 @@ constexpr auto n16_narrow8(const T a) noexcept // Narrow a 16 bits number to an 8 bits number and ASSERT (because you're reasonably sure but not absolutely certain) that it won't overflow. template [[nodiscard]] inline -auto n16_narrow8_checked(const T a) +auto n16_narrow_n8_checked(const T a) { ASSERT(a <= std::numeric_limits::max()); - return n16_narrow8(a); + return n16_narrow_n8(a); +} + +template +[[nodiscard]] +constexpr auto enum16_narrow_n8_checked(const T a) noexcept +{ + static_assert(std::is_enum_v, "Input variable is not an enum type."); + return n16_narrow_n8_checked(static_cast>(a)); } // If size_t is bigger than a 32 bits number, narrow it to a 32 bits number discarding any upper exceeding bytes, otherwise plain return the same value.. [[nodiscard]] -constexpr uint32 usize_narrow32(const size_t a) noexcept +constexpr uint32 usize_narrow_u32(const size_t a) noexcept { - // This doesn't work because n64_narrow32 static_asserts will be evaluated and fail on 32 bits compilation. + // This doesn't work because n64_narrow_n32 static_asserts will be evaluated and fail on 32 bits compilation. /* if constexpr (sizeof(size_t) == 8) - return n64_narrow32(a); + return n64_narrow_n32(a); else return a; */ #if SIZE_MAX == UINT64_MAX - return n64_narrow32(a); + return n64_narrow_n32(a); #elif SIZE_MAX == UINT32_MAX return a; #else @@ -303,10 +368,10 @@ constexpr uint32 usize_narrow32(const size_t a) noexcept // If size_t is bigger than a 32 bits number, narrow it to a 32 bits number and ASSERT (because you're reasonably sure but not absolutely certain) that it won't overflow. If size_t has 32 bits size, plain return the same value. [[nodiscard]] inline -uint32 usize_narrow32_checked(const size_t a) +uint32 usize_narrow_u32_checked(const size_t a) { ASSERT(a <= std::numeric_limits::max()); - return usize_narrow32(a); + return usize_narrow_u32(a); } @@ -378,9 +443,9 @@ template int64 i64_from_u64_checked(T) = delete; // disable implici int8 i8_from_usize_checked(const size_t a) // not clamping/capping { #if SIZE_MAX == UINT64_MAX - return n64_narrow8_checked(a); + return n64_narrow_n8_checked(a); #elif SIZE_MAX == UINT32_MAX - return n32_narrow8_checked(a); + return n32_narrow_n8_checked(a); #else # error "size_t is neither 8 nor 4 bytes?" #endif @@ -392,9 +457,9 @@ template int8 i8_from_usize_checked(T) = delete; // disable implici int16 i16_from_usize_checked(const size_t a) // not clamping/capping { #if SIZE_MAX == UINT64_MAX - return n64_narrow16_checked(a); + return n64_narrow_n16_checked(a); #elif SIZE_MAX == UINT32_MAX - return n32_narrow16_checked(a); + return n32_narrow_n16_checked(a); #else # error "size_t is neither 8 nor 4 bytes?" #endif @@ -405,7 +470,7 @@ template int16 i16_from_usize_checked(T) = delete; // disable impli int32 i32_from_usize_checked(const size_t a) // not clamping/capping { #if SIZE_MAX == UINT64_MAX - return i32_from_u32_clamping(n64_narrow32_checked(a)); + return i32_from_u32_clamping(n64_narrow_n32_checked(a)); #elif SIZE_MAX == UINT32_MAX return i32_from_u32_checked(num_alias_cast(a)); #else diff --git a/src/game/CBase.cpp b/src/game/CBase.cpp index 60c9a9587..f11a71045 100644 --- a/src/game/CBase.cpp +++ b/src/game/CBase.cpp @@ -53,15 +53,6 @@ void CBaseBaseDef::DelInstance() --_dwInstances; } -CCFaction const& CBaseBaseDef::GetFaction() const noexcept -{ - return _Faction; -} - -CCFaction & CBaseBaseDef::GetFaction() noexcept -{ - return _Faction; -} lpctstr CBaseBaseDef::GetTypeName() const { @@ -147,16 +138,6 @@ bool CBaseBaseDef::r_WriteVal( lpctstr ptcKey, CSString & sVal, CTextConsole * p sVal = GetResourceName(); break; - case OBC_FACTION_GROUP: - case OBC_SLAYER_GROUP: - sVal.FormatHex(num_alias_cast(_Faction.GetGroup())); - break; - - case OBC_FACTION_SPECIES: - case OBC_SLAYER_SPECIES: - sVal.FormatHex(num_alias_cast(_Faction.GetSpecies())); - break; - case OBC_ARMOR: { ptcKey += strlen(sm_szLoadKeys[index]); // 9; @@ -335,16 +316,6 @@ bool CBaseBaseDef::r_LoadVal( CScript & s ) } return true; - case OBC_FACTION_GROUP: - case OBC_SLAYER_GROUP: - _Faction.SetGroup(num_alias_cast(s.GetArgU32Val())); - return true; - - case OBC_FACTION_SPECIES: - case OBC_SLAYER_SPECIES: - _Faction.SetSpecies(num_alias_cast(s.GetArgU32Val())); - return true; - //Set as number only case OBC_EXPANSION: case OBC_VELOCITY: @@ -448,8 +419,6 @@ void CBaseBaseDef::CopyBasic( const CBaseBaseDef * pBase ) m_defenseBase = pBase->m_defenseBase; m_defenseRange = pBase->m_defenseRange; m_Can = pBase->m_Can; - _Faction.SetGroup(pBase->_Faction.GetGroup()); - _Faction.SetSpecies(pBase->_Faction.GetSpecies()); CEntityProps::Copy(pBase); } diff --git a/src/game/CBase.h b/src/game/CBase.h index 1228fabbd..1cf7e28fc 100644 --- a/src/game/CBase.h +++ b/src/game/CBase.h @@ -11,7 +11,6 @@ #include "../common/CVarDefMap.h" #include "../common/sphere_library/CSString.h" #include "uo_files/uofiles_types.h" -#include "components/CCFaction.h" #include "CEntityProps.h" @@ -139,14 +138,7 @@ struct CBaseBaseDef : public CResourceLink, public CEntityProps uint64 m_Can; // Base attribute flags. CAN_C_GHOST, etc -private: - CCFaction _Faction; - - public: - CCFaction const& GetFaction() const noexcept; - CCFaction &GetFaction() noexcept; - /** * @brief Gets definition string. * @param ptcKey The key. diff --git a/src/game/CComponent.h b/src/game/CComponent.h index c822f97f7..c527d8375 100644 --- a/src/game/CComponent.h +++ b/src/game/CComponent.h @@ -20,7 +20,6 @@ enum COMP_TYPE : ushort COMP_CHAMPION, COMP_SPAWN, COMP_MULTI, - COMP_FACTION, COMP_ITEMDAMAGEABLE, COMP_QTY }; diff --git a/src/game/CComponentProps.h b/src/game/CComponentProps.h index ff968b820..cbac17ed4 100644 --- a/src/game/CComponentProps.h +++ b/src/game/CComponentProps.h @@ -17,6 +17,7 @@ class CClientTooltip; enum COMPPROPS_TYPE : uchar { + COMP_PROPS_FACTION, COMP_PROPS_ITEMCHAR, COMP_PROPS_CHAR, COMP_PROPS_ITEM, @@ -138,7 +139,7 @@ class CComponentProps public: virtual ~CComponentProps() noexcept = default; - + inline COMPPROPS_TYPE GetType() const noexcept { return _iType; } diff --git a/src/game/CObjBase.cpp b/src/game/CObjBase.cpp index 818036c1c..934303f67 100644 --- a/src/game/CObjBase.cpp +++ b/src/game/CObjBase.cpp @@ -1012,10 +1012,6 @@ bool CObjBase::r_WriteVal( lpctstr ptcKey, CSString &sVal, CTextConsole * pSrc, case OC_ABILITYPRIMARY: case OC_ABILITYSECONDARY: case OC_ONAME: - case OC_SLAYER: - case OC_SLAYERLESSER: - case OC_SLAYERMISC: - case OC_SLAYERSUPER: { const CVarDefCont * pVar = GetDefKey(ptcKey, true); sVal = pVar ? pVar->GetValStr() : ""; @@ -1805,10 +1801,6 @@ bool CObjBase::r_LoadVal( CScript & s ) case OC_ABILITYPRIMARY: case OC_ABILITYSECONDARY: case OC_ONAME: - case OC_SLAYER: - case OC_SLAYERLESSER: - case OC_SLAYERMISC: - case OC_SLAYERSUPER: { bool fQuoted = false; SetDefStr(s.GetKey(), s.GetArgStr( &fQuoted ), fQuoted); @@ -3317,11 +3309,6 @@ void CObjBase::SetSpawn(CCSpawn * spawn) _uidSpawn.InitUID(); } -CCFaction * CObjBase::GetFaction() -{ - return static_cast(GetComponent(COMP_FACTION)); -} - CSString CObjBase::GetPropStr( const CComponentProps* pCompProps, CComponentProps::PropertyIndex_t iPropIndex, bool fZero, const CComponentProps* pBaseCompProps ) const { CSString sProp; diff --git a/src/game/CObjBase.h b/src/game/CObjBase.h index 94d97e2ef..c0e485fb2 100644 --- a/src/game/CObjBase.h +++ b/src/game/CObjBase.h @@ -193,13 +193,6 @@ public: virtual bool IsDeleted() const override; */ void SetSpawn(CCSpawn *spawn); - /** - * @brief Returns Faction CComponent. - * @return The CCFaction. - */ - CCFaction *GetFaction(); - - /** * @brief Gets timestamp of the item (it's a property and not related at all with TIMER). * @return The timestamp. diff --git a/src/game/CServer.cpp b/src/game/CServer.cpp index 2091b2c09..08486e5f9 100644 --- a/src/game/CServer.cpp +++ b/src/game/CServer.cpp @@ -169,7 +169,7 @@ int CServer::GetExitFlag() const noexcept return m_iExitFlag.load(std::memory_order_acquire); } -void CServer::SetExitFlag(int iFlag) +void CServer::SetExitFlag(int iFlag) noexcept { ADDTOCALLSTACK("CServer::SetExitFlag"); if ( GetExitFlag() ) diff --git a/src/game/CServer.h b/src/game/CServer.h index 7070f0aa2..4923779fe 100644 --- a/src/game/CServer.h +++ b/src/game/CServer.h @@ -86,7 +86,7 @@ extern class CServer : public CServerDef, public CTextConsole void SetServerMode( SERVMODE_TYPE mode ); bool IsValidBusy() const; int GetExitFlag() const noexcept; - void SetExitFlag(int iFlag); + void SetExitFlag(int iFlag) noexcept; bool IsLoading() const noexcept; bool IsResyncing() const noexcept; void Shutdown( int64 iMinutes ); diff --git a/src/game/CWorldTicker.h b/src/game/CWorldTicker.h index 6a70df3f0..50fd92fdb 100644 --- a/src/game/CWorldTicker.h +++ b/src/game/CWorldTicker.h @@ -8,7 +8,6 @@ #include "CTimedFunctionHandler.h" #include "CTimedObject.h" #include -//#include #ifdef ADDRESS_SANITIZER #define MYASAN_ @@ -22,7 +21,7 @@ #pragma GCC diagnostic ignored "-Wshift-count-overflow" #endif -// TODO: TEMPORARY !! +// TODO: undef is TEMPORARY !! There's a bug that needs to be solved #undef ADDRESS_SANITIZER #include #ifdef MYASAN_ diff --git a/src/game/chars/CChar.cpp b/src/game/chars/CChar.cpp index 40626e0e0..ccf2248a3 100644 --- a/src/game/chars/CChar.cpp +++ b/src/game/chars/CChar.cpp @@ -328,7 +328,6 @@ CChar::CChar( CREID_TYPE baseID ) : // SubscribeComponent Prop Components TrySubscribeComponentProps(); TrySubscribeComponentProps(); - SubscribeComponent(new CCFaction(pCharDef->GetFaction())); ASSERT(IsDisconnected()); } @@ -336,8 +335,8 @@ CChar::CChar( CREID_TYPE baseID ) : // Delete character CChar::~CChar() { - EXC_TRY("Cleanup in destructor"); ADDTOCALLSTACK("CChar::~CChar"); + EXC_TRY("Cleanup in destructor"); CChar::DeletePrepare(); CChar::DeleteCleanup(true); @@ -1248,7 +1247,7 @@ bool CChar::DupeFrom(const CChar * pChar, bool fNewbieItems ) pItem->m_uidLink = myUID; //If the character being duped has an item which linked to himself, set the newly duped character link instead. else if (IsSetOF(OF_PetSlots) && pItem->IsMemoryTypes(MEMORY_IPET) && pTest3 == NPC_PetGetOwner()) { - const short iFollowerSlots = n64_narrow16(GetDefNum("FOLLOWERSLOTS", true, 1)); + const short iFollowerSlots = n64_narrow_n16(GetDefNum("FOLLOWERSLOTS", true, 1)); //If we have reached the maximum follower slots we remove the ownership of the pet by clearing the memory flag instead of using NPC_PetClearOwners(). if (!pTest3->FollowersUpdate(this, maximum(0, iFollowerSlots))) Memory_ClearTypes(MEMORY_IPET); @@ -1472,6 +1471,19 @@ bool CChar::SetName( lpctstr pszName ) return SetNamePool( pszName ); } +const CFactionDef* CChar::GetFaction() const noexcept +{ + auto pComp = static_cast(GetComponentProps(COMP_PROPS_CHAR)); + return (!pComp ? nullptr : pComp->GetFaction()); +} + +CFactionDef* CChar::GetFaction() noexcept +{ + auto pComp = static_cast(GetComponentProps(COMP_PROPS_CHAR)); + return (!pComp ? nullptr : pComp->GetFaction()); +} + + height_t CChar::GetHeightMount( bool fEyeSubstract ) const { ADDTOCALLSTACK_DEBUG("CChar::GetHeightMount"); @@ -2517,7 +2529,7 @@ bool CChar::r_WriteVal( lpctstr ptcKey, CSString & sVal, CTextConsole * pSrc, bo } if ( m_notoSaves.size() ) { - size_t notoIndex = Exp_GetVal(ptcKey); + size_t notoIndex = Exp_GetSTVal(ptcKey); SKIP_SEPARATORS(ptcKey); if ( notoIndex < m_notoSaves.size() ) { @@ -3758,6 +3770,7 @@ bool CChar::r_LoadVal( CScript & s ) Stat_SetVal(STAT_DEX, (ushort)std::max(s.GetArgVal(), 0)); UpdateStamFlag(); break; + case CHC_STEPSTEALTH: m_StepStealth = s.GetArgVal(); break; diff --git a/src/game/chars/CChar.h b/src/game/chars/CChar.h index 13a2efaa8..ed13ffd9a 100644 --- a/src/game/chars/CChar.h +++ b/src/game/chars/CChar.h @@ -7,7 +7,6 @@ #define _INC_CCHAR_H #include "../../common/sphereproto.h" -#include "../components/CCFaction.h" #include "../clients/CParty.h" #include "../items/CItemContainer.h" #include "../items/CItemCorpse.h" @@ -23,6 +22,7 @@ class CWorldTicker; class CCharNPC; class CMapBlockingState; +class CFactionDef; enum NPCBRAIN_TYPE // General AI type. @@ -112,8 +112,8 @@ class CChar : public CObjBase, public CContainer, public CTextConsole struct NotoSaves { - dword charUID; // Character viewing me - int64 time; // Update timer + int64 time; // Updaete timer + dword charUID; // Character viewing me NOTO_TYPE color; // Color sent on movement packets NOTO_TYPE value; // Notoriety type }; @@ -136,23 +136,32 @@ class CChar : public CObjBase, public CContainer, public CTextConsole // Combat stuff. cached data. (not saved) CUID m_uidWeapon; // current Wielded weapon. (could just get rid of this ?) word m_defense; // calculated armor worn (NOT intrinsic armor) - ushort _uiRange; - - height_t m_height; // Height set in-game or under some trigger (height=) - for both items and chars + ushort _iRegenTickCount; // ticks until next regen. CUID m_UIDLastNewItem; // Last item created, used to store on this CChar the UID of the last created item via ITEM or ITEMNEWBIe in @Create and @Restock to prevent COLOR, etc properties to be called with no reference when the item was not really created, ie: ITEM=i_dagger,R5 uint m_exp; // character experience uint m_level; // character experience level - byte m_iVisualRange; // Visual Range //DIR_TYPE m_dirClimb; // we are standing on a CAN_I_CLIMB or UFLAG2_CLIMBABLE, DIR_QTY = not on climbable bool m_fClimbUpdated; // FixClimbHeight() called? bool m_fIgnoreNextPetCmd; // return 1 in speech block for this pet will make it ignore target petcmds while allowing the rest to perform them height_t m_zClimbHeight; // The height at the end of the climbable. // Saved stuff. + byte m_iVisualRange; // Visual Range + height_t m_height; // Height set in-game or under some trigger (height=) - for both items and chars + HUE_TYPE _wBloodHue; // Replicating CharDef's BloodColor on the char, or overriding it. + DIR_TYPE m_dirFace; // facing this dir. CSString m_sTitle; // Special title such as "the guard" (replaces the normal skill title) CPointMap m_ptHome; // What is our "home" region. (towns and bounding of NPC's) + + int64 _iTimeCreate; // When was i created ? + int64 _iTimePeriodicTick; + int64 _iTimeNextRegen; // When did i get my last regen tick ? + + int64 _iTimeLastHitsUpdate; + int64 _iTimeLastCallGuards; + int64 m_virtualGold; // Virtual gold used by TOL clients // Speech @@ -161,9 +170,8 @@ class CChar : public CObjBase, public CContainer, public CTextConsole HUE_TYPE m_EmoteHueOverride; // emote hue to use // In order to revert to original Hue and body. - CREID_TYPE _iPrev_id; // Backup of body type for ghosts and poly HUE_TYPE _wPrev_Hue; // Backup of skin color. in case of polymorph etc. - HUE_TYPE _wBloodHue; // Replicating CharDef's BloodColor on the char, or overriding it. + CREID_TYPE _iPrev_id; // Backup of body type for ghosts and poly CREID_TYPE m_dwDispIndex; //To change the DispID instance @@ -172,27 +180,19 @@ class CChar : public CObjBase, public CContainer, public CTextConsole struct { - ushort m_base; // Base stat: STR, INT, DEX int m_mod; // Modifier to base stat: ModSTR, ModINT, ModDex (signed to allow negative modifiers). Accepted values between -UINT16_MAX and +UINT16_MAX + int m_maxMod; // Modifier to MaxVal: ModMaxHits, ModMaxMana, ModMaxStam + ushort m_base; // Base stat: STR, INT, DEX ushort m_val; // Hits, Mana, Stam ushort m_max; // MaxVal: MaxHits, MaxMana, MaxStam - int m_maxMod; // Modifier to MaxVal: ModMaxHits, ModMaxMana, ModMaxStam + ushort m_regenVal; // Amount of Stat to gain at each regen int64 m_regenRate; // Regen each this much milliseconds. int64 m_regenLast; // Time of the last regen. - ushort m_regenVal; // Amount of Stat to gain at each regen } m_Stat[STAT_QTY]; short m_iKarma; ushort m_uiFame; - int64 _iTimeCreate; // When was i created ? - int64 _iTimePeriodicTick; - int64 _iTimeNextRegen; // When did i get my last regen tick ? - ushort _iRegenTickCount; // ticks until next regen. - - int64 _iTimeLastHitsUpdate; - int64 _iTimeLastCallGuards; - // Some character action in progress. SKILL_TYPE m_Act_SkillCurrent; // Currently using a skill. Could be combat skill. CUID m_Act_UID; // Current action target @@ -200,8 +200,11 @@ class CChar : public CObjBase, public CContainer, public CTextConsole CUID m_Act_Prv_UID; // Previous target. int m_Act_Difficulty; // -1 = fail skill. (0-100) for skill advance calc. int m_Act_Effect; - CPointMap m_Act_p; // Moving to this location. or location of forge we are working on. int m_StepStealth; // Max steps allowed to walk invisible while using Stealth skill + CPointMap m_Act_p; // Moving to this location. or location of forge we are working on. + + ushort _uiRange; + std::vector m_followers; @@ -1036,10 +1039,13 @@ public: void StatFlag_Mod(uint64 uiStatFlag, bool fMod) noexcept; void SoundChar(CRESND_TYPE type); void Action_StartSpecial(CREID_TYPE id); + const CFactionDef* GetFaction() const noexcept; + CFactionDef* GetFaction() noexcept; + private: void OnNoticeCrime( CChar * pCriminal, CChar * pCharMark ); public: - bool CheckCrimeSeen( SKILL_TYPE SkillToSee, CChar * pCharMark, const CObjBase * pItem, lpctstr pAction ); + bool CheckCrimeSeen( SKILL_TYPE SkillToSee, CChar * pCharMark, const CObjBase * pItem, lpctstr ptcAction ); private: // Armor, weapons and combat ------------------------------------ diff --git a/src/game/chars/CCharBase.h b/src/game/chars/CCharBase.h index ac6c5f4b1..cf7d10314 100644 --- a/src/game/chars/CCharBase.h +++ b/src/game/chars/CCharBase.h @@ -1,6 +1,6 @@ /** * @file CCharBase.h -* +* */ #ifndef _INC_CCHARBASE_H @@ -13,10 +13,10 @@ #include "../../common/CTextConsole.h" #include "../uo_files/uofiles_enums_creid.h" #include "../CBase.h" -#include "../components/CCFaction.h" class CScript; +class CFactionDef; class CCharBase : public CBaseBaseDef // define basic info about each "TYPE" of monster/creature. { @@ -44,7 +44,6 @@ class CCharBase : public CBaseBaseDef // define basic info about each "TYPE" of RESDISPLAY_VERSION _iEraLimitLoot; // Don't allow to create loot newer than the given era (softcoded). ushort _uiRange; - short m_iMoveRate; // move rate percent // NPC info ---------------------------------------------------- @@ -62,17 +61,20 @@ class CCharBase : public CBaseBaseDef // define basic info about each "TYPE" of static lpctstr const sm_szLoadKeys[]; -private: - void SetFoodType( lpctstr pszFood ); - void CopyBasic( const CCharBase * pCharDef ); - public: explicit CCharBase( CREID_TYPE id ); virtual ~CCharBase() = default; + CCharBase(const CCharBase& copy) = delete; + CCharBase& operator=(const CCharBase& other) = delete; + + virtual bool r_LoadVal( CScript & s ) override; + virtual bool r_WriteVal( lpctstr ptcKey, CSString & sVal, CTextConsole * pSrc = nullptr, bool fNoCallParent = false, bool fNoCallChildren = false ) override; + virtual bool r_Load( CScript & s ) override; + private: - CCharBase(const CCharBase& copy); - CCharBase& operator=(const CCharBase& other); + void SetFoodType( lpctstr pszFood ); + void CopyBasic( const CCharBase * pCharDef ); public: virtual void UnLink() override; @@ -116,10 +118,7 @@ class CCharBase : public CBaseBaseDef // define basic info about each "TYPE" of lpctstr GetTradeName() const; - virtual bool r_LoadVal( CScript & s ) override; - virtual bool r_WriteVal( lpctstr ptcKey, CSString & sVal, CTextConsole * pSrc = nullptr, bool fNoCallParent = false, bool fNoCallChildren = false ) override; - virtual bool r_Load( CScript & s ) override; }; -#endif // _INC_CCHARBASE_H \ No newline at end of file +#endif // _INC_CCHARBASE_H diff --git a/src/game/chars/CCharFight.cpp b/src/game/chars/CCharFight.cpp index 956055486..9a877570e 100644 --- a/src/game/chars/CCharFight.cpp +++ b/src/game/chars/CCharFight.cpp @@ -4,6 +4,7 @@ #include "../../network/send.h" #include "../clients/CClient.h" #include "../components/CCPropsChar.h" +#include "../components/CCPropsItemEquippable.h" #include "../components/CCPropsItemWeapon.h" #include "../CWorldGameTime.h" #include "../CWorldSearch.h" @@ -92,7 +93,7 @@ void CChar::OnNoticeCrime( CChar * pCriminal, CChar * pCharMark ) // pCharMark = offended char. // RETURN: // true = somebody saw me. -bool CChar::CheckCrimeSeen( SKILL_TYPE SkillToSee, CChar * pCharMark, const CObjBase * pItem, lpctstr pAction ) +bool CChar::CheckCrimeSeen( SKILL_TYPE SkillToSee, CChar * pCharMark, const CObjBase * pItem, lpctstr ptcAction ) { ADDTOCALLSTACK("CChar::CheckCrimeSeen"); // Who notices ? @@ -121,12 +122,13 @@ bool CChar::CheckCrimeSeen( SKILL_TYPE SkillToSee, CChar * pCharMark, const CObj continue; tchar *z = Str_GetTemp(); - if ( pItem && pAction ) + if ( pItem && ptcAction ) { if ( pCharMark ) - snprintf(z, Str_TempLength(), g_Cfg.GetDefaultMsg(DEFMSG_MSG_YOUNOTICE_2), GetName(), pAction, fYour ? g_Cfg.GetDefaultMsg(DEFMSG_MSG_YOUNOTICE_YOUR) : pCharMark->GetName(), fYour ? "" : g_Cfg.GetDefaultMsg(DEFMSG_MSG_YOUNOTICE_S), pItem->GetName()); + snprintf(z, Str_TempLength(), g_Cfg.GetDefaultMsg(DEFMSG_MSG_YOUNOTICE_2), GetName(), + ptcAction, fYour ? g_Cfg.GetDefaultMsg(DEFMSG_MSG_YOUNOTICE_YOUR) : pCharMark->GetName(), fYour ? "" : g_Cfg.GetDefaultMsg(DEFMSG_MSG_YOUNOTICE_S), pItem->GetName()); else - snprintf(z, Str_TempLength(), g_Cfg.GetDefaultMsg(DEFMSG_MSG_YOUNOTICE_1), GetName(), pAction, pItem->GetName()); + snprintf(z, Str_TempLength(), g_Cfg.GetDefaultMsg(DEFMSG_MSG_YOUNOTICE_1), GetName(), ptcAction, pItem->GetName()); } // They are not a criminal til someone calls the guards !!! @@ -134,7 +136,7 @@ bool CChar::CheckCrimeSeen( SKILL_TYPE SkillToSee, CChar * pCharMark, const CObj { if (IsTrigUsed(TRIGGER_SEESNOOP)) { - CScriptTriggerArgs Args(pAction); + CScriptTriggerArgs Args(ptcAction); Args.m_iN1 = SkillToSee; Args.m_iN2 = pItem ? (dword)pItem->GetUID() : 0; // here i can modify pItem via scripts, so it isn't really const Args.m_pO1 = pCharMark; @@ -806,70 +808,60 @@ int CChar::OnTakeDamage( int iDmg, CChar * pSrc, DAMAGE_TYPE uiType, int iDmgPhy if (IsSetCombatFlags(COMBAT_SLAYER)) { - CItem *pWeapon = nullptr; + CItem *pSrcWeapon = nullptr; if (uiType & DAMAGE_MAGIC) // If the damage is magic, we are probably using a spell or a weapon that causes also magical damage. { - pWeapon = pSrc->GetSpellbookLayer(); // Search for an equipped spellbook - if ( !pWeapon ) //No spellbook, so it's a weapon causing magical damage. - pWeapon = pSrc->m_uidWeapon.ItemFind(); // then force a weapon find. + pSrcWeapon = pSrc->GetSpellbookLayer(); // Search for an equipped spellbook + if ( !pSrcWeapon ) //No spellbook, so it's a weapon causing magical damage. + pSrcWeapon = pSrc->m_uidWeapon.ItemFind(); // then force a weapon find. } else //Other types of damage. { - pWeapon = pSrc->m_uidWeapon.ItemFind(); // force a weapon find. + pSrcWeapon = pSrc->m_uidWeapon.ItemFind(); // force a weapon find. } - int iDmgBonus = 1; - const CCFaction *pSlayer = nullptr; - const CCFaction *pFaction = GetFaction(); - //const CCFaction *pSrcFaction = pSrc->GetFaction(); - if (pWeapon) + + const CFactionDef *pMyFaction = GetFaction(); + if (pMyFaction && !pMyFaction->IsNone()) { - pSlayer = pWeapon->GetSlayer(); - if (pSlayer && !pSlayer->IsNone()) + int iDmgBonusPercent = 100; + if (pSrcWeapon) { - if (m_pNPC) // I'm an NPC attacked (Should the attacker be a player to get the bonus?). + const CFactionDef *pSrcSlayer = pSrcWeapon->GetSlayer(); + if (pSrcSlayer && !pSrcSlayer->IsNone()) { - if (pFaction && !pFaction->IsNone()) + if (m_pNPC) // I'm an NPC attacked (Should the attacker be a player to get the bonus?). { - iDmgBonus = pSlayer->GetSlayerDamageBonus(pFaction); + iDmgBonusPercent = pSrcSlayer->GetSlayerDamageBonusPercent(pMyFaction); } - } - else if (m_pPlayer && pSrc->m_pNPC) // Wielding a slayer type against its opposite will cause the attacker to take more damage - { - if (pFaction && !pFaction->IsNone()) + else if (m_pPlayer && pSrc->m_pNPC) // Wielding a slayer type against its opposite will cause the attacker to take more damage { - iDmgBonus = pSlayer->GetSlayerDamagePenalty(pFaction); + iDmgBonusPercent = pSrcSlayer->GetSlayerDamagePenaltyPercent(pMyFaction); } } } - } - if (iDmgBonus == 1) // Couldn't find a weapon, a Slayer flag or a suitable flag for the target... - { - const CItem *pTalisman = pSrc->LayerFind(LAYER_TALISMAN); // then lets try with a Talisman - if (pTalisman) + if (iDmgBonusPercent == 100) // Couldn't find a weapon, a Slayer flag or a suitable flag for the target... { - pSlayer = pTalisman->GetSlayer(); - if (pSlayer && pSlayer->IsNone()) + const CItem *pSrcTalisman = pSrc->LayerFind(LAYER_TALISMAN); // then lets try with a Talisman + if (pSrcTalisman) { - if (m_pNPC) // I'm an NPC attacked (Should the attacker be a player to get the bonus?). + const CFactionDef *pSrcSlayer = pSrcTalisman->GetSlayer(); + if (pSrcSlayer && !pSrcSlayer->IsNone()) { - if (pFaction && pFaction->IsNone()) + if (m_pNPC) // I'm an NPC attacked (Should the attacker be a player to get the bonus?). { - iDmgBonus = pSlayer->GetSlayerDamageBonus(pFaction); + iDmgBonusPercent = pSrcSlayer->GetSlayerDamageBonusPercent(pMyFaction); } - } - else if (m_pPlayer && pSrc->m_pNPC) // Wielding a slayer type against its opposite will cause the attacker to take more damage - { - if (pFaction && pFaction->IsNone()) + else if (m_pPlayer && pSrc->m_pNPC) // Wielding a slayer type against its opposite will cause the attacker to take more damage { - iDmgBonus = pSlayer->GetSlayerDamagePenalty(pFaction); + iDmgBonusPercent = pSrcSlayer->GetSlayerDamagePenaltyPercent(pMyFaction); } } } } - } - if (iDmgBonus > 1) - { - iDmg *= iDmgBonus; + if (iDmgBonusPercent != 100) + { + iDmg += (iDmg * iDmgBonusPercent) / 100; + } } } diff --git a/src/game/chars/CCharSkill.cpp b/src/game/chars/CCharSkill.cpp index e14f6531f..ac5624c40 100644 --- a/src/game/chars/CCharSkill.cpp +++ b/src/game/chars/CCharSkill.cpp @@ -226,11 +226,11 @@ void CChar::Skill_SetBase( SKILL_TYPE skill, ushort uiValue ) // We need to update the AC given by the Shield when parrying increase. if (skill == SKILL_PARRYING && g_Cfg.m_iCombatParryingEra & PARRYERA_ARSCALING) { - + m_defense = (word)CalcArmorDefense(); fUpdateStats = true; } - + if (fUpdateStats) UpdateStatsFlag(); } @@ -469,7 +469,7 @@ void CChar::Skill_Experience( SKILL_TYPE skill, int iDifficulty ) const ushort uiStatVal = Stat_GetBase((STAT_TYPE)i); if ( uiStatVal <= 0 ) // some odd condition continue; - + /*Before there was uiStatSum >= uiStatSumMax: That condition prevented the decrease of stats when the player's Stats were equal to the StatCap */ if (uiStatSum > uiStatSumMax) // stat cap already reached @@ -921,7 +921,7 @@ bool CChar::Skill_MakeItem( ITEMID_TYPE id, CUID uidTarg, SKTRIG_TYPE stage, boo { if (m_Act_Effect >= 0) iConsumePercent = m_Act_Effect; - else + else { CSkillDef* pSkillDef = g_Cfg.GetSkillDef((SKILL_TYPE)(pItemDef->m_SkillMake[i].GetResIndex())); if (pSkillDef && !pSkillDef->m_vcEffect.m_aiValues.empty()) @@ -1118,10 +1118,10 @@ bool CChar::Skill_Mining_Smelt( CItem * pItemOre, CItem * pItemTarg ) bool fSkipMiningSmeltReq = false; //Skip the minimum requirement in Mining skill for attempting the smelt action, this will be stored in ARGN3. word iOreQty = pItemOre->GetAmount(); word iResourceQty = 0; - size_t iResourceTotalQty = pOreDef->m_BaseResources.size(); //This is the total amount of different resources obtained from smelting. + size_t iResourceTotalQty = pOreDef->m_BaseResources.size(); //This is the total amount of different resources obtained from smelting. CScriptTriggerArgs Args(iMiningSkill, iResourceTotalQty); - + if ( pOreDef->IsType( IT_ORE )) { ITEMID_TYPE idIngot = (ITEMID_TYPE)(ResGetIndex( pOreDef->m_ttOre.m_idIngot)); @@ -1158,7 +1158,7 @@ bool CChar::Skill_Mining_Smelt( CItem * pItemOre, CItem * pItemTarg ) iResourceQty = (word)(pOreDef->m_BaseResources[i].GetResQty()); snprintf(pszTmp, Str_TempLength(), "resource.%u.amount", (int)i); Args.m_VarsLocal.SetNum(pszTmp, iResourceQty); - + } } @@ -1179,7 +1179,7 @@ bool CChar::Skill_Mining_Smelt( CItem * pItemOre, CItem * pItemTarg ) tchar* pszTmp = Str_GetTemp(); snprintf(pszTmp, Str_TempLength(), "resource.%u.ID", (int)i); const CItemBase* pBaseDef = CItemBase::FindItemBase((ITEMID_TYPE)(ResGetIndex((dword)Args.m_VarsLocal.GetKeyNum(pszTmp)))); - + //We have finished the ore or the item being smelted. if (iOreQty <= 0) { @@ -1217,7 +1217,7 @@ bool CChar::Skill_Mining_Smelt( CItem * pItemOre, CItem * pItemTarg ) continue; return false; } - + const int iSkillRange = pBaseDef->m_ttIngot.m_iSkillMax - pBaseDef->m_ttIngot.m_iSkillMin; int iSmeltingDifficulty = g_Rand.GetVal(iSkillRange); @@ -1240,7 +1240,7 @@ bool CChar::Skill_Mining_Smelt( CItem * pItemOre, CItem * pItemTarg ) continue; } ingots.at(i)->SetAmount(iResourceQty); - /* + /* CItem* pIngots = CItem::CreateScript(pBaseDef->GetID(), this); if ( pIngots == nullptr ) { @@ -1252,7 +1252,7 @@ bool CChar::Skill_Mining_Smelt( CItem * pItemOre, CItem * pItemTarg ) ItemBounce( pIngots ); */ - + } //We want to consume the ore before the ingots are created. pItemOre->ConsumeAmount(pItemOre->GetAmount()); @@ -1312,7 +1312,7 @@ bool CChar::Skill_Tracking( CUID uidTarg, DIR_TYPE & dirPrv, int iDistMax ) if ( pszDef[0] ) { tchar *pszMsg = Str_GetTemp(); - snprintf(pszMsg, Str_TempLength(), + snprintf(pszMsg, Str_TempLength(), pszDef, pObj->GetName(), (pObjTop->IsDisconnected() ? g_Cfg.GetDefaultMsg(DEFMSG_TRACKING_RESULT_DISC) : CPointBase::sm_szDirs[dir]) ); ObjMessage(pszMsg, this); } @@ -1757,6 +1757,10 @@ int CChar::Skill_Musicianship( SKTRIG_TYPE stage ) if ( stage == SKTRIG_STROKE ) return 0; + + // TODO: + // Slayer instruments will increase your success chance by 20% when used on the creatures it is meant for; + // Slayer instruments will decrease your success chance by 20% when used on the creatures from its opposing group if ( stage == SKTRIG_START ) return Use_PlayMusic( m_Act_UID.ItemFind(), g_Rand.GetVal(90)); // How difficult? 1-1000. If no instrument, it immediately fails @@ -1795,7 +1799,11 @@ int CChar::Skill_Peacemaking( SKTRIG_TYPE stage ) } } } - + + // TODO: + // Slayer instruments will increase your success chance by 20% when used on the creatures it is meant for; + // Slayer instruments will decrease your success chance by 20% when used on the creatures from its opposing group + // Basic skill check. int iDifficulty = Use_PlayMusic(pInstrument, g_Rand.GetVal(40)); if (iDifficulty < -1) // no instrument: immediate fail @@ -1829,6 +1837,10 @@ int CChar::Skill_Peacemaking( SKTRIG_TYPE stage ) if (iBardingDiff != 0) iPeaceDiff = ((iPeaceDiff + iBardingDiff) / 2); + // TODO: + // Slayer instruments will increase your success chance by 20% when used on the creatures it is meant for; + // Slayer instruments will decrease your success chance by 20% when used on the creatures from its opposing group + if ( iPeaceDiff > peace ) SysMessagef("%s %s.", pChar->GetName(),g_Cfg.GetDefaultMsg( DEFMSG_PEACEMAKING_IGNORE )); else @@ -1889,7 +1901,7 @@ int CChar::Skill_Enticement( SKTRIG_TYPE stage ) { DEBUG_WARN(("Invalid ACTARG1 when using skill Enticement. Expected zero or the UID of an item with type t_musical.\n")); pInstrument = nullptr; - } + } } } @@ -1900,13 +1912,17 @@ int CChar::Skill_Enticement( SKTRIG_TYPE stage ) g_Log.EventError("Act empty in skill Enticement, trigger @Start.\n"); return -SKTRIG_ABORT; } - + int iBaseDiff = (int)pChar->GetKeyNum("BARDING.DIFF"); if (iBaseDiff != 0) iBaseDiff = iBaseDiff / 18; else iBaseDiff = 40; // No TAG.BARDING.DIFF? Use default + // TODO: + // Slayer instruments will increase your success chance by 20% when used on the creatures it is meant for; + // Slayer instruments will decrease your success chance by 20% when used on the creatures from its opposing group + int iDifficulty = Use_PlayMusic(pInstrument, g_Rand.GetVal(iBaseDiff)); // How difficult? 1-100 (use RandBell). If no instrument, it immediately fails if (iDifficulty < -1) // no instrument: immediate fail return -SKTRIG_ABORT; @@ -2009,6 +2025,10 @@ int CChar::Skill_Provocation(SKTRIG_TYPE stage) else iBaseDiff = 40; // No TAG.BARDING.DIFF? Use default + // TODO: + // Slayer instruments will increase your success chance by 20% when used on the creatures it is meant for; + // Slayer instruments will decrease your success chance by 20% when used on the creatures from its opposing group + int iDifficulty = Use_PlayMusic(pInstrument, g_Rand.GetVal(iBaseDiff)); // How difficult? 1-100 (use RandBell). If no instrument, it immediately fails if (iDifficulty < -1) // no instrument: immediate fail return -SKTRIG_ABORT; @@ -2068,7 +2088,7 @@ int CChar::Skill_Provocation(SKTRIG_TYPE stage) SysMessageDefault(DEFMSG_PROVOCATION_KIND); return -SKTRIG_ABORT; } - + // If the provoked NPC/PC is good, we are flagged criminal for it and guards are called. if ( pCharProv->Noto_GetFlag(this) == NOTO_GOOD ) @@ -2224,7 +2244,7 @@ int CChar::Skill_Taming( SKTRIG_TYPE stage ) SysMessageDefault( DEFMSG_TAMING_REACH ); return -SKTRIG_QTY; } - + if ( !CanSeeLOS( pChar ) ) { SysMessageDefault( DEFMSG_TAMING_LOS ); @@ -2248,7 +2268,7 @@ int CChar::Skill_Taming( SKTRIG_TYPE stage ) Its Animal Lore is above 0 (no reason why, this is probably an old check) It's ID is either one of the playable characters (Human, Elf or Gargoyle). */ - if ( !iTameBase || pChar->Skill_GetBase(SKILL_ANIMALLORE) || + if ( !iTameBase || pChar->Skill_GetBase(SKILL_ANIMALLORE) || pChar->IsPlayableCharacter()) { SysMessagef( g_Cfg.GetDefaultMsg( DEFMSG_TAMING_TAMED ), pChar->GetName()); @@ -2264,7 +2284,7 @@ int CChar::Skill_Taming( SKTRIG_TYPE stage ) return -SKTRIG_QTY; } } - + } if ( stage == SKTRIG_START ) @@ -2681,7 +2701,7 @@ int CChar::Skill_Healing( SKTRIG_TYPE stage ) SysMessageDefault( DEFMSG_HEALING_REACH ); return -SKTRIG_QTY; } - + CChar * pChar = dynamic_cast(pObj); if (pChar && pChar->Can(CAN_C_NONSELECTABLE)) { @@ -2789,7 +2809,7 @@ int CChar::Skill_Healing( SKTRIG_TYPE stage ) if (pChar != this) pChar->SysMessagef(g_Cfg.GetDefaultMsg(DEFMSG_HEALING_CURE_2), GetName()); } - else + else { if (pChar != this) SysMessage(g_Cfg.GetDefaultMsg(DEFMSG_HEALING_CURE_3)); @@ -2983,7 +3003,7 @@ int CChar::Skill_Fighting( SKTRIG_TYPE stage ) resetting both the RecoilDelay and the SwingAnimationDelay will also cause the ID of the summoned creatured to be resetted. This only happens when the creature to be summoned is chosen on the default "summon menu". */ - if ( !m_atMagery.m_uiSummonID ) + if ( !m_atMagery.m_uiSummonID ) { m_atFight.m_iRecoilDelay = 0; m_atFight.m_iSwingAnimationDelay = 0; @@ -3240,7 +3260,7 @@ int CChar::Skill_Act_Breath( SKTRIG_TYPE stage ) id = ITEMID_FX_FIRE_BALL; if ( !effect ) effect = EFFECT_BOLT; - + if (!iDmgType) iDmgType = DAMAGE_FIRE; @@ -3269,7 +3289,7 @@ int CChar::Skill_Act_Throwing( SKTRIG_TYPE stage ) // m_Fight_Targ_UID = my target. if ( stage == SKTRIG_ABORT ) - return -SKTRIG_ABORT; + return -SKTRIG_ABORT; if ( stage == SKTRIG_STROKE ) return 0; @@ -3310,7 +3330,7 @@ int CChar::Skill_Act_Throwing( SKTRIG_TYPE stage ) int iDmgPhysical = 0, iDmgFire = 0, iDmgCold = 0, iDmgPoison = 0, iDmgEnergy = 0; CVarDefCont * pDam = GetDefKey("THROWDAM",true); - + if ( pDam ) { int64 DVal[2]; @@ -3342,7 +3362,7 @@ int CChar::Skill_Act_Throwing( SKTRIG_TYPE stage ) iDmgPhysical = 100; iDmgType |= DAMAGE_THROWN; } - + CVarDefCont * pRock = GetDefKey("THROWOBJ",true); if ( pRock ) { @@ -3697,7 +3717,7 @@ void CChar::Skill_Fail( bool fCancel ) // else We still get some credit for having tried. SKILL_TYPE skill = Skill_GetActive(); - + if ( skill == SKILL_NONE ) return; @@ -4222,7 +4242,7 @@ int CChar::Skill_Stealing(SKTRIG_TYPE stage) pPack->ContentAdd(pItem); } } - + if ((stage == SKTRIG_SUCCESS) && (g_Cfg.m_iRevealFlags & REVEALF_STEALING_SUCCESS)) Reveal(); else if ((stage == SKTRIG_FAIL) && (g_Cfg.m_iRevealFlags & REVEALF_STEALING_FAIL)) @@ -4254,7 +4274,7 @@ int CChar::Skill_Focus(STAT_TYPE stat) ushort iFocusValue = Skill_GetAdjusted(SKILL_FOCUS); //By giving the character skill focus value as difficulty, the chance to succeed is always around 50% - if (Skill_UseQuick(SKILL_FOCUS, iFocusValue/10)) + if (Skill_UseQuick(SKILL_FOCUS, iFocusValue/10)) { ushort uiGain = 0; switch (stat) @@ -4271,7 +4291,7 @@ int CChar::Skill_Focus(STAT_TYPE stat) return uiGain; } return -SKTRIG_QTY; - + } bool CChar::Skill_Start( SKILL_TYPE skill, int iDifficultyIncrease ) { @@ -4317,12 +4337,12 @@ bool CChar::Skill_Start( SKILL_TYPE skill, int iDifficultyIncrease ) { anim = Skill_GetAnim(skill); } - + CScriptTriggerArgs pArgs; pArgs.m_iN1 = skill; pArgs.m_VarsLocal.SetNumNew("Sound", sound); pArgs.m_VarsLocal.SetNumNew("Anim", anim); - + // Some skill can start right away. Need no targetting. // 0-100 scale of Difficulty if ( IsTrigUsed(TRIGGER_SKILLPRESTART) ) @@ -4350,7 +4370,7 @@ bool CChar::Skill_Start( SKILL_TYPE skill, int iDifficultyIncrease ) const CSkillDef* pSkillDef = g_Cfg.GetSkillDef(skill); int iWaitTime = 1; - + m_Act_Effect = -1; const bool fCraftSkill = g_Cfg.IsSkillFlag(skill, SKF_CRAFT); @@ -4359,7 +4379,7 @@ bool CChar::Skill_Start( SKILL_TYPE skill, int iDifficultyIncrease ) if ( IsSkillBase(skill) && pSkillDef ) { iWaitTime = pSkillDef->m_vcDelay.GetLinear(Skill_GetBase(skill)); - + if (!pSkillDef->m_vcEffect.m_aiValues.empty()) { if (!fCraftSkill) @@ -4447,7 +4467,7 @@ bool CChar::Skill_Start( SKILL_TYPE skill, int iDifficultyIncrease ) UpdateAnimate(anim); } - + //When combat starts, the first @HitTry trigger will be called after the @SkillStart/@Start (as it was before). const bool fFightSkill = g_Cfg.IsSkillFlag(skill, SKF_FIGHT); if ( fFightSkill ) diff --git a/src/game/chars/CCharUse.cpp b/src/game/chars/CCharUse.cpp index 8bee39424..b4e9ab655 100644 --- a/src/game/chars/CCharUse.cpp +++ b/src/game/chars/CCharUse.cpp @@ -1187,15 +1187,16 @@ bool CChar::FollowersUpdate( CChar * pChar, short iFollowerSlots, bool fCheckOnl if (Args.m_iN1 == 1) { - iFollowerSlots = -(short)(Args.m_iN2); + iFollowerSlots = - n64_narrow_n16(Args.m_iN2); } else { - iFollowerSlots = (short)(Args.m_iN2); + iFollowerSlots = n64_narrow_n16(Args.m_iN2); } } - short iMaxFollower = (short)(GetDefNum("MAXFOLLOWER", true)); + short iMaxFollower = n64_narrow_n16(GetDefNum("MAXFOLLOWER", true)); + ASSERT(iMaxFollower >= 0); if (IsSetEF(EF_FollowerList)) { if (iFollowerSlots >= 0) @@ -1211,7 +1212,7 @@ bool CChar::FollowersUpdate( CChar * pChar, short iFollowerSlots, bool fCheckOnl ++it; } - if (!fExists && ((short)(m_followers.size()) < iMaxFollower || IsPriv(PRIV_GM))) + if ((!fExists && (i16_from_usize_checked(m_followers.size()) < iMaxFollower)) || IsPriv(PRIV_GM)) { if (!fCheckOnly) m_followers.emplace_back(pChar->GetUID()); diff --git a/src/game/clients/CClientTarg.cpp b/src/game/clients/CClientTarg.cpp index 05c2730d0..cdf940587 100644 --- a/src/game/clients/CClientTarg.cpp +++ b/src/game/clients/CClientTarg.cpp @@ -1071,11 +1071,11 @@ int CClient::OnSkill_ArmsLore( CUID uid, int iSkillLevel, bool fTest ) if ( fWeapon && pItem->m_itWeapon.m_poison_skill ) { uint iLevel = (uint)IMulDiv( - n_promote32(pItem->m_itWeapon.m_poison_skill), - usize_narrow32(ARRAY_COUNT(sm_szPoisonMessages)), + n_promote_n32(pItem->m_itWeapon.m_poison_skill), + usize_narrow_u32(ARRAY_COUNT(sm_szPoisonMessages)), 100); if ( iLevel >= ARRAY_COUNT(sm_szPoisonMessages)) - iLevel = usize_narrow32(ARRAY_COUNT(sm_szPoisonMessages)) - 1; + iLevel = usize_narrow_u32(ARRAY_COUNT(sm_szPoisonMessages)) - 1; len += snprintf( pszTemp+len, Str_TempLength() - len, " %s", sm_szPoisonMessages[iLevel] ); } @@ -1291,7 +1291,7 @@ int CClient::OnSkill_TasteID( CUID uid, int iSkillLevel, bool fTest ) { uint iLevel = (uint)IMulDiv( iPoisonLevel, ARRAY_COUNT(sm_szPoisonMessages), 1000 ); if ( iLevel >= ARRAY_COUNT(sm_szPoisonMessages)) - iLevel = usize_narrow32(ARRAY_COUNT(sm_szPoisonMessages) - 1); + iLevel = usize_narrow_u32(ARRAY_COUNT(sm_szPoisonMessages) - 1); SysMessage(sm_szPoisonMessages[iLevel] ); } else diff --git a/src/game/components/CCFaction.cpp b/src/game/components/CCFaction.cpp deleted file mode 100644 index 3775d477f..000000000 --- a/src/game/components/CCFaction.cpp +++ /dev/null @@ -1,278 +0,0 @@ -/** -* @file CCFaction.cpp -* -*/ - -#include "CCFaction.h" -#include "../items/CItem.h" - - -CFactionDef::CFactionDef() noexcept : - _uiFactionData(0) -{ -} - -bool CFactionDef::IsNone() const noexcept -{ - return (!_uiFactionData || (GetGroup() == Group::NONE) || (GetSpecies() == Species::NONE)); -} - -CFactionDef::Group CFactionDef::GetGroup() const noexcept -{ - const auto masked_shifted = (_uiFactionData & _kuiGroupMask) >> _kuiGroupReservedBytes; - return num_alias_cast(masked_shifted); -} - -bool CFactionDef::SetGroup(CFactionDef::Group group) noexcept -{ - const auto group_numeric = num_alias_cast(group); - if (group_numeric > _kuiGroupMaxVal) - return false; - - const auto masked_shifted = (group_numeric & _kuiGroupMaxVal) << _kuiGroupReservedBytes; - _uiFactionData = (_uiFactionData & ~_kuiSpeciesMask) | num_alias_cast(masked_shifted); - return true; -} - -CFactionDef::Species CFactionDef::GetSpecies() const noexcept -{ - return num_alias_cast(_uiFactionData & _kuiSpeciesMask); -} - -bool CFactionDef::SetSpecies(CFactionDef::Species species) noexcept -{ - const auto species_numeric = num_alias_cast(species); - if (species_numeric > _kuiSpeciesMaxVal) - return false; - - const auto masked = species_numeric & _kuiSpeciesMask; - _uiFactionData = (_uiFactionData & ~_kuiSpeciesMask) | masked; - return true; -} - -//--- - -bool CCFaction::IsOppositeGroup(const CCFaction *target) const -{ - ADDTOCALLSTACK("CCFaction::IsOppositeGroup"); - const auto myGroup = GetGroup(); - const auto targGroup = target->GetGroup(); - - if ((myGroup == Group::ELEMENTAL) && (targGroup == Group::ABYSS)) - return true; - else if ((myGroup == Group::ABYSS) && ((targGroup == Group::FEY) || (targGroup == Group::ELEMENTAL))) - return true; - else if ((myGroup == Group::FEY) && (targGroup == Group::ABYSS)) - return true; - else if ((myGroup == Group::REPTILIAN) && (targGroup == Group::ARACHNID)) - return true; - else if ((myGroup == Group::ARACHNID) && (targGroup == Group::REPTILIAN)) - return true; - else if ((myGroup == Group::HUMANOID) && (targGroup == Group::UNDEAD)) - return true; - else if ((myGroup == Group::UNDEAD) && (targGroup == Group::HUMANOID)) - return true; - return false; -} - -bool CCFaction::IsOppositeSuperSlayer(const CCFaction *target) const -{ - ADDTOCALLSTACK("CCFaction::IsOppositeSuperSlayer"); - const auto myGroup = GetGroup(); - const auto targGroup = target->GetGroup(); - const auto targSpecies = target->GetSpecies(); - if ((myGroup == Group::FEY) && (targGroup == Group::FEY) && (targSpecies == Species::FEY_SSLAYER)) - return true; - else if ((myGroup == Group::ELEMENTAL) && (targGroup == Group::ELEMENTAL) && (targSpecies == Species::ELEMENTAL_SSLAYER)) - return true; - else if ((myGroup == Group::ABYSS) && (targGroup == Group::ELEMENTAL) && (targSpecies == Species::DEMON_SSLAYER)) - return true; - else if ((myGroup == Group::HUMANOID) && (targGroup == Group::HUMANOID) && (targSpecies == Species::REPOND_SSLAYER)) - return true; - else if ((myGroup == Group::UNDEAD) && (targGroup == Group::UNDEAD) && (targSpecies == Species::UNDEAD_SSLAYER)) - return true; - else if ((myGroup == Group::ARACHNID) && (targGroup == Group::ARACHNID) && (targSpecies == Species::ARACHNID_SSLAYER)) - return true; - else if ((myGroup == Group::REPTILIAN) && (targGroup == Group::REPTILIAN) && (targSpecies == Species::REPTILE_SSLAYER)) - return true; - return false; -} - -bool CCFaction::IsOppositeLesserSlayer(const CCFaction *target) const -{ - ADDTOCALLSTACK("CCFaction::IsOppositeLesserSlayer"); - - // Do i belong to the same group? - if (!( - num_alias_cast(GetGroup()) & - num_alias_cast(target->GetGroup())) - ) - return false; - - // Same species? - return (GetSpecies() == target->GetSpecies()); -} - -enum CHF_TYPE : int -{ - CHF_FACTION_GROUP, - CHF_FACTION_SPECIES, - CHF_SLAYER_GROUP, - CHF_SLAYER_SPECIES, - CHF_QTY -}; - -lpctstr const CCFaction::sm_szLoadKeys[CHF_QTY + 1] = -{ - "FACTION_GROUP", - "FACTION_SPECIES", - "SLAYER_GROUP", - "SLAYER_SPECIES", - nullptr -}; - -CCFaction::CCFaction() noexcept : - CFactionDef(), CComponent(COMP_FACTION) -{ -} - -CCFaction::CCFaction(CCFaction *copy) noexcept : - CFactionDef(), CComponent(COMP_FACTION) -{ - Copy(copy); -} - - -bool CCFaction::CanSubscribe(const CItem* pItem) noexcept // static -{ - return pItem->IsTypeEquippable(); -} - -void CCFaction::Delete(bool fForced) -{ - UnreferencedParameter(fForced); -} - -bool CCFaction::r_LoadVal(CScript & s) -{ - ADDTOCALLSTACK("CCFaction::r_LoadVal"); - CHF_TYPE iKeyNum = (CHF_TYPE)FindTableSorted(s.GetKey(), sm_szLoadKeys, ARRAY_COUNT(sm_szLoadKeys) - 1); - switch (iKeyNum) - { - case CHF_FACTION_GROUP: - case CHF_SLAYER_GROUP: - { - SetGroup(num_alias_cast(s.GetArgU32Val())); - return true; - } - - case CHF_FACTION_SPECIES: - case CHF_SLAYER_SPECIES: - { - SetSpecies(num_alias_cast(s.GetArgU32Val())); - return true; - } - } - return false; -} - -bool CCFaction::r_Load(CScript & s) -{ - ADDTOCALLSTACK("CCFaction::r_Load"); - UnreferencedParameter(s); - return true; -} - -CCRET_TYPE CCFaction::OnTickComponent() -{ - return CCRET_CONTINUE; -} - -bool CCFaction::r_WriteVal(lpctstr ptcKey, CSString & s, CTextConsole * pSrc) -{ - ADDTOCALLSTACK("CCFaction::CCFaction"); - CHF_TYPE iKeyNum = (CHF_TYPE)FindTableSorted(ptcKey, sm_szLoadKeys, ARRAY_COUNT(sm_szLoadKeys) - 1); - UnreferencedParameter(pSrc); - switch (iKeyNum) - { - case CHF_FACTION_GROUP: - case CHF_SLAYER_GROUP: - { - s.FormatHex(num_alias_cast(GetGroup())); - return true; - } - case CHF_FACTION_SPECIES: - case CHF_SLAYER_SPECIES: - { - s.FormatHex(num_alias_cast(GetSpecies())); - return true; - } - default: - break; - } - return false; -} - -void CCFaction::r_Write(CScript & s) -{ - ADDTOCALLSTACK("CCFaction::r_Write"); - if (_uiFactionData != 0) - { - s.WriteKeyHex("FACTION_GROUP", num_alias_cast(GetGroup())); - s.WriteKeyHex("FACTION_SPECIES", num_alias_cast(GetSpecies())); - } -} - -bool CCFaction::r_GetRef(lpctstr & ptcKey, CScriptObj *& pRef) -{ - UnreferencedParameter(ptcKey); - UnreferencedParameter(pRef); - return false; -} - -bool CCFaction::r_Verb(CScript & s, CTextConsole * pSrc) -{ - UnreferencedParameter(s); - UnreferencedParameter(pSrc); - return false; -} - -void CCFaction::Copy(const CComponent * target) -{ - ADDTOCALLSTACK("CCFaction::Copy"); - const CCFaction *pTarget = dynamic_cast(target); - ASSERT(pTarget); - _uiFactionData = pTarget->_uiFactionData; -} - -bool CCFaction::IsSuperSlayer() const -{ - ADDTOCALLSTACK_DEBUG("CCFaction::IsSuperSlayer"); - return (GetGroup() != Group::NONE && (_kuiSuperSlayerSpeciesIndex == num_alias_cast(GetSpecies()))); -} - -bool CCFaction::IsLesserSlayer() const -{ - ADDTOCALLSTACK_DEBUG("CCFaction::IsLesserSlayer"); - return ((GetGroup() != Group::NONE) && (GetSpecies() != Species::NONE) && !IsSuperSlayer()); -} - -int CCFaction::GetSlayerDamageBonus(const CCFaction *target) const -{ - ADDTOCALLSTACK_DEBUG("CCFaction::GetSlayerDamageBonus"); - if (IsOppositeLesserSlayer(target)) - return DAMAGE_SLAYER_LESSER; - else if (IsOppositeSuperSlayer(target)) - return DAMAGE_SLAYER_SUPER; - return 1; -} - -int CCFaction::GetSlayerDamagePenalty(const CCFaction * target) const -{ - ADDTOCALLSTACK_DEBUG("CCFaction::GetSlayerDamagePenalty"); - if (IsOppositeGroup(target)) - return DAMAGE_SLAYER_OPPOSITE; - return 1; -} - - diff --git a/src/game/components/CCPropsChar.cpp b/src/game/components/CCPropsChar.cpp index aadc5429b..92433ba4a 100644 --- a/src/game/components/CCPropsChar.cpp +++ b/src/game/components/CCPropsChar.cpp @@ -90,6 +90,18 @@ bool CCPropsChar::GetPropertyNumPtr(PropertyIndex_t iPropIndex, PropertyValNum_t { ADDTOCALLSTACK("CCPropsChar::GetPropertyNumPtr"); ASSERT(!IsPropertyStr(iPropIndex)); + + if (iPropIndex == PROPCH_FACTION_GROUP) + { + *piOutVal = num_alias_cast(_faction.GetGroup()); + return true; + } + else if (iPropIndex == PROPCH_FACTION_SPECIES) + { + *piOutVal = num_alias_cast(_faction.GetSpecies()); + return true; + } + return BaseCont_GetPropertyNum(&_mPropsNum, iPropIndex, piOutVal); } @@ -111,7 +123,18 @@ void CCPropsChar::SetPropertyNum(PropertyIndex_t iPropIndex, PropertyValNum_t iV if (0 == _mPropsNum.erase(iPropIndex)) return; // I didn't have this property, so avoid further processing. } - else + + else if (iPropIndex == PROPCH_FACTION_GROUP) + { + _faction.SetGroup(num_alias_cast(iVal)); + return; + } + else if (iPropIndex == PROPCH_FACTION_SPECIES) + { + _faction.SetSpecies(num_alias_cast(iVal)); + return; + } + { _mPropsNum[iPropIndex] = iVal; //_mPropsNum.container.shrink_to_fit(); diff --git a/src/game/components/CCPropsChar.h b/src/game/components/CCPropsChar.h index 22fd59ffb..78402b63f 100644 --- a/src/game/components/CCPropsChar.h +++ b/src/game/components/CCPropsChar.h @@ -6,6 +6,7 @@ #ifndef _INC_CCPROPSCHAR_H #define _INC_CCPROPSCHAR_H +#include "subcomponents/CFactionDef.h" #include "../CComponentProps.h" @@ -54,10 +55,23 @@ class CCPropsChar : public CComponentProps virtual void AddPropsTooltipData(CObjBase* pLinkedObj) override; + inline const CFactionDef* GetFaction() const noexcept; + inline CFactionDef* GetFaction() noexcept; + private: BaseContNum_t _mPropsNum; BaseContStr_t _mPropsStr; + + CFactionDef _faction; }; +const CFactionDef* CCPropsChar::GetFaction() const noexcept { + return &_faction; +} +CFactionDef* CCPropsChar::GetFaction() noexcept { + return &_faction; +} + + #endif //_INC_CCPROPSCHAR_H diff --git a/src/game/components/CCPropsItemEquippable.cpp b/src/game/components/CCPropsItemEquippable.cpp index 717832916..028047af3 100644 --- a/src/game/components/CCPropsItemEquippable.cpp +++ b/src/game/components/CCPropsItemEquippable.cpp @@ -95,6 +95,18 @@ bool CCPropsItemEquippable::GetPropertyNumPtr(PropertyIndex_t iPropIndex, Proper { ADDTOCALLSTACK("CCPropsItemChar::GetPropertyNumPtr"); ASSERT(!IsPropertyStr(iPropIndex)); + + if (iPropIndex == PROPIEQUIP_SLAYER_GROUP) + { + *piOutVal = num_alias_cast(_faction.GetGroup()); + return true; + } + else if (iPropIndex == PROPIEQUIP_SLAYER_SPECIES) + { + *piOutVal = num_alias_cast(_faction.GetSpecies()); + return true; + } + return BaseCont_GetPropertyNum(&_mPropsNum, iPropIndex, piOutVal); } @@ -116,6 +128,18 @@ void CCPropsItemEquippable::SetPropertyNum(PropertyIndex_t iPropIndex, PropertyV if (0 == _mPropsNum.erase(iPropIndex)) return; // I didn't have this property, so avoid further processing. } + + else if (iPropIndex == PROPIEQUIP_SLAYER_GROUP) + { + _faction.SetGroup(num_alias_cast(iVal)); + return; + } + else if (iPropIndex == PROPIEQUIP_SLAYER_SPECIES) + { + _faction.SetSpecies(num_alias_cast(iVal)); + return; + } + else { _mPropsNum[iPropIndex] = iVal; diff --git a/src/game/components/CCPropsItemEquippable.h b/src/game/components/CCPropsItemEquippable.h index b12c61c56..2406d1a62 100644 --- a/src/game/components/CCPropsItemEquippable.h +++ b/src/game/components/CCPropsItemEquippable.h @@ -6,6 +6,7 @@ #ifndef _INC_CCPROPSITEMEQUIPPABLE_H #define _INC_CCPROPSITEMEQUIPPABLE_H +#include "subcomponents/CFactionDef.h" #include "../CComponentProps.h" class CItemBase; @@ -60,10 +61,22 @@ class CCPropsItemEquippable : public CComponentProps virtual void AddPropsTooltipData(CObjBase* pLinkedObj) override; + inline const CFactionDef* GetFaction() const noexcept; + inline CFactionDef* GetFaction() noexcept; + private: BaseContNum_t _mPropsNum; BaseContStr_t _mPropsStr; + + CFactionDef _faction; }; +const CFactionDef* CCPropsItemEquippable::GetFaction() const noexcept { + return &_faction; +} +CFactionDef* CCPropsItemEquippable::GetFaction() noexcept { + return &_faction; +} + #endif //_INC_CCPROPSITEMEQUIPPABLE_H diff --git a/src/game/components/subcomponents/CFactionDef.cpp b/src/game/components/subcomponents/CFactionDef.cpp new file mode 100644 index 000000000..fc3de8b69 --- /dev/null +++ b/src/game/components/subcomponents/CFactionDef.cpp @@ -0,0 +1,146 @@ +/** +* @file CFactionDef.cpp +* +*/ + +#include "CFactionDef.h" +#include "../../items/CItem.h" + + +CFactionDef::CFactionDef() noexcept : + _uiFactionData(0) +{ +} + +bool CFactionDef::IsNone() const noexcept +{ + return (!_uiFactionData || (GetGroup() == Group::NONE) || (GetSpecies() == Species::NONE)); +} + +CFactionDef::Group CFactionDef::GetGroup() const noexcept +{ + const auto masked_shifted = (_uiFactionData & _kuiGroupMask) >> _kuiGroupReservedBytes; + return num_alias_cast(masked_shifted); +} + +bool CFactionDef::SetGroup(CFactionDef::Group group) noexcept +{ + const auto group_numeric = num_alias_cast(group); + if (group_numeric > _kuiGroupMaxVal) + return false; + + const auto masked_shifted = (group_numeric & _kuiGroupMaxVal) << _kuiGroupReservedBytes; + _uiFactionData = (_uiFactionData & ~_kuiGroupMask) | num_alias_cast(masked_shifted); + return true; +} + +CFactionDef::Species CFactionDef::GetSpecies() const noexcept +{ + return num_alias_cast(_uiFactionData & _kuiSpeciesMask); +} + +bool CFactionDef::SetSpecies(CFactionDef::Species species) noexcept +{ + const auto species_numeric = num_alias_cast(species); + if (species_numeric > _kuiSpeciesMaxVal) + return false; + + const auto masked = species_numeric & _kuiSpeciesMask; + _uiFactionData = (_uiFactionData & ~_kuiSpeciesMask) | masked; + return true; +} + +//--- + +bool CFactionDef::IsOppositeGroup(const CFactionDef *target) const noexcept +{ + ADDTOCALLSTACK("CFactionDef::IsOppositeGroup"); + const auto myGroup = GetGroup(); + const auto targGroup = target->GetGroup(); + + if ((myGroup == Group::ELEMENTAL) && (targGroup == Group::ABYSS)) + return true; + else if ((myGroup == Group::ABYSS) && ((targGroup == Group::FEY) || (targGroup == Group::ELEMENTAL))) + return true; + else if ((myGroup == Group::FEY) && (targGroup == Group::ABYSS)) + return true; + else if ((myGroup == Group::REPTILIAN) && (targGroup == Group::ARACHNID)) + return true; + else if ((myGroup == Group::ARACHNID) && (targGroup == Group::REPTILIAN)) + return true; + else if ((myGroup == Group::HUMANOID) && (targGroup == Group::UNDEAD)) + return true; + else if ((myGroup == Group::UNDEAD) && (targGroup == Group::HUMANOID)) + return true; + return false; +} + +bool CFactionDef::IsSuperSlayerVersus(const CFactionDef *target) const noexcept +{ + ADDTOCALLSTACK("CFactionDef::IsSuperSlayerVersus"); + const auto myGroup = GetGroup(); + const auto targGroup = target->GetGroup(); + const auto targSpecies = target->GetSpecies(); + if ((myGroup == Group::FEY) && (targGroup == Group::FEY) && (targSpecies == Species::FEY_SSLAYER)) + return true; + else if ((myGroup == Group::ELEMENTAL) && (targGroup == Group::ELEMENTAL) && (targSpecies == Species::ELEMENTAL_SSLAYER)) + return true; + else if ((myGroup == Group::ABYSS) && (targGroup == Group::ELEMENTAL) && (targSpecies == Species::DEMON_SSLAYER)) + return true; + else if ((myGroup == Group::HUMANOID) && (targGroup == Group::HUMANOID) && (targSpecies == Species::REPOND_SSLAYER)) + return true; + else if ((myGroup == Group::UNDEAD) && (targGroup == Group::UNDEAD) && (targSpecies == Species::UNDEAD_SSLAYER)) + return true; + else if ((myGroup == Group::ARACHNID) && (targGroup == Group::ARACHNID) && (targSpecies == Species::ARACHNID_SSLAYER)) + return true; + else if ((myGroup == Group::REPTILIAN) && (targGroup == Group::REPTILIAN) && (targSpecies == Species::REPTILE_SSLAYER)) + return true; + return false; +} + +bool CFactionDef::IsLesserSlayerVersus(const CFactionDef *target) const noexcept +{ + ADDTOCALLSTACK("CFactionDef::IsLesserSlayerVersus"); + + // Do i belong to the same group? + if (!( + num_alias_cast(GetGroup()) & + num_alias_cast(target->GetGroup())) + ) + return false; + + // Same species? + return (GetSpecies() == target->GetSpecies()); +} + +bool CFactionDef::HasSuperSlayer() const noexcept +{ + ADDTOCALLSTACK_DEBUG("CFactionDef::HasSuperSlayer"); + return (GetGroup() != Group::NONE && (_kuiSuperSlayerSpeciesIndex == num_alias_cast(GetSpecies()))); +} + +bool CFactionDef::HasLesserSlayer() const noexcept +{ + ADDTOCALLSTACK_DEBUG("CFactionDef::HasLesserSlayer"); + return ((GetGroup() != Group::NONE) && (GetSpecies() != Species::NONE) && !HasSuperSlayer()); +} + +int CFactionDef::GetSlayerDamageBonusPercent(const CFactionDef *target) const noexcept +{ + ADDTOCALLSTACK_DEBUG("CFactionDef::GetSlayerDamageBonus"); + if (IsLesserSlayerVersus(target)) + return DAMAGE_SLAYER_LESSER; + else if (IsSuperSlayerVersus(target)) + return DAMAGE_SLAYER_SUPER; + return 100; +} + +int CFactionDef::GetSlayerDamagePenaltyPercent(const CFactionDef * target) const noexcept +{ + ADDTOCALLSTACK_DEBUG("CFactionDef::GetSlayerDamagePenalty"); + if (HasSuperSlayer() && IsOppositeGroup(target)) + return DAMAGE_SLAYER_OPPOSITE; + return 100; +} + + diff --git a/src/game/components/CCFaction.h b/src/game/components/subcomponents/CFactionDef.h similarity index 77% rename from src/game/components/CCFaction.h rename to src/game/components/subcomponents/CFactionDef.h index 794d18931..adbb53ed2 100644 --- a/src/game/components/CCFaction.h +++ b/src/game/components/subcomponents/CFactionDef.h @@ -1,17 +1,17 @@ /** -* @file CCFaction.h +* @file CFactionDef.h * */ -#ifndef _INC_CCFACTION_H -#define _INC_CCFACTION_H +#ifndef _INC_CFACTIONDEF_H +#define _INC_CFACTIONDEF_H -#include "../CComponent.h" +#include "../../../common/common.h" class CChar; class CItem; - +class CItemBase; /* The Original Slayers fall into 6 groups. Abyss, Arachnid, Elemental, Humanoid, Reptilian and Undead. @@ -21,7 +21,12 @@ class CItem; – Mondain’s Legacy Slayers, usually found on Talismans, do not have an opposing group. A successful use of a Slayer Weapon, Spellbook or Instrument will yield a little white flash on the monster. Super Slayer Weapons will do double damage to the monsters they are meant for. - “Single Slayers” or Slayers that fall into a Super Slayer subcategory will do triple damage + “Single Slayers” or Slayers that fall into a Super Slayer subcategory will do triple damage. + + The following Super Slayers primarily are found on Talisman: Bat, Bear, Beetle, Bird, Bovine, Flame, Ice, Mage, Vermin, & Wolf. + The following Super Slayers primarily are found on musical instruments, weapons, and spellbooks: + Abyss, Arachnid, Elemental, Fey, Repond, Reptile, and Undead Slayer. + Slayer Weapons can both be found as monster loot and be crafted by using a runic crafting tool. Slayer Spellbooks will cause single target, direct damage spells to do double damage to the monsters they are meant for. Player written Slayer Spellbooks can only be crafted by scribes with high magery skill using a scribe pen. @@ -31,15 +36,20 @@ class CItem; Slayer Talismans are found on Mondain’s Legacy monsters or as Quest Rewards. */ -#define DAMAGE_SLAYER_LESSER 3 // Lesser Slayer does x3 damage. -#define DAMAGE_SLAYER_SUPER 2 // Super Slayer does x2 damage. -#define DAMAGE_SLAYER_OPPOSITE 2 // Opposite Slayer does x2 damage. + +/* +TODO: enable customization of slayer bonus damage? +Until the Stygian Abyss expansion, all Slayers did double damage to applicable monsters. However, following that expansion, Lesser Slayers do triple damage, and Super Slayers still do double damage. +*/ +#define DAMAGE_SLAYER_LESSER 300 // Lesser Slayer does x3 (300%) damage. +#define DAMAGE_SLAYER_SUPER 200 // Super Slayer does x2 (200%) damage. +#define DAMAGE_SLAYER_OPPOSITE 200 // Opposite Slayer does x2 (200%) damage. /* This class is used to store FACTION for NPCs and SLAYER for items Initially involved in the Slayer system it handles Super Slayer, - Lesser Slayer and Opposites to increase damage dealt/received + Lesser Slayer and Opposites to increase damage dealt/received. */ class CFactionDef { @@ -151,65 +161,46 @@ class CFactionDef bool SetGroup (Group faction) noexcept; Species GetSpecies() const noexcept; bool SetSpecies(Species species) noexcept; -}; - - -class CCFaction : public CFactionDef, public CComponent -{ - static lpctstr const sm_szLoadKeys[]; - -public: - CCFaction() noexcept; - CCFaction(CCFaction *copy) noexcept; - virtual ~CCFaction() override = default; - - static bool CanSubscribe(const CItem* pItem) noexcept; - virtual void Delete(bool fForced = false) override; - virtual bool r_LoadVal(CScript & s) override; - virtual bool r_WriteVal(lpctstr ptcKey, CSString & s, CTextConsole * pSrc = nullptr) override; - virtual void r_Write(CScript & s) override; - virtual bool r_GetRef(lpctstr & ptcKey, CScriptObj * & pRef) override; - virtual bool r_Verb(CScript & s, CTextConsole * pSrc) override; - virtual void Copy(const CComponent *target) override; - bool r_Load(CScript & s); // Load a character from Script - virtual CCRET_TYPE OnTickComponent() override; - /* + /* Checks my group and the target's one and return true if we are enemies. */ - bool IsOppositeGroup(const CCFaction *target) const; + bool IsOppositeGroup(const CFactionDef *target) const noexcept; /* Returns true if I'm a Super Slayer and the target has also the same type */ - bool IsOppositeSuperSlayer(const CCFaction *target) const; + bool IsSuperSlayerVersus(const CFactionDef *target) const noexcept; + /* Returns true if I'm a Lesser Slayer and the target has also the same type */ - bool IsOppositeLesserSlayer(const CCFaction *target) const; + bool IsLesserSlayerVersus(const CFactionDef *target) const noexcept; + /* - Returns true if I'm a Super Slayer + Returns true if I have a Super Slayer property */ - bool IsSuperSlayer() const; + bool HasSuperSlayer() const noexcept; /* - Returns true if I'm a Lesser Slayer + Returns true if I have a Lesser Slayer property */ - bool IsLesserSlayer() const; + + bool HasLesserSlayer() const noexcept; /* Returns the Slayers's damage bonus (if any). NOTE: We can't direct check for target's Super Slayer or Lesser Slayer and compare with ours because we may both have more than one Group (even if we shouldn't, Sphere's 'versatility' forces us to do so). */ - int GetSlayerDamageBonus(const CCFaction *target) const; + int GetSlayerDamageBonusPercent(const CFactionDef *target) const noexcept; /* Wielding a slayer type against its opposite will cause the attacker to take more damage returns the penalty damage. */ - int GetSlayerDamagePenalty(const CCFaction *target) const; - + int GetSlayerDamagePenaltyPercent(const CFactionDef *target) const noexcept; }; -#endif // _INC_CCFACTION_H + +#endif // _INC_CFACTIONDEF_H diff --git a/src/game/items/CItem.cpp b/src/game/items/CItem.cpp index 848a49920..aa6d4a165 100644 --- a/src/game/items/CItem.cpp +++ b/src/game/items/CItem.cpp @@ -175,10 +175,6 @@ CItem::CItem( ITEMID_TYPE id, CItemBase * pItemDef ) : { SubscribeComponent(new CCItemDamageable(this)); } - if (CCFaction::CanSubscribe(this)) - { - SubscribeComponent(new CCFaction(pItemDef->GetFaction())); // Adding it only to equippable items - } TrySubscribeComponentProps(); TrySubscribeComponentProps(); @@ -614,7 +610,7 @@ CItem * CItem::ReadTemplate( CResourceLock & s, CObjBase * pCont ) // static continue; if ( pItem->IsItemInContainer()) { - pItem->SetContainedLayer(n16_narrow8(pItem->GetAmount())); // set the Restock amount. + pItem->SetContainedLayer(n16_narrow_n8(pItem->GetAmount())); // set the Restock amount. } } continue; @@ -3913,18 +3909,6 @@ bool CItem::SetType(IT_TYPE type, bool fPreCheck) SubscribeComponent(new CCItemDamageable(this)); } - pComp = GetComponent(COMP_FACTION); - if (!CCFaction::CanSubscribe(this)) - { - if (pComp) - UnsubscribeComponent(pComp); - } - else if (!pComp) - { - CItemBase* pItemDef = Item_GetDef(); - SubscribeComponent(new CCFaction(pItemDef->GetFaction())); - } - return true; } @@ -6023,11 +6007,6 @@ bool CItem::IsResourceMatch( const CResourceID& rid, dword dwArg ) const return false; } -CCFaction * CItem::GetSlayer() const -{ - return static_cast(GetComponent(COMP_FACTION)); -} - void CItem::_GoAwake() { @@ -6362,3 +6341,14 @@ bool CItem::_OnTick() return true; } +const CFactionDef* CItem::GetSlayer() const noexcept +{ + auto pComp = static_cast(GetComponentProps(COMP_PROPS_ITEMEQUIPPABLE)); + return (!pComp ? nullptr : pComp->GetFaction()); +} + +CFactionDef* CItem::GetSlayer() noexcept +{ + auto pComp = static_cast(GetComponentProps(COMP_PROPS_ITEMEQUIPPABLE)); + return (!pComp ? nullptr : pComp->GetFaction()); +} diff --git a/src/game/items/CItem.h b/src/game/items/CItem.h index 518098b7b..14b37f9d0 100644 --- a/src/game/items/CItem.h +++ b/src/game/items/CItem.h @@ -10,7 +10,7 @@ #include "../../common/resource/CResourceHolder.h" #include "../../common/CServerMap.h" #include "../../common/CRect.h" -#include "../components/CCFaction.h" +#include "../components/subcomponents/CFactionDef.h" #include "../CServerTime.h" #include "../CBase.h" #include "../CObjBase.h" @@ -24,6 +24,7 @@ class CWorldTicker; class CCSpawn; +class CFactionDef; /** @@ -600,7 +601,6 @@ class CItem : public CObjBase protected: virtual int FixWeirdness() override; void DeleteCleanup(bool fForce); - public: virtual bool NotifyDelete(); // overridden CItemContainer:: method virtual bool Delete(bool fForce = false) override; @@ -618,7 +618,17 @@ class CItem : public CObjBase //virtual bool CanTick(bool fParentGoingToSleep = false) const override; // Not needed: the right virtual is called by CTimedObj::_CanTick. bool _CanHoldTimer() const; -public: + virtual void DupeCopy( const CObjBase * pItem ) override; + + static CItem * CreateBase( ITEMID_TYPE id, IT_TYPE type = IT_INVALID ); // If type == IT_INVALID, read the type from the def (default behaviour) + static CItem * CreateHeader( tchar * pArg, CObjBase * pCont = nullptr, bool fDupeCheck = false, CChar * pSrc = nullptr ); + static CItem * CreateScript(ITEMID_TYPE id, CChar * pSrc = nullptr, IT_TYPE type = IT_INVALID); // If type == IT_INVALID, read the type from the def (default behaviour) + CItem * GenerateScript(CChar * pSrc = nullptr); + static CItem * CreateDupeItem( const CItem * pItem, CChar * pSrc = nullptr, bool fSetNew = false ); + static CItem * CreateTemplate( ITEMID_TYPE id, CObjBase* pCont = nullptr, CChar * pSrc = nullptr ); + + static CItem * ReadTemplate( CResourceLock & s, CObjBase * pCont ); + CUID GetComponentOfMulti() const; CUID GetLockDownOfMulti() const; void SetComponentOfMulti(const CUID& uidMulti); @@ -631,7 +641,7 @@ class CItem : public CObjBase ITEMID_TYPE GetID() const; inline virtual word GetBaseID() const override { - return (word)GetID(); + return enum32_narrow_n16_checked(GetID()); } inline ITEMID_TYPE GetDispID() const noexcept { // This is what the item looks like. @@ -649,7 +659,6 @@ class CItem : public CObjBase virtual int IsWeird() const override; char GetFixZ(CPointMap pt, uint64 uiBlockFlags = 0); - CCFaction* GetSlayer() const; byte GetSpeed() const; /** @@ -855,6 +864,9 @@ protected: virtual void _SetTimeout(int64 iMsecs) override final; void ConvertBolttoCloth(); + const CFactionDef* GetSlayer() const noexcept; + CFactionDef* GetSlayer() noexcept; + // Spells SKILL_TYPE GetSpellBookSkill(); SPELL_TYPE GetScrollSpell() const; @@ -908,18 +920,7 @@ protected: virtual void _SetTimeout(int64 iMsecs) override final; bool Plant_Use( CChar * pChar ); bool Plant_SetID(ITEMID_TYPE id); - virtual void DupeCopy( const CObjBase * pItem ) override; CItem * UnStackSplit( word amount, CChar * pCharSrc = nullptr ); - - static CItem * CreateBase( ITEMID_TYPE id, IT_TYPE type = IT_INVALID ); // If type == IT_INVALID, read the type from the def (default behaviour) - static CItem * CreateHeader( tchar * pArg, CObjBase * pCont = nullptr, bool fDupeCheck = false, CChar * pSrc = nullptr ); - static CItem * CreateScript(ITEMID_TYPE id, CChar * pSrc = nullptr, IT_TYPE type = IT_INVALID); // If type == IT_INVALID, read the type from the def (default behaviour) - CItem * GenerateScript(CChar * pSrc = nullptr); - static CItem * CreateDupeItem( const CItem * pItem, CChar * pSrc = nullptr, bool fSetNew = false ); - static CItem * CreateTemplate( ITEMID_TYPE id, CObjBase* pCont = nullptr, CChar * pSrc = nullptr ); - - static CItem * ReadTemplate( CResourceLock & s, CObjBase * pCont ); - }; #endif // _INC_CITEM_H diff --git a/src/game/items/CItemBase.h b/src/game/items/CItemBase.h index 2c5b33aa6..cb3c9c333 100644 --- a/src/game/items/CItemBase.h +++ b/src/game/items/CItemBase.h @@ -12,10 +12,11 @@ #include "../uo_files/CUOItemTypeRec.h" #include "../CBase.h" #include "../CServerConfig.h" -#include "../components/CCFaction.h" #include "item_types.h" +class CFactionDef; + class CItemBase : public CBaseBaseDef { // RES_ITEMDEF @@ -24,11 +25,11 @@ class CItemBase : public CBaseBaseDef private: CSTypedArray m_flip_id; // can be flipped to make these display ids. CValueRangeDef m_values; // range of values given a quality skill - IT_TYPE m_type; // default double click action type. (if any) uint64 m_qwFlags; // UFLAG4_DOOR from CUOItemTypeRec/CUOItemTypeRec_HS - word m_weight; // weight in WEIGHT_UNITS (UINT16_MAX=not movable) defaults from the .MUL file. + IT_TYPE m_type; // default double click action type. (if any) + word m_weight; // weight in WEIGHT_UNITS (UINT16_MAX=not movable) defaults from the .MUL file. byte m_layer; // Is this item equippable on paperdoll? LAYER=LAYER_TYPE defaults from the .MUL file. - byte m_speed; + byte m_speed; public: static const char *m_sClassName; @@ -221,9 +222,25 @@ class CItemBase : public CBaseBaseDef static lpctstr const sm_szLoadKeys[]; +public: + explicit CItemBase( ITEMID_TYPE id ); + + // These don't really get destroyed til the server is shut down but keep this around anyhow. + virtual ~CItemBase() = default; + + CItemBase(const CItemBase& copy) = delete; + CItemBase& operator=(const CItemBase& other) = delete; + + void CopyBasic( const CItemBase * pBase ); + void CopyTransfer( CItemBase * pBase ); + + virtual bool r_LoadVal( CScript & s ) override; + virtual bool r_WriteVal( lpctstr ptcKey, CSString &sVal, CTextConsole * pSrc = nullptr, bool fNoCallParent = false, bool fNoCallChildren = false ) override; + private: static CItemBase * MakeDupeReplacement( CItemBase * pBase, ITEMID_TYPE iddupe ); int CalculateMakeValue( int iSkillLevel ) const; + protected: static void ReplaceItemBase( CItemBase * pOld, CResourceDef * pNew ); public: @@ -248,7 +265,7 @@ class CItemBase : public CBaseBaseDef // Classify item by ID static bool IsID_Multi( ITEMID_TYPE id ) noexcept; static bool IsID_House( ITEMID_TYPE id ) noexcept; - static int IsID_Door( ITEMID_TYPE id ) noexcept; + static int IsID_Door( ITEMID_TYPE id ) noexcept; static bool IsID_DoorOpen( ITEMID_TYPE id ) noexcept; static bool IsID_Ship( ITEMID_TYPE id ) noexcept; static bool IsID_GamePiece( ITEMID_TYPE id ) noexcept; @@ -302,9 +319,6 @@ class CItemBase : public CBaseBaseDef bool IsDupedItem( ITEMID_TYPE id ) const; ITEMID_TYPE GetNextFlipID( ITEMID_TYPE id ) const; - virtual bool r_LoadVal( CScript & s ) override; - virtual bool r_WriteVal( lpctstr ptcKey, CSString &sVal, CTextConsole * pSrc = nullptr, bool fNoCallParent = false, bool fNoCallChildren = false ) override; - bool IsMovableType() const noexcept { return ( m_weight != UINT16_MAX ); @@ -342,18 +356,6 @@ class CItemBase : public CBaseBaseDef virtual void UnLink() override; - void CopyBasic( const CItemBase * pBase ); - void CopyTransfer( CItemBase * pBase ); - -public: - explicit CItemBase( ITEMID_TYPE id ); - - // These don't really get destroyed til the server is shut down but keep this around anyhow. - virtual ~CItemBase() = default; - -private: - CItemBase(const CItemBase& copy); - CItemBase& operator=(const CItemBase& other); }; class CItemBaseDupe : public CResourceDef @@ -370,9 +372,8 @@ class CItemBaseDupe : public CResourceDef CItemBaseDupe(ITEMID_TYPE id, CItemBase* pMasterItem); virtual ~CItemBaseDupe() = default; -private: - CItemBaseDupe(const CItemBaseDupe& copy); - CItemBaseDupe& operator=(const CItemBaseDupe& other); + CItemBaseDupe(const CItemBaseDupe& copy) = delete; + CItemBaseDupe& operator=(const CItemBaseDupe& other) = delete; public: static CItemBaseDupe* GetDupeRef(ITEMID_TYPE id); @@ -442,9 +443,11 @@ class CItemBaseMulti : public CItemBase explicit CItemBaseMulti( CItemBase* pBase ); virtual ~CItemBaseMulti() = default; -private: - CItemBaseMulti(const CItemBaseMulti& copy); - CItemBaseMulti& operator=(const CItemBaseMulti& other); + CItemBaseMulti(const CItemBaseMulti& copy) = delete; + CItemBaseMulti& operator=(const CItemBaseMulti& other) = delete; + + virtual bool r_LoadVal( CScript & s ) override; + virtual bool r_WriteVal( lpctstr ptcKey, CSString & sVal, CTextConsole * pChar = nullptr, bool fNoCallParent = false, bool fNoCallChildren = false ) override; public: int GetDistanceMax() const; @@ -453,8 +456,6 @@ class CItemBaseMulti : public CItemBase bool AddComponent( ITEMID_TYPE id, short dx, short dy, char dz ); bool AddComponent( tchar * pArgs ); void SetMultiRegion( tchar * pArgs ); - virtual bool r_LoadVal( CScript & s ) override; - virtual bool r_WriteVal( lpctstr ptcKey, CSString & sVal, CTextConsole * pChar = nullptr, bool fNoCallParent = false, bool fNoCallChildren = false ) override; static CItemBase * MakeMultiRegion( CItemBase * pBase, CScript & s ); }; diff --git a/src/game/items/CItemMultiCustom.cpp b/src/game/items/CItemMultiCustom.cpp index 6955f89c9..05ee1aad1 100644 --- a/src/game/items/CItemMultiCustom.cpp +++ b/src/game/items/CItemMultiCustom.cpp @@ -643,7 +643,7 @@ void CItemMultiCustom::AddStairs(CClient * pClientSrc, ITEMID_TYPE id, int16 x, if (!pMultiItem->m_visible) continue; - AddItem(nullptr, pMultiItem->GetDispID(), x + pMultiItem->m_dx, y + pMultiItem->m_dy, z + n16_narrow8(pMultiItem->m_dz), iStairID); + AddItem(nullptr, pMultiItem->GetDispID(), x + pMultiItem->m_dx, y + pMultiItem->m_dy, z + n16_narrow_n8(pMultiItem->m_dz), iStairID); } SendStructureTo(pClientSrc); @@ -855,7 +855,7 @@ bool CItemMultiCustom::RemoveStairs(CMultiComponent * pStairComponent) int16 x = pComp->m_item.m_dx; int16 y = pComp->m_item.m_dy; - int8 z = n16_narrow8(pComp->m_item.m_dz); + int8 z = n16_narrow_n8(pComp->m_item.m_dz); it = m_designWorking.m_vectorComponents.erase(it); ++ m_designWorking.m_iRevision; @@ -1158,7 +1158,7 @@ size_t CItemMultiCustom::GetComponentsAt(int16 x, int16 y, int8 z, CMultiCompone if (pComponent->m_item.m_dx != x || pComponent->m_item.m_dy != y) continue; - if (z != INT8_MIN && GetPlane(n16_narrow8(pComponent->m_item.m_dz)) != uiPlane) + if (z != INT8_MIN && GetPlane(n16_narrow_n8(pComponent->m_item.m_dz)) != uiPlane) continue; pComponents[count++] = pComponent; @@ -1887,12 +1887,12 @@ uint8 CItemMultiCustom::GetPlane(int8 z) uint8 CItemMultiCustom::GetPlane(const CMultiComponent * pComponent) { - return GetPlane(n16_narrow8(pComponent->m_item.m_dz)); + return GetPlane(n16_narrow_n8(pComponent->m_item.m_dz)); } int8 CItemMultiCustom::GetPlaneZ(uint8 plane) { - return n32_narrow8_checked(7 + ((plane - 1) * 20)); + return n32_narrow_n8_checked(7 + ((plane - 1) * 20)); } bool CItemMultiCustom::IsValidItem(ITEMID_TYPE id, CClient * pClientSrc, bool fMulti) diff --git a/src/network/send.cpp b/src/network/send.cpp index 57d8d429d..d20e2e8fa 100644 --- a/src/network/send.cpp +++ b/src/network/send.cpp @@ -3346,7 +3346,7 @@ PacketCharacterList::PacketCharacterList(CClient* target) : PacketSend(XCMD_Char uint countPos = getPosition(); skip(1); - uchar count = n32_narrow8( + uchar count = n32_narrow_n8( target->Setup_FillCharList(this, account->m_uidLastChar.CharFind())); seek(countPos); diff --git a/src/sphere/threads.cpp b/src/sphere/threads.cpp index 96fef2987..2b9caeda9 100644 --- a/src/sphere/threads.cpp +++ b/src/sphere/threads.cpp @@ -3,6 +3,7 @@ #include #include +#include #include "../common/basic_threading.h" #include "../common/CException.h" #include "../common/CLog.h" @@ -105,6 +106,10 @@ void IThread::setThreadName(const char* name) auto athr = static_cast(ThreadHolder::get().current()); ASSERT(athr); + + g_Log.Event(LOGM_DEBUG|LOGL_EVENT, "Setting thread (ThreadHolder ID %d, internal name '%s') system name: '%s'.\n", + athr->m_threadHolderId, athr->getName(), name_trimmed); + athr->overwriteInternalThreadName(name_trimmed); } @@ -114,7 +119,7 @@ void IThread::setThreadName(const char* name) **/ ThreadHolder::ThreadHolder() noexcept : - m_threadCount(-1), m_closing(false) + m_threadCount(0), m_closingThreads(false) {} ThreadHolder& ThreadHolder::get() noexcept @@ -126,13 +131,14 @@ ThreadHolder& ThreadHolder::get() noexcept bool ThreadHolder::closing() noexcept { std::shared_lock lock(m_mutex); - volatile auto ret = m_closing; + volatile auto ret = m_closingThreads; return ret; } IThread* ThreadHolder::current() noexcept { - // Do not use ASSERTs here, would cause recursion + // Do not use ASSERTs here, would cause recursion. + // RETRY_SHARED_LOCK_FOR_TASK is used to try to not make mutex lock fail and, if needed, // handle failure while allowing this function to be noexcept. @@ -140,17 +146,24 @@ IThread* ThreadHolder::current() noexcept RETRY_SHARED_LOCK_FOR_TASK(m_mutex, lock, retval, ([this, &lock]() -> IThread* { - if (m_closing) + [[unlikely]] + if (m_closingThreads) + { + //STDERR_LOG("Closing?\n"); return nullptr; + } const threadid_t tid = IThread::getCurrentThreadSystemId(); - if (m_spherethreadpairs_systemid_ptr.empty()) { + [[unlikely]] + if (m_spherethreadpairs_systemid_ptr.empty()) + { auto thread = static_cast(DummySphereThread::getInstance()); - if (!thread) { + [[unlikely]] + if (!thread) + { // Should never happen. - EXC_NOTIFY_DEBUGGER; - std::abort(); + RaiseImmediateAbort(); } thread->m_threadSystemId = tid; @@ -160,27 +173,34 @@ IThread* ThreadHolder::current() noexcept } spherethreadpair_t *found = nullptr; - for (auto &elem : m_spherethreadpairs_systemid_ptr) { - if (elem.first == tid) { + for (auto &elem : m_spherethreadpairs_systemid_ptr) + { + if (elem.first == tid) + { found = &elem; break; } } - if (!found) { + [[unlikely]] + if (!found) + { //throw CSError(LOGL_FATAL, 0, "Thread handle not found in vector?"); - STDERR_LOG("Thread handle not found in vector?"); + //STDERR_LOG("Thread handle not found in vector?"); // Should never happen. - EXC_NOTIFY_DEBUGGER; - std::abort(); + RaiseImmediateAbort(); } auto thread = static_cast(found->second); ASSERT(thread->m_threadHolderId != -1); SphereThreadData *tdata = &(m_threads[thread->m_threadHolderId]); + [[unlikely]] if (tdata->m_closed) + { + //STDERR_LOG("Closed? Idx %u, Name %s.\n", thread->m_threadHolderId, thread->getName()); return nullptr; + } // Uncomment it only for testing purposes, since this method is called very often and we don't need the additional overhead //DEBUG_ASSERT( thread->isSameThread(thread->getId()) ); @@ -210,7 +230,7 @@ void ThreadHolder::push(IThread *thread) noexcept ASSERT(thread->m_threadHolderId == -1); m_threads.emplace_back( SphereThreadData{ thread, false }); - thread->m_threadHolderId = m_threadCount + 1; + thread->m_threadHolderId = m_threadCount; #ifdef _DEBUG auto it_thread = std::find_if( @@ -223,13 +243,15 @@ void ThreadHolder::push(IThread *thread) noexcept #endif m_spherethreadpairs_systemid_ptr.emplace_back(sphere_thread->m_threadSystemId, sphere_thread); - ++m_threadCount; + ++ m_threadCount; } catch (CAssert const& e) { fExceptionThrown = true; - STDERR_LOG("ASSERT failed.\n"); + lptstr ptcBuf = Str_GetTemp(); + e.GetErrorMessage(ptcBuf, usize_narrow_u32(Str_TempLength())); + STDERR_LOG("ASSERT failed.\n%s\n", ptcBuf); } catch (std::system_error const& e) { @@ -245,8 +267,19 @@ void ThreadHolder::push(IThread *thread) noexcept if (fExceptionThrown) { // Should never happen. - EXC_NOTIFY_DEBUGGER; - std::abort(); + RaiseImmediateAbort(); + } + + if (dynamic_cast(thread)) + { + // Too early in the init process to use the console... + printf("Registered thread '%s' with ThreadHolder ID %d.\n", + thread->getName(), thread->m_threadHolderId); + } + else + { + g_Log.Event(LOGM_DEBUG|LOGL_EVENT, "Registered thread '%s' with ThreadHolder ID %d.\n", + thread->getName(), thread->m_threadHolderId); } } @@ -296,34 +329,52 @@ void ThreadHolder::remove(IThread *thread) CANTHROW void ThreadHolder::markThreadsClosing() CANTHROW { + g_Log.Event(LOGM_INIT|LOGM_NOCONTEXT|LOGL_EVENT, "Marking threads as closing.\n"); + std::unique_lock lock(m_mutex); - m_closing = true; + m_closingThreads = true; for (auto& thread_data : m_threads) { auto sphere_thread = static_cast(thread_data.m_ptr); sphere_thread->_fIsClosing = true; thread_data.m_closed = true; } - //printf("Marking threads as closing.\n"); } -IThread * ThreadHolder::getThreadAt(size_t at) CANTHROW +IThread * ThreadHolder::getThreadAt(size_t at) noexcept { - std::shared_lock lock(m_mutex); - - if ( at > getActiveThreads() ) - return nullptr; + IThread* retval = nullptr; + RETRY_SHARED_LOCK_FOR_TASK(m_mutex, lock, retval, + ([this, at]() -> IThread* + { +// MSVC: warning C5101: use of preprocessor directive in function-like macro argument list is undefined behavior. +//#ifdef _DEBUG + [[unlikely]] + if (getActiveThreads() != m_threads.size()) + { + STDERR_LOG("Active threads %" PRIuSIZE_T ", threads container size %" PRIuSIZE_T ".\n", getActiveThreads(), m_threads.size()); + RaiseImmediateAbort(); + } +//#endif + [[unlikely]] + if ( at > getActiveThreads() ) + return nullptr; - for ( spherethreadlist_t::const_iterator it = m_threads.begin(), end = m_threads.end(); it != end; ++it ) - { - if ( at == 0 ) - return it->m_ptr; + /* + for ( spherethreadlist_t::const_iterator it = m_threads.begin(), end = m_threads.end(); it != end; ++it ) + { + if ( at == 0 ) + return it->m_ptr; - --at; - } + --at; + } + return nullptr; + */ + return m_threads[at].m_ptr; + })); - return nullptr; + return retval; } @@ -378,6 +429,11 @@ void AbstractThread::overwriteInternalThreadName(const char* name) noexcept void AbstractThread::start() { + //ThreadHolder::get().push(this); + //printf("Starting thread '%s' with ThreadHolder ID %d.\n", + // getName(), m_threadHolderId); + //fflush(stdout); + #ifdef _WIN32 m_handle = reinterpret_cast(_beginthreadex(nullptr, 0, &runner, this, 0, nullptr)); #else @@ -635,8 +691,11 @@ void AbstractThread::onStart() ThreadHolder::get().push(this); - if (isActive()) // This thread has actually been spawned and the code is executing on a different thread + if (isActive()) // This thread has actually been spawned and the code is executing on a different thread setThreadName(getName()); + + g_Log.Event(LOGM_DEBUG|LOGL_EVENT, "Started thread '%s' with ThreadHolder ID %d and system ID %" PRIu64 ".\n", + getName(), m_threadHolderId, (uint64)m_threadSystemId); } void AbstractThread::setPriority(IThread::Priority pri) @@ -787,18 +846,25 @@ void AbstractSphereThread::exceptionCaught() #endif } -#include -#include "../game/CServerConfig.h" - #ifdef THREAD_TRACK_CALLSTACK static thread_local ssize_t _stackpos = -1; -void AbstractSphereThread::pushStackCall(const char *name) NOEXCEPT_NODEBUG +void AbstractSphereThread::pushStackCall(const char *name) noexcept { + [[unlikely]] if (m_freezeCallStack == true) return; - DEBUG_ASSERT(m_stackPos >= -1); - DEBUG_ASSERT(m_stackPos < (ssize_t)sizeof(m_stackInfo)); +#ifdef _DEBUG + [[unlikely]] + if (m_stackPos < -1) { + RaiseImmediateAbort(); + } + [[unlikely]] + if (m_stackPos >= (ssize_t)sizeof(m_stackInfo)) { + RaiseImmediateAbort(); + } +#endif + ++m_stackPos; _stackpos = m_stackPos; m_stackInfo[m_stackPos].functionName = name; @@ -899,30 +965,37 @@ void DummySphereThread::tick() StackDebugInformation::StackDebugInformation(const char *name) noexcept : m_context(nullptr) { + STATIC_ASSERT_NOEXCEPT_CONSTRUCTOR(StackDebugInformation, const char*); + STATIC_ASSERT_NOEXCEPT_MEMBER_FUNCTION(AbstractSphereThread, pushStackCall, const char*); + auto& th = ThreadHolder::get(); + [[unlikely]] if (th.closing()) return; IThread *icontext = th.current(); - if (icontext == nullptr) + [[unlikely]] + if (icontext == nullptr) { // Thread was deleted, manually or by app closing signal. return; } m_context = static_cast(icontext); - if (m_context != nullptr && !m_context->closing()) + [[likely]] + if (m_context != nullptr && !m_context->closing()) { m_context->pushStackCall(name); - //printf("- - - - Pushing stack call: %s.\n", name); } } StackDebugInformation::~StackDebugInformation() noexcept { + [[unlikely]] if (!m_context || m_context->closing()) return; + [[unlikely]] if (std::uncaught_exceptions() != 0) { // Exception was thrown and stack unwinding is in progress. diff --git a/src/sphere/threads.h b/src/sphere/threads.h index 9b0871433..2c61f6318 100644 --- a/src/sphere/threads.h +++ b/src/sphere/threads.h @@ -305,7 +305,7 @@ class AbstractSphereThread : public AbstractThread m_freezeCallStack = freeze; } - void pushStackCall(const char *name) NOEXCEPT_NODEBUG; + void pushStackCall(const char *name) noexcept; void popStackCall() NOEXCEPT_NODEBUG; void exceptionNotifyStackUnwinding() noexcept; @@ -350,7 +350,7 @@ class ThreadHolder std::vector m_spherethreadpairs_systemid_ptr; int m_threadCount; - volatile std::atomic_bool m_closing; + volatile std::atomic_bool m_closingThreads; mutable std::shared_mutex m_mutex; ThreadHolder() noexcept; @@ -375,7 +375,7 @@ class ThreadHolder // removes a thread from the list. Sould NOT be called, internal usage void remove(IThread *thread) CANTHROW; // returns thread at i pos - IThread * getThreadAt(size_t at) CANTHROW; + IThread * getThreadAt(size_t at) noexcept; // returns number of running threads. Sould NOT be called, unit tests usage inline size_t getActiveThreads() noexcept { return m_threadCount; } diff --git a/src/tables/CBaseBaseDef_props.tbl b/src/tables/CBaseBaseDef_props.tbl index 80402ee19..19ca8bf2d 100644 --- a/src/tables/CBaseBaseDef_props.tbl +++ b/src/tables/CBaseBaseDef_props.tbl @@ -15,8 +15,6 @@ ADD(DEFNAME, "DEFNAME") ADD(DEFNAME2, "DEFNAME2") ADD(DESCRIPTION, "DESCRIPTION") ADD(EXPANSION, "EXPANSION") -ADD(FACTION_GROUP, "FACTION_GROUP") -ADD(FACTION_SPECIES, "FACTION_SPECIES") ADD(HASCOMPONENTPROPS, "HASCOMPONENTPROPS") ADD(HEIGHT, "HEIGHT") ADD(INSTANCES, "INSTANCES") @@ -26,8 +24,6 @@ ADD(NAMELOC, "NAMELOC") ADD(RESDISPDNHUE, "RESDISPDNHUE") ADD(RESLEVEL, "RESLEVEL") ADD(RESOURCES, "RESOURCES") -ADD(SLAYER_GROUP, "SLAYER_GROUP") -ADD(SLAYER_SPECIES, "SLAYER_SPECIES") ADD(SUBSECTION, "SUBSECTION") ADD(TAG, "TAG") ADD(TAG0, "TAG0") diff --git a/src/tables/CCPropsChar_props.tbl b/src/tables/CCPropsChar_props.tbl index db899554e..41abd4d10 100644 --- a/src/tables/CCPropsChar_props.tbl +++ b/src/tables/CCPropsChar_props.tbl @@ -20,6 +20,8 @@ ADDPROP(EATERENERGY, "EATERENERGY", RDS_SA) ADDPROP(EATERFIRE, "EATERFIRE", RDS_SA) ADDPROP(EATERKINETIC, "EATERKINETIC", RDS_SA) ADDPROP(EATERPOISON, "EATERPOISON", RDS_SA) +ADDPROP(FACTION_GROUP, "FACTION_GROUP", RDS_AOS) +ADDPROP(FACTION_SPECIES, "FACTION_SPECIES", RDS_AOS) ADDPROP(ENHANCEPOTIONS, "ENHANCEPOTIONS", RDS_AOS) ADDPROP(FASTERCASTING, "FASTERCASTING", RDS_AOS) ADDPROP(FASTERCASTRECOVERY, "FASTERCASTRECOVERY", RDS_AOS) @@ -84,4 +86,4 @@ ADDPROP(SOULCHARGEKINETIC, "SOULCHARGEKINETIC", RDS_SA) ADDPROP(SOULCHARGEPOISON, "SOULCHARGEPOISON", RDS_SA) ADDPROP(SPELLCHANNELING, "SPELLCHANNELING", RDS_AOS) ADDPROP(SPELLCONSUMPTION, "SPELLCONSUMPTION", RDS_AOS) // Not sure about expansion -ADDPROP(SPELLFOCUSING, "SPELLFOCUSING", RDS_AOS) // Not sure about expansion \ No newline at end of file +ADDPROP(SPELLFOCUSING, "SPELLFOCUSING", RDS_AOS) // Not sure about expansion diff --git a/src/tables/CCPropsItemEquippable_props.tbl b/src/tables/CCPropsItemEquippable_props.tbl index fbe77f3fc..019a88b28 100644 --- a/src/tables/CCPropsItemEquippable_props.tbl +++ b/src/tables/CCPropsItemEquippable_props.tbl @@ -101,6 +101,8 @@ ADDPROP(RESPHYSICAL, "RESPHYSICAL", RDS_PRET2A) // it's RDS_AOS, but we want ADDPROP(RESPHYSICALMAX, "RESPHYSICALMAX", RDS_PRET2A) // it's RDS_AOS, but we want it to depend on ElementalEngine, not on Expansion ADDPROP(RESPOISON, "RESPOISON", RDS_PRET2A) // it's RDS_AOS, but we want it to depend on ElementalEngine, not on Expansion ADDPROP(RESPOISONMAX, "RESPOISONMAX", RDS_PRET2A) // it's RDS_AOS, but we want it to depend on ElementalEngine, not on Expansion +ADDPROP(SLAYER_GROUP, "SLAYER_GROUP", RDS_AOS) +ADDPROP(SLAYER_SPECIES, "SLAYER_SPECIES", RDS_AOS) ADDPROP(SOULCHARGE, "SOULCHARGE", RDS_AOS) ADDPROP(SOULCHARGECOLD, "SOULCHARGECOLD", RDS_SA) ADDPROP(SOULCHARGEENERGY, "SOULCHARGEENERGY", RDS_SA) diff --git a/src/tables/CObjBase_props.tbl b/src/tables/CObjBase_props.tbl index 2372fcee3..ac4c35d01 100644 --- a/src/tables/CObjBase_props.tbl +++ b/src/tables/CObjBase_props.tbl @@ -60,10 +60,6 @@ ADD(RECIPETINKERING, "RECIPETINKERING") ADD(RESDISPDNHUE, "RESDISPDNHUE") ADD(SERIAL, "SERIAL") ADD(SEXTANTP, "SEXTANTP") -ADD(SLAYER, "SLAYER") -ADD(SLAYERLESSER, "SLAYERLESSER") -ADD(SLAYERMISC, "SLAYERMISC") -ADD(SLAYERSUPER, "SLAYERSUPER") ADD(SPAWNITEM, "SPAWNITEM") ADD(SPEED, "SPEED") ADD(TAG, "TAG") From ae8297ff1b417aba3558882ff5516e1d4b1ac0fe Mon Sep 17 00:00:00 2001 From: cbnolok Date: Thu, 5 Sep 2024 12:28:32 +0200 Subject: [PATCH 17/86] Move the workflow binariy and .ini files into the root folder #1277 --- .github/workflows/build_linux_x86.yml | 2 +- .github/workflows/build_linux_x86_64.yml | 2 +- .github/workflows/build_osx_arm.yml | 6 ++---- .github/workflows/build_osx_x86_64.yml | 5 ++--- 4 files changed, 6 insertions(+), 9 deletions(-) diff --git a/.github/workflows/build_linux_x86.yml b/.github/workflows/build_linux_x86.yml index 1e80885f6..557da3502 100644 --- a/.github/workflows/build_linux_x86.yml +++ b/.github/workflows/build_linux_x86.yml @@ -91,7 +91,7 @@ jobs: - name: Create package run: | mkdir accounts logs save scripts - tar -czf SphereSvrX-linux-x86-nightly.tar.gz accounts/ logs/ save/ scripts/ build/bin-x86/SphereSvrX32_nightly src/sphere.ini src/sphereCrypt.ini + tar -czf SphereSvrX-linux-x86-nightly.tar.gz accounts/ logs/ save/ scripts/ -C build/bin-x86/ SphereSvrX32_nightly -C ../../src sphere.ini sphereCrypt.ini # Upload artifact linked to the workflow run - only if the run is for a pull request, or for selected branches - name: Upload artifact diff --git a/.github/workflows/build_linux_x86_64.yml b/.github/workflows/build_linux_x86_64.yml index 505ad1c78..efe9296ae 100644 --- a/.github/workflows/build_linux_x86_64.yml +++ b/.github/workflows/build_linux_x86_64.yml @@ -44,7 +44,7 @@ jobs: - name: Create package run: | mkdir accounts logs save scripts - tar -czf SphereSvrX-linux-x86_64-nightly.tar.gz accounts/ logs/ save/ scripts/ build/bin-x86_64/SphereSvrX64_nightly src/sphere.ini src/sphereCrypt.ini + tar -czf SphereSvrX-linux-x86_64-nightly.tar.gz accounts/ logs/ save/ scripts/ -C build/bin-x86_64/ SphereSvrX64_nightly -C ../../src sphere.ini sphereCrypt.ini # Upload artifact linked to the workflow run - only if the run is for a pull request, or for selected branches - name: Upload artifact diff --git a/.github/workflows/build_osx_arm.yml b/.github/workflows/build_osx_arm.yml index 8639c67be..d72618273 100644 --- a/.github/workflows/build_osx_arm.yml +++ b/.github/workflows/build_osx_arm.yml @@ -45,14 +45,12 @@ jobs: mkdir -p build cmake -G "Ninja" -DCMAKE_BUILD_TYPE="Nightly" -DCMAKE_TOOLCHAIN_FILE="$CMAKE_TCH" -S . -B ./build - name: Ninja - run: cd build && ninja -v && cd .. + run: cd build && ninja && cd .. - name: Create package run: | pwd mkdir accounts logs save scripts - zip -r SphereSvrX-osx-arm64-nightly.zip accounts/ logs/ save/ scripts/ - zip SphereSvrX-osx-arm64-nightly.zip src/sphere.ini src/sphereCrypt.ini build/bin-aarch64/* - # zip SphereSvrX-osx-arm64-nightly.zip src/sphere.ini src/sphereCrypt.ini build/bin-native64/* + zip -rj SphereSvrX-osx-arm64-nightly.zip accounts/ logs/ save/ scripts/ src/sphere.ini src/sphereCrypt.ini build/bin-aarch64/* # Upload artifact linked to the workflow run - only if the run is for a pull request, or for selected branches - name: Upload artifact diff --git a/.github/workflows/build_osx_x86_64.yml b/.github/workflows/build_osx_x86_64.yml index b4e4e4ed7..41a4d4dc5 100644 --- a/.github/workflows/build_osx_x86_64.yml +++ b/.github/workflows/build_osx_x86_64.yml @@ -43,13 +43,12 @@ jobs: mkdir -p build cmake -G "Ninja" -DCMAKE_BUILD_TYPE="Nightly" -DCMAKE_TOOLCHAIN_FILE="$CMAKE_TCH" -S . -B ./build - name: Ninja - run: cd build && ninja -v && cd .. + run: cd build && ninja && cd .. - name: Create package run: | pwd mkdir accounts logs save scripts - zip -r SphereSvrX-osx-x86_64-nightly.zip accounts/ logs/ save/ scripts/ - zip SphereSvrX-osx-x86_64-nightly.zip src/sphere.ini src/sphereCrypt.ini build/bin-x86_64/* + zip -rj SphereSvrX-osx-x86_64-nightly.zip accounts/ logs/ save/ scripts/ src/sphere.ini src/sphereCrypt.ini build/bin-x86_64/* # Upload artifact linked to the workflow run - only if the run is for a pull request, or for selected branches - name: Upload artifact From 13d7afe4aa4699ea767bd894580bd419f5bb49cb Mon Sep 17 00:00:00 2001 From: cbnolok Date: Thu, 5 Sep 2024 13:19:47 +0200 Subject: [PATCH 18/86] Fixed WSC import/export relative P. --- src/game/CServer.cpp | 2 +- src/game/CWorld.h | 5 +++-- src/game/CWorldImport.cpp | 21 +++++++++++---------- src/game/items/CItem.cpp | 6 +++--- src/game/items/CItem.h | 2 +- 5 files changed, 19 insertions(+), 17 deletions(-) diff --git a/src/game/CServer.cpp b/src/game/CServer.cpp index 08486e5f9..e09429a3b 100644 --- a/src/game/CServer.cpp +++ b/src/game/CServer.cpp @@ -1639,7 +1639,7 @@ bool CServer::r_Verb( CScript &s, CTextConsole * pSrc ) // IMPFLAGS_ITEMS if ( ! g_World.Export( Arg_ppCmd[0], pSrc->GetChar(), (Arg_Qty >= 2) ? (word)atoi(Arg_ppCmd[1]) : (word)IMPFLAGS_ITEMS, - (Arg_Qty >= 3)? atoi(Arg_ppCmd[2]) : INT16_MAX )) + (Arg_Qty >= 3) ? atoi(Arg_ppCmd[2]) : INT16_MAX )) { if (pSrc != this) { diff --git a/src/game/CWorld.h b/src/game/CWorld.h index fce63a5a5..6e573c9b6 100644 --- a/src/game/CWorld.h +++ b/src/game/CWorld.h @@ -232,11 +232,12 @@ extern class CWorld : public CScriptObj, public CWorldThread void Close(); bool Export(lpctstr pszFilename, const CChar* pSrc, word iModeFlags = IMPFLAGS_ITEMS, int iDist = INT16_MAX, int dx = 0, int dy = 0); - bool Import(lpctstr pszFilename, const CChar* pSrc, word iModeFlags = IMPFLAGS_ITEMS, int iDist = INT16_MAX, tchar* pszAgs1 = nullptr, tchar* pszAgs2 = nullptr); + bool Import(lpctstr pszFilename, const CChar* pSrc, word iModeFlags = IMPFLAGS_ITEMS, int iDist = INT16_MAX, int dx = 0, int dy = 0, + tchar* pszAgs1 = nullptr, tchar* pszAgs2 = nullptr); virtual lpctstr GetName() const override { return "World"; - } + } } g_World; diff --git a/src/game/CWorldImport.cpp b/src/game/CWorldImport.cpp index 56439bcac..f4632948e 100644 --- a/src/game/CWorldImport.cpp +++ b/src/game/CWorldImport.cpp @@ -68,7 +68,7 @@ struct CImportFile void CheckLast(); void ImportFix(); bool ImportSCP( CScript & s, word wModeFlags ); - bool ImportWSC( CScript & s, word wModeFlags ); + bool ImportWSC( CScript & s, word wModeFlags, int dx, int dy ); }; void CImportFile::CheckLast() @@ -251,7 +251,7 @@ bool CImportFile::ImportSCP( CScript & s, word wModeFlags ) ImportFix(); if ( wModeFlags & IMPFLAGS_CHARS ) { - m_pCurObj = CChar::CreateBasic(static_cast(g_Cfg.ResourceGetIndexType(RES_CHARDEF, s.GetArgStr()))); + m_pCurObj = CChar::CreateBasic((CREID_TYPE)(g_Cfg.ResourceGetIndexType(RES_CHARDEF, s.GetArgStr()))); } } else if ( s.IsSectionType( "WORLDITEM" ) || s.IsSectionType("WI")) @@ -302,7 +302,7 @@ bool CImportFile::ImportSCP( CScript & s, word wModeFlags ) return true; } -bool CImportFile::ImportWSC( CScript & s, word wModeFlags ) +bool CImportFile::ImportWSC( CScript & s, word wModeFlags, int dx, int dy ) { ADDTOCALLSTACK("CImportFile::ImportWSC"); // This file is a WSC or UOX world script file. @@ -429,7 +429,7 @@ bool CImportFile::ImportWSC( CScript & s, word wModeFlags ) continue; CPointMap pt(pItem->GetUnkPoint()); - pt.m_x = *iconv; + pt.m_x = *iconv + dx; pItem->SetUnkPoint(pt); continue; } @@ -440,7 +440,7 @@ bool CImportFile::ImportWSC( CScript & s, word wModeFlags ) continue; CPointMap pt(pItem->GetUnkPoint()); - pt.m_y = (*iconv); + pt.m_y = *iconv + dy; pItem->SetUnkPoint(pt); continue; } @@ -773,7 +773,7 @@ bool CImportFile::ImportWSC( CScript & s, word wModeFlags ) return true; } -bool CWorld::Import( lpctstr pszFilename, const CChar * pSrc, word wModeFlags, int iDist, tchar * pszArg1, tchar * pszArg2 ) +bool CWorld::Import( lpctstr pszFilename, const CChar * pSrc, word wModeFlags, int iDist, int dx, int dy, tchar * pszArg1, tchar * pszArg2 ) { ADDTOCALLSTACK("CWorld::Import"); // wModeFlags = IMPFLAGS_TYPE @@ -800,8 +800,8 @@ bool CWorld::Import( lpctstr pszFilename, const CChar * pSrc, word wModeFlags, i if ( wModeFlags & IMPFLAGS_RELATIVE ) { - // dx += ptCenter.m_x; - // dy += ptCenter.m_y; + dx += ptCenter.m_x; + dy += ptCenter.m_y; } } @@ -812,7 +812,7 @@ bool CWorld::Import( lpctstr pszFilename, const CChar * pSrc, word wModeFlags, i if ( ! strcmpi( pszFilename + (iLen - 4), ".WSC" )) { - if ( ! fImport.ImportWSC(s, wModeFlags )) + if ( ! fImport.ImportWSC(s, wModeFlags, dx, dy )) return false; } else @@ -897,12 +897,13 @@ bool CWorld::Export( lpctstr pszFilename, const CChar * pSrc, word wModeFlags, i CItem * pItem = AreaItems->GetItem(); if ( pItem == nullptr ) break; - pItem->WriteUOX( s, index++ ); + pItem->WriteUOX( s, index++, dx, dy ); } return true; } // (???NPC) Chars and the stuff they are carrying. + // This format doesn't (yet?) have relative coords support. if ( wModeFlags & IMPFLAGS_CHARS ) { auto AreaChars = CWorldSearchHolder::GetInstance( pSrc->GetTopPoint(), iDist ); diff --git a/src/game/items/CItem.cpp b/src/game/items/CItem.cpp index aa6d4a165..07567f5d8 100644 --- a/src/game/items/CItem.cpp +++ b/src/game/items/CItem.cpp @@ -2261,7 +2261,7 @@ bool CItem::CanSendAmount() const noexcept return true; } -void CItem::WriteUOX( CScript & s, int index ) +void CItem::WriteUOX( CScript & s, int index, int dx, int dy ) { ADDTOCALLSTACK("CItem::WriteUOX"); s.Printf( "SECTION WORLDITEM %d\n", index ); @@ -2269,8 +2269,8 @@ void CItem::WriteUOX( CScript & s, int index ) s.Printf( "SERIAL %u\n", (dword) GetUID()); s.Printf( "NAME %s\n", GetName()); s.Printf( "ID %d\n", GetDispID()); - s.Printf( "X %d\n", GetTopPoint().m_x ); - s.Printf( "Y %d\n", GetTopPoint().m_y ); + s.Printf( "X %d\n", GetTopPoint().m_x + dx ); + s.Printf( "Y %d\n", GetTopPoint().m_y + dy ); s.Printf( "Z %d\n", GetTopZ()); s.Printf( "CONT %d\n", -1 ); s.Printf( "TYPE %d\n", m_type ); diff --git a/src/game/items/CItem.h b/src/game/items/CItem.h index 14b37f9d0..ad978cc0e 100644 --- a/src/game/items/CItem.h +++ b/src/game/items/CItem.h @@ -802,7 +802,7 @@ protected: virtual void _SetTimeout(int64 iMsecs) override final; virtual void Flip() override; bool LoadSetContainer( const CUID& uid, LAYER_TYPE layer ); - void WriteUOX( CScript & s, int index ); + void WriteUOX( CScript & s, int index, int dx, int dy ); void r_WriteMore1( CSString & sVal ); void r_WriteMore2( CSString & sVal ); From 0d95e68c3a31e333679ce9f99863e5d099a01427 Mon Sep 17 00:00:00 2001 From: cbnolok Date: Thu, 5 Sep 2024 13:20:04 +0200 Subject: [PATCH 19/86] Treat compiler/linker warnings as errors. --- cmake/toolchains/Windows-MSVC.cmake | 12 +++++++----- .../toolchains/include/Linux-Clang_common.inc.cmake | 3 ++- cmake/toolchains/include/Linux-GNU_common.inc.cmake | 3 ++- .../include/OSX-AppleClang_common.inc.cmake | 3 ++- .../include/Windows-Clang_common.inc.cmake | 3 ++- .../toolchains/include/Windows-GNU_common.inc.cmake | 3 ++- src/game/CServer.cpp | 6 ++++-- src/game/CWorld.h | 4 ++-- src/game/CWorldImport.cpp | 8 ++++---- 9 files changed, 27 insertions(+), 18 deletions(-) diff --git a/cmake/toolchains/Windows-MSVC.cmake b/cmake/toolchains/Windows-MSVC.cmake index fc607c70a..140509bde 100644 --- a/cmake/toolchains/Windows-MSVC.cmake +++ b/cmake/toolchains/Windows-MSVC.cmake @@ -80,6 +80,7 @@ function (toolchain_exe_stuff) SET (cxx_compiler_flags_common ${CXX_FLAGS_EXTRA} /W4 /MP /GR /fp:fast /std:c++20 + /WX # treat all warnings as errors /wd4310 # cast truncates constant value /wd4996 # use of deprecated stuff /wd4701 # Potentially uninitialized local variable 'name' used @@ -109,7 +110,7 @@ function (toolchain_exe_stuff) ${cxx_compiler_flags_common} $<$: $,/MT,/MD> /EHa /Oy /GL /GA /Gw /Gy /GF $,/O1 /Zi,/O2>> $<$: $,/MT,/MD> /EHa /Oy /GL /GA /Gw /Gy /GF $,/O1 /Zi,/O2>> - $<$: $,/MTd,/MDd> /EHsc /Oy- /MDd /ob1 /Od /Gs $,/Zi,/ZI>> + $<$: $,/MTd,/MDd> /EHsc /Oy- /ob1 /Od /Gs $,/Zi,/ZI>> # ASan (and compilation for ARM arch) doesn't support edit and continue option (ZI) ) @@ -123,10 +124,11 @@ function (toolchain_exe_stuff) set(CMAKE_EXE_LINKER_FLAGS_NIGHTLY CACHE INTERNAL ${CMAKE_EXE_LINKER_FLAGS_RELEASE} "") target_link_options(spheresvr PRIVATE - $<$: ${EXE_LINKER_EXTRA} /OPT:REF,ICF /LTCG /NODEFAULTLIB:libcmtd> - $<$: ${EXE_LINKER_EXTRA} /OPT:REF,ICF /LTCG /NODEFAULTLIB:libcmtd> - $<$: ${EXE_LINKER_EXTRA} /DEBUG /LTCG:OFF /SAFESEH:NO /NODEFAULTLIB:libcmt - $<$>:/INCREMENTAL /EDITANDCONTINUE> > + /WX # treat all warnings as errors + $<$: ${EXE_LINKER_EXTRA} /NODEFAULTLIB:libcmtd /OPT:REF,ICF /LTCG /INCREMENTAL:NO> + $<$: ${EXE_LINKER_EXTRA} /NODEFAULTLIB:libcmtd /OPT:REF,ICF /LTCG /INCREMENTAL:NO> + $<$: ${EXE_LINKER_EXTRA} /NODEFAULTLIB:libcmt /SAFESEH:NO /DEBUG /LTCG:OFF + $,/INCREMENTAL:NO /EDITANDCONTINUE:NO,/INCREMENTAL /EDITANDCONTINUE> > ) # MSVC doesn't yet have an option to statically link against *san sanitizer libraries. # /INCREMENTAL and /EDITANDCONTINUE not compatible with a MSVC Asan build. diff --git a/cmake/toolchains/include/Linux-Clang_common.inc.cmake b/cmake/toolchains/include/Linux-Clang_common.inc.cmake index b5be67004..75638acbc 100644 --- a/cmake/toolchains/include/Linux-Clang_common.inc.cmake +++ b/cmake/toolchains/include/Linux-Clang_common.inc.cmake @@ -84,6 +84,7 @@ See comments in the toolchain and: https://github.com/google/sanitizers/wiki/Mem #-- Store compiler flags common to all builds. set (cxx_local_opts_warnings + -Werror -Wall -Wextra -Wno-unknown-pragmas -Wno-switch -Wno-implicit-fallthrough -Wno-parentheses -Wno-misleading-indentation -Wno-conversion-null -Wno-unused-result -Wno-format-security # TODO: disable that when we'll have time to fix every printf format issue @@ -139,7 +140,7 @@ See comments in the toolchain and: https://github.com/google/sanitizers/wiki/Mem IF (${USE_MSAN}) set (CMAKE_EXE_LINKER_FLAGS_EXTRA ${CMAKE_EXE_LINKER_FLAGS_EXTRA} -pie) ENDIF() - set (cxx_linker_options_common ${CMAKE_EXE_LINKER_FLAGS_EXTRA} -pthread -dynamic + set (cxx_linker_options_common ${CMAKE_EXE_LINKER_FLAGS_EXTRA} -pthread -dynamic -Wl,--fatal-warnings $<$: -static-libstdc++ -static-libgcc> # no way to safely statically link against libc ) diff --git a/cmake/toolchains/include/Linux-GNU_common.inc.cmake b/cmake/toolchains/include/Linux-GNU_common.inc.cmake index cbd362cfe..52349da26 100644 --- a/cmake/toolchains/include/Linux-GNU_common.inc.cmake +++ b/cmake/toolchains/include/Linux-GNU_common.inc.cmake @@ -81,6 +81,7 @@ function (toolchain_exe_stuff_common) #-- Store compiler flags common to all builds. set (cxx_local_opts_warnings + -Werror -Wall -Wextra -Wno-nonnull-compare -Wno-unknown-pragmas -Wno-switch -Wno-implicit-fallthrough -Wno-parentheses -Wno-misleading-indentation -Wno-conversion-null -Wno-unused-result -Wno-format-security # TODO: disable that when we'll have time to fix every printf format issue @@ -119,7 +120,7 @@ function (toolchain_exe_stuff_common) IF (${USE_MSAN}) SET (CMAKE_EXE_LINKER_FLAGS_EXTRA ${CMAKE_EXE_LINKER_FLAGS_EXTRA} -pie) ENDIF() - set (cxx_linker_options_common ${CMAKE_EXE_LINKER_FLAGS_EXTRA} -pthread -dynamic + set (cxx_linker_options_common ${CMAKE_EXE_LINKER_FLAGS_EXTRA} -pthread -dynamic -Wl,--fatal-warnings $<$: -static-libstdc++ -static-libgcc # no way to safely statically link against libc #$<$: -fsanitize-link-runtime -fsanitize-link-c++-runtime> > diff --git a/cmake/toolchains/include/OSX-AppleClang_common.inc.cmake b/cmake/toolchains/include/OSX-AppleClang_common.inc.cmake index 8d2ecedb3..3b0374a7c 100644 --- a/cmake/toolchains/include/OSX-AppleClang_common.inc.cmake +++ b/cmake/toolchains/include/OSX-AppleClang_common.inc.cmake @@ -84,6 +84,7 @@ function (toolchain_exe_stuff_common) #-- Store compiler flags common to all builds. set (cxx_local_opts_warnings + -Werror -Wall -Wextra -Wno-unknown-pragmas -Wno-switch -Wno-implicit-fallthrough -Wno-parentheses -Wno-misleading-indentation -Wno-conversion-null -Wno-unused-result -Wno-format-security # TODO: disable that when we'll have time to fix every printf format issue @@ -128,7 +129,7 @@ function (toolchain_exe_stuff_common) IF (${USE_MSAN}) set (CMAKE_EXE_LINKER_FLAGS_EXTRA ${CMAKE_EXE_LINKER_FLAGS_EXTRA} -pie) ENDIF() - set (cxx_linker_options_common ${CMAKE_EXE_LINKER_FLAGS_EXTRA} -pthread -dynamic + set (cxx_linker_options_common ${CMAKE_EXE_LINKER_FLAGS_EXTRA} -pthread -dynamic -Wl,-fatal_warnings $<$: -static-libstdc++ -static-libgcc> # no way to statically link against libc ) diff --git a/cmake/toolchains/include/Windows-Clang_common.inc.cmake b/cmake/toolchains/include/Windows-Clang_common.inc.cmake index a0233ae4b..97ae78d1e 100644 --- a/cmake/toolchains/include/Windows-Clang_common.inc.cmake +++ b/cmake/toolchains/include/Windows-Clang_common.inc.cmake @@ -99,6 +99,7 @@ function (toolchain_exe_stuff_common) #-- Store compiler flags common to all builds. SET (cxx_local_opts_warnings + -Werror -Wall -Wextra -Wno-unknown-pragmas -Wno-switch -Wno-implicit-fallthrough -Wno-parentheses -Wno-misleading-indentation -Wno-conversion-null -Wno-unused-result -Wno-format-security # TODO: disable that when we'll have time to fix every printf format issue @@ -179,7 +180,7 @@ function (toolchain_exe_stuff_common) set (cxx_linker_options_common ${CMAKE_EXE_LINKER_FLAGS_EXTRA}) if (${CLANG_USE_GCC_LINKER}) - set (cxx_linker_options_common ${cxx_linker_options_common} -pthread -dynamic) + set (cxx_linker_options_common ${cxx_linker_options_common} -pthread -dynamic -Wl,--fatal-warnings) if (${RUNTIME_STATIC_LINK}) set (cxx_linker_options_common ${cxx_linker_options_common} -static-libstdc++ -static-libgcc) # no way to statically link against libc? maybe we can on windows? endif () diff --git a/cmake/toolchains/include/Windows-GNU_common.inc.cmake b/cmake/toolchains/include/Windows-GNU_common.inc.cmake index 4912acc8e..3a5fd6cf9 100644 --- a/cmake/toolchains/include/Windows-GNU_common.inc.cmake +++ b/cmake/toolchains/include/Windows-GNU_common.inc.cmake @@ -86,6 +86,7 @@ function (toolchain_exe_stuff_common) #-- Store compiler flags common to all builds. set (cxx_local_opts_warnings + -Werror -Wall -Wextra -Wno-nonnull-compare -Wno-unknown-pragmas -Wno-switch -Wno-implicit-fallthrough -Wno-parentheses -Wno-misleading-indentation -Wno-conversion-null -Wno-unused-result -Wno-format-security # TODO: disable that when we'll have time to fix every printf format issue @@ -126,7 +127,7 @@ function (toolchain_exe_stuff_common) IF (${USE_MSAN}) SET (CMAKE_EXE_LINKER_FLAGS_EXTRA ${CMAKE_EXE_LINKER_FLAGS_EXTRA} -pie) ENDIF() - set (cxx_linker_options_common ${CMAKE_EXE_LINKER_FLAGS_EXTRA} -pthread -dynamic + set (cxx_linker_options_common ${CMAKE_EXE_LINKER_FLAGS_EXTRA} -pthread -dynamic -Wl,--fatal-warnings $<$: -static-libstdc++ -static-libgcc> # no way to statically link against libc? maybe we can on windows? ) diff --git a/src/game/CServer.cpp b/src/game/CServer.cpp index e09429a3b..fd64ff4fe 100644 --- a/src/game/CServer.cpp +++ b/src/game/CServer.cpp @@ -1818,8 +1818,10 @@ bool CServer::r_Verb( CScript &s, CTextConsole * pSrc ) break; } if ( ! g_World.Import( Arg_ppCmd[0], pSrc->GetChar(), - IMPFLAGS_BOTH|IMPFLAGS_ACCOUNT, INT16_MAX, - Arg_ppCmd[1], Arg_ppCmd[2] )) + IMPFLAGS_BOTH|IMPFLAGS_ACCOUNT, INT16_MAX, + 0, 0, + Arg_ppCmd[1], Arg_ppCmd[2] ) + ) { if (pSrc != this) { diff --git a/src/game/CWorld.h b/src/game/CWorld.h index 6e573c9b6..ed8732c6a 100644 --- a/src/game/CWorld.h +++ b/src/game/CWorld.h @@ -231,8 +231,8 @@ extern class CWorld : public CScriptObj, public CWorldThread bool DumpAreas( CTextConsole * pSrc, lpctstr pszFilename ); void Close(); - bool Export(lpctstr pszFilename, const CChar* pSrc, word iModeFlags = IMPFLAGS_ITEMS, int iDist = INT16_MAX, int dx = 0, int dy = 0); - bool Import(lpctstr pszFilename, const CChar* pSrc, word iModeFlags = IMPFLAGS_ITEMS, int iDist = INT16_MAX, int dx = 0, int dy = 0, + bool Export(lpctstr pszFilename, const CChar* pSrc, word iModeFlags = IMPFLAGS_ITEMS, int iDist = INT16_MAX, short dx = 0, short dy = 0); + bool Import(lpctstr pszFilename, const CChar* pSrc, word iModeFlags = IMPFLAGS_ITEMS, int iDist = INT16_MAX, short dx = 0, short dy = 0, tchar* pszAgs1 = nullptr, tchar* pszAgs2 = nullptr); virtual lpctstr GetName() const override { diff --git a/src/game/CWorldImport.cpp b/src/game/CWorldImport.cpp index f4632948e..0fa4f9b68 100644 --- a/src/game/CWorldImport.cpp +++ b/src/game/CWorldImport.cpp @@ -68,7 +68,7 @@ struct CImportFile void CheckLast(); void ImportFix(); bool ImportSCP( CScript & s, word wModeFlags ); - bool ImportWSC( CScript & s, word wModeFlags, int dx, int dy ); + bool ImportWSC( CScript & s, word wModeFlags, short dx, short dy ); }; void CImportFile::CheckLast() @@ -302,7 +302,7 @@ bool CImportFile::ImportSCP( CScript & s, word wModeFlags ) return true; } -bool CImportFile::ImportWSC( CScript & s, word wModeFlags, int dx, int dy ) +bool CImportFile::ImportWSC( CScript & s, word wModeFlags, short dx, short dy ) { ADDTOCALLSTACK("CImportFile::ImportWSC"); // This file is a WSC or UOX world script file. @@ -773,7 +773,7 @@ bool CImportFile::ImportWSC( CScript & s, word wModeFlags, int dx, int dy ) return true; } -bool CWorld::Import( lpctstr pszFilename, const CChar * pSrc, word wModeFlags, int iDist, int dx, int dy, tchar * pszArg1, tchar * pszArg2 ) +bool CWorld::Import( lpctstr pszFilename, const CChar * pSrc, word wModeFlags, int iDist, short dx, short dy, tchar * pszArg1, tchar * pszArg2 ) { ADDTOCALLSTACK("CWorld::Import"); // wModeFlags = IMPFLAGS_TYPE @@ -861,7 +861,7 @@ bool CWorld::DumpAreas( CTextConsole * pSrc, lpctstr pszFilename ) -bool CWorld::Export( lpctstr pszFilename, const CChar * pSrc, word wModeFlags, int iDist, int dx, int dy ) +bool CWorld::Export( lpctstr pszFilename, const CChar * pSrc, word wModeFlags, int iDist, short dx, short dy ) { ADDTOCALLSTACK("CWorld::Export"); // wModeFlags = IMPFLAGS_TYPE From 7ecb5945cf6906713c1eba42a70b4283248d814c Mon Sep 17 00:00:00 2001 From: cbnolok Date: Thu, 5 Sep 2024 21:13:53 +0200 Subject: [PATCH 20/86] Fixed some leftover code, re-added fix from a PR not fully merged --- Changelog.txt | 6 +++++- src/game/CComponentProps.h | 1 - src/game/chars/CCharSkill.cpp | 4 ++-- src/game/components/CCPropsChar.cpp | 2 +- 4 files changed, 8 insertions(+), 5 deletions(-) diff --git a/Changelog.txt b/Changelog.txt index c784b2348..295220e34 100644 --- a/Changelog.txt +++ b/Changelog.txt @@ -3861,10 +3861,14 @@ Added: 'H' shortcut for variables to get the value as hexadecimal. 10-08-2024, Gladie - Fixed: CAN_I_DAMAGEABLE not updating status bar (PR #1259, issues #1248, #1260). -29-08-2024, Nolok +05-09-2024, Nolok WARNING! POTENTIALLY BREAKING CHANGE! Scripts will need to be updated. - Changed: since there was too much data to be stored in the FACTION/SLAYER property, so that it sometimes couldn't fit and caused issues, it has been split in two different properties: - FACTION/SLAYER_GROUP (expects a bitmask, max value of the usable flag: 0x800000), - FACTION/SLAYER_SPECIES (plain number, max value 255). SPECIES with index/value 1 are always considered to be SuperSlayers for their group. + Those properties are stored in the ComponentProps ItemEquippable and Char. +- Changed: SLAYER now works only on items, FACTION on characters. Before, they were synonyms and could be used on both chars and items to access the same property. +- Removed: unused properties SLAYER, SLAYER_LESSER, SLAYER_SUPER, SLAYER_MISC. +- Added: log message when a new thread is created or a thread is being renamed. diff --git a/src/game/CComponentProps.h b/src/game/CComponentProps.h index cbac17ed4..996b72280 100644 --- a/src/game/CComponentProps.h +++ b/src/game/CComponentProps.h @@ -17,7 +17,6 @@ class CClientTooltip; enum COMPPROPS_TYPE : uchar { - COMP_PROPS_FACTION, COMP_PROPS_ITEMCHAR, COMP_PROPS_CHAR, COMP_PROPS_ITEM, diff --git a/src/game/chars/CCharSkill.cpp b/src/game/chars/CCharSkill.cpp index ac5624c40..f32d016f6 100644 --- a/src/game/chars/CCharSkill.cpp +++ b/src/game/chars/CCharSkill.cpp @@ -3306,7 +3306,7 @@ int CChar::Skill_Act_Throwing( SKTRIG_TYPE stage ) { UpdateStatVal( STAT_DEX, -(ushort)( 4 + g_Rand.GetVal(6) ) ); if ( !g_Cfg.IsSkillFlag( Skill_GetActive(), SKF_NOANIM ) ) - UpdateAnimate( ANIM_MON_Stomp ); + UpdateAnimate( ANIM_THROW ); _SetTimeout(3000); return 0; @@ -3315,7 +3315,7 @@ int CChar::Skill_Act_Throwing( SKTRIG_TYPE stage ) if ( stage != SKTRIG_SUCCESS ) return -SKTRIG_QTY; - CPointMap pntMe = GetTopPoint(); + const CPointMap pntMe(GetTopPoint()); if ( pntMe.GetDist( m_Act_p ) > UO_MAP_VIEW_SIGHT ) m_Act_p.StepLinePath( pntMe, UO_MAP_VIEW_SIGHT ); diff --git a/src/game/components/CCPropsChar.cpp b/src/game/components/CCPropsChar.cpp index 92433ba4a..9358fa6ad 100644 --- a/src/game/components/CCPropsChar.cpp +++ b/src/game/components/CCPropsChar.cpp @@ -134,7 +134,7 @@ void CCPropsChar::SetPropertyNum(PropertyIndex_t iPropIndex, PropertyValNum_t iV _faction.SetSpecies(num_alias_cast(iVal)); return; } - + else { _mPropsNum[iPropIndex] = iVal; //_mPropsNum.container.shrink_to_fit(); From 5c5f9623e19c0e1d387587e1d07ea84c780452be Mon Sep 17 00:00:00 2001 From: cbnolok Date: Fri, 6 Sep 2024 11:14:50 +0200 Subject: [PATCH 21/86] Save SLAYER/FACTION* properties in worldsave files. Fixed some wrong ASSERTs in stypecast.h. --- src/common/assertion.h | 6 +-- src/common/sphere_library/stypecast.h | 42 ++++++++++++++++--- src/game/components/CCPropsChar.cpp | 5 +++ src/game/components/CCPropsItemEquippable.cpp | 5 +++ src/sphere/threads.cpp | 40 +++++++++--------- 5 files changed, 69 insertions(+), 29 deletions(-) diff --git a/src/common/assertion.h b/src/common/assertion.h index 7e5f90b3f..07558b259 100644 --- a/src/common/assertion.h +++ b/src/common/assertion.h @@ -9,19 +9,19 @@ extern void Assert_Fail(const char * pExp, const char *pFile, long long llLine); -#define PERSISTANT_ASSERT(exp) [[unlikely]] if ( !(exp) ) Assert_Fail(#exp, __FILE__, __LINE__) +#define PERSISTANT_ASSERT(exp) if ( !(exp) ) [[unlikely]] Assert_Fail(#exp, __FILE__, __LINE__) #if defined(STATIC_ANALYSIS) #include #define ASSERT(exp) assert(exp) #elif defined(_NIGHTLY) || defined(_DEBUG) - #define ASSERT(exp) [[unlikely]] if ( !(exp) ) Assert_Fail(#exp, __FILE__, __LINE__) + #define ASSERT(exp) if ( !(exp) ) [[unlikely]] Assert_Fail(#exp, __FILE__, __LINE__) #else #define ASSERT(exp) (void)0 #endif #if defined(_DEBUG) || defined(STATIC_ANALYSIS) - #define DEBUG_ASSERT(exp) [[unlikely]] if ( !(exp) ) Assert_Fail(#exp, __FILE__, __LINE__) + #define DEBUG_ASSERT(exp) if ( !(exp) ) [[unlikely]] Assert_Fail(#exp, __FILE__, __LINE__) #else #define DEBUG_ASSERT(exp) (void)0 #endif diff --git a/src/common/sphere_library/stypecast.h b/src/common/sphere_library/stypecast.h index a59d05601..c622b7265 100644 --- a/src/common/sphere_library/stypecast.h +++ b/src/common/sphere_library/stypecast.h @@ -155,7 +155,12 @@ template [[nodiscard]] inline auto n64_narrow_n32_checked(const T a) { - ASSERT(a <= std::numeric_limits::max()); + if constexpr (std::is_signed_v) { + ASSERT(a <= std::numeric_limits::max()); + } + else { + ASSERT(a <= std::numeric_limits::max()); + } return n64_narrow_n32(a); } @@ -194,7 +199,12 @@ template [[nodiscard]] inline auto n64_narrow_n16_checked(const T a) { - ASSERT(a <= std::numeric_limits::max()); + if constexpr (std::is_signed_v) { + ASSERT(a <= std::numeric_limits::max()); + } + else { + ASSERT(a <= std::numeric_limits::max()); + } return n64_narrow_n16(a); } @@ -229,7 +239,12 @@ template [[nodiscard]] inline auto n64_narrow_n8_checked(const T a) { - ASSERT(a <= std::numeric_limits::max()); + if constexpr (std::is_signed_v) { + ASSERT(a <= std::numeric_limits::max()); + } + else { + ASSERT(a <= std::numeric_limits::max()); + } return n64_narrow_n8(a); } @@ -267,7 +282,12 @@ template [[nodiscard]] inline auto n32_narrow_n16_checked(const T a) { - ASSERT(a <= std::numeric_limits::max()); + if constexpr (std::is_signed_v) { + ASSERT(a <= std::numeric_limits::max()); + } + else { + ASSERT(a <= std::numeric_limits::max()); + } return n32_narrow_n16(a); } @@ -300,7 +320,12 @@ template [[nodiscard]] inline auto n32_narrow_n8_checked(const T a) { - ASSERT(a <= std::numeric_limits::max()); + if constexpr (std::is_signed_v) { + ASSERT(a <= std::numeric_limits::max()); + } + else { + ASSERT(a <= std::numeric_limits::max()); + } return n32_narrow_n8(a); } @@ -334,7 +359,12 @@ template [[nodiscard]] inline auto n16_narrow_n8_checked(const T a) { - ASSERT(a <= std::numeric_limits::max()); + if constexpr (std::is_signed_v) { + ASSERT(a <= std::numeric_limits::max()); + } + else { + ASSERT(a <= std::numeric_limits::max()); + } return n16_narrow_n8(a); } diff --git a/src/game/components/CCPropsChar.cpp b/src/game/components/CCPropsChar.cpp index 9358fa6ad..fc0e55652 100644 --- a/src/game/components/CCPropsChar.cpp +++ b/src/game/components/CCPropsChar.cpp @@ -273,6 +273,9 @@ void CCPropsChar::r_Write(CScript & s) // r_Write isn't called by CItemBase/CCharBase, so we don't get base props saved BaseCont_Write_ContNum(&_mPropsNum, _ptcPropertyKeys, s); BaseCont_Write_ContStr(&_mPropsStr, _ptcPropertyKeys, s); + + s.WriteKeyVal(_ptcPropertyKeys[PROPCH_FACTION_GROUP], num_alias_cast(_faction.GetGroup())); + s.WriteKeyVal(_ptcPropertyKeys[PROPCH_FACTION_SPECIES], num_alias_cast(_faction.GetSpecies())); } void CCPropsChar::Copy(const CComponentProps * target) @@ -284,6 +287,8 @@ void CCPropsChar::Copy(const CComponentProps * target) _mPropsNum = pTarget->_mPropsNum; _mPropsStr = pTarget->_mPropsStr; + + _faction = pTarget->_faction; } void CCPropsChar::AddPropsTooltipData(CObjBase* pLinkedObj) diff --git a/src/game/components/CCPropsItemEquippable.cpp b/src/game/components/CCPropsItemEquippable.cpp index 028047af3..87b69ad55 100644 --- a/src/game/components/CCPropsItemEquippable.cpp +++ b/src/game/components/CCPropsItemEquippable.cpp @@ -216,6 +216,9 @@ void CCPropsItemEquippable::r_Write(CScript & s) // r_Write isn't called by CItemBase/CCharBase, so we don't get base props saved BaseCont_Write_ContNum(&_mPropsNum, _ptcPropertyKeys, s); BaseCont_Write_ContStr(&_mPropsStr, _ptcPropertyKeys, s); + + s.WriteKeyVal(_ptcPropertyKeys[PROPIEQUIP_SLAYER_GROUP], num_alias_cast(_faction.GetGroup())); + s.WriteKeyVal(_ptcPropertyKeys[PROPIEQUIP_SLAYER_SPECIES], num_alias_cast(_faction.GetSpecies())); } void CCPropsItemEquippable::Copy(const CComponentProps * target) @@ -228,6 +231,8 @@ void CCPropsItemEquippable::Copy(const CComponentProps * target) } _mPropsNum = pTarget->_mPropsNum; _mPropsStr = pTarget->_mPropsStr; + + _faction = pTarget->_faction; } void CCPropsItemEquippable::AddPropsTooltipData(CObjBase* pLinkedObj) diff --git a/src/sphere/threads.cpp b/src/sphere/threads.cpp index 2b9caeda9..1ecfd5f85 100644 --- a/src/sphere/threads.cpp +++ b/src/sphere/threads.cpp @@ -146,8 +146,8 @@ IThread* ThreadHolder::current() noexcept RETRY_SHARED_LOCK_FOR_TASK(m_mutex, lock, retval, ([this, &lock]() -> IThread* { - [[unlikely]] if (m_closingThreads) + [[unlikely]] { //STDERR_LOG("Closing?\n"); return nullptr; @@ -155,12 +155,12 @@ IThread* ThreadHolder::current() noexcept const threadid_t tid = IThread::getCurrentThreadSystemId(); - [[unlikely]] if (m_spherethreadpairs_systemid_ptr.empty()) + [[unlikely]] { auto thread = static_cast(DummySphereThread::getInstance()); - [[unlikely]] if (!thread) + [[unlikely]] { // Should never happen. RaiseImmediateAbort(); @@ -181,8 +181,8 @@ IThread* ThreadHolder::current() noexcept break; } } - [[unlikely]] if (!found) + [[unlikely]] { //throw CSError(LOGL_FATAL, 0, "Thread handle not found in vector?"); //STDERR_LOG("Thread handle not found in vector?"); @@ -195,8 +195,8 @@ IThread* ThreadHolder::current() noexcept ASSERT(thread->m_threadHolderId != -1); SphereThreadData *tdata = &(m_threads[thread->m_threadHolderId]); - [[unlikely]] if (tdata->m_closed) + [[unlikely]] { //STDERR_LOG("Closed? Idx %u, Name %s.\n", thread->m_threadHolderId, thread->getName()); return nullptr; @@ -350,16 +350,20 @@ IThread * ThreadHolder::getThreadAt(size_t at) noexcept { // MSVC: warning C5101: use of preprocessor directive in function-like macro argument list is undefined behavior. //#ifdef _DEBUG - [[unlikely]] if (getActiveThreads() != m_threads.size()) + [[unlikely]] { STDERR_LOG("Active threads %" PRIuSIZE_T ", threads container size %" PRIuSIZE_T ".\n", getActiveThreads(), m_threads.size()); RaiseImmediateAbort(); } //#endif - [[unlikely]] + if ( at > getActiveThreads() ) + [[unlikely]] + { return nullptr; + } + /* for ( spherethreadlist_t::const_iterator it = m_threads.begin(), end = m_threads.end(); it != end; ++it ) @@ -850,17 +854,15 @@ void AbstractSphereThread::exceptionCaught() static thread_local ssize_t _stackpos = -1; void AbstractSphereThread::pushStackCall(const char *name) noexcept { - [[unlikely]] - if (m_freezeCallStack == true) + if (m_freezeCallStack == true) [[unlikely]] { return; + } #ifdef _DEBUG - [[unlikely]] - if (m_stackPos < -1) { + if (m_stackPos < -1) [[unlikely]] { RaiseImmediateAbort(); } - [[unlikely]] - if (m_stackPos >= (ssize_t)sizeof(m_stackInfo)) { + if (m_stackPos >= (ssize_t)sizeof(m_stackInfo)) [[unlikely]] { RaiseImmediateAbort(); } #endif @@ -969,34 +971,32 @@ StackDebugInformation::StackDebugInformation(const char *name) noexcept STATIC_ASSERT_NOEXCEPT_MEMBER_FUNCTION(AbstractSphereThread, pushStackCall, const char*); auto& th = ThreadHolder::get(); - [[unlikely]] - if (th.closing()) + if (th.closing()) [[unlikely]] return; IThread *icontext = th.current(); - [[unlikely]] if (icontext == nullptr) + [[unlikely]] { // Thread was deleted, manually or by app closing signal. return; } m_context = static_cast(icontext); - [[likely]] if (m_context != nullptr && !m_context->closing()) { + [[unlikely]] m_context->pushStackCall(name); } } StackDebugInformation::~StackDebugInformation() noexcept { - [[unlikely]] - if (!m_context || m_context->closing()) + if (!m_context || m_context->closing()) [[unlikely]] return; - [[unlikely]] if (std::uncaught_exceptions() != 0) + [[unlikely]] { // Exception was thrown and stack unwinding is in progress. m_context->exceptionNotifyStackUnwinding(); From 19351c4b3bdaf06196a97fdfd6190c3e782ec883 Mon Sep 17 00:00:00 2001 From: cbnolok Date: Fri, 6 Sep 2024 11:15:22 +0200 Subject: [PATCH 22/86] Added an sh script to automate reformatting of cmake files. --- utilities/format_cmake.sh | 64 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 64 insertions(+) create mode 100644 utilities/format_cmake.sh diff --git a/utilities/format_cmake.sh b/utilities/format_cmake.sh new file mode 100644 index 000000000..9151cab66 --- /dev/null +++ b/utilities/format_cmake.sh @@ -0,0 +1,64 @@ +#!/bin/bash + +# Check if a parameter is provided +if [ "$#" -ne 1 ]; then + echo "Usage: $0 [--all|--changed|--last-commit] [--autocommit]" + exit 1 +fi + +action=$1 + +# Define the gersemi command +gersemi_cmd='gersemi -i "{}" --list-expansion favour-inlining --no-warn-about-unknown-commands' +#looks like cmake-format is unmantained +#cmake-format CMakeLists.txt --separate-ctrl-name-with-space --separate-fn-name-with-space --dangle-parens --max-subgroups-hwrap=2 --max-pargs-hwrap=4 --max-rows-cmdline=120 + +# Function to format files +format_files() { + echo "$1" | \ + xargs -P 4 -I {} sh -c ' + if [ -f "{}" ]; then + echo "Formatting {}" + '"$gersemi_cmd"' + else + echo "{} does not exist" + fi + ' +} + +# Case to determine the files based on the action +case $action in + --all) + # Find all *.cmake files and CMakeLists.txt + files=$(find "$(git rev-parse --show-toplevel)" \ + -type d -name 'CMakeFiles' -prune -o \ + -type d -name 'build' -prune -o \ + -type d -name '.*' -prune -o \ + -type f \( -name "*.cmake" -o -name "CMakeLists.txt" \) -print) + ;; + --changed) + # Get modified and staged files (combined) + unstaged_files=$(git diff --name-only) + staged_files=$(git diff --cached --name-only) + files=$( (echo "$unstaged_files" && echo "$staged_files") | sort | uniq | grep -E '\.cmake$|CMakeLists\.txt$') + ;; + --last-commit) + # Get only the files modified by the last commit + files=$( git diff --name-only HEAD~1 HEAD | grep -E '\.cmake$|CMakeLists\.txt$' ) + ;; + *) + echo "Invalid option. Use '--all' or '--changed'." + exit 1 + ;; +esac + +# Call the formatting function +format_files "$files" + +# Check if --autocommit flag is passed +if [[ "$2" == "--autocommit" ]]; then + echo "$files" | xargs git add + #git commit --amend --no-edit + git commit --no-edit -m "Auto commit: re-formatted cmake files." + echo "Previous commit amended with the staged files." +fi From 8646403d812e91c1d70b42ee3ec1a394379a921b Mon Sep 17 00:00:00 2001 From: cbnolok Date: Sat, 7 Sep 2024 19:10:44 +0200 Subject: [PATCH 23/86] Fixed SLAYER/FACTION_GROUP/SPECIES not being correctly loaded from the base def. Splitted num_alias_cast into n_alias_cast and enum_alias_cast. --- src/common/sphere_library/stypecast.h | 61 +++++++++++++++++-- src/game/CComponentProps.cpp | 8 +-- src/game/CComponentProps.h | 6 +- src/game/CObjBase.cpp | 3 +- src/game/CWorldImport.cpp | 14 ++--- src/game/chars/CCharAct.cpp | 3 +- src/game/components/CCPropsChar.cpp | 42 ++++++++----- src/game/components/CCPropsChar.h | 4 +- src/game/components/CCPropsItem.cpp | 14 +++-- src/game/components/CCPropsItem.h | 4 +- src/game/components/CCPropsItemChar.cpp | 15 +++-- src/game/components/CCPropsItemChar.h | 4 +- src/game/components/CCPropsItemEquippable.cpp | 39 +++++++----- src/game/components/CCPropsItemEquippable.h | 4 +- src/game/components/CCPropsItemWeapon.cpp | 14 +++-- src/game/components/CCPropsItemWeapon.h | 4 +- .../components/CCPropsItemWeaponRanged.cpp | 14 +++-- src/game/components/CCPropsItemWeaponRanged.h | 4 +- .../components/subcomponents/CFactionDef.cpp | 22 +++---- src/network/packet.cpp | 2 +- 20 files changed, 181 insertions(+), 100 deletions(-) diff --git a/src/common/sphere_library/stypecast.h b/src/common/sphere_library/stypecast.h index c622b7265..d450be93b 100644 --- a/src/common/sphere_library/stypecast.h +++ b/src/common/sphere_library/stypecast.h @@ -5,20 +5,71 @@ #include #include +// Helper template to work on enum types. + +// Primary template for non-enum types, T will simply be itself +template +struct underlying_or_self +{ + using type = T; +}; + +// Specialization for enum types, using SFINAE to enable only if T is an enum +template +struct underlying_or_self>> +{ + using type = std::underlying_type_t; +}; + +// Helper alias +template +using underlying_or_self_t = typename underlying_or_self::type; + // Use this as a double check, to be sure at compile time that the two variables have the same size and sign. template [[nodiscard]] -constexpr Tout num_alias_cast(const Tin a) noexcept +constexpr Tout n_alias_cast(const Tin a) noexcept { - static_assert(std::is_arithmetic_v || std::is_enum_v, "Input variable is not a numeric type."); - static_assert(std::is_arithmetic_v || std::is_enum_v, "Output variable is not a numeric type."); + static_assert(std::is_arithmetic_v, "Input variable is not an arithmetictype."); + static_assert(std::is_arithmetic_v, "Output variable is not an arithmetic type."); static_assert(sizeof(Tin) == sizeof(Tout), "Input and output types do not have the same size."); static_assert(!(std::is_signed_v && std::is_unsigned_v), "Casting signed to unsigned."); static_assert(!(std::is_signed_v && std::is_unsigned_v ), "Casting unsigned to signed."); return static_cast(a); } +template +[[nodiscard]] +constexpr Tout enum_alias_cast(const Tin a) noexcept +{ + static_assert(std::is_enum_v || std::is_enum_v, "Nor input nor output variables are an enum."); + static_assert(std::is_arithmetic_v || std::is_enum_v, "Input variable is not a numeric type."); + static_assert(std::is_arithmetic_v || std::is_enum_v, "Output variable is not a numeric type."); + static_assert(sizeof(Tin) == sizeof(Tout), "Input and output types do not have the same size."); + + static_assert(!(std::is_signed_v> && std::is_unsigned_v>), "Casting signed to unsigned."); + static_assert(!(std::is_signed_v> && std::is_unsigned_v> ), "Casting unsigned to signed."); + + /* + static_assert(std::is_enum_v || + !(std::is_signed_v> && std::is_unsigned_v), + "Casting unsigned to signed."); + static_assert(std::is_enum_v || + !(std::is_unsigned_v> && std::is_signed_v), + "Casting signed to unsigned."); + + static_assert(std::is_enum_v || + !(std::is_signed_v> && std::is_unsigned_v), + "Casting signed to unsigned."); + static_assert(std::is_enum_v || + !(std::is_unsigned_v> && std::is_signed_v), + "Casting unsigned to signed."); + */ + + return static_cast(a); +} + /* Unsigned (and size_t) to signed, clamping. */ @@ -502,7 +553,7 @@ int32 i32_from_usize_checked(const size_t a) // not clamping/capping #if SIZE_MAX == UINT64_MAX return i32_from_u32_clamping(n64_narrow_n32_checked(a)); #elif SIZE_MAX == UINT32_MAX - return i32_from_u32_checked(num_alias_cast(a)); + return i32_from_u32_checked(n_alias_cast(a)); #else # error "size_t is neither 8 nor 4 bytes?" #endif @@ -513,7 +564,7 @@ template int32 i32_from_usize_checked(T) = delete; // disable impli int64 i64_from_usize_checked(const size_t a) // not clamping/capping { #if SIZE_MAX == UINT64_MAX - return i64_from_u64_checked(num_alias_cast(a)); + return i64_from_u64_checked(n_alias_cast(a)); #elif SIZE_MAX == UINT32_MAX return static_cast(a); // For sure it will fit #else diff --git a/src/game/CComponentProps.cpp b/src/game/CComponentProps.cpp index a5f96353f..df386ed20 100644 --- a/src/game/CComponentProps.cpp +++ b/src/game/CComponentProps.cpp @@ -35,13 +35,13 @@ bool CComponentProps::BaseCont_GetPropertyStr(const BaseContStr_t* container, Pr return false; } -void CComponentProps::BaseProp_LoadPropVal(PropertyIndex_t iPropIndex, bool fPropStr, CScript & s, CObjBase* pLinkedObj, RESDISPLAY_VERSION iLimitToExpansion) +bool CComponentProps::BaseProp_LoadPropVal(PropertyIndex_t iPropIndex, bool fPropStr, CScript & s, CObjBase* pLinkedObj, RESDISPLAY_VERSION iLimitToExpansion) { ADDTOCALLSTACK("CComponentProps::BaseProp_LoadPropVal"); if (fPropStr) - SetPropertyStr(iPropIndex, s.GetArgStr(), pLinkedObj, iLimitToExpansion, true); + return SetPropertyStr(iPropIndex, s.GetArgStr(), pLinkedObj, iLimitToExpansion, true); else - SetPropertyNum(iPropIndex, s.GetArgVal(), pLinkedObj, iLimitToExpansion, true); + return SetPropertyNum(iPropIndex, s.GetArgVal(), pLinkedObj, iLimitToExpansion, true); } bool CComponentProps::BaseProp_WritePropVal(PropertyIndex_t iPropIndex, bool fPropStr, CSString & sVal) const @@ -98,4 +98,4 @@ CSString CComponentProps::GetPropertyStr(PropertyIndex_t iPropIndex, bool fZero) CSString sRet; GetPropertyStrPtr(iPropIndex, &sRet, fZero); return sRet; -} \ No newline at end of file +} diff --git a/src/game/CComponentProps.h b/src/game/CComponentProps.h index 996b72280..f8cee1db3 100644 --- a/src/game/CComponentProps.h +++ b/src/game/CComponentProps.h @@ -86,7 +86,7 @@ class CComponentProps *@param iLimitToExpansion This EntityProps accepts/stores/uses properties only up to this expansion. *@param fDeleteZero If true, if iVal == 0 or is empty, delete the prop (if already existing) */ - virtual void SetPropertyNum(PropertyIndex_t iPropIndex, PropertyValNum_t iVal, CObjBase* pLinkedObj, RESDISPLAY_VERSION iLimitToExpansion, bool fDeleteZero = true) = 0; + virtual bool SetPropertyNum(PropertyIndex_t iPropIndex, PropertyValNum_t iVal, CObjBase* pLinkedObj, RESDISPLAY_VERSION iLimitToExpansion, bool fDeleteZero = true) = 0; /* *@brief Set the string value for the given property @@ -96,7 +96,7 @@ class CComponentProps *@param iLimitToExpansion This EntityProps accepts/stores/uses properties only up to this expansion. *@param fDeleteZero If true, if ptcVal == nullptr or is empty, delete the prop (if already existing) */ - virtual void SetPropertyStr(PropertyIndex_t iPropIndex, lpctstr ptcVal, CObjBase* pLinkedObj, RESDISPLAY_VERSION iLimitToExpansion, bool fDeleteZero = true) = 0; + virtual bool SetPropertyStr(PropertyIndex_t iPropIndex, lpctstr ptcVal, CObjBase* pLinkedObj, RESDISPLAY_VERSION iLimitToExpansion, bool fDeleteZero = true) = 0; /* @brief Delete the numerical property at the given index @@ -131,7 +131,7 @@ class CComponentProps protected: bool BaseCont_GetPropertyNum(const BaseContNum_t* container, PropertyIndex_t iPropIndex, PropertyValNum_t* piOutVal) const; bool BaseCont_GetPropertyStr(const BaseContStr_t* container, PropertyIndex_t iPropIndex, CSString *psOutVal, bool fZero = false) const; - void BaseProp_LoadPropVal(PropertyIndex_t iPropIndex, bool fPropStr, CScript & s, CObjBase* pLinkedObj, RESDISPLAY_VERSION iLimitToExpansion); + bool BaseProp_LoadPropVal(PropertyIndex_t iPropIndex, bool fPropStr, CScript & s, CObjBase* pLinkedObj, RESDISPLAY_VERSION iLimitToExpansion); bool BaseProp_WritePropVal(PropertyIndex_t iPropIndex, bool fPropStr, CSString & sVal) const; static void BaseCont_Write_ContNum(const BaseContNum_t* container, const lpctstr *ptcPropsTable, CScript &s); static void BaseCont_Write_ContStr(const BaseContStr_t* container, const lpctstr *ptcPropsTable, CScript &s); diff --git a/src/game/CObjBase.cpp b/src/game/CObjBase.cpp index 934303f67..435377476 100644 --- a/src/game/CObjBase.cpp +++ b/src/game/CObjBase.cpp @@ -3646,7 +3646,7 @@ bool CObjBase::CallPersonalTrigger(tchar * pArgs, CTextConsole * pSrc, TRIGRET_T if ( pTriggerArgObj ) csTriggerArgs.m_pO1 = pTriggerArgObj; } - else if ( iTriggerArgType == 4 ) // FULL TRIGGER + else if ( iTriggerArgType == 4 ) // FULLTRIGGER { tchar * Arg_ppCmd[5]; iResultArgs = Str_ParseCmds(ppCmdTrigger[2], Arg_ppCmd, ARRAY_COUNT(Arg_ppCmd), ","); @@ -3680,4 +3680,3 @@ bool CObjBase::CallPersonalTrigger(tchar * pArgs, CTextConsole * pSrc, TRIGRET_T return false; } - diff --git a/src/game/CWorldImport.cpp b/src/game/CWorldImport.cpp index 0fa4f9b68..2ad5f3a3c 100644 --- a/src/game/CWorldImport.cpp +++ b/src/game/CWorldImport.cpp @@ -599,7 +599,7 @@ bool CImportFile::ImportWSC( CScript & s, word wModeFlags, short dx, short dy ) if (!iconv.has_value()) return false; - pChar->SetID(num_alias_cast(*iconv)); + pChar->SetID(enum_alias_cast(*iconv)); continue; } else if ( s.IsKey("SKIN" )) @@ -608,7 +608,7 @@ bool CImportFile::ImportWSC( CScript & s, word wModeFlags, short dx, short dy ) if (!iconv.has_value()) return false; - pChar->SetHue(num_alias_cast(*iconv)); + pChar->SetHue(n_alias_cast(*iconv)); continue; } else if ( s.IsKey("DIR" )) @@ -617,7 +617,7 @@ bool CImportFile::ImportWSC( CScript & s, word wModeFlags, short dx, short dy ) if (!iconv.has_value()) return false; - pChar->m_dirFace = num_alias_cast(*iconv); + pChar->m_dirFace = enum_alias_cast(*iconv); if ( (pChar->m_dirFace < 0) || (pChar->m_dirFace >= DIR_QTY) ) pChar->m_dirFace = DIR_SE; continue; @@ -628,7 +628,7 @@ bool CImportFile::ImportWSC( CScript & s, word wModeFlags, short dx, short dy ) if (!iconv.has_value()) return false; - pChar->_iPrev_id = num_alias_cast(*iconv); + pChar->_iPrev_id = enum_alias_cast(*iconv); continue; } else if ( s.IsKey("XSKIN" )) @@ -637,7 +637,7 @@ bool CImportFile::ImportWSC( CScript & s, word wModeFlags, short dx, short dy ) if (!iconv.has_value()) return false; - pChar->_wPrev_Hue = num_alias_cast(*iconv); + pChar->_wPrev_Hue = n_alias_cast(*iconv); continue; } else if ( s.IsKey("FONT" )) @@ -646,7 +646,7 @@ bool CImportFile::ImportWSC( CScript & s, word wModeFlags, short dx, short dy ) if (!iconv.has_value()) return false; - pChar->m_fonttype = num_alias_cast(*iconv); + pChar->m_fonttype = enum_alias_cast(*iconv); continue; } else if ( s.IsKey("KARMA" )) @@ -727,7 +727,7 @@ bool CImportFile::ImportWSC( CScript & s, word wModeFlags, short dx, short dy ) if (!iconv_int.has_value()) return false; - const auto skill = num_alias_cast(*iconv_int); + const auto skill = enum_alias_cast(*iconv_int); std::optional iconv = Str_ToU16(pArg); if (!iconv.has_value()) diff --git a/src/game/chars/CCharAct.cpp b/src/game/chars/CCharAct.cpp index 6e3ac6137..fbad02be7 100644 --- a/src/game/chars/CCharAct.cpp +++ b/src/game/chars/CCharAct.cpp @@ -45,8 +45,9 @@ bool CChar::TeleportToObj( int iType, tchar * pszArgs ) iArg = ResGetIndex( Exp_GetVal( pszArgs )); } - while ( dwCount-- ) + while ( dwCount ) { + -- dwCount; if ( ++dwUID >= dwTotal ) { dwUID = 1; diff --git a/src/game/components/CCPropsChar.cpp b/src/game/components/CCPropsChar.cpp index fc0e55652..7c34a1664 100644 --- a/src/game/components/CCPropsChar.cpp +++ b/src/game/components/CCPropsChar.cpp @@ -93,15 +93,20 @@ bool CCPropsChar::GetPropertyNumPtr(PropertyIndex_t iPropIndex, PropertyValNum_t if (iPropIndex == PROPCH_FACTION_GROUP) { - *piOutVal = num_alias_cast(_faction.GetGroup()); + auto group = _faction.GetGroup(); + if (group == CFactionDef::Group::NONE) + return false; + *piOutVal = (int32)enum_alias_cast(group); return true; } else if (iPropIndex == PROPCH_FACTION_SPECIES) { - *piOutVal = num_alias_cast(_faction.GetSpecies()); + auto species = _faction.GetSpecies(); + if (species == CFactionDef::Species::NONE) + return false; + *piOutVal = (int32)enum_alias_cast(species); return true; } - return BaseCont_GetPropertyNum(&_mPropsNum, iPropIndex, piOutVal); } @@ -112,7 +117,7 @@ bool CCPropsChar::GetPropertyStrPtr(PropertyIndex_t iPropIndex, CSString* psOutV return BaseCont_GetPropertyStr(&_mPropsStr, iPropIndex, psOutVal, fZero); } -void CCPropsChar::SetPropertyNum(PropertyIndex_t iPropIndex, PropertyValNum_t iVal, CObjBase* pLinkedObj, RESDISPLAY_VERSION iLimitToExpansion, bool fDeleteZero) +bool CCPropsChar::SetPropertyNum(PropertyIndex_t iPropIndex, PropertyValNum_t iVal, CObjBase* pLinkedObj, RESDISPLAY_VERSION iLimitToExpansion, bool fDeleteZero) { ADDTOCALLSTACK("CCPropsChar::SetPropertyNum"); ASSERT(!IsPropertyStr(iPropIndex)); @@ -121,18 +126,16 @@ void CCPropsChar::SetPropertyNum(PropertyIndex_t iPropIndex, PropertyValNum_t iV if ((fDeleteZero && (iVal == 0)) || (_iPropertyExpansion[iPropIndex] > iLimitToExpansion) /*|| IgnoreElementalProperty(iPropIndex)*/) { if (0 == _mPropsNum.erase(iPropIndex)) - return; // I didn't have this property, so avoid further processing. + return true; // I didn't have this property, so avoid further processing. } else if (iPropIndex == PROPCH_FACTION_GROUP) { - _faction.SetGroup(num_alias_cast(iVal)); - return; + return _faction.SetGroup(enum_alias_cast(uint32(iVal))); } else if (iPropIndex == PROPCH_FACTION_SPECIES) { - _faction.SetSpecies(num_alias_cast(iVal)); - return; + return _faction.SetSpecies(enum_alias_cast(uint32(iVal))); } else { @@ -141,7 +144,7 @@ void CCPropsChar::SetPropertyNum(PropertyIndex_t iPropIndex, PropertyValNum_t iV } if (!pLinkedObj) - return; + return true; // Do stuff to the pLinkedObj switch (iPropIndex) @@ -198,9 +201,11 @@ void CCPropsChar::SetPropertyNum(PropertyIndex_t iPropIndex, PropertyValNum_t iV //pLinkedObj->UpdatePropertyFlag(); break; } + + return true; } -void CCPropsChar::SetPropertyStr(PropertyIndex_t iPropIndex, lpctstr ptcVal, CObjBase* pLinkedObj, RESDISPLAY_VERSION iLimitToExpansion, bool fDeleteZero) +bool CCPropsChar::SetPropertyStr(PropertyIndex_t iPropIndex, lpctstr ptcVal, CObjBase* pLinkedObj, RESDISPLAY_VERSION iLimitToExpansion, bool fDeleteZero) { ADDTOCALLSTACK("CCPropsChar::SetPropertyStr"); ASSERT(ptcVal); @@ -210,7 +215,7 @@ void CCPropsChar::SetPropertyStr(PropertyIndex_t iPropIndex, lpctstr ptcVal, COb if ((fDeleteZero && (*ptcVal == '\0')) || (_iPropertyExpansion[iPropIndex] > iLimitToExpansion) /*|| IgnoreElementalProperty(iPropIndex)*/) { if (0 == _mPropsNum.erase(iPropIndex)) - return; // I didn't have this property, so avoid further processing. + return true; // I didn't have this property, so avoid further processing. } else { @@ -219,10 +224,12 @@ void CCPropsChar::SetPropertyStr(PropertyIndex_t iPropIndex, lpctstr ptcVal, COb } if (!pLinkedObj) - return; + return true; // Do stuff to the pLinkedObj - //pLinkedObj->UpdatePropertyFlag(); + pLinkedObj->UpdatePropertyFlag(); + + return true; } void CCPropsChar::DeletePropertyNum(PropertyIndex_t iPropIndex) @@ -240,6 +247,7 @@ void CCPropsChar::DeletePropertyStr(PropertyIndex_t iPropIndex) bool CCPropsChar::FindLoadPropVal(CScript & s, CObjBase* pLinkedObj, RESDISPLAY_VERSION iLimitToExpansion, PropertyIndex_t iPropIndex, bool fPropStr) { ADDTOCALLSTACK("CCPropsChar::FindLoadPropVal"); + if (iPropIndex == PROPCH_NIGHTSIGHT) { // Special case if it has empty args: Keep old 'switch' from 0 to 1 and viceversa behaviour @@ -274,8 +282,10 @@ void CCPropsChar::r_Write(CScript & s) BaseCont_Write_ContNum(&_mPropsNum, _ptcPropertyKeys, s); BaseCont_Write_ContStr(&_mPropsStr, _ptcPropertyKeys, s); - s.WriteKeyVal(_ptcPropertyKeys[PROPCH_FACTION_GROUP], num_alias_cast(_faction.GetGroup())); - s.WriteKeyVal(_ptcPropertyKeys[PROPCH_FACTION_SPECIES], num_alias_cast(_faction.GetSpecies())); + if (_faction.GetGroup() != CFactionDef::Group::NONE) + s.WriteKeyVal(_ptcPropertyKeys[PROPCH_FACTION_GROUP], (int64)enum_alias_cast(_faction.GetGroup())); + if (_faction.GetSpecies() != CFactionDef::Species::NONE) + s.WriteKeyVal(_ptcPropertyKeys[PROPCH_FACTION_SPECIES], (int64)enum_alias_cast(_faction.GetSpecies())); } void CCPropsChar::Copy(const CComponentProps * target) diff --git a/src/game/components/CCPropsChar.h b/src/game/components/CCPropsChar.h index 78402b63f..96e1586e7 100644 --- a/src/game/components/CCPropsChar.h +++ b/src/game/components/CCPropsChar.h @@ -43,8 +43,8 @@ class CCPropsChar : public CComponentProps virtual bool IsPropertyStr(PropertyIndex_t iPropIndex) const override; virtual bool GetPropertyNumPtr(PropertyIndex_t iPropIndex, PropertyValNum_t* piOutVal) const override; virtual bool GetPropertyStrPtr(PropertyIndex_t iPropIndex, CSString *psOutVal, bool fZero = false) const override; - virtual void SetPropertyNum(PropertyIndex_t iPropIndex, PropertyValNum_t iVal, CObjBase* pLinkedObj, RESDISPLAY_VERSION iLimitToExpansion = RDS_PRET2A, bool fDeleteZero = true) override; - virtual void SetPropertyStr(PropertyIndex_t iPropIndex, lpctstr ptcVal, CObjBase* pLinkedObj, RESDISPLAY_VERSION iLimitToExpansion = RDS_PRET2A, bool fDeleteZero = true) override; + virtual bool SetPropertyNum(PropertyIndex_t iPropIndex, PropertyValNum_t iVal, CObjBase* pLinkedObj, RESDISPLAY_VERSION iLimitToExpansion = RDS_PRET2A, bool fDeleteZero = true) override; + virtual bool SetPropertyStr(PropertyIndex_t iPropIndex, lpctstr ptcVal, CObjBase* pLinkedObj, RESDISPLAY_VERSION iLimitToExpansion = RDS_PRET2A, bool fDeleteZero = true) override; virtual void DeletePropertyNum(PropertyIndex_t iPropIndex) override; virtual void DeletePropertyStr(PropertyIndex_t iPropIndex) override; diff --git a/src/game/components/CCPropsItem.cpp b/src/game/components/CCPropsItem.cpp index b37b1e186..0a2a90426 100644 --- a/src/game/components/CCPropsItem.cpp +++ b/src/game/components/CCPropsItem.cpp @@ -71,7 +71,7 @@ bool CCPropsItem::GetPropertyStrPtr(PropertyIndex_t iPropIndex, CSString* psOutV return BaseCont_GetPropertyStr(&_mPropsStr, iPropIndex, psOutVal, fZero); } -void CCPropsItem::SetPropertyNum(PropertyIndex_t iPropIndex, PropertyValNum_t iVal, CObjBase* pLinkedObj, RESDISPLAY_VERSION iLimitToExpansion, bool fDeleteZero) +bool CCPropsItem::SetPropertyNum(PropertyIndex_t iPropIndex, PropertyValNum_t iVal, CObjBase* pLinkedObj, RESDISPLAY_VERSION iLimitToExpansion, bool fDeleteZero) { ADDTOCALLSTACK("CCPropsItem::SetPropertyNum"); ASSERT(!IsPropertyStr(iPropIndex)); @@ -80,7 +80,7 @@ void CCPropsItem::SetPropertyNum(PropertyIndex_t iPropIndex, PropertyValNum_t iV if ((fDeleteZero && (iVal == 0)) || (_iPropertyExpansion[iPropIndex] > iLimitToExpansion)) { if (0 == _mPropsNum.erase(iPropIndex)) - return; // I didn't have this property, so avoid further processing. + return true; // I didn't have this property, so avoid further processing. } else { @@ -89,13 +89,14 @@ void CCPropsItem::SetPropertyNum(PropertyIndex_t iPropIndex, PropertyValNum_t iV } if (!pLinkedObj) - return; + return true; // Do stuff to the pLinkedObj pLinkedObj->UpdatePropertyFlag(); + return true; } -void CCPropsItem::SetPropertyStr(PropertyIndex_t iPropIndex, lpctstr ptcVal, CObjBase* pLinkedObj, RESDISPLAY_VERSION iLimitToExpansion, bool fDeleteZero) +bool CCPropsItem::SetPropertyStr(PropertyIndex_t iPropIndex, lpctstr ptcVal, CObjBase* pLinkedObj, RESDISPLAY_VERSION iLimitToExpansion, bool fDeleteZero) { ADDTOCALLSTACK("CCPropsItem::SetPropertyStr"); ASSERT(ptcVal); @@ -105,7 +106,7 @@ void CCPropsItem::SetPropertyStr(PropertyIndex_t iPropIndex, lpctstr ptcVal, COb if ((fDeleteZero && (*ptcVal == '\0')) || (_iPropertyExpansion[iPropIndex] > iLimitToExpansion)) { if (0 == _mPropsNum.erase(iPropIndex)) - return; // I didn't have this property, so avoid further processing. + return true; // I didn't have this property, so avoid further processing. } else { @@ -114,10 +115,11 @@ void CCPropsItem::SetPropertyStr(PropertyIndex_t iPropIndex, lpctstr ptcVal, COb } if (!pLinkedObj) - return; + return true; // Do stuff to the pLinkedObj pLinkedObj->UpdatePropertyFlag(); + return true; } void CCPropsItem::DeletePropertyNum(PropertyIndex_t iPropIndex) diff --git a/src/game/components/CCPropsItem.h b/src/game/components/CCPropsItem.h index a252a2324..fd4f58421 100644 --- a/src/game/components/CCPropsItem.h +++ b/src/game/components/CCPropsItem.h @@ -41,8 +41,8 @@ class CCPropsItem : public CComponentProps virtual bool IsPropertyStr(PropertyIndex_t iPropIndex) const override; virtual bool GetPropertyNumPtr(PropertyIndex_t iPropIndex, PropertyValNum_t* piOutVal) const override; virtual bool GetPropertyStrPtr(PropertyIndex_t iPropIndex, CSString *psOutVal, bool fZero = false) const override; - virtual void SetPropertyNum(PropertyIndex_t iPropIndex, PropertyValNum_t iVal, CObjBase* pLinkedObj, RESDISPLAY_VERSION iLimitToExpansion = RDS_QTY, bool fDeleteZero = true) override; - virtual void SetPropertyStr(PropertyIndex_t iPropIndex, lpctstr ptcVal, CObjBase* pLinkedObj, RESDISPLAY_VERSION iLimitToExpansion = RDS_QTY, bool fDeleteZero = true) override; + virtual bool SetPropertyNum(PropertyIndex_t iPropIndex, PropertyValNum_t iVal, CObjBase* pLinkedObj, RESDISPLAY_VERSION iLimitToExpansion = RDS_QTY, bool fDeleteZero = true) override; + virtual bool SetPropertyStr(PropertyIndex_t iPropIndex, lpctstr ptcVal, CObjBase* pLinkedObj, RESDISPLAY_VERSION iLimitToExpansion = RDS_QTY, bool fDeleteZero = true) override; virtual void DeletePropertyNum(PropertyIndex_t iPropIndex) override; virtual void DeletePropertyStr(PropertyIndex_t iPropIndex) override; diff --git a/src/game/components/CCPropsItemChar.cpp b/src/game/components/CCPropsItemChar.cpp index f62b155dc..8348fb683 100644 --- a/src/game/components/CCPropsItemChar.cpp +++ b/src/game/components/CCPropsItemChar.cpp @@ -73,7 +73,7 @@ bool CCPropsItemChar::GetPropertyStrPtr(PropertyIndex_t iPropIndex, CSString* ps return BaseCont_GetPropertyStr(&_mPropsStr, iPropIndex, psOutVal, fZero); } -void CCPropsItemChar::SetPropertyNum(PropertyIndex_t iPropIndex, PropertyValNum_t iVal, CObjBase* pLinkedObj, RESDISPLAY_VERSION iLimitToExpansion, bool fDeleteZero) +bool CCPropsItemChar::SetPropertyNum(PropertyIndex_t iPropIndex, PropertyValNum_t iVal, CObjBase* pLinkedObj, RESDISPLAY_VERSION iLimitToExpansion, bool fDeleteZero) { ADDTOCALLSTACK("CCPropsItemChar::SetPropertyNum"); ASSERT(!IsPropertyStr(iPropIndex)); @@ -94,7 +94,7 @@ void CCPropsItemChar::SetPropertyNum(PropertyIndex_t iPropIndex, PropertyValNum_ if ((fDeleteZero && (iVal == 0)) || (_iPropertyExpansion[iPropIndex] > iLimitToExpansion)) { if (0 == _mPropsNum.erase(iPropIndex)) - return; // I didn't have this property, so avoid further processing. + return true; // I didn't have this property, so avoid further processing. } else { @@ -103,7 +103,7 @@ void CCPropsItemChar::SetPropertyNum(PropertyIndex_t iPropIndex, PropertyValNum_ } if (!pLinkedObj) - return; + return true; // Do stuff to the pLinkedObj switch (iPropIndex) @@ -128,9 +128,11 @@ void CCPropsItemChar::SetPropertyNum(PropertyIndex_t iPropIndex, PropertyValNum_ // pLinkedObj->UpdatePropertyFlag(); // break; } + + return true; } -void CCPropsItemChar::SetPropertyStr(PropertyIndex_t iPropIndex, lpctstr ptcVal, CObjBase* pLinkedObj, RESDISPLAY_VERSION iLimitToExpansion, bool fDeleteZero) +bool CCPropsItemChar::SetPropertyStr(PropertyIndex_t iPropIndex, lpctstr ptcVal, CObjBase* pLinkedObj, RESDISPLAY_VERSION iLimitToExpansion, bool fDeleteZero) { ADDTOCALLSTACK("CCPropsItemChar::SetPropertyStr"); ASSERT(ptcVal); @@ -140,7 +142,7 @@ void CCPropsItemChar::SetPropertyStr(PropertyIndex_t iPropIndex, lpctstr ptcVal, if ((fDeleteZero && (*ptcVal == '\0')) || (_iPropertyExpansion[iPropIndex] > iLimitToExpansion)) { if (0 == _mPropsNum.erase(iPropIndex)) - return; // I didn't have this property, so avoid further processing. + return true; // I didn't have this property, so avoid further processing. } else { @@ -149,10 +151,11 @@ void CCPropsItemChar::SetPropertyStr(PropertyIndex_t iPropIndex, lpctstr ptcVal, } if (!pLinkedObj) - return; + return true; // Do stuff to the pLinkedObj pLinkedObj->UpdatePropertyFlag(); + return true; } void CCPropsItemChar::DeletePropertyNum(PropertyIndex_t iPropIndex) diff --git a/src/game/components/CCPropsItemChar.h b/src/game/components/CCPropsItemChar.h index 8597f4375..e86f60908 100644 --- a/src/game/components/CCPropsItemChar.h +++ b/src/game/components/CCPropsItemChar.h @@ -41,8 +41,8 @@ class CCPropsItemChar : public CComponentProps virtual bool IsPropertyStr(PropertyIndex_t iPropIndex) const override; virtual bool GetPropertyNumPtr(PropertyIndex_t iPropIndex, PropertyValNum_t* piOutVal) const override; virtual bool GetPropertyStrPtr(PropertyIndex_t iPropIndex, CSString *psOutVal, bool fZero = false) const override; - virtual void SetPropertyNum(PropertyIndex_t iPropIndex, PropertyValNum_t iVal, CObjBase* pLinkedObj, RESDISPLAY_VERSION iLimitToExpansion = RDS_QTY, bool fDeleteZero = true) override; - virtual void SetPropertyStr(PropertyIndex_t iPropIndex, lpctstr ptcVal, CObjBase* pLinkedObj, RESDISPLAY_VERSION iLimitToExpansion = RDS_QTY, bool fDeleteZero = true) override; + virtual bool SetPropertyNum(PropertyIndex_t iPropIndex, PropertyValNum_t iVal, CObjBase* pLinkedObj, RESDISPLAY_VERSION iLimitToExpansion = RDS_QTY, bool fDeleteZero = true) override; + virtual bool SetPropertyStr(PropertyIndex_t iPropIndex, lpctstr ptcVal, CObjBase* pLinkedObj, RESDISPLAY_VERSION iLimitToExpansion = RDS_QTY, bool fDeleteZero = true) override; virtual void DeletePropertyNum(PropertyIndex_t iPropIndex) override; virtual void DeletePropertyStr(PropertyIndex_t iPropIndex) override; diff --git a/src/game/components/CCPropsItemEquippable.cpp b/src/game/components/CCPropsItemEquippable.cpp index 87b69ad55..10edf041f 100644 --- a/src/game/components/CCPropsItemEquippable.cpp +++ b/src/game/components/CCPropsItemEquippable.cpp @@ -98,12 +98,18 @@ bool CCPropsItemEquippable::GetPropertyNumPtr(PropertyIndex_t iPropIndex, Proper if (iPropIndex == PROPIEQUIP_SLAYER_GROUP) { - *piOutVal = num_alias_cast(_faction.GetGroup()); + auto group = _faction.GetGroup(); + if (group == CFactionDef::Group::NONE) + return false; + *piOutVal = (int32)enum_alias_cast(group); return true; } else if (iPropIndex == PROPIEQUIP_SLAYER_SPECIES) { - *piOutVal = num_alias_cast(_faction.GetSpecies()); + auto species = _faction.GetSpecies(); + if (species == CFactionDef::Species::NONE) + return false; + *piOutVal = (int32)enum_alias_cast(species); return true; } @@ -117,7 +123,7 @@ bool CCPropsItemEquippable::GetPropertyStrPtr(PropertyIndex_t iPropIndex, CSStri return BaseCont_GetPropertyStr(&_mPropsStr, iPropIndex, psOutVal, fZero); } -void CCPropsItemEquippable::SetPropertyNum(PropertyIndex_t iPropIndex, PropertyValNum_t iVal, CObjBase* pLinkedObj, RESDISPLAY_VERSION iLimitToExpansion, bool fDeleteZero) +bool CCPropsItemEquippable::SetPropertyNum(PropertyIndex_t iPropIndex, PropertyValNum_t iVal, CObjBase* pLinkedObj, RESDISPLAY_VERSION iLimitToExpansion, bool fDeleteZero) { ADDTOCALLSTACK("CCPropsItemEquippable::SetPropertyNum"); ASSERT(!IsPropertyStr(iPropIndex)); @@ -126,18 +132,18 @@ void CCPropsItemEquippable::SetPropertyNum(PropertyIndex_t iPropIndex, PropertyV if ((fDeleteZero && (iVal == 0)) || (_iPropertyExpansion[iPropIndex] > iLimitToExpansion) /*|| IgnoreElementalProperty(iPropIndex)*/) { if (0 == _mPropsNum.erase(iPropIndex)) - return; // I didn't have this property, so avoid further processing. + return true; // I didn't have this property, so avoid further processing. } else if (iPropIndex == PROPIEQUIP_SLAYER_GROUP) { - _faction.SetGroup(num_alias_cast(iVal)); - return; + _faction.SetGroup(enum_alias_cast((uint32)iVal)); + return true; } else if (iPropIndex == PROPIEQUIP_SLAYER_SPECIES) { - _faction.SetSpecies(num_alias_cast(iVal)); - return; + _faction.SetSpecies(enum_alias_cast((uint32)iVal)); + return true; } else @@ -147,13 +153,15 @@ void CCPropsItemEquippable::SetPropertyNum(PropertyIndex_t iPropIndex, PropertyV } if (!pLinkedObj) - return; + return true; // Do stuff to the pLinkedObj pLinkedObj->UpdatePropertyFlag(); + + return true; } -void CCPropsItemEquippable::SetPropertyStr(PropertyIndex_t iPropIndex, lpctstr ptcVal, CObjBase* pLinkedObj, RESDISPLAY_VERSION iLimitToExpansion, bool fDeleteZero) +bool CCPropsItemEquippable::SetPropertyStr(PropertyIndex_t iPropIndex, lpctstr ptcVal, CObjBase* pLinkedObj, RESDISPLAY_VERSION iLimitToExpansion, bool fDeleteZero) { ADDTOCALLSTACK("CCPropsItemEquippable::SetPropertyStr"); ASSERT(ptcVal); @@ -163,7 +171,7 @@ void CCPropsItemEquippable::SetPropertyStr(PropertyIndex_t iPropIndex, lpctstr p if ((fDeleteZero && (*ptcVal == '\0')) || (_iPropertyExpansion[iPropIndex] > iLimitToExpansion) /*|| IgnoreElementalProperty(iPropIndex)*/) { if (0 == _mPropsNum.erase(iPropIndex)) - return; // I didn't have this property, so avoid further processing. + return true; // I didn't have this property, so avoid further processing. } else { @@ -172,10 +180,11 @@ void CCPropsItemEquippable::SetPropertyStr(PropertyIndex_t iPropIndex, lpctstr p } if (!pLinkedObj) - return; + return true; // Do stuff to the pLinkedObj pLinkedObj->UpdatePropertyFlag(); + return true; } void CCPropsItemEquippable::DeletePropertyNum(PropertyIndex_t iPropIndex) @@ -217,8 +226,10 @@ void CCPropsItemEquippable::r_Write(CScript & s) BaseCont_Write_ContNum(&_mPropsNum, _ptcPropertyKeys, s); BaseCont_Write_ContStr(&_mPropsStr, _ptcPropertyKeys, s); - s.WriteKeyVal(_ptcPropertyKeys[PROPIEQUIP_SLAYER_GROUP], num_alias_cast(_faction.GetGroup())); - s.WriteKeyVal(_ptcPropertyKeys[PROPIEQUIP_SLAYER_SPECIES], num_alias_cast(_faction.GetSpecies())); + if (_faction.GetGroup() != CFactionDef::Group::NONE) + s.WriteKeyVal(_ptcPropertyKeys[PROPIEQUIP_SLAYER_GROUP], (int64)enum_alias_cast(_faction.GetGroup())); + if (_faction.GetSpecies() != CFactionDef::Species::NONE) + s.WriteKeyVal(_ptcPropertyKeys[PROPIEQUIP_SLAYER_SPECIES], (int64)enum_alias_cast(_faction.GetSpecies())); } void CCPropsItemEquippable::Copy(const CComponentProps * target) diff --git a/src/game/components/CCPropsItemEquippable.h b/src/game/components/CCPropsItemEquippable.h index 2406d1a62..35afcaadd 100644 --- a/src/game/components/CCPropsItemEquippable.h +++ b/src/game/components/CCPropsItemEquippable.h @@ -49,8 +49,8 @@ class CCPropsItemEquippable : public CComponentProps virtual bool IsPropertyStr(PropertyIndex_t iPropIndex) const override; virtual bool GetPropertyNumPtr(PropertyIndex_t iPropIndex, PropertyValNum_t* piOutVal) const override; virtual bool GetPropertyStrPtr(PropertyIndex_t iPropIndex, CSString *psOutVal, bool fZero = false) const override; - virtual void SetPropertyNum(PropertyIndex_t iPropIndex, PropertyValNum_t iVal, CObjBase* pLinkedObj, RESDISPLAY_VERSION iLimitToExpansion = RDS_QTY, bool fDeleteZero = true) override; - virtual void SetPropertyStr(PropertyIndex_t iPropIndex, lpctstr ptcVal, CObjBase* pLinkedObj, RESDISPLAY_VERSION iLimitToExpansion = RDS_QTY, bool fDeleteZero = true) override; + virtual bool SetPropertyNum(PropertyIndex_t iPropIndex, PropertyValNum_t iVal, CObjBase* pLinkedObj, RESDISPLAY_VERSION iLimitToExpansion = RDS_QTY, bool fDeleteZero = true) override; + virtual bool SetPropertyStr(PropertyIndex_t iPropIndex, lpctstr ptcVal, CObjBase* pLinkedObj, RESDISPLAY_VERSION iLimitToExpansion = RDS_QTY, bool fDeleteZero = true) override; virtual void DeletePropertyNum(PropertyIndex_t iPropIndex) override; virtual void DeletePropertyStr(PropertyIndex_t iPropIndex) override; diff --git a/src/game/components/CCPropsItemWeapon.cpp b/src/game/components/CCPropsItemWeapon.cpp index 20242746c..96c8909b2 100644 --- a/src/game/components/CCPropsItemWeapon.cpp +++ b/src/game/components/CCPropsItemWeapon.cpp @@ -122,7 +122,7 @@ bool CCPropsItemWeapon::GetPropertyStrPtr(PropertyIndex_t iPropIndex, CSString* } } -void CCPropsItemWeapon::SetPropertyNum(PropertyIndex_t iPropIndex, PropertyValNum_t iVal, CObjBase* pLinkedObj, RESDISPLAY_VERSION iLimitToExpansion, bool fDeleteZero) +bool CCPropsItemWeapon::SetPropertyNum(PropertyIndex_t iPropIndex, PropertyValNum_t iVal, CObjBase* pLinkedObj, RESDISPLAY_VERSION iLimitToExpansion, bool fDeleteZero) { ADDTOCALLSTACK("CCPropsItemWeapon::SetPropertyNum"); @@ -146,7 +146,7 @@ void CCPropsItemWeapon::SetPropertyNum(PropertyIndex_t iPropIndex, PropertyValNu if ((fDeleteZero && (iVal == 0)) || (_iPropertyExpansion[iPropIndex] > iLimitToExpansion)) { if (0 == _mPropsNum.erase(iPropIndex)) - return; // I didn't have this property, so avoid further processing. + return true; // I didn't have this property, so avoid further processing. } else { @@ -157,13 +157,14 @@ void CCPropsItemWeapon::SetPropertyNum(PropertyIndex_t iPropIndex, PropertyValNu } if (!pLinkedObj) - return; + return true; // Do stuff to the pLinkedObj pLinkedObj->UpdatePropertyFlag(); + return true; } -void CCPropsItemWeapon::SetPropertyStr(PropertyIndex_t iPropIndex, lpctstr ptcVal, CObjBase* pLinkedObj, RESDISPLAY_VERSION iLimitToExpansion, bool fDeleteZero) +bool CCPropsItemWeapon::SetPropertyStr(PropertyIndex_t iPropIndex, lpctstr ptcVal, CObjBase* pLinkedObj, RESDISPLAY_VERSION iLimitToExpansion, bool fDeleteZero) { ADDTOCALLSTACK("CCPropsItemWeapon::SetPropertyStr"); ASSERT(ptcVal); @@ -183,7 +184,7 @@ void CCPropsItemWeapon::SetPropertyStr(PropertyIndex_t iPropIndex, lpctstr ptcVa if ((fDeleteZero && (*ptcVal == '\0')) || (_iPropertyExpansion[iPropIndex] > iLimitToExpansion)) { if (0 == _mPropsNum.erase(iPropIndex)) - return; // I didn't have this property, so avoid further processing. + return true; // I didn't have this property, so avoid further processing. } else { @@ -194,10 +195,11 @@ void CCPropsItemWeapon::SetPropertyStr(PropertyIndex_t iPropIndex, lpctstr ptcVa } if (!pLinkedObj) - return; + return true; // Do stuff to the pLinkedObj pLinkedObj->UpdatePropertyFlag(); + return true; } void CCPropsItemWeapon::DeletePropertyNum(PropertyIndex_t iPropIndex) diff --git a/src/game/components/CCPropsItemWeapon.h b/src/game/components/CCPropsItemWeapon.h index c28a68a0a..19e14b4aa 100644 --- a/src/game/components/CCPropsItemWeapon.h +++ b/src/game/components/CCPropsItemWeapon.h @@ -47,8 +47,8 @@ class CCPropsItemWeapon : public CComponentProps virtual bool IsPropertyStr(PropertyIndex_t iPropIndex) const override; virtual bool GetPropertyNumPtr(PropertyIndex_t iPropIndex, PropertyValNum_t* piOutVal) const override; virtual bool GetPropertyStrPtr(PropertyIndex_t iPropIndex, CSString *psOutVal, bool fZero = false) const override; - virtual void SetPropertyNum(PropertyIndex_t iPropIndex, PropertyValNum_t iVal, CObjBase* pLinkedObj, RESDISPLAY_VERSION iLimitToExpansion = RDS_QTY, bool fDeleteZero = true) override; - virtual void SetPropertyStr(PropertyIndex_t iPropIndex, lpctstr ptcVal, CObjBase* pLinkedObj, RESDISPLAY_VERSION iLimitToExpansion = RDS_QTY, bool fDeleteZero = true) override; + virtual bool SetPropertyNum(PropertyIndex_t iPropIndex, PropertyValNum_t iVal, CObjBase* pLinkedObj, RESDISPLAY_VERSION iLimitToExpansion = RDS_QTY, bool fDeleteZero = true) override; + virtual bool SetPropertyStr(PropertyIndex_t iPropIndex, lpctstr ptcVal, CObjBase* pLinkedObj, RESDISPLAY_VERSION iLimitToExpansion = RDS_QTY, bool fDeleteZero = true) override; virtual void DeletePropertyNum(PropertyIndex_t iPropIndex) override; virtual void DeletePropertyStr(PropertyIndex_t iPropIndex) override; diff --git a/src/game/components/CCPropsItemWeaponRanged.cpp b/src/game/components/CCPropsItemWeaponRanged.cpp index 03ddc02f7..b05890382 100644 --- a/src/game/components/CCPropsItemWeaponRanged.cpp +++ b/src/game/components/CCPropsItemWeaponRanged.cpp @@ -77,7 +77,7 @@ bool CCPropsItemWeaponRanged::GetPropertyStrPtr(PropertyIndex_t iPropIndex, CSSt return BaseCont_GetPropertyStr(&_mPropsStr, iPropIndex, psOutVal, fZero); } -void CCPropsItemWeaponRanged::SetPropertyNum(PropertyIndex_t iPropIndex, PropertyValNum_t iVal, CObjBase* pLinkedObj, RESDISPLAY_VERSION iLimitToExpansion, bool fDeleteZero) +bool CCPropsItemWeaponRanged::SetPropertyNum(PropertyIndex_t iPropIndex, PropertyValNum_t iVal, CObjBase* pLinkedObj, RESDISPLAY_VERSION iLimitToExpansion, bool fDeleteZero) { ADDTOCALLSTACK("CCPropsItemWeaponRanged::SetPropertyNum"); ASSERT(!IsPropertyStr(iPropIndex)); @@ -86,7 +86,7 @@ void CCPropsItemWeaponRanged::SetPropertyNum(PropertyIndex_t iPropIndex, Propert if ((fDeleteZero && (iVal == 0)) || (_iPropertyExpansion[iPropIndex] > iLimitToExpansion)) { if (0 == _mPropsNum.erase(iPropIndex)) - return; // I didn't have this property, so avoid further processing. + return true; // I didn't have this property, so avoid further processing. } else { @@ -95,13 +95,14 @@ void CCPropsItemWeaponRanged::SetPropertyNum(PropertyIndex_t iPropIndex, Propert } if (!pLinkedObj) - return; + return true; // Do stuff to the pLinkedObj pLinkedObj->UpdatePropertyFlag(); + return true; } -void CCPropsItemWeaponRanged::SetPropertyStr(PropertyIndex_t iPropIndex, lpctstr ptcVal, CObjBase* pLinkedObj, RESDISPLAY_VERSION iLimitToExpansion, bool fDeleteZero) +bool CCPropsItemWeaponRanged::SetPropertyStr(PropertyIndex_t iPropIndex, lpctstr ptcVal, CObjBase* pLinkedObj, RESDISPLAY_VERSION iLimitToExpansion, bool fDeleteZero) { ADDTOCALLSTACK("CCPropsItemWeaponRanged::SetPropertyStr"); ASSERT(ptcVal); @@ -111,7 +112,7 @@ void CCPropsItemWeaponRanged::SetPropertyStr(PropertyIndex_t iPropIndex, lpctstr if ((fDeleteZero && (*ptcVal == '\0')) || (_iPropertyExpansion[iPropIndex] > iLimitToExpansion)) { if (0 == _mPropsNum.erase(iPropIndex)) - return; // I didn't have this property, so avoid further processing. + return true; // I didn't have this property, so avoid further processing. } else { @@ -120,10 +121,11 @@ void CCPropsItemWeaponRanged::SetPropertyStr(PropertyIndex_t iPropIndex, lpctstr } if (!pLinkedObj) - return; + return true; // Do stuff to the pLinkedObj pLinkedObj->UpdatePropertyFlag(); + return true; } void CCPropsItemWeaponRanged::DeletePropertyNum(PropertyIndex_t iPropIndex) diff --git a/src/game/components/CCPropsItemWeaponRanged.h b/src/game/components/CCPropsItemWeaponRanged.h index 83e5f6857..992ded9eb 100644 --- a/src/game/components/CCPropsItemWeaponRanged.h +++ b/src/game/components/CCPropsItemWeaponRanged.h @@ -45,8 +45,8 @@ class CCPropsItemWeaponRanged : public CComponentProps virtual bool IsPropertyStr(PropertyIndex_t iPropIndex) const override; virtual bool GetPropertyNumPtr(PropertyIndex_t iPropIndex, PropertyValNum_t* piOutVal) const override; virtual bool GetPropertyStrPtr(PropertyIndex_t iPropIndex, CSString *psOutVal, bool fZero = false) const override; - virtual void SetPropertyNum(PropertyIndex_t iPropIndex, PropertyValNum_t iVal, CObjBase* pLinkedObj, RESDISPLAY_VERSION iLimitToExpansion = RDS_QTY, bool fDeleteZero = true) override; - virtual void SetPropertyStr(PropertyIndex_t iPropIndex, lpctstr ptcVal, CObjBase* pLinkedObj, RESDISPLAY_VERSION iLimitToExpansion = RDS_QTY, bool fDeleteZero = true) override; + virtual bool SetPropertyNum(PropertyIndex_t iPropIndex, PropertyValNum_t iVal, CObjBase* pLinkedObj, RESDISPLAY_VERSION iLimitToExpansion = RDS_QTY, bool fDeleteZero = true) override; + virtual bool SetPropertyStr(PropertyIndex_t iPropIndex, lpctstr ptcVal, CObjBase* pLinkedObj, RESDISPLAY_VERSION iLimitToExpansion = RDS_QTY, bool fDeleteZero = true) override; virtual void DeletePropertyNum(PropertyIndex_t iPropIndex) override; virtual void DeletePropertyStr(PropertyIndex_t iPropIndex) override; diff --git a/src/game/components/subcomponents/CFactionDef.cpp b/src/game/components/subcomponents/CFactionDef.cpp index fc3de8b69..9e2d52220 100644 --- a/src/game/components/subcomponents/CFactionDef.cpp +++ b/src/game/components/subcomponents/CFactionDef.cpp @@ -19,33 +19,33 @@ bool CFactionDef::IsNone() const noexcept CFactionDef::Group CFactionDef::GetGroup() const noexcept { - const auto masked_shifted = (_uiFactionData & _kuiGroupMask) >> _kuiGroupReservedBytes; - return num_alias_cast(masked_shifted); + const uint32 masked_shifted = (_uiFactionData & _kuiGroupMask) >> _kuiGroupReservedBytes; + return enum_alias_cast(masked_shifted); } bool CFactionDef::SetGroup(CFactionDef::Group group) noexcept { - const auto group_numeric = num_alias_cast(group); + const uint32 group_numeric = enum_alias_cast(group); if (group_numeric > _kuiGroupMaxVal) return false; - const auto masked_shifted = (group_numeric & _kuiGroupMaxVal) << _kuiGroupReservedBytes; - _uiFactionData = (_uiFactionData & ~_kuiGroupMask) | num_alias_cast(masked_shifted); + const uint32 masked_shifted = (group_numeric & _kuiGroupMaxVal) << _kuiGroupReservedBytes; + _uiFactionData = (_uiFactionData & ~_kuiGroupMask) | n_alias_cast(masked_shifted); return true; } CFactionDef::Species CFactionDef::GetSpecies() const noexcept { - return num_alias_cast(_uiFactionData & _kuiSpeciesMask); + return enum_alias_cast(_uiFactionData & _kuiSpeciesMask); } bool CFactionDef::SetSpecies(CFactionDef::Species species) noexcept { - const auto species_numeric = num_alias_cast(species); + const uint32 species_numeric = enum_alias_cast(species); if (species_numeric > _kuiSpeciesMaxVal) return false; - const auto masked = species_numeric & _kuiSpeciesMask; + const uint32 masked = species_numeric & _kuiSpeciesMask; _uiFactionData = (_uiFactionData & ~_kuiSpeciesMask) | masked; return true; } @@ -104,8 +104,8 @@ bool CFactionDef::IsLesserSlayerVersus(const CFactionDef *target) const noexcept // Do i belong to the same group? if (!( - num_alias_cast(GetGroup()) & - num_alias_cast(target->GetGroup())) + enum_alias_cast(GetGroup()) & + enum_alias_cast(target->GetGroup())) ) return false; @@ -116,7 +116,7 @@ bool CFactionDef::IsLesserSlayerVersus(const CFactionDef *target) const noexcept bool CFactionDef::HasSuperSlayer() const noexcept { ADDTOCALLSTACK_DEBUG("CFactionDef::HasSuperSlayer"); - return (GetGroup() != Group::NONE && (_kuiSuperSlayerSpeciesIndex == num_alias_cast(GetSpecies()))); + return (GetGroup() != Group::NONE && (_kuiSuperSlayerSpeciesIndex == enum_alias_cast(GetSpecies()))); } bool CFactionDef::HasLesserSlayer() const noexcept diff --git a/src/network/packet.cpp b/src/network/packet.cpp index fd6a48f3e..2e2eb33c8 100644 --- a/src/network/packet.cpp +++ b/src/network/packet.cpp @@ -211,7 +211,7 @@ void Packet::skip(int count) } ASSERT((int64)m_position + count < UINT32_MAX); - m_position += (uint)count; + m_position = (uint)((int64)m_position + count); } byte &Packet::operator[](uint index) From eae1a452760585393d3bcd5a91df82c24d34318a Mon Sep 17 00:00:00 2001 From: cbnolok Date: Sun, 8 Sep 2024 14:33:56 +0200 Subject: [PATCH 24/86] Formatted cmake files with gersemi. --- .gersemirc | 12 + CMakeLists.txt | 307 +++-- cmake/CMakeDefaultToolchain.cmake | 58 +- cmake/CMakeDetectArch.cmake | 203 ++-- cmake/CMakeGitStatus.cmake | 177 ++- cmake/toolchains/Linux-Clang-AArch64.cmake | 111 +- cmake/toolchains/Linux-Clang-native.cmake | 111 +- cmake/toolchains/Linux-Clang-x86.cmake | 154 ++- cmake/toolchains/Linux-Clang-x86_64.cmake | 115 +- cmake/toolchains/Linux-GNU-AArch64.cmake | 116 +- cmake/toolchains/Linux-GNU-native.cmake | 101 +- cmake/toolchains/Linux-GNU-x86.cmake | 158 ++- cmake/toolchains/Linux-GNU-x86_64.cmake | 119 +- cmake/toolchains/OSX-AppleClang-AArch64.cmake | 57 +- cmake/toolchains/OSX-AppleClang-native.cmake | 67 +- cmake/toolchains/OSX-AppleClang-x86_64.cmake | 56 +- cmake/toolchains/Windows-Clang-native.cmake | 93 +- cmake/toolchains/Windows-Clang-x86.cmake | 88 +- cmake/toolchains/Windows-Clang-x86_64.cmake | 90 +- cmake/toolchains/Windows-GNU-native.cmake | 68 +- cmake/toolchains/Windows-GNU-x86.cmake | 62 +- cmake/toolchains/Windows-GNU-x86_64.cmake | 62 +- cmake/toolchains/Windows-MSVC.cmake | 325 +++--- .../include/Linux-Clang_common.inc.cmake | 379 +++--- .../include/Linux-GNU_common.inc.cmake | 343 +++--- .../include/OSX-AppleClang_common.inc.cmake | 373 +++--- .../include/Windows-Clang_common.inc.cmake | 461 ++++---- .../include/Windows-GNU_common.inc.cmake | 310 ++--- lib/CMakeLists.txt | 95 +- lib/bcrypt/CMakeLists.txt | 14 +- lib/cdrc/CMakeLists.txt | 31 +- lib/flat_containers/CMakeLists.txt | 8 +- lib/lib_build_flags_common_c.cmake | 46 +- lib/libev/CMakeLists.txt | 32 +- lib/libev/configure.cmake | 83 +- lib/mariadb_connector_c/CMakeLists.txt | 13 +- lib/mariadb_connector_c/mysql/configure.cmake | 73 +- lib/object_ptr/CMakeLists.txt | 10 +- lib/parallel_hashmap/CMakeLists.txt | 8 +- lib/rand/CMakeLists.txt | 10 +- lib/regex/CMakeLists.txt | 10 +- lib/sqlite/CMakeLists.txt | 19 +- lib/twofish/CMakeLists.txt | 20 +- lib/zlib/CMakeLists.txt | 24 +- src/CMakeSources.cmake | 1025 ++++++++--------- src/CompilerFlags.cmake | 117 +- ...ormat_cmake.sh => cmake_format_gersemi.sh} | 11 +- 47 files changed, 3133 insertions(+), 3092 deletions(-) create mode 100644 .gersemirc rename utilities/{format_cmake.sh => cmake_format_gersemi.sh} (82%) diff --git a/.gersemirc b/.gersemirc new file mode 100644 index 000000000..0928830f1 --- /dev/null +++ b/.gersemirc @@ -0,0 +1,12 @@ +# yaml-language-server: $schema=https://raw.githubusercontent.com/BlankSpruce/gersemi/master/gersemi/configuration.schema.json + +cache: false +color: false +definitions: [] +indent: 4 +line_length: 120 +list_expansion: favour-inlining +quiet: false +unsafe: false +warn_about_unknown_commands: false +workers: 4 diff --git a/CMakeLists.txt b/CMakeLists.txt index 7fb98d1fd..89e3b41b6 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,211 +1,202 @@ # Main config # -CMAKE_MINIMUM_REQUIRED (VERSION 3.19) -set (CMAKE_SUPPRESS_REGENERATION TRUE) # Supress the ZERO_CHECK generation +cmake_minimum_required(VERSION 3.19) +set(CMAKE_SUPPRESS_REGENERATION TRUE) # Supress the ZERO_CHECK generation # GUI checkboxes -option (CMAKE_NO_GIT_REVISION - "Do not try to retrieve the current git revision. Useful for building source not git-cloned from Github." - FALSE +option( + CMAKE_NO_GIT_REVISION + "Do not try to retrieve the current git revision. Useful for building source not git-cloned from Github." + FALSE ) -option (CROSSCOMPILE - "Are we compiling for a different target architecture?" - FALSE -) -option (RUNTIME_STATIC_LINK - "Statically link inside the executable the runtime libraries? (MSVC, libc/libcc, libstdc++)." - FALSE +option(CROSSCOMPILE "Are we compiling for a different target architecture?" FALSE) +option( + RUNTIME_STATIC_LINK + "Statically link inside the executable the runtime libraries? (MSVC, libc/libcc, libstdc++)." + FALSE ) -set (predef_LIB_LIBEV_BUILD FALSE) -if (NOT WIN32) - set (predef_LIB_LIBEV_BUILD TRUE) +set(predef_LIB_LIBEV_BUILD FALSE) +if(NOT WIN32) + set(predef_LIB_LIBEV_BUILD TRUE) endif() -option (LIB_LIBEV_BUILD "Build libev." ${predef_LIB_LIBEV_BUILD}) -option (LIB_SQLITE_BUILD "Build sqlite." TRUE) -option (LIB_ZLIB_BUILD "Build zlib." TRUE) +option(LIB_LIBEV_BUILD "Build libev." ${predef_LIB_LIBEV_BUILD}) +option(LIB_SQLITE_BUILD "Build sqlite." TRUE) +option(LIB_ZLIB_BUILD "Build zlib." TRUE) -if (WIN32) - option (WIN32_SPAWN_CONSOLE "Spawn an additional console, useful for debugging." FALSE) +if(WIN32) + option(WIN32_SPAWN_CONSOLE "Spawn an additional console, useful for debugging." FALSE) endif() -option (USE_ASAN "Enable AddressSanitizer." FALSE) -option (USE_MSAN "Enable MemorySanitizer." FALSE) -option (USE_LSAN "Enable LeakSanitizer." FALSE) -option (USE_UBSAN "Enable Undefined Behavior Sanitizer." FALSE) - +option(USE_ASAN "Enable AddressSanitizer." FALSE) +option(USE_MSAN "Enable MemorySanitizer." FALSE) +option(USE_LSAN "Enable LeakSanitizer." FALSE) +option(USE_UBSAN "Enable Undefined Behavior Sanitizer." FALSE) # Utility functions -FUNCTION (booleanize_str_find VAR) - IF (${VAR} EQUAL -1) - UNSET (${VAR} PARENT_SCOPE) - ELSE () - SET (${VAR} 1 PARENT_SCOPE) - ENDIF () -ENDFUNCTION () - +function(booleanize_str_find VAR) + if(${VAR} EQUAL -1) + unset(${VAR} PARENT_SCOPE) + else() + set(${VAR} 1 PARENT_SCOPE) + endif() +endfunction() # -- Start: initializations # Should i load the toolchain passed as argument? -IF ((NOT TOOLCHAIN_LOADED) AND (NOT ${CMAKE_TOOLCHAIN_FILE} STREQUAL "")) - INCLUDE (${CMAKE_TOOLCHAIN_FILE}) - toolchain_force_compiler () -ENDIF () - +if((NOT TOOLCHAIN_LOADED) AND (NOT ${CMAKE_TOOLCHAIN_FILE} STREQUAL "")) + include(${CMAKE_TOOLCHAIN_FILE}) + toolchain_force_compiler() +endif() -MESSAGE (STATUS "Scanning system build tools...") +message(STATUS "Scanning system build tools...") -PROJECT (SphereServer CXX C) # does a scan for C++ and C compilers +project(SphereServer CXX C) # does a scan for C++ and C compilers # Setup global flags, to be done before creating targets. -if (NOT DEFINED CMAKE_CXX_STANDARD) - # only set CMAKE_CXX_STANDARD if not already set - # this allows the standard to be set by the caller, for example with -DCMAKE_CXX_STANDARD:STRING=20 - set (CMAKE_CXX_STANDARD 20) -elseif (CMAKE_CXX_STANDARD LESS 20) - message (WARNING "Current C++ standard ({CMAKE_CXX_STANDARD}) too low, defaulting to the minimum supported, 20.") - set (CMAKE_CXX_STANDARD 20) -endif () +if(NOT DEFINED CMAKE_CXX_STANDARD) + # only set CMAKE_CXX_STANDARD if not already set + # this allows the standard to be set by the caller, for example with -DCMAKE_CXX_STANDARD:STRING=20 + set(CMAKE_CXX_STANDARD 20) +elseif(CMAKE_CXX_STANDARD LESS 20) + message(WARNING "Current C++ standard ({CMAKE_CXX_STANDARD}) too low, defaulting to the minimum supported, 20.") + set(CMAKE_CXX_STANDARD 20) +endif() set(CMAKE_CXX_STANDARD_REQUIRED ON) set(CMAKE_CXX_EXTENSIONS OFF) - # Need to clear shared library flags. If not, cmake sets -rdynamic and this # add to the executable the full symbol table (included unused symbols). # This is a problem because the binary is >700 KB bigger. -SET (CMAKE_SHARED_LIBRARY_LINK_C_FLAGS "") -SET (CMAKE_SHARED_LIBRARY_LINK_CXX_FLAGS "") +set(CMAKE_SHARED_LIBRARY_LINK_C_FLAGS "") +set(CMAKE_SHARED_LIBRARY_LINK_CXX_FLAGS "") # CMake also sets other predefined flags, which we don't want... -SET (CMAKE_C_FLAGS "") -SET (CMAKE_C_FLAGS_DEBUG "") -SET (CMAKE_C_FLAGS_NIGHTLY "") -SET (CMAKE_C_FLAGS_RELEASE "") - -SET (CMAKE_CXX_FLAGS "") -SET (CMAKE_CXX_FLAGS_DEBUG "") -SET (CMAKE_CXX_FLAGS_NIGHTLY "") -SET (CMAKE_CXX_FLAGS_RELEASE "") - -SET (CMAKE_EXE_LINKER_FLAGS "") -SET (CMAKE_EXE_LINKER_FLAGS_DEBUG "") -SET (CMAKE_EXE_LINKER_FLAGS_NIGHTLY "") -SET (CMAKE_EXE_LINKER_FLAGS_RELEASE "") - -set (is_win32_app_linker) -IF (WIN32 AND NOT ${WIN32_SPAWN_CONSOLE}) - set (is_win32_app_linker WIN32) # if not set, it defaults to console subsystem -ENDIF () - +set(CMAKE_C_FLAGS "") +set(CMAKE_C_FLAGS_DEBUG "") +set(CMAKE_C_FLAGS_NIGHTLY "") +set(CMAKE_C_FLAGS_RELEASE "") + +set(CMAKE_CXX_FLAGS "") +set(CMAKE_CXX_FLAGS_DEBUG "") +set(CMAKE_CXX_FLAGS_NIGHTLY "") +set(CMAKE_CXX_FLAGS_RELEASE "") + +set(CMAKE_EXE_LINKER_FLAGS "") +set(CMAKE_EXE_LINKER_FLAGS_DEBUG "") +set(CMAKE_EXE_LINKER_FLAGS_NIGHTLY "") +set(CMAKE_EXE_LINKER_FLAGS_RELEASE "") + +set(is_win32_app_linker) +if(WIN32 AND NOT ${WIN32_SPAWN_CONSOLE}) + set(is_win32_app_linker WIN32) # if not set, it defaults to console subsystem +endif() # If we have not specified a toolchain, let's detect which one we should use, using the detected arch. -IF (NOT TOOLCHAIN_LOADED) - INCLUDE ("cmake/CMakeDefaultToolchain.cmake") -ENDIF () - +if(NOT TOOLCHAIN_LOADED) + include("cmake/CMakeDefaultToolchain.cmake") +endif() #-- Stuff that needs to be executed after PROJECT but before ADD_EXECUTABLE toolchain_after_project() -STRING (FIND "${CMAKE_GENERATOR}" "Makefiles" GEN_IS_MAKEFILE) -STRING (FIND "${CMAKE_GENERATOR}" "Ninja" GEN_IS_NINJA) +string(FIND "${CMAKE_GENERATOR}" "Makefiles" GEN_IS_MAKEFILE) +string(FIND "${CMAKE_GENERATOR}" "Ninja" GEN_IS_NINJA) booleanize_str_find(GEN_IS_MAKEFILE) booleanize_str_find(GEN_IS_NINJA) -IF ( (GEN_IS_MAKEFILE OR GEN_IS_NINJA) AND (NOT MSVC) ) - SET (SINGLE_TARGET 1) -ENDIF () +if((GEN_IS_MAKEFILE OR GEN_IS_NINJA) AND (NOT MSVC)) + set(SINGLE_TARGET 1) +endif() # TODO: check if Ninja can handle different targets. -IF (SINGLE_TARGET) - # If you want to manually specify the build type, call cmake with parameter: -DCMAKE_BUILD_TYPE=something - - MESSAGE (STATUS "Single-target build system (${CMAKE_GENERATOR}) detected: generating multiple projects!") - IF (NOT ${CMAKE_BUILD_TYPE} STREQUAL "") - IF ((NOT ${CMAKE_BUILD_TYPE} STREQUAL "Release") AND (NOT ${CMAKE_BUILD_TYPE} STREQUAL "Debug") AND (NOT ${CMAKE_BUILD_TYPE} STREQUAL "Nightly")) - MESSAGE (WARNING "Invalid parameter -DCMAKE_BUILD_TYPE, defaulting to Nightly.") - # -> needed only for MAKEFILE-STYLE generators, which can't switch between different configs - SET (CMAKE_BUILD_TYPE "Nightly" CACHE STRING "" FORCE) - ELSE () - MESSAGE (STATUS "Generating only specified project: ${CMAKE_BUILD_TYPE}.") - ENDIF () - ELSE () - MESSAGE (STATUS "No target specified: building all the projects (Release, Debug, Nightly).") - # The only situation supported here is using MSVC, and /MP (multi-core) is set in its compiler flags. - ENDIF () - - IF (GEN_IS_MAKEFILE) - # Setting parallel make; ninja does that by default. - INCLUDE (ProcessorCount) - ProcessorCount (MAKE_THREADS) - IF (NOT MAKE_THREADS EQUAL 0) - MATH (EXPR MAKE_THREADS "${MAKE_THREADS} + (${MAKE_THREADS}/2)") # Suggested number of threads: cores * 1.5 - SET (CMAKE_MAKE_PROGRAM "${CMAKE_MAKE_PROGRAM} -j${MAKE_THREADS}") - ELSE () - MESSAGE (STATUS "Can't determine CPU cores number. Parallel compilation turned off.") - ENDIF () - ENDIF () - -ELSE (SINGLE_TARGET) - - MESSAGE (STATUS "Multi-target build system detected: generating single project with multiple targets!") - SET (CMAKE_CONFIGURATION_TYPES "Debug;Release;Nightly" CACHE STRING "" FORCE) - -ENDIF (SINGLE_TARGET) - +if(SINGLE_TARGET) + # If you want to manually specify the build type, call cmake with parameter: -DCMAKE_BUILD_TYPE=something + + message(STATUS "Single-target build system (${CMAKE_GENERATOR}) detected: generating multiple projects!") + if(NOT ${CMAKE_BUILD_TYPE} STREQUAL "") + if( + (NOT ${CMAKE_BUILD_TYPE} STREQUAL "Release") + AND (NOT ${CMAKE_BUILD_TYPE} STREQUAL "Debug") + AND (NOT ${CMAKE_BUILD_TYPE} STREQUAL "Nightly") + ) + message(WARNING "Invalid parameter -DCMAKE_BUILD_TYPE, defaulting to Nightly.") + # -> needed only for MAKEFILE-STYLE generators, which can't switch between different configs + set(CMAKE_BUILD_TYPE "Nightly" CACHE STRING "" FORCE) + else() + message(STATUS "Generating only specified project: ${CMAKE_BUILD_TYPE}.") + endif() + else() + message(STATUS "No target specified: building all the projects (Release, Debug, Nightly).") + # The only situation supported here is using MSVC, and /MP (multi-core) is set in its compiler flags. + endif() + + if(GEN_IS_MAKEFILE) + # Setting parallel make; ninja does that by default. + include(ProcessorCount) + processorcount(MAKE_THREADS) + if(NOT MAKE_THREADS EQUAL 0) + math(EXPR MAKE_THREADS "${MAKE_THREADS} + (${MAKE_THREADS}/2)") # Suggested number of threads: cores * 1.5 + set(CMAKE_MAKE_PROGRAM "${CMAKE_MAKE_PROGRAM} -j${MAKE_THREADS}") + else() + message(STATUS "Can't determine CPU cores number. Parallel compilation turned off.") + endif() + endif() +else(SINGLE_TARGET) + message(STATUS "Multi-target build system detected: generating single project with multiple targets!") + set(CMAKE_CONFIGURATION_TYPES "Debug;Release;Nightly" CACHE STRING "" FORCE) +endif(SINGLE_TARGET) # Include the list of all Sphere source files include("src/CMakeSources.cmake") # Configure output binaries set(TARGETS "" CACHE INTERNAL "List of Sphere targets to build.") -IF (SINGLE_TARGET) - - IF (("${CMAKE_BUILD_TYPE}" STREQUAL "") OR (${CMAKE_BUILD_TYPE} MATCHES "(R|r?)elease")) - SET (TARGETS ${TARGETS} spheresvr_release) - ADD_EXECUTABLE (spheresvr_release ${is_win32_app_linker} - ${SPHERE_SOURCES} - # ${docs_TEXT} - ) - SET_TARGET_PROPERTIES (spheresvr_release PROPERTIES OUTPUT_NAME SphereSvrX${ARCH_BITS}_release) - ENDIF () - IF (("${CMAKE_BUILD_TYPE}" STREQUAL "") OR (${CMAKE_BUILD_TYPE} MATCHES "(N|n?)ightly")) - SET (TARGETS ${TARGETS} spheresvr_nightly) - ADD_EXECUTABLE (spheresvr_nightly ${is_win32_app_linker} - ${SPHERE_SOURCES} - # ${docs_TEXT} - ) - SET_TARGET_PROPERTIES (spheresvr_nightly PROPERTIES OUTPUT_NAME SphereSvrX${ARCH_BITS}_nightly) - ENDIF () - IF (("${CMAKE_BUILD_TYPE}" STREQUAL "") OR (${CMAKE_BUILD_TYPE} MATCHES "(D|d?)ebug")) - SET (TARGETS ${TARGETS} spheresvr_debug) - ADD_EXECUTABLE (spheresvr_debug ${is_win32_app_linker} - ${SPHERE_SOURCES} - # ${docs_TEXT} - ) - SET_TARGET_PROPERTIES (spheresvr_debug PROPERTIES OUTPUT_NAME SphereSvrX${ARCH_BITS}_debug) - ENDIF () - -ELSE (SINGLE_TARGET) - - SET (TARGETS ${TARGETS} spheresvr) - ADD_EXECUTABLE (spheresvr ${is_win32_app_linker} - ${SPHERE_SOURCES} - ${docs_TEXT} - ) - SET_TARGET_PROPERTIES (spheresvr PROPERTIES OUTPUT_NAME_RELEASE SphereSvrX${ARCH_BITS}_release) - SET_TARGET_PROPERTIES (spheresvr PROPERTIES OUTPUT_NAME_NIGHTLY SphereSvrX${ARCH_BITS}_nightly) - SET_TARGET_PROPERTIES (spheresvr PROPERTIES OUTPUT_NAME_DEBUG SphereSvrX${ARCH_BITS}_debug) - -ENDIF (SINGLE_TARGET) +if(SINGLE_TARGET) + if(("${CMAKE_BUILD_TYPE}" STREQUAL "") OR (${CMAKE_BUILD_TYPE} MATCHES "(R|r?)elease")) + set(TARGETS ${TARGETS} spheresvr_release) + add_executable( + spheresvr_release + ${is_win32_app_linker} + ${SPHERE_SOURCES} + # ${docs_TEXT} + ) + set_target_properties(spheresvr_release PROPERTIES OUTPUT_NAME SphereSvrX${ARCH_BITS}_release) + endif() + if(("${CMAKE_BUILD_TYPE}" STREQUAL "") OR (${CMAKE_BUILD_TYPE} MATCHES "(N|n?)ightly")) + set(TARGETS ${TARGETS} spheresvr_nightly) + add_executable( + spheresvr_nightly + ${is_win32_app_linker} + ${SPHERE_SOURCES} + # ${docs_TEXT} + ) + set_target_properties(spheresvr_nightly PROPERTIES OUTPUT_NAME SphereSvrX${ARCH_BITS}_nightly) + endif() + if(("${CMAKE_BUILD_TYPE}" STREQUAL "") OR (${CMAKE_BUILD_TYPE} MATCHES "(D|d?)ebug")) + set(TARGETS ${TARGETS} spheresvr_debug) + add_executable( + spheresvr_debug + ${is_win32_app_linker} + ${SPHERE_SOURCES} + # ${docs_TEXT} + ) + set_target_properties(spheresvr_debug PROPERTIES OUTPUT_NAME SphereSvrX${ARCH_BITS}_debug) + endif() +else(SINGLE_TARGET) + set(TARGETS ${TARGETS} spheresvr) + add_executable(spheresvr ${is_win32_app_linker} ${SPHERE_SOURCES} ${docs_TEXT}) + set_target_properties(spheresvr PROPERTIES OUTPUT_NAME_RELEASE SphereSvrX${ARCH_BITS}_release) + set_target_properties(spheresvr PROPERTIES OUTPUT_NAME_NIGHTLY SphereSvrX${ARCH_BITS}_nightly) + set_target_properties(spheresvr PROPERTIES OUTPUT_NAME_DEBUG SphereSvrX${ARCH_BITS}_debug) +endif(SINGLE_TARGET) # Now include external libraries add_subdirectory(lib) -toolchain_exe_stuff() # stuff to be executed after ADD_EXECUTABLE +toolchain_exe_stuff() # stuff to be executed after ADD_EXECUTABLE # Get the Git revision number -INCLUDE ("cmake/CMakeGitStatus.cmake") - +include("cmake/CMakeGitStatus.cmake") diff --git a/cmake/CMakeDefaultToolchain.cmake b/cmake/CMakeDefaultToolchain.cmake index 72ce5a897..ac44effed 100644 --- a/cmake/CMakeDefaultToolchain.cmake +++ b/cmake/CMakeDefaultToolchain.cmake @@ -1,29 +1,29 @@ -MESSAGE (STATUS "Toolchain not specified. Detecting the one to use.") -IF (MSVC) - INCLUDE ("cmake/toolchains/Windows-MSVC.cmake") -ELSE () - IF (APPLE) - MESSAGE (STATUS "Defaulting to AArch64 (ARM) arch.") - INCLUDE ("cmake/toolchains/OSX-AppleClang-AArch64.cmake") - ELSEIF (UNIX) - IF ("${ARCH}" STREQUAL "x86_64") - INCLUDE ("cmake/toolchains/Linux-GNU-x86_64.cmake") - ELSEIF ("${ARCH}" STREQUAL "x86") - INCLUDE ("cmake/toolchains/Linux-GNU-x86.cmake") - ELSEIF ("${ARCH}" STREQUAL "arm64") - INCLUDE ("cmake/toolchains/Linux-Clang-AArch64.cmake") - ELSE () - MESSAGE (STATUS "Unsupported architecture, defaulting to native.") - INCLUDE ("cmake/toolchains/Linux-GNU-native.cmake") - ENDIF () - ELSE () - IF ("${ARCH}" STREQUAL "x86_64") - INCLUDE ("cmake/toolchains/Windows-GNU-x86_64.cmake") - ELSEIF ("${ARCH}" STREQUAL "x86") - INCLUDE ("cmake/toolchains/Windows-GNU-x86.cmake") - ELSE () - MESSAGE (STATUS "Unsupported architecture, defaulting to native.") - INCLUDE ("cmake/toolchains/Windows-GNU-native.cmake") - ENDIF () - ENDIF () -ENDIF () +message(STATUS "Toolchain not specified. Detecting the one to use.") +if(MSVC) + include("cmake/toolchains/Windows-MSVC.cmake") +else() + if(APPLE) + message(STATUS "Defaulting to AArch64 (ARM) arch.") + include("cmake/toolchains/OSX-AppleClang-AArch64.cmake") + elseif(UNIX) + if("${ARCH}" STREQUAL "x86_64") + include("cmake/toolchains/Linux-GNU-x86_64.cmake") + elseif("${ARCH}" STREQUAL "x86") + include("cmake/toolchains/Linux-GNU-x86.cmake") + elseif("${ARCH}" STREQUAL "arm64") + include("cmake/toolchains/Linux-Clang-AArch64.cmake") + else() + message(STATUS "Unsupported architecture, defaulting to native.") + include("cmake/toolchains/Linux-GNU-native.cmake") + endif() + else() + if("${ARCH}" STREQUAL "x86_64") + include("cmake/toolchains/Windows-GNU-x86_64.cmake") + elseif("${ARCH}" STREQUAL "x86") + include("cmake/toolchains/Windows-GNU-x86.cmake") + else() + message(STATUS "Unsupported architecture, defaulting to native.") + include("cmake/toolchains/Windows-GNU-native.cmake") + endif() + endif() +endif() diff --git a/cmake/CMakeDetectArch.cmake b/cmake/CMakeDetectArch.cmake index 1846b3713..88064147a 100644 --- a/cmake/CMakeDetectArch.cmake +++ b/cmake/CMakeDetectArch.cmake @@ -7,130 +7,145 @@ # Convert CMake vars into the format that OpenBLAS expects (modified for SphereServer) # If i'm not overriding it, use mine (host machine). -if (NOT CMAKE_SYSTEM_PROCESSOR) - set (CMAKE_SYSTEM_PROCESSOR "${CMAKE_HOST_SYSTEM_PROCESSOR}" CACHE INTERNAL "" FORCE) -endif () +if(NOT CMAKE_SYSTEM_PROCESSOR) + set(CMAKE_SYSTEM_PROCESSOR "${CMAKE_HOST_SYSTEM_PROCESSOR}" CACHE INTERNAL "" FORCE) +endif() string(TOUPPER "${CMAKE_SYSTEM_NAME}" HOST_OS) -if ("${HOST_OS}" STREQUAL "WINDOWS") - set(HOST_OS WINNT CACHE INTERNAL "") -endif () +if("${HOST_OS}" STREQUAL "WINDOWS") + set(HOST_OS WINNT CACHE INTERNAL "") +endif() -if ("${HOST_OS}" STREQUAL "LINUX") -# check if we're building natively on Android (TERMUX) - EXECUTE_PROCESS( COMMAND uname -o COMMAND tr -d '\n' OUTPUT_VARIABLE OPERATING_SYSTEM) - if("${OPERATING_SYSTEM}" MATCHES "Android") +if("${HOST_OS}" STREQUAL "LINUX") + # check if we're building natively on Android (TERMUX) + execute_process(COMMAND uname -o COMMAND tr -d '\n' OUTPUT_VARIABLE OPERATING_SYSTEM) + if("${OPERATING_SYSTEM}" MATCHES "Android") set(HOST_OS ANDROID CACHE INTERNAL "") - endif() + endif() endif() -message (STATUS "Host machine: [OS] ${HOST_OS} [Arch] ${CMAKE_HOST_SYSTEM_PROCESSOR}") +message(STATUS "Host machine: [OS] ${HOST_OS} [Arch] ${CMAKE_HOST_SYSTEM_PROCESSOR}") if(MINGW) - execute_process(COMMAND ${CMAKE_C_COMPILER} -dumpmachine - OUTPUT_VARIABLE MINGW_TARGET_MACHINE - OUTPUT_STRIP_TRAILING_WHITESPACE) + execute_process( + COMMAND ${CMAKE_C_COMPILER} -dumpmachine + OUTPUT_VARIABLE MINGW_TARGET_MACHINE + OUTPUT_STRIP_TRAILING_WHITESPACE + ) if("${MINGW_TARGET_MACHINE}" MATCHES "amd64|x86_64|AMD64") - set(MINGW64 1) + set(MINGW64 1) endif() endif() # Pretty thorough determination of arch. Add more if needed if(CMAKE_CL_64 OR MINGW64) - if ("${CMAKE_SYSTEM_PROCESSOR}" MATCHES "^(aarch64.*|AARCH64.*|arm64.*|ARM64.*)") - set(ARM64 1) - else() - set(X86_64 1) - endif() + if("${CMAKE_SYSTEM_PROCESSOR}" MATCHES "^(aarch64.*|AARCH64.*|arm64.*|ARM64.*)") + set(ARM64 1) + else() + set(X86_64 1) + endif() elseif(MINGW OR (MSVC AND NOT CMAKE_CROSSCOMPILING)) - set(X86 1) -elseif("${CMAKE_SYSTEM_PROCESSOR}" MATCHES "ppc.*|power.*|Power.*" OR ("${CMAKE_SYSTEM_NAME}" MATCHES "Darwin" AND "${CMAKE_OSX_ARCHITECTURES}" MATCHES "ppc.*")) - set(POWER 1) + set(X86 1) +elseif( + "${CMAKE_SYSTEM_PROCESSOR}" MATCHES "ppc.*|power.*|Power.*" + OR ("${CMAKE_SYSTEM_NAME}" MATCHES "Darwin" AND "${CMAKE_OSX_ARCHITECTURES}" MATCHES "ppc.*") +) + set(POWER 1) elseif("${CMAKE_SYSTEM_PROCESSOR}" MATCHES "mips64.*") - set(MIPS64 1) + set(MIPS64 1) elseif("${CMAKE_SYSTEM_PROCESSOR}" MATCHES "loongarch64.*") - set(LOONGARCH64 1) + set(LOONGARCH64 1) elseif("${CMAKE_SYSTEM_PROCESSOR}" MATCHES "riscv64.*") - set(RISCV64 1) -elseif("${CMAKE_SYSTEM_PROCESSOR}" MATCHES "amd64.*|x86_64.*|AMD64.*" OR ("${CMAKE_SYSTEM_NAME}" MATCHES "Darwin" AND "${CMAKE_SYSTEM_PROCESSOR}" MATCHES "i686.*|i386.*|x86.*")) - #if (${ARCH_BITS} EQUAL 64) - set(X86_64 1) - #else () - # set(X86 1) - #endif() + set(RISCV64 1) +elseif( + "${CMAKE_SYSTEM_PROCESSOR}" MATCHES "amd64.*|x86_64.*|AMD64.*" + OR ("${CMAKE_SYSTEM_NAME}" MATCHES "Darwin" AND "${CMAKE_SYSTEM_PROCESSOR}" MATCHES "i686.*|i386.*|x86.*") +) + #if (${ARCH_BITS} EQUAL 64) + set(X86_64 1) + #else () + # set(X86 1) + #endif() elseif("${CMAKE_SYSTEM_PROCESSOR}" MATCHES "i686.*|i386.*|x86.*") - #if (${ARCH_BITS} EQUAL 64) - # set(X86_64 1) - #else () + #if (${ARCH_BITS} EQUAL 64) + # set(X86_64 1) + #else () set(X86 1) - #endif() + #endif() elseif("${CMAKE_SYSTEM_PROCESSOR}" MATCHES "^(aarch64.*|AARCH64.*|arm64.*|ARM64.*|armv8.*)") - #if (${ARCH_BITS} EQUAL 64) + #if (${ARCH_BITS} EQUAL 64) set(ARM64 1) - #else() - # set(ARM 1) - #endif() + #else() + # set(ARM 1) + #endif() elseif("${CMAKE_SYSTEM_PROCESSOR}" MATCHES "^(arm.*|ARM.*)") - set(ARM 1) -elseif (CMAKE_CROSSCOMPILING) - if ("${TARGET}" STREQUAL "CORE2") - if (NOT ARCH_BITS) - set(X86 1) - elseif (${ARCH_BITS} EQUAL 64) - set(X86_64 1) - else () - set(X86 1) + set(ARM 1) +elseif(CMAKE_CROSSCOMPILING) + if("${TARGET}" STREQUAL "CORE2") + if(NOT ARCH_BITS) + set(X86 1) + elseif(${ARCH_BITS} EQUAL 64) + set(X86_64 1) + else() + set(X86 1) + endif() + elseif("${TARGET}" STREQUAL "P5600" OR "${TARGET}" MATCHES "MIPS.*") + set(MIPS32 1) + elseif("${TARGET}" STREQUAL "ARMV7") + set(ARM 1) + else() + set(ARM64 1) endif() - elseif ("${TARGET}" STREQUAL "P5600" OR "${TARGET}" MATCHES "MIPS.*") - set(MIPS32 1) - elseif ("${TARGET}" STREQUAL "ARMV7") - set(ARM 1) - else() - set(ARM64 1) - endif () -else () - message(WARNING "Target ARCH could not be determined, got \"${CMAKE_SYSTEM_PROCESSOR}\"") +else() + message(WARNING "Target ARCH could not be determined, got \"${CMAKE_SYSTEM_PROCESSOR}\"") endif() -if (NOT ARCH) - if (X86_64) - set(ARCH "x86_64" CACHE INTERNAL "") - set(ARCH_BASE "x86" CACHE INTERNAL "") - elseif(X86) - set(ARCH "x86" CACHE INTERNAL "") - set(ARCH_BASE "x86" CACHE INTERNAL "") - elseif(POWER) - set(ARCH "power" CACHE INTERNAL "") - set(ARCH_BASE "power" CACHE INTERNAL "") - elseif(MIPS32) - set(ARCH "mips" CACHE INTERNAL "") - set(ARCH_BASE "mips" CACHE INTERNAL "") - elseif(MIPS64) - set(ARCH "mips64" CACHE INTERNAL "") - set(ARCH_BASE "mips" CACHE INTERNAL "") - elseif(ARM) - set(ARCH "arm" CACHE INTERNAL "") - set(ARCH_BASE "arm" CACHE INTERNAL "") - elseif(ARM64) - set(ARCH "arm64" CACHE INTERNAL "") - set(ARCH_BASE "arm" CACHE INTERNAL "") - else() - set(ARCH ${CMAKE_SYSTEM_PROCESSOR} CACHE INTERNAL "Target Architecture") - endif () -endif () +if(NOT ARCH) + if(X86_64) + set(ARCH "x86_64" CACHE INTERNAL "") + set(ARCH_BASE "x86" CACHE INTERNAL "") + elseif(X86) + set(ARCH "x86" CACHE INTERNAL "") + set(ARCH_BASE "x86" CACHE INTERNAL "") + elseif(POWER) + set(ARCH "power" CACHE INTERNAL "") + set(ARCH_BASE "power" CACHE INTERNAL "") + elseif(MIPS32) + set(ARCH "mips" CACHE INTERNAL "") + set(ARCH_BASE "mips" CACHE INTERNAL "") + elseif(MIPS64) + set(ARCH "mips64" CACHE INTERNAL "") + set(ARCH_BASE "mips" CACHE INTERNAL "") + elseif(ARM) + set(ARCH "arm" CACHE INTERNAL "") + set(ARCH_BASE "arm" CACHE INTERNAL "") + elseif(ARM64) + set(ARCH "arm64" CACHE INTERNAL "") + set(ARCH_BASE "arm" CACHE INTERNAL "") + else() + set(ARCH ${CMAKE_SYSTEM_PROCESSOR} CACHE INTERNAL "Target Architecture") + endif() +endif() -if (NOT ARCH_BITS) - if (X86_64 OR ARM64 OR MIPS64 OR LOONGARCH64 OR RISCV64 OR (POWER AND NOT (CMAKE_OSX_ARCHITECTURES STREQUAL "ppc"))) - set(ARCH_BITS 64 CACHE INTERNAL "") - else () - set(ARCH_BITS 32 CACHE INTERNAL "") - endif () +if(NOT ARCH_BITS) + if( + X86_64 + OR ARM64 + OR MIPS64 + OR LOONGARCH64 + OR RISCV64 + OR (POWER AND NOT (CMAKE_OSX_ARCHITECTURES STREQUAL "ppc")) + ) + set(ARCH_BITS 64 CACHE INTERNAL "") + else() + set(ARCH_BITS 32 CACHE INTERNAL "") + endif() endif() if(ARCH_BITS EQUAL 64) - set(ARCH_BITS64 1 CACHE INTERNAL "") + set(ARCH_BITS64 1 CACHE INTERNAL "") else() - set(ARCH_BITS32 1 CACHE INTERNAL "") + set(ARCH_BITS32 1 CACHE INTERNAL "") endif() -MESSAGE (STATUS "Target Arch: ${ARCH}") +message(STATUS "Target Arch: ${ARCH}") diff --git a/cmake/CMakeGitStatus.cmake b/cmake/CMakeGitStatus.cmake index 9b84588a4..d36285c0e 100644 --- a/cmake/CMakeGitStatus.cmake +++ b/cmake/CMakeGitStatus.cmake @@ -1,93 +1,88 @@ # Git revision checker -SET (GITBRANCH_VAL "N/A") -SET (GITHASH_VAL "N/A") -SET (GITREV_VAL 0) - -IF (CMAKE_NO_GIT_REVISION) - MESSAGE (STATUS "As per CMAKE_NO_GIT_REVISION, Git revision number and hash will not be available.") - -ELSE () - find_package(Git) - IF (NOT GIT_FOUND) - MESSAGE (WARNING "Git not found! Revision number and hash will not be available.") - - ELSE () - SET (GIT_CMD git) - SET (GIT_ARGS_VALID_REPO rev-parse) - SET (GIT_ARGS_REV_HASH rev-parse HEAD) - SET (GIT_ARGS_REV_COUNT rev-list --count HEAD) - SET (GIT_ARGS_BRANCH branch --show-current) - - MESSAGE (STATUS "Checking if the folder is a valid git repo...") - - EXECUTE_PROCESS (COMMAND ${GIT_CMD} ${GIT_ARGS_VALID_REPO} - WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} - RESULT_VARIABLE RES_VALID_REPO - OUTPUT_STRIP_TRAILING_WHITESPACE - ) - - IF (NOT "${RES_VALID_REPO}" STREQUAL "0") - MESSAGE (WARNING "Invalid Git repo! Revision number and hash will not be available.") - - ELSE () - MESSAGE (STATUS "Checking git revision...") - - EXECUTE_PROCESS (COMMAND ${GIT_CMD} ${GIT_ARGS_REV_COUNT} - WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} - OUTPUT_VARIABLE OUT_REV_COUNT - OUTPUT_STRIP_TRAILING_WHITESPACE - ) - - IF ("${OUT_REV_COUNT}" STREQUAL "") - MESSAGE (WARNING "Git repo has no commits (not a clone from remote?). Revision number and hash will not be available.") - - ELSE () - MATH (EXPR RET_REV_COUNT "${OUT_REV_COUNT}") - - IF ("${OUT_REV_COUNT}" STREQUAL "") - MESSAGE (WARNING "Git revision not available!") - - ELSE () - MESSAGE (STATUS "Git revision number: ${OUT_REV_COUNT}") - SET (GITREV_VAL ${OUT_REV_COUNT}) - - MESSAGE (STATUS "Checking git revision hash...") - EXECUTE_PROCESS (COMMAND ${GIT_CMD} ${GIT_ARGS_REV_HASH} - WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} - OUTPUT_VARIABLE OUT_REV_HASH - OUTPUT_STRIP_TRAILING_WHITESPACE - ) - MESSAGE (STATUS "Git revision hash: ${OUT_REV_HASH}") - SET (GITHASH_VAL ${OUT_REV_HASH}) - - ENDIF () - - ENDIF () - - MESSAGE (STATUS "Checking git branch...") - - EXECUTE_PROCESS (COMMAND ${GIT_CMD} ${GIT_ARGS_BRANCH} - WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} - OUTPUT_VARIABLE OUT_BRANCH - OUTPUT_STRIP_TRAILING_WHITESPACE - ) - - IF ("${OUT_BRANCH}" STREQUAL "") - MESSAGE (WARNING "Git branch not available!") - - ELSE () - MESSAGE (STATUS "Git branch: ${OUT_BRANCH}") - SET (GITBRANCH_VAL ${OUT_BRANCH}) - - ENDIF () - - ENDIF () - - ENDIF() - -ENDIF() - -CONFIGURE_FILE ( - "${CMAKE_SOURCE_DIR}/src/common/version/GitRevision.h.in" - "${CMAKE_SOURCE_DIR}/src/common/version/GitRevision.h" +set(GITBRANCH_VAL "N/A") +set(GITHASH_VAL "N/A") +set(GITREV_VAL 0) + +if(CMAKE_NO_GIT_REVISION) + message(STATUS "As per CMAKE_NO_GIT_REVISION, Git revision number and hash will not be available.") +else() + find_package(Git) + if(NOT GIT_FOUND) + message(WARNING "Git not found! Revision number and hash will not be available.") + else() + set(GIT_CMD git) + set(GIT_ARGS_VALID_REPO rev-parse) + set(GIT_ARGS_REV_HASH rev-parse HEAD) + set(GIT_ARGS_REV_COUNT rev-list --count HEAD) + set(GIT_ARGS_BRANCH branch --show-current) + + message(STATUS "Checking if the folder is a valid git repo...") + + execute_process( + COMMAND ${GIT_CMD} ${GIT_ARGS_VALID_REPO} + WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} + RESULT_VARIABLE RES_VALID_REPO + OUTPUT_STRIP_TRAILING_WHITESPACE + ) + + if(NOT "${RES_VALID_REPO}" STREQUAL "0") + message(WARNING "Invalid Git repo! Revision number and hash will not be available.") + else() + message(STATUS "Checking git revision...") + + execute_process( + COMMAND ${GIT_CMD} ${GIT_ARGS_REV_COUNT} + WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} + OUTPUT_VARIABLE OUT_REV_COUNT + OUTPUT_STRIP_TRAILING_WHITESPACE + ) + + if("${OUT_REV_COUNT}" STREQUAL "") + message( + WARNING + "Git repo has no commits (not a clone from remote?). Revision number and hash will not be available." + ) + else() + math(EXPR RET_REV_COUNT "${OUT_REV_COUNT}") + + if("${OUT_REV_COUNT}" STREQUAL "") + message(WARNING "Git revision not available!") + else() + message(STATUS "Git revision number: ${OUT_REV_COUNT}") + set(GITREV_VAL ${OUT_REV_COUNT}) + + message(STATUS "Checking git revision hash...") + execute_process( + COMMAND ${GIT_CMD} ${GIT_ARGS_REV_HASH} + WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} + OUTPUT_VARIABLE OUT_REV_HASH + OUTPUT_STRIP_TRAILING_WHITESPACE + ) + message(STATUS "Git revision hash: ${OUT_REV_HASH}") + set(GITHASH_VAL ${OUT_REV_HASH}) + endif() + endif() + + message(STATUS "Checking git branch...") + + execute_process( + COMMAND ${GIT_CMD} ${GIT_ARGS_BRANCH} + WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} + OUTPUT_VARIABLE OUT_BRANCH + OUTPUT_STRIP_TRAILING_WHITESPACE + ) + + if("${OUT_BRANCH}" STREQUAL "") + message(WARNING "Git branch not available!") + else() + message(STATUS "Git branch: ${OUT_BRANCH}") + set(GITBRANCH_VAL ${OUT_BRANCH}) + endif() + endif() + endif() +endif() + +configure_file( + "${CMAKE_SOURCE_DIR}/src/common/version/GitRevision.h.in" + "${CMAKE_SOURCE_DIR}/src/common/version/GitRevision.h" ) diff --git a/cmake/toolchains/Linux-Clang-AArch64.cmake b/cmake/toolchains/Linux-Clang-AArch64.cmake index ca47e0bbe..a0cad0d7b 100644 --- a/cmake/toolchains/Linux-Clang-AArch64.cmake +++ b/cmake/toolchains/Linux-Clang-AArch64.cmake @@ -1,67 +1,68 @@ -INCLUDE("${CMAKE_CURRENT_LIST_DIR}/include/Linux-Clang_common.inc.cmake") +include("${CMAKE_CURRENT_LIST_DIR}/include/Linux-Clang_common.inc.cmake") +function(toolchain_force_compiler) + set(CMAKE_C_COMPILER "clang" CACHE STRING "C compiler" FORCE) + set(CMAKE_CXX_COMPILER "clang++" CACHE STRING "C++ compiler" FORCE) -function (toolchain_force_compiler) - SET (CMAKE_C_COMPILER "clang" CACHE STRING "C compiler" FORCE) - SET (CMAKE_CXX_COMPILER "clang++" CACHE STRING "C++ compiler" FORCE) + if(CROSSCOMPILING_ARCH) + # where is the target environment located + set(CMAKE_FIND_ROOT_PATH "/usr/aarch64-linux-gnu" CACHE INTERNAL "" FORCE) - if (CROSSCOMPILING_ARCH) - # where is the target environment located - set(CMAKE_FIND_ROOT_PATH "/usr/aarch64-linux-gnu" CACHE INTERNAL "" FORCE) - - # adjust the default behavior of the FIND_XXX() commands: - # search programs in the host environment - set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM "NEVER" CACHE INTERNAL "" FORCE) - - # search headers and libraries in the target environment - set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE "ONLY" CACHE INTERNAL "" FORCE) - set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY "ONLY" CACHE INTERNAL "" FORCE) - endif() -endfunction () + # adjust the default behavior of the FIND_XXX() commands: + # search programs in the host environment + set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM "NEVER" CACHE INTERNAL "" FORCE) + # search headers and libraries in the target environment + set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE "ONLY" CACHE INTERNAL "" FORCE) + set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY "ONLY" CACHE INTERNAL "" FORCE) + endif() +endfunction() -function (toolchain_after_project) - MESSAGE (STATUS "Toolchain: Linux-Clang-AArch64.cmake.") - # Do not set CMAKE_SYSTEM_NAME if compiling for the same OS, otherwise CMAKE_CROSSCOMPILING will be set to TRUE - #SET(CMAKE_SYSTEM_NAME "Linux" CACHE INTERNAL "" FORCE) - SET(CMAKE_SYSTEM_PROCESSOR "aarch64" CACHE INTERNAL "" FORCE) - SET(CMAKE_RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/bin-aarch64" PARENT_SCOPE) - #set(ARCH_BITS 64 CACHE INTERNAL "" FORCE) # provide it +function(toolchain_after_project) + message(STATUS "Toolchain: Linux-Clang-AArch64.cmake.") + # Do not set CMAKE_SYSTEM_NAME if compiling for the same OS, otherwise CMAKE_CROSSCOMPILING will be set to TRUE + #SET(CMAKE_SYSTEM_NAME "Linux" CACHE INTERNAL "" FORCE) + set(CMAKE_SYSTEM_PROCESSOR "aarch64" CACHE INTERNAL "" FORCE) + set(CMAKE_RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/bin-aarch64" PARENT_SCOPE) + #set(ARCH_BITS 64 CACHE INTERNAL "" FORCE) # provide it - if (CROSSCOMPILING_ARCH) - # possible cross-compilation foreign arch lib locations - set (lib_search_paths - "/usr/aarch64-linux-gnu/usr/lib/libmariadb3" - "/usr/aarch64-linux-gnu/usr/lib/mysql" - "/usr/aarch64-linux-gnu/usr/lib/" - CACHE STRING "Library search paths" FORCE - ) - else () - # possible native/host lib locations - set (lib_search_paths - "/usr/lib/aarch64-linux-gnu/libmariadb3" - "/usr/lib/aarch64-linux-gnu/mysql" - "/usr/lib/aarch64-linux-gnu" - "/usr/lib64/mysql" - "/usr/lib64" - "/usr/lib/mysql" - "/usr/lib" - CACHE STRING "Library search paths" FORCE - ) - endif () + if(CROSSCOMPILING_ARCH) + # possible cross-compilation foreign arch lib locations + set(lib_search_paths + "/usr/aarch64-linux-gnu/usr/lib/libmariadb3" + "/usr/aarch64-linux-gnu/usr/lib/mysql" + "/usr/aarch64-linux-gnu/usr/lib/" + CACHE STRING + "Library search paths" + FORCE + ) + else() + # possible native/host lib locations + set(lib_search_paths + "/usr/lib/aarch64-linux-gnu/libmariadb3" + "/usr/lib/aarch64-linux-gnu/mysql" + "/usr/lib/aarch64-linux-gnu" + "/usr/lib64/mysql" + "/usr/lib64" + "/usr/lib/mysql" + "/usr/lib" + CACHE STRING + "Library search paths" + FORCE + ) + endif() - toolchain_after_project_common() + toolchain_after_project_common() - SET (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} --target=aarch64-linux-gnu" PARENT_SCOPE) - SET (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} --target=aarch64-linux-gnu" PARENT_SCOPE) + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} --target=aarch64-linux-gnu" PARENT_SCOPE) + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} --target=aarch64-linux-gnu" PARENT_SCOPE) endfunction() +function(toolchain_exe_stuff) + toolchain_exe_stuff_common() -function (toolchain_exe_stuff) - toolchain_exe_stuff_common() - - # Propagate global variables set in toolchain_exe_stuff_common to the upper scope - #SET (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${C_ARCH_OPTS}" PARENT_SCOPE) - #SET (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${CXX_ARCH_OPTS}" PARENT_SCOPE) - #SET (CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS}" PARENT_SCOPE) + # Propagate global variables set in toolchain_exe_stuff_common to the upper scope + #SET (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${C_ARCH_OPTS}" PARENT_SCOPE) + #SET (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${CXX_ARCH_OPTS}" PARENT_SCOPE) + #SET (CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS}" PARENT_SCOPE) endfunction() diff --git a/cmake/toolchains/Linux-Clang-native.cmake b/cmake/toolchains/Linux-Clang-native.cmake index 22fbf79e5..c4f2792bd 100644 --- a/cmake/toolchains/Linux-Clang-native.cmake +++ b/cmake/toolchains/Linux-Clang-native.cmake @@ -1,68 +1,61 @@ -INCLUDE("${CMAKE_CURRENT_LIST_DIR}/include/Linux-Clang_common.inc.cmake") +include("${CMAKE_CURRENT_LIST_DIR}/include/Linux-Clang_common.inc.cmake") +function(toolchain_force_compiler) + if(CROSSCOMPILING_ARCH) + message(FATAL_ERROR "Can't cross-compile with a 'native' toolchain.") + endif() -function (toolchain_force_compiler) - if (CROSSCOMPILING_ARCH) - message(FATAL_ERROR "Can't cross-compile with a 'native' toolchain.") - endif () - - SET (CMAKE_C_COMPILER "clang" CACHE STRING "C compiler" FORCE) - SET (CMAKE_CXX_COMPILER "clang++" CACHE STRING "C++ compiler" FORCE) -endfunction () - - -function (toolchain_after_project) - MESSAGE (STATUS "Toolchain: Linux-Clang-native.cmake.") - # Do not set CMAKE_SYSTEM_NAME if compiling for the same OS, otherwise CMAKE_CROSSCOMPILING will be set to TRUE - #SET(CMAKE_SYSTEM_NAME "Linux" CACHE INTERNAL "" FORCE) # target OS - IF (CMAKE_SIZEOF_VOID_P EQUAL 8) - SET(CMAKE_RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/bin-native64" PARENT_SCOPE) - ELSE () - SET(CMAKE_RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/bin-native32" PARENT_SCOPE) - ENDIF () + set(CMAKE_C_COMPILER "clang" CACHE STRING "C compiler" FORCE) + set(CMAKE_CXX_COMPILER "clang++" CACHE STRING "C++ compiler" FORCE) +endfunction() - # possible native/host lib locations - set (local_usr_lib_subfolders - "libmariadb3" - "mysql" - ) - foreach (local_usr_lib_subfolders subfolder) - # ARCH variable is set by CMakeGitStatus - set (local_lib_search_paths - ${local_lib_search_paths} - "/usr/${ARCH}-linux-gnu/${subfolder}" +function(toolchain_after_project) + message(STATUS "Toolchain: Linux-Clang-native.cmake.") + # Do not set CMAKE_SYSTEM_NAME if compiling for the same OS, otherwise CMAKE_CROSSCOMPILING will be set to TRUE + #SET(CMAKE_SYSTEM_NAME "Linux" CACHE INTERNAL "" FORCE) # target OS + if(CMAKE_SIZEOF_VOID_P EQUAL 8) + set(CMAKE_RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/bin-native64" PARENT_SCOPE) + else() + set(CMAKE_RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/bin-native32" PARENT_SCOPE) + endif() + + # possible native/host lib locations + set(local_usr_lib_subfolders "libmariadb3" "mysql") + foreach(local_usr_lib_subfolders subfolder) + # ARCH variable is set by CMakeGitStatus + set(local_lib_search_paths ${local_lib_search_paths} "/usr/${ARCH}-linux-gnu/${subfolder}") + endforeach() + set(lib_search_paths + ${local_lib_search_paths} + "/usr/lib64/mysql" + "/usr/lib64" + "/usr/lib/mysql" + "/usr/lib" + CACHE STRING + "Library search paths" + FORCE ) - endforeach() - set (lib_search_paths - ${local_lib_search_paths} - "/usr/lib64/mysql" - "/usr/lib64" - "/usr/lib/mysql" - "/usr/lib" - CACHE STRING "Library search paths" FORCE - ) - - toolchain_after_project_common() - if ("${ARCH_BASE}" STREQUAL "arm") - # Clang doesn't support -march=native for ARM (but it IS supported by Apple Clang, btw) - # Also: - # https://community.arm.com/arm-community-blogs/b/tools-software-ides-blog/posts/compiler-flags-across-architectures-march-mtune-and-mcpu - # https://code.fmsolvr.fz-juelich.de/i.lilikakis/fmsolvr/commit/bd010058b8b8c92385d1ccc321912bf1359d66b0 - set (local_arch_cmd -mcpu=native) - else () - set (local_arch_cmd -march=native -mtune=native) - endif () - SET (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${local_arch_cmd}" PARENT_SCOPE) - SET (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${local_arch_cmd}" PARENT_SCOPE) + toolchain_after_project_common() + + if("${ARCH_BASE}" STREQUAL "arm") + # Clang doesn't support -march=native for ARM (but it IS supported by Apple Clang, btw) + # Also: + # https://community.arm.com/arm-community-blogs/b/tools-software-ides-blog/posts/compiler-flags-across-architectures-march-mtune-and-mcpu + # https://code.fmsolvr.fz-juelich.de/i.lilikakis/fmsolvr/commit/bd010058b8b8c92385d1ccc321912bf1359d66b0 + set(local_arch_cmd -mcpu=native) + else() + set(local_arch_cmd -march=native -mtune=native) + endif() + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${local_arch_cmd}" PARENT_SCOPE) + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${local_arch_cmd}" PARENT_SCOPE) endfunction() +function(toolchain_exe_stuff) + toolchain_exe_stuff_common() -function (toolchain_exe_stuff) - toolchain_exe_stuff_common() - - # Propagate global variables set in toolchain_exe_stuff_common to the upper scope - #SET (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${C_ARCH_OPTS}" PARENT_SCOPE) - #SET (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${CXX_ARCH_OPTS}" PARENT_SCOPE) - #SET (CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS}" PARENT_SCOPE) + # Propagate global variables set in toolchain_exe_stuff_common to the upper scope + #SET (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${C_ARCH_OPTS}" PARENT_SCOPE) + #SET (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${CXX_ARCH_OPTS}" PARENT_SCOPE) + #SET (CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS}" PARENT_SCOPE) endfunction() diff --git a/cmake/toolchains/Linux-Clang-x86.cmake b/cmake/toolchains/Linux-Clang-x86.cmake index edcfb7904..335c522ce 100644 --- a/cmake/toolchains/Linux-Clang-x86.cmake +++ b/cmake/toolchains/Linux-Clang-x86.cmake @@ -1,89 +1,87 @@ -INCLUDE("${CMAKE_CURRENT_LIST_DIR}/include/Linux-Clang_common.inc.cmake") +include("${CMAKE_CURRENT_LIST_DIR}/include/Linux-Clang_common.inc.cmake") +function(toolchain_force_compiler) + set(CMAKE_C_COMPILER "clang" CACHE STRING "C compiler" FORCE) + set(CMAKE_CXX_COMPILER "clang++" CACHE STRING "C++ compiler" FORCE) -function (toolchain_force_compiler) - SET (CMAKE_C_COMPILER "clang" CACHE STRING "C compiler" FORCE) - SET (CMAKE_CXX_COMPILER "clang++" CACHE STRING "C++ compiler" FORCE) + if(CROSSCOMPILING_ARCH) + message(FATAL_ERROR "Incomplete/to be tested.") # are the names/paths correct? - if (CROSSCOMPILING_ARCH) - message(FATAL_ERROR "Incomplete/to be tested.") # are the names/paths correct? + # where is the target environment located + set(CMAKE_FIND_ROOT_PATH "/usr/i386-pc-linux-gnu" CACHE INTERNAL "" FORCE) - # where is the target environment located - set(CMAKE_FIND_ROOT_PATH "/usr/i386-pc-linux-gnu" CACHE INTERNAL "" FORCE) + # adjust the default behavior of the FIND_XXX() commands: + # search programs in the host environment + set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM "NEVER" CACHE INTERNAL "" FORCE) - # adjust the default behavior of the FIND_XXX() commands: - # search programs in the host environment - set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM "NEVER" CACHE INTERNAL "" FORCE) - - # search headers and libraries in the target environment - set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE "ONLY" CACHE INTERNAL "" FORCE) - set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY "ONLY" CACHE INTERNAL "" FORCE) - endif() -endfunction () - - -function (toolchain_after_project) - MESSAGE (STATUS "Toolchain: Linux-Clang-x86.cmake.") - # Do not set CMAKE_SYSTEM_NAME if compiling for the same OS, otherwise CMAKE_CROSSCOMPILING will be set to TRUE - #SET(CMAKE_SYSTEM_NAME "Linux" CACHE INTERNAL "" FORCE) # target OS - SET(CMAKE_SYSTEM_PROCESSOR "x86" CACHE INTERNAL "" FORCE) # target arch - SET(CMAKE_RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/bin-x86" PARENT_SCOPE) - #set(ARCH_BITS 32 CACHE INTERNAL "" FORCE) # provide it - - if (CROSSCOMPILING_ARCH) - # possible cross-compilation foreign arch lib locations - set (lib_search_paths - "/usr/i686-linux-gnu/usr/lib/libmariadb3" - "/usr/i686-linux-gnu/usr/lib/mysql" - "/usr/i686-linux-gnu/usr/lib/" - "/usr/i386-linux-gnu/usr/lib/libmariadb3" - "/usr/i386-linux-gnu/usr/lib/mysql" - "/usr/i386-linux-gnu/usr/lib/" - CACHE STRING "Library search paths" FORCE - ) - else (CROSSCOMPILING_ARCH) - set (local_lib_search_paths - "/usr/lib/i686-linux-gnu/libmariadb3" - "/usr/lib/i686-linux-gnu/mysql" - "/usr/lib/i686-linux-gnu" - "/usr/lib/i386-linux-gnu/libmariadb3" - "/usr/lib/i386-linux-gnu/mysql" - "/usr/lib/i386-linux-gnu" - "/usr/lib32/mysql" - "/usr/lib32" - ) - - if ("${CMAKE_HOST_SYSTEM_PROCESSOR}" STREQUAL "x86_64") - # I'm compiling for x86 on an x86_64 host. - set (CMAKE_LIBRARY_PATH ${local_lib_search_paths} CACHE PATH "") - else () - # I'm compiling for x86 on an x86 OS (32 bits), so natively: i have libs on /usr/lib and not /usr/lib32. - set (local_extra_lib_search_paths - "/usr/lib/mysql" - "/usr/lib" - ) + # search headers and libraries in the target environment + set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE "ONLY" CACHE INTERNAL "" FORCE) + set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY "ONLY" CACHE INTERNAL "" FORCE) endif() - - set (lib_search_paths - ${local_lib_search_paths} - ${local_extra_lib_search_paths} - CACHE STRING "Library search paths" FORCE - ) - endif (CROSSCOMPILING_ARCH) - - toolchain_after_project_common() - - # --target=-x86-unknown-linux-gnu? - SET (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -march=i686 -m32" PARENT_SCOPE) - SET (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -march=i686 -m32" PARENT_SCOPE) endfunction() +function(toolchain_after_project) + message(STATUS "Toolchain: Linux-Clang-x86.cmake.") + # Do not set CMAKE_SYSTEM_NAME if compiling for the same OS, otherwise CMAKE_CROSSCOMPILING will be set to TRUE + #SET(CMAKE_SYSTEM_NAME "Linux" CACHE INTERNAL "" FORCE) # target OS + set(CMAKE_SYSTEM_PROCESSOR "x86" CACHE INTERNAL "" FORCE) # target arch + set(CMAKE_RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/bin-x86" PARENT_SCOPE) + #set(ARCH_BITS 32 CACHE INTERNAL "" FORCE) # provide it + + if(CROSSCOMPILING_ARCH) + # possible cross-compilation foreign arch lib locations + set(lib_search_paths + "/usr/i686-linux-gnu/usr/lib/libmariadb3" + "/usr/i686-linux-gnu/usr/lib/mysql" + "/usr/i686-linux-gnu/usr/lib/" + "/usr/i386-linux-gnu/usr/lib/libmariadb3" + "/usr/i386-linux-gnu/usr/lib/mysql" + "/usr/i386-linux-gnu/usr/lib/" + CACHE STRING + "Library search paths" + FORCE + ) + else(CROSSCOMPILING_ARCH) + set(local_lib_search_paths + "/usr/lib/i686-linux-gnu/libmariadb3" + "/usr/lib/i686-linux-gnu/mysql" + "/usr/lib/i686-linux-gnu" + "/usr/lib/i386-linux-gnu/libmariadb3" + "/usr/lib/i386-linux-gnu/mysql" + "/usr/lib/i386-linux-gnu" + "/usr/lib32/mysql" + "/usr/lib32" + ) + + if("${CMAKE_HOST_SYSTEM_PROCESSOR}" STREQUAL "x86_64") + # I'm compiling for x86 on an x86_64 host. + set(CMAKE_LIBRARY_PATH ${local_lib_search_paths} CACHE PATH "") + else() + # I'm compiling for x86 on an x86 OS (32 bits), so natively: i have libs on /usr/lib and not /usr/lib32. + set(local_extra_lib_search_paths "/usr/lib/mysql" "/usr/lib") + endif() + + set(lib_search_paths + ${local_lib_search_paths} + ${local_extra_lib_search_paths} + CACHE STRING + "Library search paths" + FORCE + ) + endif(CROSSCOMPILING_ARCH) + + toolchain_after_project_common() + + # --target=-x86-unknown-linux-gnu? + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -march=i686 -m32" PARENT_SCOPE) + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -march=i686 -m32" PARENT_SCOPE) +endfunction() -function (toolchain_exe_stuff) - toolchain_exe_stuff_common() +function(toolchain_exe_stuff) + toolchain_exe_stuff_common() - # Propagate global variables set in toolchain_exe_stuff_common to the upper scope - #SET (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${C_ARCH_OPTS}" PARENT_SCOPE) - #SET (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${CXX_ARCH_OPTS}" PARENT_SCOPE) - #SET (CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS}" PARENT_SCOPE) + # Propagate global variables set in toolchain_exe_stuff_common to the upper scope + #SET (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${C_ARCH_OPTS}" PARENT_SCOPE) + #SET (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${CXX_ARCH_OPTS}" PARENT_SCOPE) + #SET (CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS}" PARENT_SCOPE) endfunction() diff --git a/cmake/toolchains/Linux-Clang-x86_64.cmake b/cmake/toolchains/Linux-Clang-x86_64.cmake index ca95c9128..562738bbd 100644 --- a/cmake/toolchains/Linux-Clang-x86_64.cmake +++ b/cmake/toolchains/Linux-Clang-x86_64.cmake @@ -1,70 +1,71 @@ -INCLUDE("${CMAKE_CURRENT_LIST_DIR}/include/Linux-Clang_common.inc.cmake") +include("${CMAKE_CURRENT_LIST_DIR}/include/Linux-Clang_common.inc.cmake") +function(toolchain_force_compiler) + set(CMAKE_C_COMPILER "clang" CACHE STRING "C compiler" FORCE) + set(CMAKE_CXX_COMPILER "clang++" CACHE STRING "C++ compiler" FORCE) -function (toolchain_force_compiler) - SET (CMAKE_C_COMPILER "clang" CACHE STRING "C compiler" FORCE) - SET (CMAKE_CXX_COMPILER "clang++" CACHE STRING "C++ compiler" FORCE) + if(CROSSCOMPILING_ARCH) + message(FATAL_ERROR "Incomplete/to be tested.") # are the names/paths correct? - if (CROSSCOMPILING_ARCH) - message(FATAL_ERROR "Incomplete/to be tested.") # are the names/paths correct? + # where is the target environment located + set(CMAKE_FIND_ROOT_PATH "/usr/x86_64-pc-linux-gnu" CACHE INTERNAL "" FORCE) - # where is the target environment located - set(CMAKE_FIND_ROOT_PATH "/usr/x86_64-pc-linux-gnu" CACHE INTERNAL "" FORCE) - - # adjust the default behavior of the FIND_XXX() commands: - # search programs in the host environment - set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM "NEVER" CACHE INTERNAL "" FORCE) - - # search headers and libraries in the target environment - set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE "ONLY" CACHE INTERNAL "" FORCE) - set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY "ONLY" CACHE INTERNAL "" FORCE) - endif() -endfunction () + # adjust the default behavior of the FIND_XXX() commands: + # search programs in the host environment + set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM "NEVER" CACHE INTERNAL "" FORCE) + # search headers and libraries in the target environment + set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE "ONLY" CACHE INTERNAL "" FORCE) + set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY "ONLY" CACHE INTERNAL "" FORCE) + endif() +endfunction() -function (toolchain_after_project) - MESSAGE (STATUS "Toolchain: Linux-Clang-x86_64.cmake.") - # Do not set CMAKE_SYSTEM_NAME if compiling for the same OS, otherwise CMAKE_CROSSCOMPILING will be set to TRUE - #SET(CMAKE_SYSTEM_NAME "Linux" CACHE INTERNAL "" FORCE) # target OS - SET(CMAKE_SYSTEM_PROCESSOR "x86_64" CACHE INTERNAL "" FORCE) # target arch - SET(CMAKE_RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/bin-x86_64" PARENT_SCOPE) - set(ARCH_BITS 64 CACHE INTERNAL "" FORCE) # provide it +function(toolchain_after_project) + message(STATUS "Toolchain: Linux-Clang-x86_64.cmake.") + # Do not set CMAKE_SYSTEM_NAME if compiling for the same OS, otherwise CMAKE_CROSSCOMPILING will be set to TRUE + #SET(CMAKE_SYSTEM_NAME "Linux" CACHE INTERNAL "" FORCE) # target OS + set(CMAKE_SYSTEM_PROCESSOR "x86_64" CACHE INTERNAL "" FORCE) # target arch + set(CMAKE_RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/bin-x86_64" PARENT_SCOPE) + set(ARCH_BITS 64 CACHE INTERNAL "" FORCE) # provide it - if (CROSSCOMPILING_ARCH) - # possible cross-compilation foreign arch lib locations - set (lib_search_paths - "/usr/x86_64-linux-gnu/usr/lib/libmariadb3" - "/usr/x86_64-linux-gnu/usr/lib/mysql" - "/usr/x86_64-linux-gnu/usr/lib/" - CACHE STRING "Library search paths" FORCE - ) - else () - # possible native/host lib locations - set (lib_search_paths - "/usr/lib/x86_64-linux-gnu/libmariadb3" - "/usr/lib/x86_64-linux-gnu/mysql" - "/usr/lib/x86_64-linux-gnu" - "/usr/lib64/mysql" - "/usr/lib64" - "/usr/lib/mysql" - "/usr/lib" - CACHE STRING "Library search paths" FORCE - ) - endif () + if(CROSSCOMPILING_ARCH) + # possible cross-compilation foreign arch lib locations + set(lib_search_paths + "/usr/x86_64-linux-gnu/usr/lib/libmariadb3" + "/usr/x86_64-linux-gnu/usr/lib/mysql" + "/usr/x86_64-linux-gnu/usr/lib/" + CACHE STRING + "Library search paths" + FORCE + ) + else() + # possible native/host lib locations + set(lib_search_paths + "/usr/lib/x86_64-linux-gnu/libmariadb3" + "/usr/lib/x86_64-linux-gnu/mysql" + "/usr/lib/x86_64-linux-gnu" + "/usr/lib64/mysql" + "/usr/lib64" + "/usr/lib/mysql" + "/usr/lib" + CACHE STRING + "Library search paths" + FORCE + ) + endif() - toolchain_after_project_common() + toolchain_after_project_common() - # --target=-x86_64-unknown-linux-gnu ? - SET (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -march=x86-64 -m64" PARENT_SCOPE) - SET (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -march=x86-64 -m64" PARENT_SCOPE) + # --target=-x86_64-unknown-linux-gnu ? + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -march=x86-64 -m64" PARENT_SCOPE) + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -march=x86-64 -m64" PARENT_SCOPE) endfunction() +function(toolchain_exe_stuff) + toolchain_exe_stuff_common() -function (toolchain_exe_stuff) - toolchain_exe_stuff_common() - - # Propagate global variables set in toolchain_exe_stuff_common to the upper scope - #SET (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${C_ARCH_OPTS}" PARENT_SCOPE) - #SET (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${CXX_ARCH_OPTS}" PARENT_SCOPE) - #SET (CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS}" PARENT_SCOPE) + # Propagate global variables set in toolchain_exe_stuff_common to the upper scope + #SET (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${C_ARCH_OPTS}" PARENT_SCOPE) + #SET (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${CXX_ARCH_OPTS}" PARENT_SCOPE) + #SET (CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS}" PARENT_SCOPE) endfunction() diff --git a/cmake/toolchains/Linux-GNU-AArch64.cmake b/cmake/toolchains/Linux-GNU-AArch64.cmake index cc278462c..ae5da2bd6 100644 --- a/cmake/toolchains/Linux-GNU-AArch64.cmake +++ b/cmake/toolchains/Linux-GNU-AArch64.cmake @@ -1,69 +1,71 @@ -INCLUDE("${CMAKE_CURRENT_LIST_DIR}/include/Linux-GNU_common.inc.cmake") +include("${CMAKE_CURRENT_LIST_DIR}/include/Linux-GNU_common.inc.cmake") +function(toolchain_force_compiler) + if(NOT CROSSCOMPILING_ARCH) + set(CMAKE_C_COMPILER "gcc" CACHE STRING "C compiler" FORCE) + set(CMAKE_CXX_COMPILER "g++" CACHE STRING "C++ compiler" FORCE) + else() + set(CMAKE_C_COMPILER "aarch64-linux-gnu-gcc" CACHE STRING "C compiler" FORCE) + set(CMAKE_CXX_COMPILER "aarch64-linux-gnu-g++" CACHE STRING "C++ compiler" FORCE) -function (toolchain_force_compiler) - if (NOT CROSSCOMPILING_ARCH) - SET (CMAKE_C_COMPILER "gcc" CACHE STRING "C compiler" FORCE) - SET (CMAKE_CXX_COMPILER "g++" CACHE STRING "C++ compiler" FORCE) - else () - set(CMAKE_C_COMPILER "aarch64-linux-gnu-gcc" CACHE STRING "C compiler" FORCE) - set(CMAKE_CXX_COMPILER "aarch64-linux-gnu-g++" CACHE STRING "C++ compiler" FORCE) + # where is the target environment located + set(CMAKE_FIND_ROOT_PATH "/usr/aarch64-linux-gnu" CACHE INTERNAL "" FORCE) - # where is the target environment located - set(CMAKE_FIND_ROOT_PATH "/usr/aarch64-linux-gnu" CACHE INTERNAL "" FORCE) - - # adjust the default behavior of the FIND_XXX() commands: - # search programs in the host environment - set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM "NEVER" CACHE INTERNAL "" FORCE) - - # search headers and libraries in the target environment - set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE "ONLY" CACHE INTERNAL "" FORCE) - set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY "ONLY" CACHE INTERNAL "" FORCE) - endif() -endfunction () + # adjust the default behavior of the FIND_XXX() commands: + # search programs in the host environment + set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM "NEVER" CACHE INTERNAL "" FORCE) + # search headers and libraries in the target environment + set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE "ONLY" CACHE INTERNAL "" FORCE) + set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY "ONLY" CACHE INTERNAL "" FORCE) + endif() +endfunction() -function (toolchain_after_project) - MESSAGE (STATUS "Toolchain: Linux-GNU-AArch64.cmake.") - # Do not set CMAKE_SYSTEM_NAME if compiling for the same OS, otherwise CMAKE_CROSSCOMPILING will be set to TRUE - #SET(CMAKE_SYSTEM_NAME "Linux" CACHE INTERNAL "" FORCE) - SET(CMAKE_SYSTEM_PROCESSOR "aarch64" CACHE INTERNAL "" FORCE) - SET(CMAKE_RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/bin-aarch64" CACHE INTERNAL "" FORCE) - set(ARCH_BITS 64 CACHE INTERNAL "" FORCE) # provide it +function(toolchain_after_project) + message(STATUS "Toolchain: Linux-GNU-AArch64.cmake.") + # Do not set CMAKE_SYSTEM_NAME if compiling for the same OS, otherwise CMAKE_CROSSCOMPILING will be set to TRUE + #SET(CMAKE_SYSTEM_NAME "Linux" CACHE INTERNAL "" FORCE) + set(CMAKE_SYSTEM_PROCESSOR "aarch64" CACHE INTERNAL "" FORCE) + set(CMAKE_RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/bin-aarch64" CACHE INTERNAL "" FORCE) + set(ARCH_BITS 64 CACHE INTERNAL "" FORCE) # provide it - if (CROSSCOMPILING_ARCH) - # possible cross-compilation foreign arch lib locations - set (lib_search_paths - "/usr/aarch64-linux-gnu/usr/lib/libmariadb3" - "/usr/aarch64-linux-gnu/usr/lib/mysql" - "/usr/aarch64-linux-gnu/usr/lib/" - CACHE STRING "Library search paths" FORCE - ) - else () - # possible native/host lib locations - set (lib_search_paths - "/usr/lib/aarch64-linux-gnu/libmariadb3" - "/usr/lib/aarch64-linux-gnu/mysql" - "/usr/lib/aarch64-linux-gnu" - "/usr/lib64/mysql" - "/usr/lib64" - "/usr/lib/mysql" - "/usr/lib" - CACHE STRING "Library search paths" FORCE - ) - endif () + if(CROSSCOMPILING_ARCH) + # possible cross-compilation foreign arch lib locations + set(lib_search_paths + "/usr/aarch64-linux-gnu/usr/lib/libmariadb3" + "/usr/aarch64-linux-gnu/usr/lib/mysql" + "/usr/aarch64-linux-gnu/usr/lib/" + CACHE STRING + "Library search paths" + FORCE + ) + else() + # possible native/host lib locations + set(lib_search_paths + "/usr/lib/aarch64-linux-gnu/libmariadb3" + "/usr/lib/aarch64-linux-gnu/mysql" + "/usr/lib/aarch64-linux-gnu" + "/usr/lib64/mysql" + "/usr/lib64" + "/usr/lib/mysql" + "/usr/lib" + CACHE STRING + "Library search paths" + FORCE + ) + endif() - toolchain_after_project_common() + toolchain_after_project_common() - SET (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -march=armv8-a" PARENT_SCOPE) - SET (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -march=armv8-a" PARENT_SCOPE) + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -march=armv8-a" PARENT_SCOPE) + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -march=armv8-a" PARENT_SCOPE) endfunction() -function (toolchain_exe_stuff) - toolchain_exe_stuff_common() +function(toolchain_exe_stuff) + toolchain_exe_stuff_common() - # Propagate global variables set in toolchain_exe_stuff_common to the upper scope - #SET (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${C_ARCH_OPTS}" PARENT_SCOPE) - #SET (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${CXX_ARCH_OPTS}" PARENT_SCOPE) - #SET (CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS}" PARENT_SCOPE) + # Propagate global variables set in toolchain_exe_stuff_common to the upper scope + #SET (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${C_ARCH_OPTS}" PARENT_SCOPE) + #SET (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${CXX_ARCH_OPTS}" PARENT_SCOPE) + #SET (CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS}" PARENT_SCOPE) endfunction() diff --git a/cmake/toolchains/Linux-GNU-native.cmake b/cmake/toolchains/Linux-GNU-native.cmake index b22b02163..322dcff3b 100644 --- a/cmake/toolchains/Linux-GNU-native.cmake +++ b/cmake/toolchains/Linux-GNU-native.cmake @@ -1,59 +1,52 @@ -INCLUDE("${CMAKE_CURRENT_LIST_DIR}/include/Linux-GNU_common.inc.cmake") - - -function (toolchain_force_compiler) - if (CROSSCOMPILING_ARCH) - message(FATAL_ERROR "Can't cross-compile with a 'native' toolchain.") - endif () - - SET (CMAKE_C_COMPILER "gcc" CACHE STRING "C compiler" FORCE) - SET (CMAKE_CXX_COMPILER "g++" CACHE STRING "C++ compiler" FORCE) -endfunction () - - -function (toolchain_after_project) - MESSAGE (STATUS "Toolchain: Linux-GNU-native.cmake.") - # Do not set CMAKE_SYSTEM_NAME if compiling for the same OS, otherwise CMAKE_CROSSCOMPILING will be set to TRUE - #SET(CMAKE_SYSTEM_NAME "Linux" CACHE INTERNAL "" FORCE) # target OS - IF (CMAKE_SIZEOF_VOID_P EQUAL 8) - SET(CMAKE_RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/bin-native64" PARENT_SCOPE) - ELSE () - SET(CMAKE_RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/bin-native32" PARENT_SCOPE) - ENDIF () - - # possible native/host lib locations - set (local_usr_lib_subfolders - "libmariadb3" - "mysql" - ) - foreach (local_usr_lib_subfolders subfolder) - # ARCH variable is set by CMakeGitStatus - set (local_lib_search_paths - ${local_lib_search_paths} - "/usr/${ARCH}-linux-gnu/${subfolder}" - ) - endforeach() - set (lib_search_paths - ${local_lib_search_paths} - "/usr/lib64/mysql" - "/usr/lib64" - "/usr/lib/mysql" - "/usr/lib" - CACHE STRING "Library search paths" FORCE - ) - - toolchain_after_project_common() - - SET (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -march=native -mtune=native" PARENT_SCOPE) - SET (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -march=native -mtune=native" PARENT_SCOPE) +include("${CMAKE_CURRENT_LIST_DIR}/include/Linux-GNU_common.inc.cmake") + +function(toolchain_force_compiler) + if(CROSSCOMPILING_ARCH) + message(FATAL_ERROR "Can't cross-compile with a 'native' toolchain.") + endif() + + set(CMAKE_C_COMPILER "gcc" CACHE STRING "C compiler" FORCE) + set(CMAKE_CXX_COMPILER "g++" CACHE STRING "C++ compiler" FORCE) endfunction() +function(toolchain_after_project) + message(STATUS "Toolchain: Linux-GNU-native.cmake.") + # Do not set CMAKE_SYSTEM_NAME if compiling for the same OS, otherwise CMAKE_CROSSCOMPILING will be set to TRUE + #SET(CMAKE_SYSTEM_NAME "Linux" CACHE INTERNAL "" FORCE) # target OS + if(CMAKE_SIZEOF_VOID_P EQUAL 8) + set(CMAKE_RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/bin-native64" PARENT_SCOPE) + else() + set(CMAKE_RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/bin-native32" PARENT_SCOPE) + endif() + + # possible native/host lib locations + set(local_usr_lib_subfolders "libmariadb3" "mysql") + foreach(local_usr_lib_subfolders subfolder) + # ARCH variable is set by CMakeGitStatus + set(local_lib_search_paths ${local_lib_search_paths} "/usr/${ARCH}-linux-gnu/${subfolder}") + endforeach() + set(lib_search_paths + ${local_lib_search_paths} + "/usr/lib64/mysql" + "/usr/lib64" + "/usr/lib/mysql" + "/usr/lib" + CACHE STRING + "Library search paths" + FORCE + ) + + toolchain_after_project_common() + + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -march=native -mtune=native" PARENT_SCOPE) + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -march=native -mtune=native" PARENT_SCOPE) +endfunction() -function (toolchain_exe_stuff) - toolchain_exe_stuff_common() +function(toolchain_exe_stuff) + toolchain_exe_stuff_common() - # Propagate global variables set in toolchain_exe_stuff_common to the upper scope - #SET (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${C_ARCH_OPTS}" PARENT_SCOPE) - #SET (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${CXX_ARCH_OPTS}" PARENT_SCOPE) - #SET (CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS}" PARENT_SCOPE) + # Propagate global variables set in toolchain_exe_stuff_common to the upper scope + #SET (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${C_ARCH_OPTS}" PARENT_SCOPE) + #SET (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${CXX_ARCH_OPTS}" PARENT_SCOPE) + #SET (CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS}" PARENT_SCOPE) endfunction() diff --git a/cmake/toolchains/Linux-GNU-x86.cmake b/cmake/toolchains/Linux-GNU-x86.cmake index 9ffd7aeed..a20c4fb0e 100644 --- a/cmake/toolchains/Linux-GNU-x86.cmake +++ b/cmake/toolchains/Linux-GNU-x86.cmake @@ -1,92 +1,90 @@ -INCLUDE("${CMAKE_CURRENT_LIST_DIR}/include/Linux-GNU_common.inc.cmake") +include("${CMAKE_CURRENT_LIST_DIR}/include/Linux-GNU_common.inc.cmake") # For this toolchain, the operating system is the same between host and target, but target can have a different arch than host's. +function(toolchain_force_compiler) + if(NOT CROSSCOMPILING_ARCH) + set(CMAKE_C_COMPILER "gcc" CACHE STRING "C compiler" FORCE) + set(CMAKE_CXX_COMPILER "g++" CACHE STRING "C++ compiler" FORCE) + else() + message(FATAL_ERROR "Incomplete/to be tested.") # are the names/paths correct? -function (toolchain_force_compiler) - if (NOT CROSSCOMPILING_ARCH) - SET (CMAKE_C_COMPILER "gcc" CACHE STRING "C compiler" FORCE) - SET (CMAKE_CXX_COMPILER "g++" CACHE STRING "C++ compiler" FORCE) - else () - message(FATAL_ERROR "Incomplete/to be tested.") # are the names/paths correct? + set(CMAKE_C_COMPILER "i386-pc-linux-gnu-gcc" CACHE STRING "C compiler" FORCE) + set(CMAKE_CXX_COMPILER "i386-pc-linux-gnu-g++" CACHE STRING "C++ compiler" FORCE) - set(CMAKE_C_COMPILER "i386-pc-linux-gnu-gcc" CACHE STRING "C compiler" FORCE) - set(CMAKE_CXX_COMPILER "i386-pc-linux-gnu-g++" CACHE STRING "C++ compiler" FORCE) + # where is the target environment located + set(CMAKE_FIND_ROOT_PATH "/usr/i386-pc-linux-gnu" CACHE INTERNAL "" FORCE) - # where is the target environment located - set(CMAKE_FIND_ROOT_PATH "/usr/i386-pc-linux-gnu" CACHE INTERNAL "" FORCE) + # adjust the default behavior of the FIND_XXX() commands: + # search programs in the host environment + set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM "NEVER" CACHE INTERNAL "" FORCE) - # adjust the default behavior of the FIND_XXX() commands: - # search programs in the host environment - set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM "NEVER" CACHE INTERNAL "" FORCE) - - # search headers and libraries in the target environment - set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE "ONLY" CACHE INTERNAL "" FORCE) - set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY "ONLY" CACHE INTERNAL "" FORCE) - endif() -endfunction () - - -function (toolchain_after_project) - MESSAGE (STATUS "Toolchain: Linux-GNU-x86.cmake.") - # Do not set CMAKE_SYSTEM_NAME if compiling for the same OS, otherwise CMAKE_CROSSCOMPILING will be set to TRUE - #SET(CMAKE_SYSTEM_NAME "Linux" CACHE INTERNAL "" FORCE) - SET(CMAKE_SYSTEM_PROCESSOR "x86" CACHE INTERNAL "" FORCE) - SET(CMAKE_RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/bin-x86" PARENT_SCOPE) - #set(ARCH_BITS 32 CACHE INTERNAL "" FORCE) # provide it - - if (CROSSCOMPILING_ARCH) - # possible cross-compilation foreign arch lib locations - set (lib_search_paths - "/usr/i686-linux-gnu/usr/lib/libmariadb3" - "/usr/i686-linux-gnu/usr/lib/mysql" - "/usr/i686-linux-gnu/usr/lib/" - "/usr/i386-linux-gnu/usr/lib/libmariadb3" - "/usr/i386-linux-gnu/usr/lib/mysql" - "/usr/i386-linux-gnu/usr/lib/" - CACHE STRING "Library search paths" FORCE - ) - else (CROSSCOMPILING_ARCH) - set (local_lib_search_paths - "/usr/lib/i686-linux-gnu/libmariadb3" - "/usr/lib/i686-linux-gnu/mysql" - "/usr/lib/i686-linux-gnu" - "/usr/lib/i386-linux-gnu/libmariadb3" - "/usr/lib/i386-linux-gnu/mysql" - "/usr/lib/i386-linux-gnu" - "/usr/lib32/mysql" - "/usr/lib32" - ) - - if ("${CMAKE_HOST_SYSTEM_PROCESSOR}" STREQUAL "x86_64") - # I'm compiling for x86 on an x86_64 host. - set (CMAKE_LIBRARY_PATH ${local_lib_search_paths} CACHE PATH "") - else () - # I'm compiling for x86 on an x86 OS (32 bits), so natively: i have libs on /usr/lib and not /usr/lib32. - set (local_extra_lib_search_paths - "/usr/lib/mysql" - "/usr/lib" - ) + # search headers and libraries in the target environment + set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE "ONLY" CACHE INTERNAL "" FORCE) + set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY "ONLY" CACHE INTERNAL "" FORCE) endif() - - set (lib_search_paths - ${local_lib_search_paths} - ${local_extra_lib_search_paths} - CACHE STRING "Library search paths (hint)" FORCE - ) - endif (CROSSCOMPILING_ARCH) - - toolchain_after_project_common() - - SET (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -march=i686 -m32" PARENT_SCOPE) - SET (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -march=i686 -m32" PARENT_SCOPE) endfunction() +function(toolchain_after_project) + message(STATUS "Toolchain: Linux-GNU-x86.cmake.") + # Do not set CMAKE_SYSTEM_NAME if compiling for the same OS, otherwise CMAKE_CROSSCOMPILING will be set to TRUE + #SET(CMAKE_SYSTEM_NAME "Linux" CACHE INTERNAL "" FORCE) + set(CMAKE_SYSTEM_PROCESSOR "x86" CACHE INTERNAL "" FORCE) + set(CMAKE_RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/bin-x86" PARENT_SCOPE) + #set(ARCH_BITS 32 CACHE INTERNAL "" FORCE) # provide it + + if(CROSSCOMPILING_ARCH) + # possible cross-compilation foreign arch lib locations + set(lib_search_paths + "/usr/i686-linux-gnu/usr/lib/libmariadb3" + "/usr/i686-linux-gnu/usr/lib/mysql" + "/usr/i686-linux-gnu/usr/lib/" + "/usr/i386-linux-gnu/usr/lib/libmariadb3" + "/usr/i386-linux-gnu/usr/lib/mysql" + "/usr/i386-linux-gnu/usr/lib/" + CACHE STRING + "Library search paths" + FORCE + ) + else(CROSSCOMPILING_ARCH) + set(local_lib_search_paths + "/usr/lib/i686-linux-gnu/libmariadb3" + "/usr/lib/i686-linux-gnu/mysql" + "/usr/lib/i686-linux-gnu" + "/usr/lib/i386-linux-gnu/libmariadb3" + "/usr/lib/i386-linux-gnu/mysql" + "/usr/lib/i386-linux-gnu" + "/usr/lib32/mysql" + "/usr/lib32" + ) + + if("${CMAKE_HOST_SYSTEM_PROCESSOR}" STREQUAL "x86_64") + # I'm compiling for x86 on an x86_64 host. + set(CMAKE_LIBRARY_PATH ${local_lib_search_paths} CACHE PATH "") + else() + # I'm compiling for x86 on an x86 OS (32 bits), so natively: i have libs on /usr/lib and not /usr/lib32. + set(local_extra_lib_search_paths "/usr/lib/mysql" "/usr/lib") + endif() + + set(lib_search_paths + ${local_lib_search_paths} + ${local_extra_lib_search_paths} + CACHE STRING + "Library search paths (hint)" + FORCE + ) + endif(CROSSCOMPILING_ARCH) + + toolchain_after_project_common() + + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -march=i686 -m32" PARENT_SCOPE) + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -march=i686 -m32" PARENT_SCOPE) +endfunction() -function (toolchain_exe_stuff) - toolchain_exe_stuff_common() +function(toolchain_exe_stuff) + toolchain_exe_stuff_common() - # Propagate global variables set in toolchain_exe_stuff_common to the upper scope - #SET (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${C_ARCH_OPTS}" PARENT_SCOPE) - #SET (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${CXX_ARCH_OPTS}" PARENT_SCOPE) - #SET (CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS}" PARENT_SCOPE) + # Propagate global variables set in toolchain_exe_stuff_common to the upper scope + #SET (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${C_ARCH_OPTS}" PARENT_SCOPE) + #SET (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${CXX_ARCH_OPTS}" PARENT_SCOPE) + #SET (CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS}" PARENT_SCOPE) endfunction() diff --git a/cmake/toolchains/Linux-GNU-x86_64.cmake b/cmake/toolchains/Linux-GNU-x86_64.cmake index a2c2cdd68..bb399e508 100644 --- a/cmake/toolchains/Linux-GNU-x86_64.cmake +++ b/cmake/toolchains/Linux-GNU-x86_64.cmake @@ -1,73 +1,74 @@ -INCLUDE("${CMAKE_CURRENT_LIST_DIR}/include/Linux-GNU_common.inc.cmake") +include("${CMAKE_CURRENT_LIST_DIR}/include/Linux-GNU_common.inc.cmake") # For this toolchain, the operating system is the same between host and target, but target can have a different arch than host's. +function(toolchain_force_compiler) + if(NOT CROSSCOMPILING_ARCH) + set(CMAKE_C_COMPILER "gcc" CACHE STRING "C compiler" FORCE) + set(CMAKE_CXX_COMPILER "g++" CACHE STRING "C++ compiler" FORCE) + else() + message(FATAL_ERROR "Incomplete/to be tested.") # are the names/paths correct? -function (toolchain_force_compiler) - if (NOT CROSSCOMPILING_ARCH) - SET (CMAKE_C_COMPILER "gcc" CACHE STRING "C compiler" FORCE) - SET (CMAKE_CXX_COMPILER "g++" CACHE STRING "C++ compiler" FORCE) - else () - message(FATAL_ERROR "Incomplete/to be tested.") # are the names/paths correct? + set(CMAKE_C_COMPILER "x86_64-pc-linux-gnu-gcc" CACHE STRING "C compiler" FORCE) + set(CMAKE_CXX_COMPILER "x86_64-pc-linux-gnu-g++" CACHE STRING "C++ compiler" FORCE) - set(CMAKE_C_COMPILER "x86_64-pc-linux-gnu-gcc" CACHE STRING "C compiler" FORCE) - set(CMAKE_CXX_COMPILER "x86_64-pc-linux-gnu-g++" CACHE STRING "C++ compiler" FORCE) + # where is the target environment located + set(CMAKE_FIND_ROOT_PATH "/usr/x86_64-pc-linux-gnu" CACHE INTERNAL "" FORCE) - # where is the target environment located - set(CMAKE_FIND_ROOT_PATH "/usr/x86_64-pc-linux-gnu" CACHE INTERNAL "" FORCE) - - # adjust the default behavior of the FIND_XXX() commands: - # search programs in the host environment - set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM "NEVER" CACHE INTERNAL "" FORCE) - - # search headers and libraries in the target environment - set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE "ONLY" CACHE INTERNAL "" FORCE) - set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY "ONLY" CACHE INTERNAL "" FORCE) - endif() -endfunction () + # adjust the default behavior of the FIND_XXX() commands: + # search programs in the host environment + set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM "NEVER" CACHE INTERNAL "" FORCE) + # search headers and libraries in the target environment + set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE "ONLY" CACHE INTERNAL "" FORCE) + set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY "ONLY" CACHE INTERNAL "" FORCE) + endif() +endfunction() -function (toolchain_after_project) - MESSAGE (STATUS "Toolchain: Linux-GNU-x86_64.cmake.") - # Do not set CMAKE_SYSTEM_NAME if compiling for the same OS, otherwise CMAKE_CROSSCOMPILING will be set to TRUE - #SET(CMAKE_SYSTEM_NAME "Linux" CACHE INTERNAL "" FORCE) # target os - SET(CMAKE_SYSTEM_PROCESSOR "x86_64" CACHE INTERNAL "" FORCE) # target arch - SET(CMAKE_RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/bin-x86_64" PARENT_SCOPE) - #set(ARCH_BITS 64 CACHE INTERNAL "" FORCE) # provide it +function(toolchain_after_project) + message(STATUS "Toolchain: Linux-GNU-x86_64.cmake.") + # Do not set CMAKE_SYSTEM_NAME if compiling for the same OS, otherwise CMAKE_CROSSCOMPILING will be set to TRUE + #SET(CMAKE_SYSTEM_NAME "Linux" CACHE INTERNAL "" FORCE) # target os + set(CMAKE_SYSTEM_PROCESSOR "x86_64" CACHE INTERNAL "" FORCE) # target arch + set(CMAKE_RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/bin-x86_64" PARENT_SCOPE) + #set(ARCH_BITS 64 CACHE INTERNAL "" FORCE) # provide it - if (CROSSCOMPILING_ARCH) - # possible cross-compilation foreign arch lib locations - set (lib_search_paths - "/usr/x86_64-linux-gnu/usr/lib/libmariadb3" - "/usr/x86_64-linux-gnu/usr/lib/mysql" - "/usr/x86_64-linux-gnu/usr/lib/" - CACHE STRING "Library search paths" FORCE - ) - else () - # possible native/host lib locations - set (lib_search_paths - "/usr/lib/x86_64-linux-gnu/libmariadb3" - "/usr/lib/x86_64-linux-gnu/mysql" - "/usr/lib/x86_64-linux-gnu" - "/usr/lib64/mysql" - "/usr/lib64" - "/usr/lib/mysql" - "/usr/lib" - CACHE STRING "Library search paths" FORCE - ) - endif () + if(CROSSCOMPILING_ARCH) + # possible cross-compilation foreign arch lib locations + set(lib_search_paths + "/usr/x86_64-linux-gnu/usr/lib/libmariadb3" + "/usr/x86_64-linux-gnu/usr/lib/mysql" + "/usr/x86_64-linux-gnu/usr/lib/" + CACHE STRING + "Library search paths" + FORCE + ) + else() + # possible native/host lib locations + set(lib_search_paths + "/usr/lib/x86_64-linux-gnu/libmariadb3" + "/usr/lib/x86_64-linux-gnu/mysql" + "/usr/lib/x86_64-linux-gnu" + "/usr/lib64/mysql" + "/usr/lib64" + "/usr/lib/mysql" + "/usr/lib" + CACHE STRING + "Library search paths" + FORCE + ) + endif() - toolchain_after_project_common() + toolchain_after_project_common() - SET (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -march=x86-64 -m64" PARENT_SCOPE) - SET (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -march=x86-64 -m64" PARENT_SCOPE) + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -march=x86-64 -m64" PARENT_SCOPE) + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -march=x86-64 -m64" PARENT_SCOPE) endfunction() +function(toolchain_exe_stuff) + toolchain_exe_stuff_common() -function (toolchain_exe_stuff) - toolchain_exe_stuff_common() - - # Propagate global variables set in toolchain_exe_stuff_common to the upper scope - #SET (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${C_ARCH_OPTS}" PARENT_SCOPE) - #SET (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${CXX_ARCH_OPTS}" PARENT_SCOPE) - #SET (CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS}" PARENT_SCOPE) + # Propagate global variables set in toolchain_exe_stuff_common to the upper scope + #SET (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${C_ARCH_OPTS}" PARENT_SCOPE) + #SET (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${CXX_ARCH_OPTS}" PARENT_SCOPE) + #SET (CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS}" PARENT_SCOPE) endfunction() diff --git a/cmake/toolchains/OSX-AppleClang-AArch64.cmake b/cmake/toolchains/OSX-AppleClang-AArch64.cmake index 0508d1b86..860371728 100644 --- a/cmake/toolchains/OSX-AppleClang-AArch64.cmake +++ b/cmake/toolchains/OSX-AppleClang-AArch64.cmake @@ -1,40 +1,37 @@ -INCLUDE("${CMAKE_CURRENT_LIST_DIR}/include/OSX-AppleClang_common.inc.cmake") +include("${CMAKE_CURRENT_LIST_DIR}/include/OSX-AppleClang_common.inc.cmake") +function(toolchain_force_compiler) + if(CROSSCOMPILING_ARCH) + message(FATAL_ERROR "This toolchain (as it is now) doesn't support cross-compilation.") + endif() -function (toolchain_force_compiler) - if (CROSSCOMPILING_ARCH) - message(FATAL_ERROR "This toolchain (as it is now) doesn't support cross-compilation.") - endif () - - SET (CMAKE_C_COMPILER "clang" CACHE STRING "C compiler" FORCE) - SET (CMAKE_CXX_COMPILER "clang++" CACHE STRING "C++ compiler" FORCE) - - # In order to enable ninja to be verbose - set(CMAKE_VERBOSE_MAKEFILE ON CACHE BOOL "ON") -endfunction () + set(CMAKE_C_COMPILER "clang" CACHE STRING "C compiler" FORCE) + set(CMAKE_CXX_COMPILER "clang++" CACHE STRING "C++ compiler" FORCE) + # In order to enable ninja to be verbose + set(CMAKE_VERBOSE_MAKEFILE ON CACHE BOOL "ON") +endfunction() -function (toolchain_after_project) - MESSAGE (STATUS "Toolchain: OSX-AppleClang-AArch64.cmake.") - # Do not set CMAKE_SYSTEM_NAME if compiling for the same OS, otherwise CMAKE_CROSSCOMPILING will be set to TRUE - #SET(CMAKE_SYSTEM_NAME "Darwin" CACHE INTERNAL "" FORCE) - SET(CMAKE_SYSTEM_PROCESSOR "aarch64" CACHE INTERNAL "" FORCE) - SET(CMAKE_RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/bin-aarch64" PARENT_SCOPE) - #set(ARCH_BITS 64 CACHE INTERNAL "" FORCE) # provide it +function(toolchain_after_project) + message(STATUS "Toolchain: OSX-AppleClang-AArch64.cmake.") + # Do not set CMAKE_SYSTEM_NAME if compiling for the same OS, otherwise CMAKE_CROSSCOMPILING will be set to TRUE + #SET(CMAKE_SYSTEM_NAME "Darwin" CACHE INTERNAL "" FORCE) + set(CMAKE_SYSTEM_PROCESSOR "aarch64" CACHE INTERNAL "" FORCE) + set(CMAKE_RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/bin-aarch64" PARENT_SCOPE) + #set(ARCH_BITS 64 CACHE INTERNAL "" FORCE) # provide it - toolchain_after_project_common() + toolchain_after_project_common() - # Official Clang doesn't support -march=native for ARM arch, but Apple Clang does... - SET (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} --target=aarch64-apple-darwin" PARENT_SCOPE) - SET (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} --target=aarch64-apple-darwin" PARENT_SCOPE) + # Official Clang doesn't support -march=native for ARM arch, but Apple Clang does... + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} --target=aarch64-apple-darwin" PARENT_SCOPE) + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} --target=aarch64-apple-darwin" PARENT_SCOPE) endfunction() +function(toolchain_exe_stuff) + toolchain_exe_stuff_common() -function (toolchain_exe_stuff) - toolchain_exe_stuff_common() - - # Propagate global variables set in toolchain_exe_stuff_common to the upper scope - #SET (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${C_ARCH_OPTS}" PARENT_SCOPE) - #SET (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${CXX_ARCH_OPTS}" PARENT_SCOPE) - #SET (CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS}" PARENT_SCOPE) + # Propagate global variables set in toolchain_exe_stuff_common to the upper scope + #SET (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${C_ARCH_OPTS}" PARENT_SCOPE) + #SET (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${CXX_ARCH_OPTS}" PARENT_SCOPE) + #SET (CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS}" PARENT_SCOPE) endfunction() diff --git a/cmake/toolchains/OSX-AppleClang-native.cmake b/cmake/toolchains/OSX-AppleClang-native.cmake index e9d80cecf..39ca1784b 100644 --- a/cmake/toolchains/OSX-AppleClang-native.cmake +++ b/cmake/toolchains/OSX-AppleClang-native.cmake @@ -1,43 +1,40 @@ -INCLUDE("${CMAKE_CURRENT_LIST_DIR}/include/OSX-AppleClang_common.inc.cmake") +include("${CMAKE_CURRENT_LIST_DIR}/include/OSX-AppleClang_common.inc.cmake") +function(toolchain_force_compiler) + if(CROSSCOMPILING_ARCH) + message(FATAL_ERROR "Can't cross-compile with a 'native' toolchain.") + endif() -function (toolchain_force_compiler) - if (CROSSCOMPILING_ARCH) - message(FATAL_ERROR "Can't cross-compile with a 'native' toolchain.") - endif () + set(CMAKE_C_COMPILER "clang" CACHE STRING "C compiler" FORCE) + set(CMAKE_CXX_COMPILER "clang++" CACHE STRING "C++ compiler" FORCE) - SET (CMAKE_C_COMPILER "clang" CACHE STRING "C compiler" FORCE) - SET (CMAKE_CXX_COMPILER "clang++" CACHE STRING "C++ compiler" FORCE) - - # In order to enable ninja to be verbose - set(CMAKE_VERBOSE_MAKEFILE ON CACHE BOOL "ON") -endfunction () - - -function (toolchain_after_project) - MESSAGE (STATUS "Toolchain: OSX-AppleClang-native.cmake.") - # Do not set CMAKE_SYSTEM_NAME if compiling for the same OS, otherwise CMAKE_CROSSCOMPILING will be set to TRUE - #SET(CMAKE_SYSTEM_NAME "Darwin" CACHE INTERNAL "" FORCE) - IF (CMAKE_SIZEOF_VOID_P EQUAL 8) - SET(CMAKE_RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/bin-native64" PARENT_SCOPE) - ELSE () - SET(CMAKE_RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/bin-native32" PARENT_SCOPE) - ENDIF () - - toolchain_after_project_common() - - # Official Clang doesn't support -march=native for ARM arch, but Apple Clang does... - # Otherwise, mind this for ARM crossbuilding -march=apple-m1' - SET (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -march=native -mcpu=native" PARENT_SCOPE) - SET (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -march=native -mcpu=native" PARENT_SCOPE) + # In order to enable ninja to be verbose + set(CMAKE_VERBOSE_MAKEFILE ON CACHE BOOL "ON") endfunction() +function(toolchain_after_project) + message(STATUS "Toolchain: OSX-AppleClang-native.cmake.") + # Do not set CMAKE_SYSTEM_NAME if compiling for the same OS, otherwise CMAKE_CROSSCOMPILING will be set to TRUE + #SET(CMAKE_SYSTEM_NAME "Darwin" CACHE INTERNAL "" FORCE) + if(CMAKE_SIZEOF_VOID_P EQUAL 8) + set(CMAKE_RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/bin-native64" PARENT_SCOPE) + else() + set(CMAKE_RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/bin-native32" PARENT_SCOPE) + endif() + + toolchain_after_project_common() + + # Official Clang doesn't support -march=native for ARM arch, but Apple Clang does... + # Otherwise, mind this for ARM crossbuilding -march=apple-m1' + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -march=native -mcpu=native" PARENT_SCOPE) + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -march=native -mcpu=native" PARENT_SCOPE) +endfunction() -function (toolchain_exe_stuff) - toolchain_exe_stuff_common() +function(toolchain_exe_stuff) + toolchain_exe_stuff_common() - # Propagate global variables set in toolchain_exe_stuff_common to the upper scope - #SET (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${C_ARCH_OPTS}" PARENT_SCOPE) - #SET (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${CXX_ARCH_OPTS}" PARENT_SCOPE) - #SET (CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS}" PARENT_SCOPE) + # Propagate global variables set in toolchain_exe_stuff_common to the upper scope + #SET (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${C_ARCH_OPTS}" PARENT_SCOPE) + #SET (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${CXX_ARCH_OPTS}" PARENT_SCOPE) + #SET (CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS}" PARENT_SCOPE) endfunction() diff --git a/cmake/toolchains/OSX-AppleClang-x86_64.cmake b/cmake/toolchains/OSX-AppleClang-x86_64.cmake index 17f71e3ab..a15a68ac3 100644 --- a/cmake/toolchains/OSX-AppleClang-x86_64.cmake +++ b/cmake/toolchains/OSX-AppleClang-x86_64.cmake @@ -1,40 +1,38 @@ -INCLUDE("${CMAKE_CURRENT_LIST_DIR}/include/OSX-AppleClang_common.inc.cmake") +include("${CMAKE_CURRENT_LIST_DIR}/include/OSX-AppleClang_common.inc.cmake") # UNTESTED ! -function (toolchain_force_compiler) - if (CROSSCOMPILE_ARCH) - message(FATAL_ERROR "This toolchain (as it is now) doesn't support cross-compilation.") - endif () +function(toolchain_force_compiler) + if(CROSSCOMPILE_ARCH) + message(FATAL_ERROR "This toolchain (as it is now) doesn't support cross-compilation.") + endif() - SET (CMAKE_C_COMPILER "clang" CACHE STRING "C compiler" FORCE) - SET (CMAKE_CXX_COMPILER "clang++" CACHE STRING "C++ compiler" FORCE) - - # In order to enable ninja to be verbose - set(CMAKE_VERBOSE_MAKEFILE ON CACHE BOOL "ON") -endfunction () + set(CMAKE_C_COMPILER "clang" CACHE STRING "C compiler" FORCE) + set(CMAKE_CXX_COMPILER "clang++" CACHE STRING "C++ compiler" FORCE) + # In order to enable ninja to be verbose + set(CMAKE_VERBOSE_MAKEFILE ON CACHE BOOL "ON") +endfunction() -function (toolchain_after_project) - MESSAGE (STATUS "Toolchain: OSX-AppleClang-x86_64.cmake.") - # Do not set CMAKE_SYSTEM_NAME if compiling for the same OS, otherwise CMAKE_CROSSCOMPILING will be set to TRUE - #SET(CMAKE_SYSTEM_NAME "Darwin" CACHE INTERNAL "" FORCE) - SET(CMAKE_SYSTEM_PROCESSOR "x86_64" CACHE INTERNAL "" FORCE) - SET(CMAKE_RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/bin-x86_64" PARENT_SCOPE) - #set(ARCH_BITS 64 CACHE INTERNAL "" FORCE) # provide it +function(toolchain_after_project) + message(STATUS "Toolchain: OSX-AppleClang-x86_64.cmake.") + # Do not set CMAKE_SYSTEM_NAME if compiling for the same OS, otherwise CMAKE_CROSSCOMPILING will be set to TRUE + #SET(CMAKE_SYSTEM_NAME "Darwin" CACHE INTERNAL "" FORCE) + set(CMAKE_SYSTEM_PROCESSOR "x86_64" CACHE INTERNAL "" FORCE) + set(CMAKE_RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/bin-x86_64" PARENT_SCOPE) + #set(ARCH_BITS 64 CACHE INTERNAL "" FORCE) # provide it - toolchain_after_project_common() + toolchain_after_project_common() - # -target=-x86_64-apple-darwin ? - SET (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -march=x86-64 -m64" PARENT_SCOPE) - SET (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -march=x86-64 -m64" PARENT_SCOPE) + # -target=-x86_64-apple-darwin ? + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -march=x86-64 -m64" PARENT_SCOPE) + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -march=x86-64 -m64" PARENT_SCOPE) endfunction() +function(toolchain_exe_stuff) + toolchain_exe_stuff_common() -function (toolchain_exe_stuff) - toolchain_exe_stuff_common() - - # Propagate global variables set in toolchain_exe_stuff_common to the upper scope - #SET (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${C_ARCH_OPTS}" PARENT_SCOPE) - #SET (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${CXX_ARCH_OPTS}" PARENT_SCOPE) - #SET (CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS}" PARENT_SCOPE) + # Propagate global variables set in toolchain_exe_stuff_common to the upper scope + #SET (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${C_ARCH_OPTS}" PARENT_SCOPE) + #SET (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${CXX_ARCH_OPTS}" PARENT_SCOPE) + #SET (CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS}" PARENT_SCOPE) endfunction() diff --git a/cmake/toolchains/Windows-Clang-native.cmake b/cmake/toolchains/Windows-Clang-native.cmake index 3121a48e0..ba396e5e4 100644 --- a/cmake/toolchains/Windows-Clang-native.cmake +++ b/cmake/toolchains/Windows-Clang-native.cmake @@ -1,58 +1,53 @@ -INCLUDE("${CMAKE_CURRENT_LIST_DIR}/include/Windows-Clang_common.inc.cmake") +include("${CMAKE_CURRENT_LIST_DIR}/include/Windows-Clang_common.inc.cmake") +function(toolchain_force_compiler) + if(CROSSCOMPILING_ARCH) + message(FATAL_ERROR "Can't cross-compile with a 'native' toolchain.") + endif() -function (toolchain_force_compiler) - if (CROSSCOMPILING_ARCH) - message(FATAL_ERROR "Can't cross-compile with a 'native' toolchain.") - endif () + set(CMAKE_C_COMPILER "clang" CACHE STRING "C compiler" FORCE) + set(CMAKE_CXX_COMPILER "clang++" CACHE STRING "C++ compiler" FORCE) - SET (CMAKE_C_COMPILER "clang" CACHE STRING "C compiler" FORCE) - SET (CMAKE_CXX_COMPILER "clang++" CACHE STRING "C++ compiler" FORCE) - - # In order to enable ninja to be verbose - #set(CMAKE_VERBOSE_MAKEFILE ON CACHE BOOL "ON") - - IF (CLANG_USE_GCC_LINKER) - # Not working, see CLANG_USE_GCC_LINKER option. Use MSVC. - SET (CLANG_VENDOR "gnu" PARENT_SCOPE) - ELSE () - SET (CLANG_VENDOR "msvc" PARENT_SCOPE) - ENDIF () -endfunction () - - -function (toolchain_after_project) - MESSAGE (STATUS "Toolchain: Windows-Clang-native.cmake.") - # Do not set CMAKE_SYSTEM_NAME if compiling for the same OS, otherwise CMAKE_CROSSCOMPILING will be set to TRUE - #SET(CMAKE_SYSTEM_NAME "Windows" INTERNAL "" FORCE) - IF (CMAKE_SIZEOF_VOID_P EQUAL 8) - SET(CMAKE_RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/bin-native64" PARENT_SCOPE) - ELSE () - SET(CMAKE_RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/bin-native32" PARENT_SCOPE) - ENDIF () - - toolchain_after_project_common() # To enable RC language, to compile Windows Resource files - - #SET (CLANG_TARGET "--target=x86_64-pc-windows-${CLANG_VENDOR}") - #SET (C_ARCH_OPTS "-march=native ${CLANG_TARGET}") - #SET (CXX_ARCH_OPTS "-march=native ${CLANG_TARGET}") - #SET (RC_FLAGS "${CLANG_TARGET}") - - # TODO: fix the target, maybe using CMAKE_HOST_SYSTEM_PROCESSOR ? - LINK_DIRECTORIES ("lib/_bin/{ARCH}/mariadb/") - SET (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -march=native -mtune=native" PARENT_SCOPE) - SET (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -march=native -mtune=native" PARENT_SCOPE) + # In order to enable ninja to be verbose + #set(CMAKE_VERBOSE_MAKEFILE ON CACHE BOOL "ON") + if(CLANG_USE_GCC_LINKER) + # Not working, see CLANG_USE_GCC_LINKER option. Use MSVC. + set(CLANG_VENDOR "gnu" PARENT_SCOPE) + else() + set(CLANG_VENDOR "msvc" PARENT_SCOPE) + endif() endfunction() +function(toolchain_after_project) + message(STATUS "Toolchain: Windows-Clang-native.cmake.") + # Do not set CMAKE_SYSTEM_NAME if compiling for the same OS, otherwise CMAKE_CROSSCOMPILING will be set to TRUE + #SET(CMAKE_SYSTEM_NAME "Windows" INTERNAL "" FORCE) + if(CMAKE_SIZEOF_VOID_P EQUAL 8) + set(CMAKE_RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/bin-native64" PARENT_SCOPE) + else() + set(CMAKE_RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/bin-native32" PARENT_SCOPE) + endif() + + toolchain_after_project_common() # To enable RC language, to compile Windows Resource files + + #SET (CLANG_TARGET "--target=x86_64-pc-windows-${CLANG_VENDOR}") + #SET (C_ARCH_OPTS "-march=native ${CLANG_TARGET}") + #SET (CXX_ARCH_OPTS "-march=native ${CLANG_TARGET}") + #SET (RC_FLAGS "${CLANG_TARGET}") + + # TODO: fix the target, maybe using CMAKE_HOST_SYSTEM_PROCESSOR ? + link_directories("lib/_bin/{ARCH}/mariadb/") + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -march=native -mtune=native" PARENT_SCOPE) + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -march=native -mtune=native" PARENT_SCOPE) +endfunction() -function (toolchain_exe_stuff) - toolchain_exe_stuff_common() - - # Propagate global variables set in toolchain_exe_stuff_common to the upper scope - #SET (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${C_ARCH_OPTS}" PARENT_SCOPE) - #SET (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${CXX_ARCH_OPTS}" PARENT_SCOPE) - #SET (CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS}" PARENT_SCOPE) - #SET (CMAKE_RC_FLAGS "${RC_FLAGS}" PARENT_SCOPE) +function(toolchain_exe_stuff) + toolchain_exe_stuff_common() + # Propagate global variables set in toolchain_exe_stuff_common to the upper scope + #SET (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${C_ARCH_OPTS}" PARENT_SCOPE) + #SET (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${CXX_ARCH_OPTS}" PARENT_SCOPE) + #SET (CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS}" PARENT_SCOPE) + #SET (CMAKE_RC_FLAGS "${RC_FLAGS}" PARENT_SCOPE) endfunction() diff --git a/cmake/toolchains/Windows-Clang-x86.cmake b/cmake/toolchains/Windows-Clang-x86.cmake index d874dabae..a6a139946 100644 --- a/cmake/toolchains/Windows-Clang-x86.cmake +++ b/cmake/toolchains/Windows-Clang-x86.cmake @@ -1,56 +1,52 @@ -INCLUDE("${CMAKE_CURRENT_LIST_DIR}/include/Windows-Clang_common.inc.cmake") +include("${CMAKE_CURRENT_LIST_DIR}/include/Windows-Clang_common.inc.cmake") +function(toolchain_force_compiler) + if(CROSSCOMPILE_ARCH) + message(FATAL_ERROR "This toolchain (as it is now) doesn't support cross-compilation.") + endif() -function (toolchain_force_compiler) - if (CROSSCOMPILE_ARCH) - message(FATAL_ERROR "This toolchain (as it is now) doesn't support cross-compilation.") - endif () + set(CMAKE_C_COMPILER "clang" CACHE STRING "C compiler" FORCE) + set(CMAKE_CXX_COMPILER "clang++" CACHE STRING "C++ compiler" FORCE) - SET (CMAKE_C_COMPILER "clang" CACHE STRING "C compiler" FORCE) - SET (CMAKE_CXX_COMPILER "clang++" CACHE STRING "C++ compiler" FORCE) + # In order to enable ninja to be verbose + #set(CMAKE_VERBOSE_MAKEFILE ON CACHE BOOL "ON") - # In order to enable ninja to be verbose - #set(CMAKE_VERBOSE_MAKEFILE ON CACHE BOOL "ON") - - IF (CLANG_USE_GCC_LINKER) - # Not working, see CLANG_USE_GCC_LINKER option. Use MSVC. - SET (CLANG_VENDOR "gnu" PARENT_SCOPE) - ELSE () - SET (CLANG_VENDOR "msvc" PARENT_SCOPE) - ENDIF () -endfunction () - - -function (toolchain_after_project) - MESSAGE (STATUS "Toolchain: Windows-Clang-x86.cmake.") - # Do not set CMAKE_SYSTEM_NAME if compiling for the same OS, otherwise CMAKE_CROSSCOMPILING will be set to TRUE - #SET(CMAKE_SYSTEM_NAME "Windows" CACHE INTERNAL "" FORCE) - SET(CMAKE_SYSTEM_PROCESSOR "x86" CACHE INTERNAL "" FORCE) - SET(CMAKE_RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/bin-x86" PARENT_SCOPE) - #set(ARCH_BITS 32 CACHE INTERNAL "" FORCE) # provide it - - toolchain_after_project_common() # To enable RC language, to compile Windows Resource files - - LINK_DIRECTORIES ("lib/_bin/x86/mariadb/") - SET (CLANG_TARGET "--target=i686-pc-windows-${CLANG_VENDOR}") - SET (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -march=i686 -m32 ${CLANG_TARGET}" PARENT_SCOPE) - SET (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -march=i686 -m32 ${CLANG_TARGET}" PARENT_SCOPE) - SET (RC_FLAGS "${CLANG_TARGET}" PARENT_SCOPE) + if(CLANG_USE_GCC_LINKER) + # Not working, see CLANG_USE_GCC_LINKER option. Use MSVC. + set(CLANG_VENDOR "gnu" PARENT_SCOPE) + else() + set(CLANG_VENDOR "msvc" PARENT_SCOPE) + endif() endfunction() +function(toolchain_after_project) + message(STATUS "Toolchain: Windows-Clang-x86.cmake.") + # Do not set CMAKE_SYSTEM_NAME if compiling for the same OS, otherwise CMAKE_CROSSCOMPILING will be set to TRUE + #SET(CMAKE_SYSTEM_NAME "Windows" CACHE INTERNAL "" FORCE) + set(CMAKE_SYSTEM_PROCESSOR "x86" CACHE INTERNAL "" FORCE) + set(CMAKE_RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/bin-x86" PARENT_SCOPE) + #set(ARCH_BITS 32 CACHE INTERNAL "" FORCE) # provide it + + toolchain_after_project_common() # To enable RC language, to compile Windows Resource files + + link_directories("lib/_bin/x86/mariadb/") + set(CLANG_TARGET "--target=i686-pc-windows-${CLANG_VENDOR}") + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -march=i686 -m32 ${CLANG_TARGET}" PARENT_SCOPE) + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -march=i686 -m32 ${CLANG_TARGET}" PARENT_SCOPE) + set(RC_FLAGS "${CLANG_TARGET}" PARENT_SCOPE) +endfunction() -function (toolchain_exe_stuff) - toolchain_exe_stuff_common() - - # Propagate global variables set in toolchain_exe_stuff_common to the upper scope - #SET (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${C_ARCH_OPTS}" PARENT_SCOPE) - #SET (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${CXX_ARCH_OPTS}" PARENT_SCOPE) - #SET (CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS}" PARENT_SCOPE) - #SET (CMAKE_RC_FLAGS "${RC_FLAGS}" PARENT_SCOPE) +function(toolchain_exe_stuff) + toolchain_exe_stuff_common() - # Set different output folders for each build type - SET_TARGET_PROPERTIES(spheresvr PROPERTIES RUNTIME_OUTPUT_RELEASE "${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/Release" ) - SET_TARGET_PROPERTIES(spheresvr PROPERTIES RUNTIME_OUTPUT_DEBUG "${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/Debug" ) - SET_TARGET_PROPERTIES(spheresvr PROPERTIES RUNTIME_OUTPUT_NIGHTLY "${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/Nightly" ) + # Propagate global variables set in toolchain_exe_stuff_common to the upper scope + #SET (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${C_ARCH_OPTS}" PARENT_SCOPE) + #SET (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${CXX_ARCH_OPTS}" PARENT_SCOPE) + #SET (CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS}" PARENT_SCOPE) + #SET (CMAKE_RC_FLAGS "${RC_FLAGS}" PARENT_SCOPE) + # Set different output folders for each build type + set_target_properties(spheresvr PROPERTIES RUNTIME_OUTPUT_RELEASE "${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/Release") + set_target_properties(spheresvr PROPERTIES RUNTIME_OUTPUT_DEBUG "${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/Debug") + set_target_properties(spheresvr PROPERTIES RUNTIME_OUTPUT_NIGHTLY "${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/Nightly") endfunction() diff --git a/cmake/toolchains/Windows-Clang-x86_64.cmake b/cmake/toolchains/Windows-Clang-x86_64.cmake index 620a4572c..84e9ae72a 100644 --- a/cmake/toolchains/Windows-Clang-x86_64.cmake +++ b/cmake/toolchains/Windows-Clang-x86_64.cmake @@ -1,56 +1,52 @@ -INCLUDE("${CMAKE_CURRENT_LIST_DIR}/include/Windows-Clang_common.inc.cmake") +include("${CMAKE_CURRENT_LIST_DIR}/include/Windows-Clang_common.inc.cmake") +function(toolchain_force_compiler) + if(CROSSCOMPILE_ARCH) + message(FATAL_ERROR "This toolchain (as it is now) doesn't support cross-compilation.") + endif() -function (toolchain_force_compiler) - if (CROSSCOMPILE_ARCH) - message(FATAL_ERROR "This toolchain (as it is now) doesn't support cross-compilation.") - endif () + set(CMAKE_C_COMPILER "clang" CACHE STRING "C compiler" FORCE) + set(CMAKE_CXX_COMPILER "clang++" CACHE STRING "C++ compiler" FORCE) - SET (CMAKE_C_COMPILER "clang" CACHE STRING "C compiler" FORCE) - SET (CMAKE_CXX_COMPILER "clang++" CACHE STRING "C++ compiler" FORCE) + # In order to enable ninja to be verbose + #set(CMAKE_VERBOSE_MAKEFILE ON CACHE BOOL "ON") - # In order to enable ninja to be verbose - #set(CMAKE_VERBOSE_MAKEFILE ON CACHE BOOL "ON") - - IF (CLANG_USE_GCC_LINKER) - # Not working, see CLANG_USE_GCC_LINKER option. Use MSVC. - SET (CLANG_VENDOR "gnu" PARENT_SCOPE) - ELSE () - SET (CLANG_VENDOR "msvc" PARENT_SCOPE) - ENDIF () -endfunction () - - -function (toolchain_after_project) - MESSAGE (STATUS "Toolchain: Windows-Clang-x86_64.cmake.") - # Do not set CMAKE_SYSTEM_NAME if compiling for the same OS, otherwise CMAKE_CROSSCOMPILING will be set to TRUE - #SET(CMAKE_SYSTEM_NAME "Windows" CACHE INTERNAL "" FORCE) - SET(CMAKE_SYSTEM_PROCESSOR "x86_64" CACHE INTERNAL "" FORCE) - SET(CMAKE_RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/bin-x86_64" PARENT_SCOPE) - #set(ARCH_BITS 64 CACHE INTERNAL "" FORCE) # provide it - - toolchain_after_project_common() # To enable RC language, to compile Windows Resource files - - LINK_DIRECTORIES ("lib/_bin/x86_64/mariadb/") - SET (CLANG_TARGET "--target=x86_64-pc-windows-${CLANG_VENDOR}") - SET (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -march=x86-64 -m64 ${CLANG_TARGET}" PARENT_SCOPE) - SET (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -march=x86-64 -m64 ${CLANG_TARGET}" PARENT_SCOPE) - SET (RC_FLAGS "${CLANG_TARGET}" PARENT_SCOPE) - - # We can't override -fuse-ld=lld-link to use GNU ld, nor we can change --dependent-lib=msvcrtd - # Maybe changing CMAKE_${lang}_LINK_EXECUTABLE ? - # Check CMake code here: https://gitlab.kitware.com/cmake/cmake/-/blob/v3.25.1/Modules/Platform/Windows-Clang.cmake#L76-80 + if(CLANG_USE_GCC_LINKER) + # Not working, see CLANG_USE_GCC_LINKER option. Use MSVC. + set(CLANG_VENDOR "gnu" PARENT_SCOPE) + else() + set(CLANG_VENDOR "msvc" PARENT_SCOPE) + endif() endfunction() +function(toolchain_after_project) + message(STATUS "Toolchain: Windows-Clang-x86_64.cmake.") + # Do not set CMAKE_SYSTEM_NAME if compiling for the same OS, otherwise CMAKE_CROSSCOMPILING will be set to TRUE + #SET(CMAKE_SYSTEM_NAME "Windows" CACHE INTERNAL "" FORCE) + set(CMAKE_SYSTEM_PROCESSOR "x86_64" CACHE INTERNAL "" FORCE) + set(CMAKE_RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/bin-x86_64" PARENT_SCOPE) + #set(ARCH_BITS 64 CACHE INTERNAL "" FORCE) # provide it + + toolchain_after_project_common() # To enable RC language, to compile Windows Resource files + + link_directories("lib/_bin/x86_64/mariadb/") + set(CLANG_TARGET "--target=x86_64-pc-windows-${CLANG_VENDOR}") + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -march=x86-64 -m64 ${CLANG_TARGET}" PARENT_SCOPE) + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -march=x86-64 -m64 ${CLANG_TARGET}" PARENT_SCOPE) + set(RC_FLAGS "${CLANG_TARGET}" PARENT_SCOPE) + + # We can't override -fuse-ld=lld-link to use GNU ld, nor we can change --dependent-lib=msvcrtd + # Maybe changing CMAKE_${lang}_LINK_EXECUTABLE ? + # Check CMake code here: https://gitlab.kitware.com/cmake/cmake/-/blob/v3.25.1/Modules/Platform/Windows-Clang.cmake#L76-80 +endfunction() -function (toolchain_exe_stuff) - #SET (CMAKE_EXE_LINKER_FLAGS_COMMON "${CMAKE_EXE_LINKER_FLAGS_COMMON} ${CLANG_TARGET}" PARENT_SCOPE) # -stdlib=libc++ -lc++abi - toolchain_exe_stuff_common() - - # Propagate global variables set in toolchain_exe_stuff_common to the upper scope - #SET (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${C_ARCH_OPTS}" PARENT_SCOPE) - #SET (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${CXX_ARCH_OPTS}" PARENT_SCOPE) - #SET (CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS}" PARENT_SCOPE) - #SET (CMAKE_RC_FLAGS "${RC_FLAGS}" PARENT_SCOPE) +function(toolchain_exe_stuff) + #SET (CMAKE_EXE_LINKER_FLAGS_COMMON "${CMAKE_EXE_LINKER_FLAGS_COMMON} ${CLANG_TARGET}" PARENT_SCOPE) # -stdlib=libc++ -lc++abi + toolchain_exe_stuff_common() + # Propagate global variables set in toolchain_exe_stuff_common to the upper scope + #SET (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${C_ARCH_OPTS}" PARENT_SCOPE) + #SET (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${CXX_ARCH_OPTS}" PARENT_SCOPE) + #SET (CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS}" PARENT_SCOPE) + #SET (CMAKE_RC_FLAGS "${RC_FLAGS}" PARENT_SCOPE) endfunction() diff --git a/cmake/toolchains/Windows-GNU-native.cmake b/cmake/toolchains/Windows-GNU-native.cmake index 443ef04ad..173772020 100644 --- a/cmake/toolchains/Windows-GNU-native.cmake +++ b/cmake/toolchains/Windows-GNU-native.cmake @@ -1,44 +1,40 @@ -INCLUDE("${CMAKE_CURRENT_LIST_DIR}/include/Windows-GNU_common.inc.cmake") +include("${CMAKE_CURRENT_LIST_DIR}/include/Windows-GNU_common.inc.cmake") +function(toolchain_force_compiler) + if(CROSSCOMPILE_ARCH) + message(FATAL_ERROR "Can't cross-compile with a 'native' toolchain.") + endif() -function (toolchain_force_compiler) - if (CROSSCOMPILE_ARCH) - message(FATAL_ERROR "Can't cross-compile with a 'native' toolchain.") - endif () + set(CMAKE_C_COMPILER "gcc" CACHE STRING "C compiler" FORCE) + set(CMAKE_CXX_COMPILER "g++" CACHE STRING "C++ compiler" FORCE) - SET (CMAKE_C_COMPILER "gcc" CACHE STRING "C compiler" FORCE) - SET (CMAKE_CXX_COMPILER "g++" CACHE STRING "C++ compiler" FORCE) - - # In order to enable ninja to be verbose - #set(CMAKE_VERBOSE_MAKEFILE ON CACHE BOOL "ON") -endfunction () - - -function (toolchain_after_project) - MESSAGE (STATUS "Toolchain: Windows-GNU-native.cmake.") - # Do not set CMAKE_SYSTEM_NAME if compiling for the same OS, otherwise CMAKE_CROSSCOMPILING will be set to TRUE - #SET(CMAKE_SYSTEM_NAME "Windows" CACHE INTERNAL "" FORCE) - IF (CMAKE_SIZEOF_VOID_P EQUAL 8) - SET(CMAKE_RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/bin-native64" PARENT_SCOPE) - ELSE () - SET(CMAKE_RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/bin-native32" PARENT_SCOPE) - ENDIF () - - toolchain_after_project_common() # To enable RC language, to compile Windows Resource files - - LINK_DIRECTORIES ("lib/_bin/${ARCH}/mariadb/") - SET (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -march=native" PARENT_SCOPE) - SET (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -march=native" PARENT_SCOPE) + # In order to enable ninja to be verbose + #set(CMAKE_VERBOSE_MAKEFILE ON CACHE BOOL "ON") endfunction() +function(toolchain_after_project) + message(STATUS "Toolchain: Windows-GNU-native.cmake.") + # Do not set CMAKE_SYSTEM_NAME if compiling for the same OS, otherwise CMAKE_CROSSCOMPILING will be set to TRUE + #SET(CMAKE_SYSTEM_NAME "Windows" CACHE INTERNAL "" FORCE) + if(CMAKE_SIZEOF_VOID_P EQUAL 8) + set(CMAKE_RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/bin-native64" PARENT_SCOPE) + else() + set(CMAKE_RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/bin-native32" PARENT_SCOPE) + endif() + + toolchain_after_project_common() # To enable RC language, to compile Windows Resource files + + link_directories("lib/_bin/${ARCH}/mariadb/") + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -march=native" PARENT_SCOPE) + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -march=native" PARENT_SCOPE) +endfunction() -function (toolchain_exe_stuff) - toolchain_exe_stuff_common() - - # Propagate global variables set in toolchain_exe_stuff_common to the upper scope - #SET (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${C_ARCH_OPTS}" PARENT_SCOPE) - #SET (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${CXX_ARCH_OPTS}" PARENT_SCOPE) - #SET (CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS}" PARENT_SCOPE) - #SET (CMAKE_RC_FLAGS "${CMAKE_RC_FLAGS}" PARENT_SCOPE) +function(toolchain_exe_stuff) + toolchain_exe_stuff_common() + # Propagate global variables set in toolchain_exe_stuff_common to the upper scope + #SET (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${C_ARCH_OPTS}" PARENT_SCOPE) + #SET (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${CXX_ARCH_OPTS}" PARENT_SCOPE) + #SET (CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS}" PARENT_SCOPE) + #SET (CMAKE_RC_FLAGS "${CMAKE_RC_FLAGS}" PARENT_SCOPE) endfunction() diff --git a/cmake/toolchains/Windows-GNU-x86.cmake b/cmake/toolchains/Windows-GNU-x86.cmake index e5ecdc995..4c056f300 100644 --- a/cmake/toolchains/Windows-GNU-x86.cmake +++ b/cmake/toolchains/Windows-GNU-x86.cmake @@ -1,43 +1,39 @@ -INCLUDE("${CMAKE_CURRENT_LIST_DIR}/include/Windows-GNU_common.inc.cmake") +include("${CMAKE_CURRENT_LIST_DIR}/include/Windows-GNU_common.inc.cmake") +function(toolchain_force_compiler) + if(CROSSCOMPILE_ARCH) + message(FATAL_ERROR "This toolchain (as it is now) doesn't support cross-compilation.") + endif() -function (toolchain_force_compiler) - if (CROSSCOMPILE_ARCH) - message(FATAL_ERROR "This toolchain (as it is now) doesn't support cross-compilation.") - endif () - - SET (CMAKE_C_COMPILER "gcc" CACHE STRING "C compiler" FORCE) - SET (CMAKE_CXX_COMPILER "g++" CACHE STRING "C++ compiler" FORCE) - - # In order to enable ninja to be verbose - #set(CMAKE_VERBOSE_MAKEFILE ON CACHE BOOL "ON") -endfunction () + set(CMAKE_C_COMPILER "gcc" CACHE STRING "C compiler" FORCE) + set(CMAKE_CXX_COMPILER "g++" CACHE STRING "C++ compiler" FORCE) + # In order to enable ninja to be verbose + #set(CMAKE_VERBOSE_MAKEFILE ON CACHE BOOL "ON") +endfunction() -function (toolchain_after_project) - MESSAGE (STATUS "Toolchain: Windows-GNU-x86.cmake.") - # Do not set CMAKE_SYSTEM_NAME if compiling for the same OS, otherwise CMAKE_CROSSCOMPILING will be set to TRUE - #SET(CMAKE_SYSTEM_NAME "Windows" CACHE INTERNAL "" FORCE) - SET(CMAKE_SYSTEM_PROCESSOR "x86" CACHE INTERNAL "" FORCE) - SET(CMAKE_RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/bin_x86" PARENT_SCOPE) - #set(ARCH_BITS 32 CACHE INTERNAL "" FORCE) # provide it +function(toolchain_after_project) + message(STATUS "Toolchain: Windows-GNU-x86.cmake.") + # Do not set CMAKE_SYSTEM_NAME if compiling for the same OS, otherwise CMAKE_CROSSCOMPILING will be set to TRUE + #SET(CMAKE_SYSTEM_NAME "Windows" CACHE INTERNAL "" FORCE) + set(CMAKE_SYSTEM_PROCESSOR "x86" CACHE INTERNAL "" FORCE) + set(CMAKE_RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/bin_x86" PARENT_SCOPE) + #set(ARCH_BITS 32 CACHE INTERNAL "" FORCE) # provide it - toolchain_after_project_common() # Also to enable RC language, to compile Windows Resource files + toolchain_after_project_common() # Also to enable RC language, to compile Windows Resource files - LINK_DIRECTORIES ("lib/_bin/x86/mariadb/") - SET (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -march=i686 -m32" PARENT_SCOPE) - SET (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -march=i686 -m32" PARENT_SCOPE) - SET (RC_FLAGS "--target=pe-i386" PARENT_SCOPE) + link_directories("lib/_bin/x86/mariadb/") + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -march=i686 -m32" PARENT_SCOPE) + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -march=i686 -m32" PARENT_SCOPE) + set(RC_FLAGS "--target=pe-i386" PARENT_SCOPE) endfunction() +function(toolchain_exe_stuff) + toolchain_exe_stuff_common() -function (toolchain_exe_stuff) - toolchain_exe_stuff_common() - - # Propagate global variables set in toolchain_exe_stuff_common to the upper scope - #SET (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${C_ARCH_OPTS}" PARENT_SCOPE) - #SET (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${CXX_ARCH_OPTS}" PARENT_SCOPE) - #SET (CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS}" PARENT_SCOPE) - #SET (CMAKE_RC_FLAGS "${RC_FLAGS}" PARENT_SCOPE) - + # Propagate global variables set in toolchain_exe_stuff_common to the upper scope + #SET (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${C_ARCH_OPTS}" PARENT_SCOPE) + #SET (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${CXX_ARCH_OPTS}" PARENT_SCOPE) + #SET (CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS}" PARENT_SCOPE) + #SET (CMAKE_RC_FLAGS "${RC_FLAGS}" PARENT_SCOPE) endfunction() diff --git a/cmake/toolchains/Windows-GNU-x86_64.cmake b/cmake/toolchains/Windows-GNU-x86_64.cmake index bcaf199b1..f3291237d 100644 --- a/cmake/toolchains/Windows-GNU-x86_64.cmake +++ b/cmake/toolchains/Windows-GNU-x86_64.cmake @@ -1,43 +1,39 @@ -INCLUDE("${CMAKE_CURRENT_LIST_DIR}/include/Windows-GNU_common.inc.cmake") +include("${CMAKE_CURRENT_LIST_DIR}/include/Windows-GNU_common.inc.cmake") +function(toolchain_force_compiler) + if(CROSSCOMPILE_ARCH) + message(FATAL_ERROR "This toolchain (as it is now) doesn't support cross-compilation.") + endif() -function (toolchain_force_compiler) - if (CROSSCOMPILE_ARCH) - message(FATAL_ERROR "This toolchain (as it is now) doesn't support cross-compilation.") - endif () - - SET (CMAKE_C_COMPILER "gcc" CACHE STRING "C compiler" FORCE) - SET (CMAKE_CXX_COMPILER "g++" CACHE STRING "C++ compiler" FORCE) - - # In order to enable ninja to be verbose - #set(CMAKE_VERBOSE_MAKEFILE ON CACHE BOOL "ON") -endfunction () + set(CMAKE_C_COMPILER "gcc" CACHE STRING "C compiler" FORCE) + set(CMAKE_CXX_COMPILER "g++" CACHE STRING "C++ compiler" FORCE) + # In order to enable ninja to be verbose + #set(CMAKE_VERBOSE_MAKEFILE ON CACHE BOOL "ON") +endfunction() -function (toolchain_after_project) - MESSAGE (STATUS "Toolchain: Windows-GNU-x86_64.cmake.") - # Do not set CMAKE_SYSTEM_NAME if compiling for the same OS, otherwise CMAKE_CROSSCOMPILING will be set to TRUE - #SET(CMAKE_SYSTEM_NAME "Windows" CACHE INTERNAL "" FORCE) - SET(CMAKE_SYSTEM_PROCESSOR "x86_64" CACHE INTERNAL "" FORCE) - SET(CMAKE_RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/bin-x86_64" PARENT_SCOPE) - #set(ARCH_BITS 64 CACHE INTERNAL "" FORCE) # provide it +function(toolchain_after_project) + message(STATUS "Toolchain: Windows-GNU-x86_64.cmake.") + # Do not set CMAKE_SYSTEM_NAME if compiling for the same OS, otherwise CMAKE_CROSSCOMPILING will be set to TRUE + #SET(CMAKE_SYSTEM_NAME "Windows" CACHE INTERNAL "" FORCE) + set(CMAKE_SYSTEM_PROCESSOR "x86_64" CACHE INTERNAL "" FORCE) + set(CMAKE_RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/bin-x86_64" PARENT_SCOPE) + #set(ARCH_BITS 64 CACHE INTERNAL "" FORCE) # provide it - toolchain_after_project_common() # To enable RC language, to compile Windows Resource files + toolchain_after_project_common() # To enable RC language, to compile Windows Resource files - LINK_DIRECTORIES ("lib/_bin/x86_64/mariadb/") - SET (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -march=x86-64 -m64" PARENT_SCOPE) - SET (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -march=x86-64 -m64" PARENT_SCOPE) - SET (RC_FLAGS "--target=pe-x86-64" PARENT_SCOPE) + link_directories("lib/_bin/x86_64/mariadb/") + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -march=x86-64 -m64" PARENT_SCOPE) + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -march=x86-64 -m64" PARENT_SCOPE) + set(RC_FLAGS "--target=pe-x86-64" PARENT_SCOPE) endfunction() +function(toolchain_exe_stuff) + toolchain_exe_stuff_common() -function (toolchain_exe_stuff) - toolchain_exe_stuff_common() - - # Propagate global variables set in toolchain_exe_stuff_common to the upper scope - #SET (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${C_ARCH_OPTS}" PARENT_SCOPE) - #SET (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${CXX_ARCH_OPTS}" PARENT_SCOPE) - #SET (CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS}" PARENT_SCOPE) - #SET (CMAKE_RC_FLAGS "${RC_FLAGS}" PARENT_SCOPE) - + # Propagate global variables set in toolchain_exe_stuff_common to the upper scope + #SET (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${C_ARCH_OPTS}" PARENT_SCOPE) + #SET (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${CXX_ARCH_OPTS}" PARENT_SCOPE) + #SET (CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS}" PARENT_SCOPE) + #SET (CMAKE_RC_FLAGS "${RC_FLAGS}" PARENT_SCOPE) endfunction() diff --git a/cmake/toolchains/Windows-MSVC.cmake b/cmake/toolchains/Windows-MSVC.cmake index 140509bde..8ac30f1b5 100644 --- a/cmake/toolchains/Windows-MSVC.cmake +++ b/cmake/toolchains/Windows-MSVC.cmake @@ -1,111 +1,111 @@ -SET (TOOLCHAIN_LOADED 1) +set(TOOLCHAIN_LOADED 1) -function (toolchain_force_compiler) - # Already managed by the generator. - #SET (CMAKE_C_COMPILER "...cl.exe" CACHE STRING "C compiler" FORCE) - #SET (CMAKE_CXX_COMPILER "...cl.exe" CACHE STRING "C++ compiler" FORCE) +function(toolchain_force_compiler) + # Already managed by the generator. + #SET (CMAKE_C_COMPILER "...cl.exe" CACHE STRING "C compiler" FORCE) + #SET (CMAKE_CXX_COMPILER "...cl.exe" CACHE STRING "C++ compiler" FORCE) - MESSAGE (STATUS "Toolchain: Windows-MSVC.cmake.") - #SET(CMAKE_SYSTEM_NAME "Windows" CACHE INTERNAL "" FORCE) -endfunction () - - -function (toolchain_after_project) - if (NOT CMAKE_VS_PLATFORM_NAME) - set (CMAKE_VS_PLATFORM_NAME "${CMAKE_VS_PLATFORM_NAME_DEFAULT}") - endif () - if (${CMAKE_VS_PLATFORM_NAME} STREQUAL "Win32") - set (CMAKE_SYSTEM_PROCESSOR "x86" CACHE INTERNAL "" FORCE) - endif () - set (CMAKE_SYSTEM_PROCESSOR "${CMAKE_VS_PLATFORM_NAME}" CACHE INTERNAL "" FORCE) - - include ("${CMAKE_SOURCE_DIR}/cmake/CMakeDetectArch.cmake") - - MESSAGE (STATUS "Generating for MSVC platform ${CMAKE_VS_PLATFORM_NAME}.") + message(STATUS "Toolchain: Windows-MSVC.cmake.") + #SET(CMAKE_SYSTEM_NAME "Windows" CACHE INTERNAL "" FORCE) endfunction() +function(toolchain_after_project) + if(NOT CMAKE_VS_PLATFORM_NAME) + set(CMAKE_VS_PLATFORM_NAME "${CMAKE_VS_PLATFORM_NAME_DEFAULT}") + endif() + if(${CMAKE_VS_PLATFORM_NAME} STREQUAL "Win32") + set(CMAKE_SYSTEM_PROCESSOR "x86" CACHE INTERNAL "" FORCE) + endif() + set(CMAKE_SYSTEM_PROCESSOR "${CMAKE_VS_PLATFORM_NAME}" CACHE INTERNAL "" FORCE) -function (toolchain_exe_stuff) - - #-- Set mariadb .lib directory for the linker. - - IF (CMAKE_CL_64) - TARGET_LINK_DIRECTORIES (spheresvr PRIVATE "lib/_bin/x86_64/mariadb/") - ELSE () - TARGET_LINK_DIRECTORIES (spheresvr PRIVATE "lib/_bin/x86/mariadb/") - ENDIF () - - - #-- Configure the Windows application type and add global linker flags. - - IF (${WIN32_SPAWN_CONSOLE}) - add_link_options ("LINKER:/ENTRY:WinMainCRTStartup") # Handled by is_win32_app_linker -> "LINKER:/SUBSYSTEM:CONSOLE" - SET (PREPROCESSOR_DEFS_EXTRA _WINDOWS_CONSOLE) - #ELSE () - # add_link_options ("LINKER:/ENTRY:WinMainCRTStartup") # Handled by is_win32_app_linker -> "LINKER: /SUBSYSTEM:WINDOWS" - ENDIF () - - - #-- Validate sanitizers options and store them between the common compiler flags. - - SET (ENABLED_SANITIZER false) - IF (${USE_ASAN}) - IF (${MSVC_TOOLSET_VERSION} LESS_EQUAL 141) # VS 2017 - MESSAGE (FATAL_ERROR "This MSVC version doesn't yet support ASAN. Use a newer one instead.") - ENDIF() - SET (CXX_FLAGS_EXTRA ${CXX_FLAGS_EXTRA} /fsanitize=address) - SET (ENABLED_SANITIZER true) - ENDIF () - IF (${USE_MSAN}) - MESSAGE (FATAL_ERROR "MSVC doesn't yet support MSAN.") - SET (USE_MSAN false) - #SET (ENABLED_SANITIZER true) - ENDIF () - IF (${USE_LSAN}) - MESSAGE (FATAL_ERROR "MSVC doesn't yet support LSAN.") - SET (USE_LSAN false) - #SET (ENABLED_SANITIZER true) - ENDIF () - IF (${USE_UBSAN}) - MESSAGE (FATAL_ERROR "MSVC doesn't yet support UBSAN.") - SET (USE_UBSAN false) - #SET (ENABLED_SANITIZER true) - ENDIF () - IF (${ENABLED_SANITIZER}) - SET (PREPROCESSOR_DEFS_EXTRA ${PREPROCESSOR_DEFS_EXTRA} _SANITIZERS) - ENDIF () - - - #-- Apply compiler flags. - - SET (cxx_compiler_flags_common - ${CXX_FLAGS_EXTRA} /W4 /MP /GR /fp:fast /std:c++20 - /WX # treat all warnings as errors - /wd4310 # cast truncates constant value - /wd4996 # use of deprecated stuff - /wd4701 # Potentially uninitialized local variable 'name' used - /wd4702 # Unreachable code - /wd4703 # Potentially uninitialized local pointer variable 'name' used - /wd4127 # The controlling expression of an if statement or while loop evaluates to a constant. - /wd26812# The enum type 'type-name' is unscoped. Prefer 'enum class' over 'enum' - ) + include("${CMAKE_SOURCE_DIR}/cmake/CMakeDetectArch.cmake") - # /Zc:__cplusplus is required to make __cplusplus accurate - # /Zc:__cplusplus is available starting with Visual Studio 2017 version 15.7 - # (according to https://learn.microsoft.com/en-us/cpp/build/reference/zc-cplusplus) - # That version is equivalent to _MSC_VER==1914 - # (according to https://learn.microsoft.com/en-us/cpp/preprocessor/predefined-macros?view=vs-2019) - # CMake's ${MSVC_VERSION} is equivalent to _MSC_VER - # (according to https://cmake.org/cmake/help/latest/variable/MSVC_VERSION.html#variable:MSVC_VERSION) - if (MSVC_VERSION GREATER_EQUAL 1914) - SET(local_msvc_compat_options /Zc:__cplusplus) - endif() - SET(cxx_compiler_flags_common ${cxx_compiler_flags_common} /Zc:preprocessor ${local_msvc_compat_options}) - - # Needed, otherwise throws a error... Regression? - set(CMAKE_C_FLAGS_DEBUG_INIT "" INTERNAL) - set(CMAKE_CXX_FLAGS_DEBUG_INIT "" INTERNAL) + message(STATUS "Generating for MSVC platform ${CMAKE_VS_PLATFORM_NAME}.") +endfunction() +function(toolchain_exe_stuff) + #-- Set mariadb .lib directory for the linker. + + if(CMAKE_CL_64) + target_link_directories(spheresvr PRIVATE "lib/_bin/x86_64/mariadb/") + else() + target_link_directories(spheresvr PRIVATE "lib/_bin/x86/mariadb/") + endif() + + #-- Configure the Windows application type and add global linker flags. + + if(${WIN32_SPAWN_CONSOLE}) + add_link_options("LINKER:/ENTRY:WinMainCRTStartup") # Handled by is_win32_app_linker -> "LINKER:/SUBSYSTEM:CONSOLE" + set(PREPROCESSOR_DEFS_EXTRA _WINDOWS_CONSOLE) + #ELSE () + # add_link_options ("LINKER:/ENTRY:WinMainCRTStartup") # Handled by is_win32_app_linker -> "LINKER: /SUBSYSTEM:WINDOWS" + endif() + + #-- Validate sanitizers options and store them between the common compiler flags. + + set(ENABLED_SANITIZER false) + if(${USE_ASAN}) + if(${MSVC_TOOLSET_VERSION} LESS_EQUAL 141) # VS 2017 + message(FATAL_ERROR "This MSVC version doesn't yet support ASAN. Use a newer one instead.") + endif() + set(CXX_FLAGS_EXTRA ${CXX_FLAGS_EXTRA} /fsanitize=address) + set(ENABLED_SANITIZER true) + endif() + if(${USE_MSAN}) + message(FATAL_ERROR "MSVC doesn't yet support MSAN.") + set(USE_MSAN false) + #SET (ENABLED_SANITIZER true) + endif() + if(${USE_LSAN}) + message(FATAL_ERROR "MSVC doesn't yet support LSAN.") + set(USE_LSAN false) + #SET (ENABLED_SANITIZER true) + endif() + if(${USE_UBSAN}) + message(FATAL_ERROR "MSVC doesn't yet support UBSAN.") + set(USE_UBSAN false) + #SET (ENABLED_SANITIZER true) + endif() + if(${ENABLED_SANITIZER}) + set(PREPROCESSOR_DEFS_EXTRA ${PREPROCESSOR_DEFS_EXTRA} _SANITIZERS) + endif() + + #-- Apply compiler flags. + + set(cxx_compiler_flags_common + ${CXX_FLAGS_EXTRA} + /W4 + /MP + /GR + /fp:fast + /std:c++20 + /WX # treat all warnings as errors + /wd4310 # cast truncates constant value + /wd4996 # use of deprecated stuff + /wd4701 # Potentially uninitialized local variable 'name' used + /wd4702 # Unreachable code + /wd4703 # Potentially uninitialized local pointer variable 'name' used + /wd4127 # The controlling expression of an if statement or while loop evaluates to a constant. + /wd26812 # The enum type 'type-name' is unscoped. Prefer 'enum class' over 'enum' + ) + + # /Zc:__cplusplus is required to make __cplusplus accurate + # /Zc:__cplusplus is available starting with Visual Studio 2017 version 15.7 + # (according to https://learn.microsoft.com/en-us/cpp/build/reference/zc-cplusplus) + # That version is equivalent to _MSC_VER==1914 + # (according to https://learn.microsoft.com/en-us/cpp/preprocessor/predefined-macros?view=vs-2019) + # CMake's ${MSVC_VERSION} is equivalent to _MSC_VER + # (according to https://cmake.org/cmake/help/latest/variable/MSVC_VERSION.html#variable:MSVC_VERSION) + if(MSVC_VERSION GREATER_EQUAL 1914) + set(local_msvc_compat_options /Zc:__cplusplus) + endif() + set(cxx_compiler_flags_common ${cxx_compiler_flags_common} /Zc:preprocessor ${local_msvc_compat_options}) + + # Needed, otherwise throws a error... Regression? + set(CMAKE_C_FLAGS_DEBUG_INIT "" INTERNAL) + set(CMAKE_CXX_FLAGS_DEBUG_INIT "" INTERNAL) + + # gersemi: off target_compile_options(spheresvr PRIVATE ${cxx_compiler_flags_common} $<$: $,/MT,/MD> /EHa /Oy /GL /GA /Gw /Gy /GF $,/O1 /Zi,/O2>> @@ -113,16 +113,18 @@ function (toolchain_exe_stuff) $<$: $,/MTd,/MDd> /EHsc /Oy- /ob1 /Od /Gs $,/Zi,/ZI>> # ASan (and compilation for ARM arch) doesn't support edit and continue option (ZI) ) + # gersemi: on - if ("${ARCH}" STREQUAL "x86_64") - target_compile_options(spheresvr PRIVATE /arch:SSE2) - endif () + if("${ARCH}" STREQUAL "x86_64") + target_compile_options(spheresvr PRIVATE /arch:SSE2) + endif() - #-- Apply linker flags. + #-- Apply linker flags. - # For some reason only THIS one isn't created, and CMake complains with an error... - set(CMAKE_EXE_LINKER_FLAGS_NIGHTLY CACHE INTERNAL ${CMAKE_EXE_LINKER_FLAGS_RELEASE} "") + # For some reason only THIS one isn't created, and CMake complains with an error... + set(CMAKE_EXE_LINKER_FLAGS_NIGHTLY CACHE INTERNAL ${CMAKE_EXE_LINKER_FLAGS_RELEASE} "") + # gersemi: off target_link_options(spheresvr PRIVATE /WX # treat all warnings as errors $<$: ${EXE_LINKER_EXTRA} /NODEFAULTLIB:libcmtd /OPT:REF,ICF /LTCG /INCREMENTAL:NO> @@ -130,55 +132,62 @@ function (toolchain_exe_stuff) $<$: ${EXE_LINKER_EXTRA} /NODEFAULTLIB:libcmt /SAFESEH:NO /DEBUG /LTCG:OFF $,/INCREMENTAL:NO /EDITANDCONTINUE:NO,/INCREMENTAL /EDITANDCONTINUE> > ) - # MSVC doesn't yet have an option to statically link against *san sanitizer libraries. - # /INCREMENTAL and /EDITANDCONTINUE not compatible with a MSVC Asan build. - - - #-- Windows libraries to link against. - TARGET_LINK_LIBRARIES ( spheresvr PRIVATE ws2_32 libmariadb ) - - - #-- Set define macros. - - # Common defines - TARGET_COMPILE_DEFINITIONS ( spheresvr PRIVATE - ${PREPROCESSOR_DEFS_EXTRA} - $<$>:_GITVERSION> - _CRT_SECURE_NO_WARNINGS - # Temporary setting _CRT_SECURE_NO_WARNINGS to do not spam so much in the build proccess. - _EXCEPTIONS_DEBUG - # Enable advanced exceptions catching. Consumes some more resources, but is very useful for debug - # on a running environment. Also it makes sphere more stable since exceptions are local. - _WINSOCK_DEPRECATED_NO_WARNINGS - # Removing WINSOCK warnings until the code gets updated or reviewed. - - # Per-build defines - $<$>: NDEBUG> - $<$: _NIGHTLYBUILD THREAD_TRACK_CALLSTACK> - $<$: _DEBUG THREAD_TRACK_CALLSTACK _PACKETDUMP> - ) - - - #-- Custom output directory. - - IF (CMAKE_CL_64) - SET(OUTDIR "${CMAKE_BINARY_DIR}/bin-x86_64/") - ELSE () - SET(OUTDIR "${CMAKE_BINARY_DIR}/bin-x86/") - ENDIF () - SET_TARGET_PROPERTIES(spheresvr PROPERTIES RUNTIME_OUTPUT_DIRECTORY "${OUTDIR}" ) - SET_TARGET_PROPERTIES(spheresvr PROPERTIES RUNTIME_OUTPUT_RELEASE "${OUTDIR}/Release" ) - SET_TARGET_PROPERTIES(spheresvr PROPERTIES RUNTIME_OUTPUT_NIGHTLY "${OUTDIR}/Nightly" ) - SET_TARGET_PROPERTIES(spheresvr PROPERTIES RUNTIME_OUTPUT_DEBUG "${OUTDIR}/Debug" ) - - - #-- Custom .vcxproj settings (for now, it only affects the debugger working directory). - - SET (SRCDIR ${CMAKE_SOURCE_DIR}) # for the sake of shortness - CONFIGURE_FILE("${CMAKE_SOURCE_DIR}/cmake/toolchains/include/spheresvr.vcxproj.user.in" "${CMAKE_BINARY_DIR}/spheresvr.vcxproj.user" @ONLY) - - - #-- Solution settings. - # Set spheresvr as startup project. - set_property(DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} PROPERTY VS_STARTUP_PROJECT spheresvr) + # gersemi: on + # MSVC doesn't yet have an option to statically link against *san sanitizer libraries. + # /INCREMENTAL and /EDITANDCONTINUE not compatible with a MSVC Asan build. + + #-- Windows libraries to link against. + target_link_libraries(spheresvr PRIVATE ws2_32 libmariadb) + + #-- Set define macros. + + # Common defines + target_compile_definitions( + spheresvr + PRIVATE + ${PREPROCESSOR_DEFS_EXTRA} + $<$>:_GITVERSION> + _CRT_SECURE_NO_WARNINGS + # Temporary setting _CRT_SECURE_NO_WARNINGS to do not spam so much in the build proccess. + _EXCEPTIONS_DEBUG + # Enable advanced exceptions catching. Consumes some more resources, but is very useful for debug + # on a running environment. Also it makes sphere more stable since exceptions are local. + _WINSOCK_DEPRECATED_NO_WARNINGS + # Removing WINSOCK warnings until the code gets updated or reviewed. + # Per-build defines + $<$>: + NDEBUG> + $<$: + _NIGHTLYBUILD + THREAD_TRACK_CALLSTACK> + $<$: + _DEBUG + THREAD_TRACK_CALLSTACK + _PACKETDUMP> + ) + + #-- Custom output directory. + + if(CMAKE_CL_64) + set(OUTDIR "${CMAKE_BINARY_DIR}/bin-x86_64/") + else() + set(OUTDIR "${CMAKE_BINARY_DIR}/bin-x86/") + endif() + set_target_properties(spheresvr PROPERTIES RUNTIME_OUTPUT_DIRECTORY "${OUTDIR}") + set_target_properties(spheresvr PROPERTIES RUNTIME_OUTPUT_RELEASE "${OUTDIR}/Release") + set_target_properties(spheresvr PROPERTIES RUNTIME_OUTPUT_NIGHTLY "${OUTDIR}/Nightly") + set_target_properties(spheresvr PROPERTIES RUNTIME_OUTPUT_DEBUG "${OUTDIR}/Debug") + + #-- Custom .vcxproj settings (for now, it only affects the debugger working directory). + + set(SRCDIR ${CMAKE_SOURCE_DIR}) # for the sake of shortness + configure_file( + "${CMAKE_SOURCE_DIR}/cmake/toolchains/include/spheresvr.vcxproj.user.in" + "${CMAKE_BINARY_DIR}/spheresvr.vcxproj.user" + @ONLY + ) + + #-- Solution settings. + # Set spheresvr as startup project. + set_property(DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} PROPERTY VS_STARTUP_PROJECT spheresvr) endfunction() diff --git a/cmake/toolchains/include/Linux-Clang_common.inc.cmake b/cmake/toolchains/include/Linux-Clang_common.inc.cmake index 75638acbc..986b79646 100644 --- a/cmake/toolchains/include/Linux-Clang_common.inc.cmake +++ b/cmake/toolchains/include/Linux-Clang_common.inc.cmake @@ -1,187 +1,206 @@ -SET (TOOLCHAIN_LOADED 1) +set(TOOLCHAIN_LOADED 1) -function (toolchain_after_project_common) - include ("${CMAKE_SOURCE_DIR}/cmake/CMakeDetectArch.cmake") -endfunction () - - -function (toolchain_exe_stuff_common) +function(toolchain_after_project_common) + include("${CMAKE_SOURCE_DIR}/cmake/CMakeDetectArch.cmake") +endfunction() - #-- Find libraries to be linked to. +function(toolchain_exe_stuff_common) + #-- Find libraries to be linked to. + + message(STATUS "Locating libraries to be linked to...") + + set(LIBS_LINK_LIST mariadb dl) + foreach(LIB_NAME ${LIBS_LINK_LIST}) + find_library(LIB_${LIB_NAME}_WITH_PATH ${LIB_NAME} PATH ${lib_search_paths}) + message(STATUS "Library ${LIB_NAME}: ${LIB_${LIB_NAME}_WITH_PATH}") + endforeach() + + #-- Validate sanitizers options and store them between the common compiler flags. + + set(ENABLED_SANITIZER false) + # From https://clang.llvm.org/docs/ClangCommandLineReference.html + # -static-libsan Statically link the sanitizer runtime (Not supported for ASan, TSan or UBSan on darwin) + + #string(REPLACE ";" " " CXX_FLAGS_EXTRA "${CXX_FLAGS_EXTRA}") + + if(${USE_ASAN}) + set(CXX_FLAGS_EXTRA + ${CXX_FLAGS_EXTRA} # -fsanitize=safe-stack # Can't be used with asan! + -fsanitize=address + -fno-sanitize-recover=address #-fsanitize-cfi # cfi: control flow integrity + -fsanitize-address-use-after-scope + -fsanitize=pointer-compare + -fsanitize=pointer-subtract + # Flags for additional instrumentation not strictly needing asan to be enabled + -fcf-protection=full + -fstack-check + -fstack-protector-all + -fstack-clash-protection + # Not supported by Clang, but supported by GCC + #-fvtable-verify=preinit -fharden-control-flow-redundancy -fhardcfr-check-exceptions + # Other + #-fsanitize-trap=all + ) + set(CMAKE_EXE_LINKER_FLAGS_EXTRA ${CMAKE_EXE_LINKER_FLAGS_EXTRA} -fsanitize=address) + set(PREPROCESSOR_DEFS_EXTRA ${PREPROCESSOR_DEFS_EXTRA} ADDRESS_SANITIZER) + set(ENABLED_SANITIZER true) + endif() + if(${USE_MSAN}) + message( + WARNING + "You have enabled MSAN. Make sure you do know what you are doing. It doesn't work out of the box. \ +See comments in the toolchain and: https://github.com/google/sanitizers/wiki/MemorySanitizerLibcxxHowTo" + ) + set(CXX_FLAGS_EXTRA ${CXX_FLAGS_EXTRA} -fsanitize=memory -fsanitize-memory-track-origins -fPIE) + set(CMAKE_EXE_LINKER_FLAGS_EXTRA ${CMAKE_EXE_LINKER_FLAGS_EXTRA} -fsanitize=memory) + set(PREPROCESSOR_DEFS_EXTRA ${PREPROCESSOR_DEFS_EXTRA} MEMORY_SANITIZER) + set(ENABLED_SANITIZER true) + endif() + if(${USE_LSAN}) + set(CXX_FLAGS_EXTRA ${CXX_FLAGS_EXTRA} -fsanitize=leak) + set(CMAKE_EXE_LINKER_FLAGS_EXTRA ${CMAKE_EXE_LINKER_FLAGS_EXTRA} -fsanitize=leak>) + set(PREPROCESSOR_DEFS_EXTRA ${PREPROCESSOR_DEFS_EXTRA} LEAK_SANITIZER) + set(ENABLED_SANITIZER true) + endif() + if(${USE_UBSAN}) + set(UBSAN_FLAGS + -fsanitize=undefined,float-divide-by-zero,local-bounds + -fno-sanitize=enum + # Supported? + -fsanitize=unsigned-integer-overflow #Unlike signed integer overflow, this is not undefined behavior, but it is often unintentional. + -fsanitize=implicit-conversion + ) + set(CXX_FLAGS_EXTRA ${CXX_FLAGS_EXTRA} ${UBSAN_FLAGS} -fsanitize=return,vptr) + set(CMAKE_EXE_LINKER_FLAGS_EXTRA ${CMAKE_EXE_LINKER_FLAGS_EXTRA} -fsanitize=undefined) + set(PREPROCESSOR_DEFS_EXTRA ${PREPROCESSOR_DEFS_EXTRA} UNDEFINED_BEHAVIOR_SANITIZER) + set(ENABLED_SANITIZER true) + endif() + + if(${ENABLED_SANITIZER}) + set(PREPROCESSOR_DEFS_EXTRA ${PREPROCESSOR_DEFS_EXTRA} _SANITIZERS) + set(CMAKE_EXE_LINKER_FLAGS_EXTRA + ${CMAKE_EXE_LINKER_FLAGS_EXTRA} + $<$:-static-libsan> + ) + endif() + + #-- Store compiler flags common to all builds. + + set(cxx_local_opts_warnings + -Werror + -Wall + -Wextra + -Wno-unknown-pragmas + -Wno-switch + -Wno-implicit-fallthrough + -Wno-parentheses + -Wno-misleading-indentation + -Wno-conversion-null + -Wno-unused-result + -Wno-format-security # TODO: disable that when we'll have time to fix every printf format issue + # clang -specific: + # -fforce-emit-vtables + ) + set(cxx_local_opts + -std=c++20 + -pthread + -fexceptions + -fnon-call-exceptions + -pipe + -ffast-math + ) + set(cxx_compiler_options_common ${cxx_local_opts_warnings} ${cxx_local_opts} ${CXX_FLAGS_EXTRA}) + #separate_arguments(cxx_compiler_options_common) + + # GCC flags not supported by clang: + # Warnings: "-Wno-nonnull-compare -Wno-maybe-uninitialized" + # Other: "-fno-expensive-optimizations" + + # MemorySanitizer: it doesn't work out of the box. It needs to be linked to an MSAN-instrumented build of libc++ and libc++abi. + # This means: one should build them from LLVM source... + # https://github.com/google/sanitizers/wiki/MemorySanitizerLibcxxHowTo + #IF (${USE_MSAN}) + # SET (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -stdlib=libc++") + #ENDIF() + # Use "-stdlib=libstdc++" to link against GCC c/c++ libs (this is done by default) + # To use LLVM libc++ use "-stdlib=libc++", but you need to install it separately + + #-- Apply compiler flags, only the ones specific per build type. + + # -fno-omit-frame-pointer disables a good optimization which may corrupt the debugger stack trace. + set(COMPILE_OPTIONS_EXTRA) + if(ENABLED_SANITIZER OR TARGET spheresvr_debug) + set(COMPILE_OPTIONS_EXTRA -fno-omit-frame-pointer -fno-inline) + endif() + if(TARGET spheresvr_release) + target_compile_options( + spheresvr_release + PUBLIC -O3 -flto=full -fvirtual-function-elimination ${COMPILE_OPTIONS_EXTRA} + ) + endif() + if(TARGET spheresvr_nightly) + if(ENABLED_SANITIZER) + target_compile_options(spheresvr_nightly PUBLIC -ggdb3 -O1 ${COMPILE_OPTIONS_EXTRA}) + else() + target_compile_options( + spheresvr_nightly + PUBLIC -O3 -flto=full -fvirtual-function-elimination ${COMPILE_OPTIONS_EXTRA} + ) + endif() + endif() + if(TARGET spheresvr_debug) + target_compile_options(spheresvr_debug PUBLIC -ggdb3 -O1 ${COMPILE_OPTIONS_EXTRA}) + endif() + + #-- Store common linker flags. + + if(${USE_MSAN}) + set(CMAKE_EXE_LINKER_FLAGS_EXTRA ${CMAKE_EXE_LINKER_FLAGS_EXTRA} -pie) + endif() + set(cxx_linker_options_common + ${CMAKE_EXE_LINKER_FLAGS_EXTRA} + -pthread + -dynamic + -Wl,--fatal-warnings + $<$: + -static-libstdc++ + -static-libgcc> # no way to safely statically link against libc + ) - MESSAGE(STATUS "Locating libraries to be linked to...") + #-- Store common define macros. - SET (LIBS_LINK_LIST - mariadb - dl - ) - FOREACH (LIB_NAME ${LIBS_LINK_LIST}) - FIND_LIBRARY( - LIB_${LIB_NAME}_WITH_PATH ${LIB_NAME} - PATH ${lib_search_paths} - ) - MESSAGE (STATUS "Library ${LIB_NAME}: ${LIB_${LIB_NAME}_WITH_PATH}") - ENDFOREACH () - - - #-- Validate sanitizers options and store them between the common compiler flags. - - SET (ENABLED_SANITIZER false) - # From https://clang.llvm.org/docs/ClangCommandLineReference.html - # -static-libsan Statically link the sanitizer runtime (Not supported for ASan, TSan or UBSan on darwin) - - #string(REPLACE ";" " " CXX_FLAGS_EXTRA "${CXX_FLAGS_EXTRA}") - - IF (${USE_ASAN}) - SET (CXX_FLAGS_EXTRA ${CXX_FLAGS_EXTRA} # -fsanitize=safe-stack # Can't be used with asan! - -fsanitize=address -fno-sanitize-recover=address #-fsanitize-cfi # cfi: control flow integrity - -fsanitize-address-use-after-scope -fsanitize=pointer-compare -fsanitize=pointer-subtract - # Flags for additional instrumentation not strictly needing asan to be enabled - -fcf-protection=full -fstack-check -fstack-protector-all -fstack-clash-protection - # Not supported by Clang, but supported by GCC - #-fvtable-verify=preinit -fharden-control-flow-redundancy -fhardcfr-check-exceptions - # Other - #-fsanitize-trap=all - ) - set (CMAKE_EXE_LINKER_FLAGS_EXTRA ${CMAKE_EXE_LINKER_FLAGS_EXTRA} -fsanitize=address) - SET (PREPROCESSOR_DEFS_EXTRA ${PREPROCESSOR_DEFS_EXTRA} ADDRESS_SANITIZER) - SET (ENABLED_SANITIZER true) - ENDIF () - IF (${USE_MSAN}) - MESSAGE (WARNING "You have enabled MSAN. Make sure you do know what you are doing. It doesn't work out of the box. \ -See comments in the toolchain and: https://github.com/google/sanitizers/wiki/MemorySanitizerLibcxxHowTo") - SET (CXX_FLAGS_EXTRA ${CXX_FLAGS_EXTRA} -fsanitize=memory -fsanitize-memory-track-origins -fPIE) - set (CMAKE_EXE_LINKER_FLAGS_EXTRA ${CMAKE_EXE_LINKER_FLAGS_EXTRA} -fsanitize=memory) - SET (PREPROCESSOR_DEFS_EXTRA ${PREPROCESSOR_DEFS_EXTRA} MEMORY_SANITIZER) - SET (ENABLED_SANITIZER true) - ENDIF () - IF (${USE_LSAN}) - SET (CXX_FLAGS_EXTRA ${CXX_FLAGS_EXTRA} -fsanitize=leak) - set (CMAKE_EXE_LINKER_FLAGS_EXTRA ${CMAKE_EXE_LINKER_FLAGS_EXTRA} -fsanitize=leak>) - SET (PREPROCESSOR_DEFS_EXTRA ${PREPROCESSOR_DEFS_EXTRA} LEAK_SANITIZER) - SET (ENABLED_SANITIZER true) - ENDIF () - IF (${USE_UBSAN}) - SET (UBSAN_FLAGS - -fsanitize=undefined,float-divide-by-zero,local-bounds - -fno-sanitize=enum - # Supported? - -fsanitize=unsigned-integer-overflow #Unlike signed integer overflow, this is not undefined behavior, but it is often unintentional. - -fsanitize=implicit-conversion + set(cxx_compiler_definitions_common + ${PREPROCESSOR_DEFS_EXTRA} + $<$>:_GITVERSION> + _EXCEPTIONS_DEBUG + # _EXCEPTIONS_DEBUG: Enable advanced exceptions catching. Consumes some more resources, but is very useful for debug + # on a running environment. Also it makes sphere more stable since exceptions are local. ) - SET (CXX_FLAGS_EXTRA ${CXX_FLAGS_EXTRA} ${UBSAN_FLAGS} -fsanitize=return,vptr) - set (CMAKE_EXE_LINKER_FLAGS_EXTRA ${CMAKE_EXE_LINKER_FLAGS_EXTRA} -fsanitize=undefined) - SET (PREPROCESSOR_DEFS_EXTRA ${PREPROCESSOR_DEFS_EXTRA} UNDEFINED_BEHAVIOR_SANITIZER) - SET (ENABLED_SANITIZER true) - ENDIF () - - IF (${ENABLED_SANITIZER}) - SET (PREPROCESSOR_DEFS_EXTRA ${PREPROCESSOR_DEFS_EXTRA} _SANITIZERS) - set (CMAKE_EXE_LINKER_FLAGS_EXTRA ${CMAKE_EXE_LINKER_FLAGS_EXTRA} $<$:-static-libsan>) - ENDIF () - - - #-- Store compiler flags common to all builds. - - set (cxx_local_opts_warnings - -Werror - -Wall -Wextra -Wno-unknown-pragmas -Wno-switch -Wno-implicit-fallthrough - -Wno-parentheses -Wno-misleading-indentation -Wno-conversion-null -Wno-unused-result - -Wno-format-security # TODO: disable that when we'll have time to fix every printf format issue - - # clang -specific: - # -fforce-emit-vtables - ) - set (cxx_local_opts - -std=c++20 -pthread -fexceptions -fnon-call-exceptions - -pipe -ffast-math - ) - set (cxx_compiler_options_common ${cxx_local_opts_warnings} ${cxx_local_opts} ${CXX_FLAGS_EXTRA}) - #separate_arguments(cxx_compiler_options_common) - - # GCC flags not supported by clang: - # Warnings: "-Wno-nonnull-compare -Wno-maybe-uninitialized" - # Other: "-fno-expensive-optimizations" - - # MemorySanitizer: it doesn't work out of the box. It needs to be linked to an MSAN-instrumented build of libc++ and libc++abi. - # This means: one should build them from LLVM source... - # https://github.com/google/sanitizers/wiki/MemorySanitizerLibcxxHowTo - #IF (${USE_MSAN}) - # SET (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -stdlib=libc++") - #ENDIF() - # Use "-stdlib=libstdc++" to link against GCC c/c++ libs (this is done by default) - # To use LLVM libc++ use "-stdlib=libc++", but you need to install it separately - - - #-- Apply compiler flags, only the ones specific per build type. - - # -fno-omit-frame-pointer disables a good optimization which may corrupt the debugger stack trace. - SET (COMPILE_OPTIONS_EXTRA) - IF (ENABLED_SANITIZER OR TARGET spheresvr_debug) - SET (COMPILE_OPTIONS_EXTRA -fno-omit-frame-pointer -fno-inline) - ENDIF () - IF (TARGET spheresvr_release) - TARGET_COMPILE_OPTIONS ( spheresvr_release PUBLIC -O3 -flto=full -fvirtual-function-elimination ${COMPILE_OPTIONS_EXTRA}) - ENDIF () - IF (TARGET spheresvr_nightly) - IF (ENABLED_SANITIZER) - TARGET_COMPILE_OPTIONS ( spheresvr_nightly PUBLIC -ggdb3 -O1 ${COMPILE_OPTIONS_EXTRA}) - ELSE () - TARGET_COMPILE_OPTIONS ( spheresvr_nightly PUBLIC -O3 -flto=full -fvirtual-function-elimination ${COMPILE_OPTIONS_EXTRA}) - ENDIF () - ENDIF () - IF (TARGET spheresvr_debug) - TARGET_COMPILE_OPTIONS ( spheresvr_debug PUBLIC -ggdb3 -O1 ${COMPILE_OPTIONS_EXTRA}) - ENDIF () - - - #-- Store common linker flags. - - IF (${USE_MSAN}) - set (CMAKE_EXE_LINKER_FLAGS_EXTRA ${CMAKE_EXE_LINKER_FLAGS_EXTRA} -pie) - ENDIF() - set (cxx_linker_options_common ${CMAKE_EXE_LINKER_FLAGS_EXTRA} -pthread -dynamic -Wl,--fatal-warnings - $<$: -static-libstdc++ -static-libgcc> # no way to safely statically link against libc - ) - - - #-- Store common define macros. - - set(cxx_compiler_definitions_common - ${PREPROCESSOR_DEFS_EXTRA} - $<$>:_GITVERSION> - _EXCEPTIONS_DEBUG - # _EXCEPTIONS_DEBUG: Enable advanced exceptions catching. Consumes some more resources, but is very useful for debug - # on a running environment. Also it makes sphere more stable since exceptions are local. - ) - - - #-- Apply define macros, only the ones specific per build type. - - IF (TARGET spheresvr_release) - TARGET_COMPILE_DEFINITIONS ( spheresvr_release PUBLIC NDEBUG ) - ENDIF (TARGET spheresvr_release) - IF (TARGET spheresvr_nightly) - TARGET_COMPILE_DEFINITIONS ( spheresvr_nightly PUBLIC NDEBUG THREAD_TRACK_CALLSTACK _NIGHTLYBUILD ) - ENDIF (TARGET spheresvr_nightly) - IF (TARGET spheresvr_debug) - TARGET_COMPILE_DEFINITIONS ( spheresvr_debug PUBLIC _DEBUG THREAD_TRACK_CALLSTACK _PACKETDUMP ) - ENDIF (TARGET spheresvr_debug) - - - #-- Now add back the common compiler options, preprocessor macros, linker targets and options. - - foreach(tgt ${TARGETS}) - target_compile_options (${tgt} PRIVATE ${cxx_compiler_options_common}) - target_compile_definitions (${tgt} PRIVATE ${cxx_compiler_definitions_common}) - target_link_options (${tgt} PRIVATE ${cxx_linker_options_common}) - target_link_libraries (${tgt} PRIVATE ${LIB_mariadb_WITH_PATH} ${LIB_dl_WITH_PATH}) - endforeach() - - #-- Set different output folders for each build type - # (When we'll have support for multi-target builds...) - #SET_TARGET_PROPERTIES(spheresvr PROPERTIES RUNTIME_OUTPUT_RELEASE "${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/Release" ) - #SET_TARGET_PROPERTIES(spheresvr PROPERTIES RUNTIME_OUTPUT_DEBUG "${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/Debug" ) - #SET_TARGET_PROPERTIES(spheresvr PROPERTIES RUNTIME_OUTPUT_NIGHTLY "${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/Nightly" ) + #-- Apply define macros, only the ones specific per build type. + + if(TARGET spheresvr_release) + target_compile_definitions(spheresvr_release PUBLIC NDEBUG) + endif(TARGET spheresvr_release) + if(TARGET spheresvr_nightly) + target_compile_definitions(spheresvr_nightly PUBLIC NDEBUG THREAD_TRACK_CALLSTACK _NIGHTLYBUILD) + endif(TARGET spheresvr_nightly) + if(TARGET spheresvr_debug) + target_compile_definitions(spheresvr_debug PUBLIC _DEBUG THREAD_TRACK_CALLSTACK _PACKETDUMP) + endif(TARGET spheresvr_debug) + + #-- Now add back the common compiler options, preprocessor macros, linker targets and options. + + foreach(tgt ${TARGETS}) + target_compile_options(${tgt} PRIVATE ${cxx_compiler_options_common}) + target_compile_definitions(${tgt} PRIVATE ${cxx_compiler_definitions_common}) + target_link_options(${tgt} PRIVATE ${cxx_linker_options_common}) + target_link_libraries(${tgt} PRIVATE ${LIB_mariadb_WITH_PATH} ${LIB_dl_WITH_PATH}) + endforeach() + + #-- Set different output folders for each build type + # (When we'll have support for multi-target builds...) + #SET_TARGET_PROPERTIES(spheresvr PROPERTIES RUNTIME_OUTPUT_RELEASE "${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/Release" ) + #SET_TARGET_PROPERTIES(spheresvr PROPERTIES RUNTIME_OUTPUT_DEBUG "${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/Debug" ) + #SET_TARGET_PROPERTIES(spheresvr PROPERTIES RUNTIME_OUTPUT_NIGHTLY "${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/Nightly" ) endfunction() diff --git a/cmake/toolchains/include/Linux-GNU_common.inc.cmake b/cmake/toolchains/include/Linux-GNU_common.inc.cmake index 52349da26..c483926c8 100644 --- a/cmake/toolchains/include/Linux-GNU_common.inc.cmake +++ b/cmake/toolchains/include/Linux-GNU_common.inc.cmake @@ -1,169 +1,188 @@ -SET (TOOLCHAIN_LOADED 1) +set(TOOLCHAIN_LOADED 1) -function (toolchain_after_project_common) - include ("${CMAKE_SOURCE_DIR}/cmake/CMakeDetectArch.cmake") -endfunction () - - -function (toolchain_exe_stuff_common) +function(toolchain_after_project_common) + include("${CMAKE_SOURCE_DIR}/cmake/CMakeDetectArch.cmake") +endfunction() - #-- Find libraries to be linked to. +function(toolchain_exe_stuff_common) + #-- Find libraries to be linked to. + + message(STATUS "Locating libraries to be linked to...") + + set(LIBS_LINK_LIST mariadb dl) + foreach(LIB_NAME ${LIBS_LINK_LIST}) + find_library(LIB_${LIB_NAME}_WITH_PATH ${LIB_NAME} PATH ${lib_search_paths}) + message(STATUS "Library ${LIB_NAME}: ${LIB_${LIB_NAME}_WITH_PATH}") + endforeach() + + #-- Validate sanitizers options and store them between the common compiler flags. + + set(ENABLED_SANITIZER false) + + if(${USE_ASAN}) + set(CXX_FLAGS_EXTRA + ${CXX_FLAGS_EXTRA} + -fsanitize=address + -fno-sanitize-recover=address #-fsanitize-cfi # cfi: control flow integrity, not supported by GCC + -fsanitize-address-use-after-scope + -fsanitize=pointer-compare + -fsanitize=pointer-subtract + # Flags for additional instrumentation not strictly needing asan to be enabled + #-fvtable-verify=preinit # This causes a GCC internal error! Tested with 13.2.0 + -fstack-check + -fstack-protector-all + -fcf-protection=full + # GCC 14? + #-fharden-control-flow-redundancy -fhardcfr-check-exceptions + # Other + #-fsanitize-trap=all + ) + set(CMAKE_EXE_LINKER_FLAGS_EXTRA + ${CMAKE_EXE_LINKER_FLAGS_EXTRA} + -fsanitize=address + $<$:-static-libasan> + ) + set(PREPROCESSOR_DEFS_EXTRA ${PREPROCESSOR_DEFS_EXTRA} ADDRESS_SANITIZER) + set(ENABLED_SANITIZER true) + endif() + if(${USE_MSAN}) + message(FATAL_ERROR "Linux GCC doesn't yet support MSAN") + set(USE_MSAN false) + #SET (CXX_FLAGS_EXTRA ${CXX_FLAGS_EXTRA} -fsanitize=memory -fsanitize-memory-track-origins=2 -fPIE) + #set (CMAKE_EXE_LINKER_FLAGS_EXTRA ${CMAKE_EXE_LINKER_FLAGS_EXTRA} -fsanitize=memory )#$<$:-static-libmsan>) + #SET (PREPROCESSOR_DEFS_EXTRA ${PREPROCESSOR_DEFS_EXTRA} MEMORY_SANITIZER) + #SET (ENABLED_SANITIZER true) + endif() + if(${USE_LSAN}) + set(CXX_FLAGS_EXTRA ${CXX_FLAGS_EXTRA} -fsanitize=leak) + set(CMAKE_EXE_LINKER_FLAGS_EXTRA + ${CMAKE_EXE_LINKER_FLAGS_EXTRA} + -fsanitize=leak + $<$:-static-liblsan> + ) + set(PREPROCESSOR_DEFS_EXTRA ${PREPROCESSOR_DEFS_EXTRA} LEAK_SANITIZER) + set(ENABLED_SANITIZER true) + endif() + if(${USE_UBSAN}) + set(UBSAN_FLAGS + -fsanitize=undefined,float-divide-by-zero + -fno-sanitize=enum + # Unsupported (yet?) by GCC 13 + #-fsanitize=unsigned-integer-overflow #Unlike signed integer overflow, this is not undefined behavior, but it is often unintentional. + #-fsanitize=implicit-conversion, local-bounds + ) + set(CXX_FLAGS_EXTRA ${CXX_FLAGS_EXTRA} ${UBSAN_FLAGS} -fsanitize=return,vptr) + set(CMAKE_EXE_LINKER_FLAGS_EXTRA + ${CMAKE_EXE_LINKER_FLAGS_EXTRA} + -fsanitize=undefined + $<$:-static-libubsan> + ) + set(PREPROCESSOR_DEFS_EXTRA ${PREPROCESSOR_DEFS_EXTRA} UNDEFINED_BEHAVIOR_SANITIZER) + set(ENABLED_SANITIZER true) + endif() + + if(${ENABLED_SANITIZER}) + set(PREPROCESSOR_DEFS_EXTRA ${PREPROCESSOR_DEFS_EXTRA} _SANITIZERS) + endif() + + #-- Store compiler flags common to all builds. + + set(cxx_local_opts_warnings + -Werror + -Wall + -Wextra + -Wno-nonnull-compare + -Wno-unknown-pragmas + -Wno-switch + -Wno-implicit-fallthrough + -Wno-parentheses + -Wno-misleading-indentation + -Wno-conversion-null + -Wno-unused-result + -Wno-format-security # TODO: disable that when we'll have time to fix every printf format issue + ) + set(cxx_local_opts + -std=c++20 + -pthread + -fexceptions + -fnon-call-exceptions + -pipe + -ffast-math + ) + set(cxx_compiler_options_common ${cxx_local_opts_warnings} ${cxx_local_opts} ${CXX_FLAGS_EXTRA}) + + #-- Apply compiler flags, only the ones specific per build type. + + # -fno-omit-frame-pointer disables a good optimization which may corrupt the debugger stack trace. + set(COMPILE_OPTIONS_EXTRA) + if(ENABLED_SANITIZER OR TARGET spheresvr_debug) + set(COMPILE_OPTIONS_EXTRA -fno-omit-frame-pointer -fno-inline) + endif() + if(TARGET spheresvr_release) + target_compile_options(spheresvr_release PUBLIC -s -O3 ${COMPILE_OPTIONS_EXTRA}) + endif() + if(TARGET spheresvr_nightly) + if(ENABLED_SANITIZER) + target_compile_options(spheresvr_nightly PUBLIC -ggdb3 -O1 ${COMPILE_OPTIONS_EXTRA}) + else() + target_compile_options(spheresvr_nightly PUBLIC -O3 ${COMPILE_OPTIONS_EXTRA}) + endif() + endif() + if(TARGET spheresvr_debug) + target_compile_options(spheresvr_debug PUBLIC -ggdb3 -O1 ${COMPILE_OPTIONS_EXTRA}) + endif() + + #-- Store common linker flags. + + if(${USE_MSAN}) + set(CMAKE_EXE_LINKER_FLAGS_EXTRA ${CMAKE_EXE_LINKER_FLAGS_EXTRA} -pie) + endif() + set(cxx_linker_options_common + ${CMAKE_EXE_LINKER_FLAGS_EXTRA} + -pthread + -dynamic + -Wl,--fatal-warnings + $<$: + -static-libstdc++ + -static-libgcc # no way to safely statically link against libc + #$<$: -fsanitize-link-runtime -fsanitize-link-c++-runtime> + > + ) - MESSAGE(STATUS "Locating libraries to be linked to...") + #-- Store common define macros. - SET (LIBS_LINK_LIST - mariadb - dl - ) - FOREACH (LIB_NAME ${LIBS_LINK_LIST}) - FIND_LIBRARY( - LIB_${LIB_NAME}_WITH_PATH ${LIB_NAME} - PATH ${lib_search_paths} - ) - MESSAGE (STATUS "Library ${LIB_NAME}: ${LIB_${LIB_NAME}_WITH_PATH}") - ENDFOREACH () - - - #-- Validate sanitizers options and store them between the common compiler flags. - - SET (ENABLED_SANITIZER false) - - IF (${USE_ASAN}) - SET (CXX_FLAGS_EXTRA ${CXX_FLAGS_EXTRA} - -fsanitize=address -fno-sanitize-recover=address #-fsanitize-cfi # cfi: control flow integrity, not supported by GCC - -fsanitize-address-use-after-scope -fsanitize=pointer-compare -fsanitize=pointer-subtract - # Flags for additional instrumentation not strictly needing asan to be enabled - #-fvtable-verify=preinit # This causes a GCC internal error! Tested with 13.2.0 - -fstack-check -fstack-protector-all - -fcf-protection=full - # GCC 14? - #-fharden-control-flow-redundancy -fhardcfr-check-exceptions - # Other - #-fsanitize-trap=all + set(cxx_compiler_definitions_common + ${PREPROCESSOR_DEFS_EXTRA} + $<$>:_GITVERSION> + _EXCEPTIONS_DEBUG + # _EXCEPTIONS_DEBUG: Enable advanced exceptions catching. Consumes some more resources, but is very useful for debug + # on a running environment. Also it makes sphere more stable since exceptions are local. ) - set (CMAKE_EXE_LINKER_FLAGS_EXTRA ${CMAKE_EXE_LINKER_FLAGS_EXTRA} -fsanitize=address $<$:-static-libasan>) - SET (PREPROCESSOR_DEFS_EXTRA ${PREPROCESSOR_DEFS_EXTRA} ADDRESS_SANITIZER) - SET (ENABLED_SANITIZER true) - ENDIF () - IF (${USE_MSAN}) - MESSAGE (FATAL_ERROR "Linux GCC doesn't yet support MSAN") - SET (USE_MSAN false) - #SET (CXX_FLAGS_EXTRA ${CXX_FLAGS_EXTRA} -fsanitize=memory -fsanitize-memory-track-origins=2 -fPIE) - #set (CMAKE_EXE_LINKER_FLAGS_EXTRA ${CMAKE_EXE_LINKER_FLAGS_EXTRA} -fsanitize=memory )#$<$:-static-libmsan>) - #SET (PREPROCESSOR_DEFS_EXTRA ${PREPROCESSOR_DEFS_EXTRA} MEMORY_SANITIZER) - #SET (ENABLED_SANITIZER true) - ENDIF () - IF (${USE_LSAN}) - SET (CXX_FLAGS_EXTRA ${CXX_FLAGS_EXTRA} -fsanitize=leak) - set (CMAKE_EXE_LINKER_FLAGS_EXTRA ${CMAKE_EXE_LINKER_FLAGS_EXTRA} -fsanitize=leak $<$:-static-liblsan>) - SET (PREPROCESSOR_DEFS_EXTRA ${PREPROCESSOR_DEFS_EXTRA} LEAK_SANITIZER) - SET (ENABLED_SANITIZER true) - ENDIF () - IF (${USE_UBSAN}) - SET (UBSAN_FLAGS - -fsanitize=undefined,float-divide-by-zero - -fno-sanitize=enum - # Unsupported (yet?) by GCC 13 - #-fsanitize=unsigned-integer-overflow #Unlike signed integer overflow, this is not undefined behavior, but it is often unintentional. - #-fsanitize=implicit-conversion, local-bounds - ) - SET (CXX_FLAGS_EXTRA ${CXX_FLAGS_EXTRA} ${UBSAN_FLAGS} -fsanitize=return,vptr) - set (CMAKE_EXE_LINKER_FLAGS_EXTRA ${CMAKE_EXE_LINKER_FLAGS_EXTRA} -fsanitize=undefined $<$:-static-libubsan>) - SET (PREPROCESSOR_DEFS_EXTRA ${PREPROCESSOR_DEFS_EXTRA} UNDEFINED_BEHAVIOR_SANITIZER) - SET (ENABLED_SANITIZER true) - ENDIF () - - IF (${ENABLED_SANITIZER}) - SET (PREPROCESSOR_DEFS_EXTRA ${PREPROCESSOR_DEFS_EXTRA} _SANITIZERS) - ENDIF () - - - #-- Store compiler flags common to all builds. - - set (cxx_local_opts_warnings - -Werror - -Wall -Wextra -Wno-nonnull-compare -Wno-unknown-pragmas -Wno-switch -Wno-implicit-fallthrough - -Wno-parentheses -Wno-misleading-indentation -Wno-conversion-null -Wno-unused-result - -Wno-format-security # TODO: disable that when we'll have time to fix every printf format issue - ) - set (cxx_local_opts - -std=c++20 -pthread -fexceptions -fnon-call-exceptions - -pipe -ffast-math - ) - set (cxx_compiler_options_common ${cxx_local_opts_warnings} ${cxx_local_opts} ${CXX_FLAGS_EXTRA}) - - - #-- Apply compiler flags, only the ones specific per build type. - - # -fno-omit-frame-pointer disables a good optimization which may corrupt the debugger stack trace. - SET (COMPILE_OPTIONS_EXTRA) - IF (ENABLED_SANITIZER OR TARGET spheresvr_debug) - SET (COMPILE_OPTIONS_EXTRA -fno-omit-frame-pointer -fno-inline) - ENDIF () - IF (TARGET spheresvr_release) - TARGET_COMPILE_OPTIONS ( spheresvr_release PUBLIC -s -O3 ${COMPILE_OPTIONS_EXTRA}) - ENDIF () - IF (TARGET spheresvr_nightly) - IF (ENABLED_SANITIZER) - TARGET_COMPILE_OPTIONS ( spheresvr_nightly PUBLIC -ggdb3 -O1 ${COMPILE_OPTIONS_EXTRA}) - ELSE () - TARGET_COMPILE_OPTIONS ( spheresvr_nightly PUBLIC -O3 ${COMPILE_OPTIONS_EXTRA}) - ENDIF () - ENDIF () - IF (TARGET spheresvr_debug) - TARGET_COMPILE_OPTIONS ( spheresvr_debug PUBLIC -ggdb3 -O1 ${COMPILE_OPTIONS_EXTRA}) - ENDIF () - - - #-- Store common linker flags. - - IF (${USE_MSAN}) - SET (CMAKE_EXE_LINKER_FLAGS_EXTRA ${CMAKE_EXE_LINKER_FLAGS_EXTRA} -pie) - ENDIF() - set (cxx_linker_options_common ${CMAKE_EXE_LINKER_FLAGS_EXTRA} -pthread -dynamic -Wl,--fatal-warnings - $<$: -static-libstdc++ -static-libgcc # no way to safely statically link against libc - #$<$: -fsanitize-link-runtime -fsanitize-link-c++-runtime> - > - ) - - - #-- Store common define macros. - - set (cxx_compiler_definitions_common - ${PREPROCESSOR_DEFS_EXTRA} - $<$>:_GITVERSION> - _EXCEPTIONS_DEBUG - # _EXCEPTIONS_DEBUG: Enable advanced exceptions catching. Consumes some more resources, but is very useful for debug - # on a running environment. Also it makes sphere more stable since exceptions are local. - ) - - - #-- Apply define macros, only the ones specific per build type. - - IF (TARGET spheresvr_release) - TARGET_COMPILE_DEFINITIONS ( spheresvr_release PUBLIC NDEBUG ) - ENDIF (TARGET spheresvr_release) - IF (TARGET spheresvr_nightly) - TARGET_COMPILE_DEFINITIONS ( spheresvr_nightly PUBLIC NDEBUG THREAD_TRACK_CALLSTACK _NIGHTLYBUILD ) - ENDIF (TARGET spheresvr_nightly) - IF (TARGET spheresvr_debug) - TARGET_COMPILE_DEFINITIONS ( spheresvr_debug PUBLIC _DEBUG THREAD_TRACK_CALLSTACK _PACKETDUMP ) - ENDIF (TARGET spheresvr_debug) - - - #-- Now apply the common compiler options, preprocessor macros, linker options. - - foreach(tgt ${TARGETS}) - target_compile_options (${tgt} PRIVATE ${cxx_compiler_options_common}) - target_compile_definitions (${tgt} PRIVATE ${cxx_compiler_definitions_common}) - target_link_options (${tgt} PRIVATE ${cxx_linker_options_common}) - target_link_libraries (${tgt} PRIVATE ${LIB_mariadb_WITH_PATH} ${LIB_dl_WITH_PATH}) - endforeach() - - #-- Set different output folders for each build type - # (When we'll have support for multi-target builds...) - #SET_TARGET_PROPERTIES(spheresvr PROPERTIES RUNTIME_OUTPUT_RELEASE "${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/Release" ) - #SET_TARGET_PROPERTIES(spheresvr PROPERTIES RUNTIME_OUTPUT_DEBUG "${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/Debug" ) - #SET_TARGET_PROPERTIES(spheresvr PROPERTIES RUNTIME_OUTPUT_NIGHTLY "${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/Nightly" ) + #-- Apply define macros, only the ones specific per build type. + + if(TARGET spheresvr_release) + target_compile_definitions(spheresvr_release PUBLIC NDEBUG) + endif(TARGET spheresvr_release) + if(TARGET spheresvr_nightly) + target_compile_definitions(spheresvr_nightly PUBLIC NDEBUG THREAD_TRACK_CALLSTACK _NIGHTLYBUILD) + endif(TARGET spheresvr_nightly) + if(TARGET spheresvr_debug) + target_compile_definitions(spheresvr_debug PUBLIC _DEBUG THREAD_TRACK_CALLSTACK _PACKETDUMP) + endif(TARGET spheresvr_debug) + + #-- Now apply the common compiler options, preprocessor macros, linker options. + + foreach(tgt ${TARGETS}) + target_compile_options(${tgt} PRIVATE ${cxx_compiler_options_common}) + target_compile_definitions(${tgt} PRIVATE ${cxx_compiler_definitions_common}) + target_link_options(${tgt} PRIVATE ${cxx_linker_options_common}) + target_link_libraries(${tgt} PRIVATE ${LIB_mariadb_WITH_PATH} ${LIB_dl_WITH_PATH}) + endforeach() + + #-- Set different output folders for each build type + # (When we'll have support for multi-target builds...) + #SET_TARGET_PROPERTIES(spheresvr PROPERTIES RUNTIME_OUTPUT_RELEASE "${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/Release" ) + #SET_TARGET_PROPERTIES(spheresvr PROPERTIES RUNTIME_OUTPUT_DEBUG "${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/Debug" ) + #SET_TARGET_PROPERTIES(spheresvr PROPERTIES RUNTIME_OUTPUT_NIGHTLY "${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/Nightly" ) endfunction() diff --git a/cmake/toolchains/include/OSX-AppleClang_common.inc.cmake b/cmake/toolchains/include/OSX-AppleClang_common.inc.cmake index 3b0374a7c..914e3247a 100644 --- a/cmake/toolchains/include/OSX-AppleClang_common.inc.cmake +++ b/cmake/toolchains/include/OSX-AppleClang_common.inc.cmake @@ -1,186 +1,199 @@ -SET (TOOLCHAIN_LOADED 1) +set(TOOLCHAIN_LOADED 1) +function(toolchain_after_project_common) + include("${CMAKE_SOURCE_DIR}/cmake/CMakeDetectArch.cmake") +endfunction() -function (toolchain_after_project_common) - include ("${CMAKE_SOURCE_DIR}/cmake/CMakeDetectArch.cmake") -endfunction () - - -function (toolchain_exe_stuff_common) - - #-- Find libraries to be linked to. - - MESSAGE(STATUS "Locating libraries to be linked to...") - - SET (LIBS_LINK_LIST - mariadb - dl - ) - FOREACH (LIB_NAME ${LIBS_LINK_LIST}) - FIND_LIBRARY( - LIB_${LIB_NAME}_WITH_PATH ${LIB_NAME} - HINT - "/usr/local/opt/mariadb-connector-c/lib/mariadb" - "/opt/homebrew/var/mariadb-connector-c/lib/mariadb" - "/opt/homebrew/lib/mariadb" - ) - MESSAGE (STATUS "Library ${LIB_NAME}: ${LIB_${LIB_NAME}_WITH_PATH}") - ENDFOREACH () - - - #-- Validate sanitizers options and store them between the common compiler flags. - - SET (ENABLED_SANITIZER false) - # From https://clang.llvm.org/docs/ClangCommandLineReference.html - # -static-libsan Statically link the sanitizer runtime (Not supported for ASan, TSan or UBSan on darwin) - - IF (${USE_ASAN}) - SET (CXX_FLAGS_EXTRA ${CXX_FLAGS_EXTRA} # -fsanitize=safe-stack # Can't be used with asan! - -fsanitize=address -fno-sanitize-recover=address #-fsanitize-cfi # cfi: control flow integrity - -fsanitize-address-use-after-scope -fsanitize=pointer-compare -fsanitize=pointer-subtract - # Flags for additional instrumentation not strictly needing asan to be enabled - -fcf-protection=full -fstack-check -fstack-protector-all -fstack-clash-protection - # Not supported by Clang, but supported by GCC - #-fvtable-verify=preinit -fharden-control-flow-redundancy -fhardcfr-check-exceptions - # Other - #-fsanitize-trap=all +function(toolchain_exe_stuff_common) + #-- Find libraries to be linked to. + + message(STATUS "Locating libraries to be linked to...") + + set(LIBS_LINK_LIST mariadb dl) + foreach(LIB_NAME ${LIBS_LINK_LIST}) + find_library( + LIB_${LIB_NAME}_WITH_PATH + ${LIB_NAME} + HINT + "/usr/local/opt/mariadb-connector-c/lib/mariadb" + "/opt/homebrew/var/mariadb-connector-c/lib/mariadb" + "/opt/homebrew/lib/mariadb" + ) + message(STATUS "Library ${LIB_NAME}: ${LIB_${LIB_NAME}_WITH_PATH}") + endforeach() + + #-- Validate sanitizers options and store them between the common compiler flags. + + set(ENABLED_SANITIZER false) + # From https://clang.llvm.org/docs/ClangCommandLineReference.html + # -static-libsan Statically link the sanitizer runtime (Not supported for ASan, TSan or UBSan on darwin) + + if(${USE_ASAN}) + set(CXX_FLAGS_EXTRA + ${CXX_FLAGS_EXTRA} # -fsanitize=safe-stack # Can't be used with asan! + -fsanitize=address + -fno-sanitize-recover=address #-fsanitize-cfi # cfi: control flow integrity + -fsanitize-address-use-after-scope + -fsanitize=pointer-compare + -fsanitize=pointer-subtract + # Flags for additional instrumentation not strictly needing asan to be enabled + -fcf-protection=full + -fstack-check + -fstack-protector-all + -fstack-clash-protection + # Not supported by Clang, but supported by GCC + #-fvtable-verify=preinit -fharden-control-flow-redundancy -fhardcfr-check-exceptions + # Other + #-fsanitize-trap=all + ) + set(CMAKE_EXE_LINKER_FLAGS_EXTRA ${CMAKE_EXE_LINKER_FLAGS_EXTRA} -fsanitize=address) + set(PREPROCESSOR_DEFS_EXTRA ${PREPROCESSOR_DEFS_EXTRA} ADDRESS_SANITIZER) + set(ENABLED_SANITIZER true) + endif() + if(${USE_MSAN}) + set(CXX_FLAGS_EXTRA ${CXX_FLAGS_EXTRA} -fsanitize=memory -fsanitize-memory-track-origins=2 -fPIE) + set(CMAKE_EXE_LINKER_FLAGS_EXTRA ${CMAKE_EXE_LINKER_FLAGS_EXTRA} -fsanitize=memory) + set(PREPROCESSOR_DEFS_EXTRA ${PREPROCESSOR_DEFS_EXTRA} MEMORY_SANITIZER) + set(ENABLED_SANITIZER true) + endif() + if(${USE_LSAN}) + set(CXX_FLAGS_EXTRA ${CXX_FLAGS_EXTRA} -fsanitize=leak) + set(CMAKE_EXE_LINKER_FLAGS_EXTRA ${CMAKE_EXE_LINKER_FLAGS_EXTRA} -fsanitize=leak) + set(PREPROCESSOR_DEFS_EXTRA ${PREPROCESSOR_DEFS_EXTRA} LEAK_SANITIZER) + set(ENABLED_SANITIZER true) + endif() + if(${USE_UBSAN}) + set(UBSAN_FLAGS + -fsanitize=undefined,float-divide-by-zero,local-bounds + -fno-sanitize=enum + # Supported? + -fsanitize=unsigned-integer-overflow #Unlike signed integer overflow, this is not undefined behavior, but it is often unintentional. + -fsanitize=implicit-conversion + ) + set(CXX_FLAGS_EXTRA ${CXX_FLAGS_EXTRA} ${UBSAN_FLAGS} -fsanitize=return,vptr) + set(CMAKE_EXE_LINKER_FLAGS_EXTRA ${CMAKE_EXE_LINKER_FLAGS_EXTRA} -fsanitize=undefined) + set(PREPROCESSOR_DEFS_EXTRA ${PREPROCESSOR_DEFS_EXTRA} UNDEFINED_BEHAVIOR_SANITIZER) + set(ENABLED_SANITIZER true) + endif() + + if(${ENABLED_SANITIZER}) + set(PREPROCESSOR_DEFS_EXTRA ${PREPROCESSOR_DEFS_EXTRA} _SANITIZERS) + set(CMAKE_EXE_LINKER_FLAGS_EXTRA + ${CMAKE_EXE_LINKER_FLAGS_EXTRA} + $<$:-static-libsan> + ) + endif() + + #-- Store compiler flags common to all builds. + + set(cxx_local_opts_warnings + -Werror + -Wall + -Wextra + -Wno-unknown-pragmas + -Wno-switch + -Wno-implicit-fallthrough + -Wno-parentheses + -Wno-misleading-indentation + -Wno-conversion-null + -Wno-unused-result + -Wno-format-security # TODO: disable that when we'll have time to fix every printf format issue + # clang-specific: + -Wno-deprecated-declarations # spams so much warnings for the use of sprintf ) - set (CMAKE_EXE_LINKER_FLAGS_EXTRA ${CMAKE_EXE_LINKER_FLAGS_EXTRA} -fsanitize=address ) - SET (PREPROCESSOR_DEFS_EXTRA ${PREPROCESSOR_DEFS_EXTRA} ADDRESS_SANITIZER) - SET (ENABLED_SANITIZER true) - ENDIF () - IF (${USE_MSAN}) - SET (CXX_FLAGS_EXTRA ${CXX_FLAGS_EXTRA} -fsanitize=memory -fsanitize-memory-track-origins=2 -fPIE) - set (CMAKE_EXE_LINKER_FLAGS_EXTRA ${CMAKE_EXE_LINKER_FLAGS_EXTRA} -fsanitize=memory ) - SET (PREPROCESSOR_DEFS_EXTRA ${PREPROCESSOR_DEFS_EXTRA} MEMORY_SANITIZER) - SET (ENABLED_SANITIZER true) - ENDIF () - IF (${USE_LSAN}) - SET (CXX_FLAGS_EXTRA ${CXX_FLAGS_EXTRA} -fsanitize=leak) - set (CMAKE_EXE_LINKER_FLAGS_EXTRA ${CMAKE_EXE_LINKER_FLAGS_EXTRA} -fsanitize=leak ) - SET (PREPROCESSOR_DEFS_EXTRA ${PREPROCESSOR_DEFS_EXTRA} LEAK_SANITIZER) - SET (ENABLED_SANITIZER true) - ENDIF () - IF (${USE_UBSAN}) - SET (UBSAN_FLAGS - -fsanitize=undefined,float-divide-by-zero,local-bounds - -fno-sanitize=enum - # Supported? - -fsanitize=unsigned-integer-overflow #Unlike signed integer overflow, this is not undefined behavior, but it is often unintentional. - -fsanitize=implicit-conversion + set(cxx_local_opts + -std=c++20 + -pthread + -fexceptions + -fnon-call-exceptions + -pipe + -ffast-math + ) + set(cxx_compiler_options_common ${cxx_local_opts_warnings} ${cxx_local_opts} ${CXX_FLAGS_EXTRA}) + + # GCC flags not supported by clang: + # Warnings: "-Wno-nonnull-compare -Wno-maybe-uninitialized" + # Other: "-fno-expensive-optimizations" + + #-- Apply compiler flags, only the ones specific per build type. + + # -fno-omit-frame-pointer disables a good optimization which may corrupt the debugger stack trace. + set(COMPILE_OPTIONS_EXTRA) + if(ENABLED_SANITIZER OR TARGET spheresvr_debug) + set(COMPILE_OPTIONS_EXTRA -fno-omit-frame-pointer -fno-inline) + endif() + if(TARGET spheresvr_release) + target_compile_options(spheresvr_release PUBLIC -O3 ${COMPILE_OPTIONS_EXTRA}) + endif() + if(TARGET spheresvr_nightly) + if(ENABLED_SANITIZER) + target_compile_options(spheresvr_nightly PUBLIC -ggdb3 -O1 ${COMPILE_OPTIONS_EXTRA}) + else() + target_compile_options(spheresvr_nightly PUBLIC -O3 ${COMPILE_OPTIONS_EXTRA}) + endif() + endif() + if(TARGET spheresvr_debug) + target_compile_options(spheresvr_debug PUBLIC -ggdb3 -Og ${COMPILE_OPTIONS_EXTRA}) + endif() + + #-- Store common linker flags. + + if(${USE_MSAN}) + set(CMAKE_EXE_LINKER_FLAGS_EXTRA ${CMAKE_EXE_LINKER_FLAGS_EXTRA} -pie) + endif() + set(cxx_linker_options_common + ${CMAKE_EXE_LINKER_FLAGS_EXTRA} + -pthread + -dynamic + -Wl,-fatal_warnings + $<$: + -static-libstdc++ + -static-libgcc> # no way to statically link against libc + ) + + #-- Apply linker flags, only the ones specific per build type. + # -s got deprecated, we could directly call 'strip' + #IF (TARGET spheresvr_release) + # target_link_options (spheresvr_release PRIVATE -s) + #ENDIF () + #IF (TARGET spheresvr_nightly AND NOT ${ENABLED_SANITIZER}) + # target_link_options (spheresvr_nightly PRIVATE -s) + #ENDIF () + + #-- Store common define macros. + + set(cxx_compiler_definitions_common + ${PREPROCESSOR_DEFS_EXTRA} + $<$>:_GITVERSION> + _EXCEPTIONS_DEBUG + # _EXCEPTIONS_DEBUG: Enable advanced exceptions catching. Consumes some more resources, but is very useful for debug + # on a running environment. Also it makes sphere more stable since exceptions are local. ) - SET (CXX_FLAGS_EXTRA ${CXX_FLAGS_EXTRA} ${UBSAN_FLAGS} -fsanitize=return,vptr) - set (CMAKE_EXE_LINKER_FLAGS_EXTRA ${CMAKE_EXE_LINKER_FLAGS_EXTRA} -fsanitize=undefined) - SET (PREPROCESSOR_DEFS_EXTRA ${PREPROCESSOR_DEFS_EXTRA} UNDEFINED_BEHAVIOR_SANITIZER) - SET (ENABLED_SANITIZER true) - ENDIF () - - IF (${ENABLED_SANITIZER}) - SET (PREPROCESSOR_DEFS_EXTRA ${PREPROCESSOR_DEFS_EXTRA} _SANITIZERS) - set (CMAKE_EXE_LINKER_FLAGS_EXTRA ${CMAKE_EXE_LINKER_FLAGS_EXTRA} $<$:-static-libsan>) - ENDIF () - - - #-- Store compiler flags common to all builds. - - set (cxx_local_opts_warnings - -Werror - -Wall -Wextra -Wno-unknown-pragmas -Wno-switch -Wno-implicit-fallthrough - -Wno-parentheses -Wno-misleading-indentation -Wno-conversion-null -Wno-unused-result - -Wno-format-security # TODO: disable that when we'll have time to fix every printf format issue - # clang-specific: - -Wno-deprecated-declarations # spams so much warnings for the use of sprintf - ) - set (cxx_local_opts - -std=c++20 -pthread -fexceptions -fnon-call-exceptions - -pipe -ffast-math - ) - set (cxx_compiler_options_common ${cxx_local_opts_warnings} ${cxx_local_opts} ${CXX_FLAGS_EXTRA}) - - # GCC flags not supported by clang: - # Warnings: "-Wno-nonnull-compare -Wno-maybe-uninitialized" - # Other: "-fno-expensive-optimizations" - - - #-- Apply compiler flags, only the ones specific per build type. - - # -fno-omit-frame-pointer disables a good optimization which may corrupt the debugger stack trace. - SET (COMPILE_OPTIONS_EXTRA) - IF (ENABLED_SANITIZER OR TARGET spheresvr_debug) - SET (COMPILE_OPTIONS_EXTRA -fno-omit-frame-pointer -fno-inline) - ENDIF () - IF (TARGET spheresvr_release) - TARGET_COMPILE_OPTIONS ( spheresvr_release PUBLIC -O3 ${COMPILE_OPTIONS_EXTRA}) - ENDIF () - IF (TARGET spheresvr_nightly) - IF (ENABLED_SANITIZER) - TARGET_COMPILE_OPTIONS ( spheresvr_nightly PUBLIC -ggdb3 -O1 ${COMPILE_OPTIONS_EXTRA}) - ELSE () - TARGET_COMPILE_OPTIONS ( spheresvr_nightly PUBLIC -O3 ${COMPILE_OPTIONS_EXTRA}) - ENDIF () - ENDIF () - IF (TARGET spheresvr_debug) - TARGET_COMPILE_OPTIONS ( spheresvr_debug PUBLIC -ggdb3 -Og ${COMPILE_OPTIONS_EXTRA}) - ENDIF () - - - #-- Store common linker flags. - - IF (${USE_MSAN}) - set (CMAKE_EXE_LINKER_FLAGS_EXTRA ${CMAKE_EXE_LINKER_FLAGS_EXTRA} -pie) - ENDIF() - set (cxx_linker_options_common ${CMAKE_EXE_LINKER_FLAGS_EXTRA} -pthread -dynamic -Wl,-fatal_warnings - $<$: -static-libstdc++ -static-libgcc> # no way to statically link against libc - ) - - - #-- Apply linker flags, only the ones specific per build type. - # -s got deprecated, we could directly call 'strip' - #IF (TARGET spheresvr_release) - # target_link_options (spheresvr_release PRIVATE -s) - #ENDIF () - #IF (TARGET spheresvr_nightly AND NOT ${ENABLED_SANITIZER}) - # target_link_options (spheresvr_nightly PRIVATE -s) - #ENDIF () - - - #-- Store common define macros. - - set(cxx_compiler_definitions_common - ${PREPROCESSOR_DEFS_EXTRA} - $<$>:_GITVERSION> - _EXCEPTIONS_DEBUG - # _EXCEPTIONS_DEBUG: Enable advanced exceptions catching. Consumes some more resources, but is very useful for debug - # on a running environment. Also it makes sphere more stable since exceptions are local. - ) - - - #-- Apply define macros, only the ones specific per build type. - - IF (TARGET spheresvr_release) - TARGET_COMPILE_DEFINITIONS ( spheresvr_release PUBLIC NDEBUG ) - ENDIF (TARGET spheresvr_release) - IF (TARGET spheresvr_nightly) - TARGET_COMPILE_DEFINITIONS ( spheresvr_nightly PUBLIC NDEBUG THREAD_TRACK_CALLSTACK _NIGHTLYBUILD ) - ENDIF (TARGET spheresvr_nightly) - IF (TARGET spheresvr_debug) - TARGET_COMPILE_DEFINITIONS ( spheresvr_debug PUBLIC _DEBUG THREAD_TRACK_CALLSTACK _PACKETDUMP ) - ENDIF (TARGET spheresvr_debug) - - - #-- Now add back the common compiler options, preprocessor macros, linker options. - - foreach(tgt ${TARGETS}) - target_compile_options (${tgt} PRIVATE ${cxx_compiler_options_common}) - target_compile_definitions (${tgt} PRIVATE ${cxx_compiler_definitions_common}) - target_link_options (${tgt} PRIVATE ${cxx_linker_options_common}) - target_link_libraries (${tgt} PRIVATE ${LIB_mariadb_WITH_PATH} ${LIB_dl_WITH_PATH}) - endforeach() - - #-- Set different output folders for each build type - # (When we'll have support for multi-target builds...) - #SET_TARGET_PROPERTIES(spheresvr PROPERTIES RUNTIME_OUTPUT_RELEASE "${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/Release" ) - #SET_TARGET_PROPERTIES(spheresvr PROPERTIES RUNTIME_OUTPUT_DEBUG "${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/Debug" ) - #SET_TARGET_PROPERTIES(spheresvr PROPERTIES RUNTIME_OUTPUT_NIGHTLY "${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/Nightly" ) + #-- Apply define macros, only the ones specific per build type. + + if(TARGET spheresvr_release) + target_compile_definitions(spheresvr_release PUBLIC NDEBUG) + endif(TARGET spheresvr_release) + if(TARGET spheresvr_nightly) + target_compile_definitions(spheresvr_nightly PUBLIC NDEBUG THREAD_TRACK_CALLSTACK _NIGHTLYBUILD) + endif(TARGET spheresvr_nightly) + if(TARGET spheresvr_debug) + target_compile_definitions(spheresvr_debug PUBLIC _DEBUG THREAD_TRACK_CALLSTACK _PACKETDUMP) + endif(TARGET spheresvr_debug) + + #-- Now add back the common compiler options, preprocessor macros, linker options. + + foreach(tgt ${TARGETS}) + target_compile_options(${tgt} PRIVATE ${cxx_compiler_options_common}) + target_compile_definitions(${tgt} PRIVATE ${cxx_compiler_definitions_common}) + target_link_options(${tgt} PRIVATE ${cxx_linker_options_common}) + target_link_libraries(${tgt} PRIVATE ${LIB_mariadb_WITH_PATH} ${LIB_dl_WITH_PATH}) + endforeach() + + #-- Set different output folders for each build type + # (When we'll have support for multi-target builds...) + #SET_TARGET_PROPERTIES(spheresvr PROPERTIES RUNTIME_OUTPUT_RELEASE "${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/Release" ) + #SET_TARGET_PROPERTIES(spheresvr PROPERTIES RUNTIME_OUTPUT_DEBUG "${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/Debug" ) + #SET_TARGET_PROPERTIES(spheresvr PROPERTIES RUNTIME_OUTPUT_NIGHTLY "${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/Nightly" ) endfunction() diff --git a/cmake/toolchains/include/Windows-Clang_common.inc.cmake b/cmake/toolchains/include/Windows-Clang_common.inc.cmake index 97ae78d1e..aa481a011 100644 --- a/cmake/toolchains/include/Windows-Clang_common.inc.cmake +++ b/cmake/toolchains/include/Windows-Clang_common.inc.cmake @@ -1,138 +1,150 @@ -SET (TOOLCHAIN_LOADED 1) +set(TOOLCHAIN_LOADED 1) -option (CLANG_USE_GCC_LINKER - "NOT CURRENTLY WORKING. By default, Clang requires MSVC (Microsoft's) linker. With this flag, it can be asked to use MinGW-GCC's one." - FALSE +option( + CLANG_USE_GCC_LINKER + "NOT CURRENTLY WORKING. By default, Clang requires MSVC (Microsoft's) linker. With this flag, it can be asked to use MinGW-GCC's one." + FALSE ) +function(toolchain_after_project_common) + enable_language(RC) + include("${CMAKE_SOURCE_DIR}/cmake/CMakeDetectArch.cmake") +endfunction() -function (toolchain_after_project_common) - ENABLE_LANGUAGE(RC) - include ("${CMAKE_SOURCE_DIR}/cmake/CMakeDetectArch.cmake") -endfunction () - - -function (toolchain_exe_stuff_common) - - #-- Configure the Windows application type and add global linker flags. - - IF (${WIN32_SPAWN_CONSOLE}) - SET (PREPROCESSOR_DEFS_EXTRA _WINDOWS_CONSOLE) - IF (${CLANG_USE_GCC_LINKER}) - # --entry might not work - add_link_options ("LINKER:--entry=WinMainCRTStartup") # Handled by is_win32_app_linker -> "LINKER:SHELL:-m$,CONSOLE,WINDOWS>" - ELSE () - add_link_options ("LINKER:/ENTRY:WinMainCRTStartup") # Handled by is_win32_app_linker -> "LINKER:SHELL:/SUBSYSTEM:$,CONSOLE,WINDOWS>" - ENDIF() - ENDIF() - - - #-- Validate sanitizers options and store them between the common compiler flags. - - SET (ENABLED_SANITIZER false) - # From https://clang.llvm.org/docs/ClangCommandLineReference.html - # -static-libsan Statically link the sanitizer runtime (Not supported for ASan, TSan or UBSan on darwin) - - IF (${USE_ASAN}) - SET (CXX_FLAGS_EXTRA ${CXX_FLAGS_EXTRA} # -fsanitize=safe-stack # Can't be used with asan! - -fsanitize=address -fno-sanitize-recover=address #-fsanitize-cfi # cfi: control flow integrity - -fsanitize-address-use-after-scope -fsanitize=pointer-compare -fsanitize=pointer-subtract - # Flags for additional instrumentation not strictly needing asan to be enabled - -fcf-protection=full -fstack-check -fstack-protector-all -fstack-clash-protection - # Not supported by Clang, but supported by GCC - #-fvtable-verify=preinit -fharden-control-flow-redundancy -fhardcfr-check-exceptions - # Other - #-fsanitize-trap=all +function(toolchain_exe_stuff_common) + #-- Configure the Windows application type and add global linker flags. + + if(${WIN32_SPAWN_CONSOLE}) + set(PREPROCESSOR_DEFS_EXTRA _WINDOWS_CONSOLE) + if(${CLANG_USE_GCC_LINKER}) + # --entry might not work + add_link_options("LINKER:--entry=WinMainCRTStartup") # Handled by is_win32_app_linker -> "LINKER:SHELL:-m$,CONSOLE,WINDOWS>" + else() + add_link_options("LINKER:/ENTRY:WinMainCRTStartup") # Handled by is_win32_app_linker -> "LINKER:SHELL:/SUBSYSTEM:$,CONSOLE,WINDOWS>" + endif() + endif() + + #-- Validate sanitizers options and store them between the common compiler flags. + + set(ENABLED_SANITIZER false) + # From https://clang.llvm.org/docs/ClangCommandLineReference.html + # -static-libsan Statically link the sanitizer runtime (Not supported for ASan, TSan or UBSan on darwin) + + if(${USE_ASAN}) + set(CXX_FLAGS_EXTRA + ${CXX_FLAGS_EXTRA} # -fsanitize=safe-stack # Can't be used with asan! + -fsanitize=address + -fno-sanitize-recover=address #-fsanitize-cfi # cfi: control flow integrity + -fsanitize-address-use-after-scope + -fsanitize=pointer-compare + -fsanitize=pointer-subtract + # Flags for additional instrumentation not strictly needing asan to be enabled + -fcf-protection=full + -fstack-check + -fstack-protector-all + -fstack-clash-protection + # Not supported by Clang, but supported by GCC + #-fvtable-verify=preinit -fharden-control-flow-redundancy -fhardcfr-check-exceptions + # Other + #-fsanitize-trap=all + ) + if(${CLANG_USE_GCC_LINKER}) + set(CMAKE_EXE_LINKER_FLAGS_EXTRA ${CMAKE_EXE_LINKER_FLAGS_EXTRA} -fsanitize=address) + endif() + set(PREPROCESSOR_DEFS_EXTRA ${PREPROCESSOR_DEFS_EXTRA} ADDRESS_SANITIZER) + set(ENABLED_SANITIZER true) + endif() + if(${USE_MSAN}) + message(FATAL_ERROR "Windows Clang doesn't yet support MSAN") + set(USE_MSAN false) + #SET (CXX_FLAGS_EXTRA ${CXX_FLAGS_EXTRA} -fsanitize=memory -fsanitize-memory-track-origins=2 -fPIE) + #IF (${CLANG_USE_GCC_LINKER}) + #set (CMAKE_EXE_LINKER_FLAGS_EXTRA ${CMAKE_EXE_LINKER_FLAGS_EXTRA} -fsanitize=memory) + #ENDIF + #SET (PREPROCESSOR_DEFS_EXTRA ${PREPROCESSOR_DEFS_EXTRA} MEMORY_SANITIZER) + #SET (ENABLED_SANITIZER true) + endif() + if(${USE_LSAN}) + message(FATAL_ERROR "Windows Clang doesn't yet support LSAN") + set(USE_LSAN false) + #SET (CXX_FLAGS_EXTRA ${CXX_FLAGS_EXTRA} -fsanitize=leak) + #IF (${CLANG_USE_GCC_LINKER}) + #set (CMAKE_EXE_LINKER_FLAGS_EXTRA ${CMAKE_EXE_LINKER_FLAGS_EXTRA} -fsanitize=leak) + #ENDIF + #SET (PREPROCESSOR_DEFS_EXTRA ${PREPROCESSOR_DEFS_EXTRA} LEAK_SANITIZER) + #SET (ENABLED_SANITIZER true) + endif() + if(${USE_UBSAN}) + set(UBSAN_FLAGS + -fsanitize=undefined,float-divide-by-zero,local-bounds + -fno-sanitize=enum + # Supported? + -fsanitize=unsigned-integer-overflow #Unlike signed integer overflow, this is not undefined behavior, but it is often unintentional. + -fsanitize=implicit-conversion + ) + set(CXX_FLAGS_EXTRA ${CXX_FLAGS_EXTRA} ${UBSAN_FLAGS} -fsanitize=return) + #IF (${CLANG_USE_GCC_LINKER}) + #set (CMAKE_EXE_LINKER_FLAGS_EXTRA ${CMAKE_EXE_LINKER_FLAGS_EXTRA} -fsanitize=undefined) + #ENDIF + set(PREPROCESSOR_DEFS_EXTRA ${PREPROCESSOR_DEFS_EXTRA} UNDEFINED_BEHAVIOR_SANITIZER) + set(ENABLED_SANITIZER true) + endif() + + if(${ENABLED_SANITIZER}) + set(PREPROCESSOR_DEFS_EXTRA ${PREPROCESSOR_DEFS_EXTRA} _SANITIZERS) + if(${RUNTIME_STATIC_LINK}) + set(CMAKE_EXE_LINKER_FLAGS_EXTRA ${CMAKE_EXE_LINKER_FLAGS_EXTRA} -static-libsan) + else() + set(CMAKE_EXE_LINKER_FLAGS_EXTRA ${CMAKE_EXE_LINKER_FLAGS_EXTRA} -shared-libsan) + endif() + endif() + + #-- Store compiler flags common to all builds. + + set(cxx_local_opts_warnings + -Werror + -Wall + -Wextra + -Wno-unknown-pragmas + -Wno-switch + -Wno-implicit-fallthrough + -Wno-parentheses + -Wno-misleading-indentation + -Wno-conversion-null + -Wno-unused-result + -Wno-format-security # TODO: disable that when we'll have time to fix every printf format issue + # clang -specific: + # -fforce-emit-vtables ) - IF (${CLANG_USE_GCC_LINKER}) - set (CMAKE_EXE_LINKER_FLAGS_EXTRA ${CMAKE_EXE_LINKER_FLAGS_EXTRA} -fsanitize=address) - ENDIF () - SET (PREPROCESSOR_DEFS_EXTRA ${PREPROCESSOR_DEFS_EXTRA} ADDRESS_SANITIZER) - SET (ENABLED_SANITIZER true) - ENDIF () - IF (${USE_MSAN}) - MESSAGE (FATAL_ERROR "Windows Clang doesn't yet support MSAN") - SET (USE_MSAN false) - #SET (CXX_FLAGS_EXTRA ${CXX_FLAGS_EXTRA} -fsanitize=memory -fsanitize-memory-track-origins=2 -fPIE) - #IF (${CLANG_USE_GCC_LINKER}) - #set (CMAKE_EXE_LINKER_FLAGS_EXTRA ${CMAKE_EXE_LINKER_FLAGS_EXTRA} -fsanitize=memory) - #ENDIF - #SET (PREPROCESSOR_DEFS_EXTRA ${PREPROCESSOR_DEFS_EXTRA} MEMORY_SANITIZER) - #SET (ENABLED_SANITIZER true) - ENDIF () - IF (${USE_LSAN}) - MESSAGE (FATAL_ERROR "Windows Clang doesn't yet support LSAN") - SET (USE_LSAN false) - #SET (CXX_FLAGS_EXTRA ${CXX_FLAGS_EXTRA} -fsanitize=leak) - #IF (${CLANG_USE_GCC_LINKER}) - #set (CMAKE_EXE_LINKER_FLAGS_EXTRA ${CMAKE_EXE_LINKER_FLAGS_EXTRA} -fsanitize=leak) - #ENDIF - #SET (PREPROCESSOR_DEFS_EXTRA ${PREPROCESSOR_DEFS_EXTRA} LEAK_SANITIZER) - #SET (ENABLED_SANITIZER true) - ENDIF () - IF (${USE_UBSAN}) - SET (UBSAN_FLAGS - -fsanitize=undefined,float-divide-by-zero,local-bounds - -fno-sanitize=enum - # Supported? - -fsanitize=unsigned-integer-overflow #Unlike signed integer overflow, this is not undefined behavior, but it is often unintentional. - -fsanitize=implicit-conversion + set(cxx_local_opts + -std=c++20 + -fexceptions + -fnon-call-exceptions + -pipe + -ffast-math + -mno-ms-bitfields + # -mno-ms-bitfields is needed to fix structure packing; + # -pthread unused here? we only need to specify that to the linker? + -Wno-format-security # TODO: disable that when we'll have time to fix every printf format issue + # clang-specific: + # + # Flags supported by GCC but not by Clang: -fno-expensive-optimizations, -Wno-error=maybe-uninitialized ) - SET (CXX_FLAGS_EXTRA ${CXX_FLAGS_EXTRA} ${UBSAN_FLAGS} -fsanitize=return) - #IF (${CLANG_USE_GCC_LINKER}) - #set (CMAKE_EXE_LINKER_FLAGS_EXTRA ${CMAKE_EXE_LINKER_FLAGS_EXTRA} -fsanitize=undefined) - #ENDIF - SET (PREPROCESSOR_DEFS_EXTRA ${PREPROCESSOR_DEFS_EXTRA} UNDEFINED_BEHAVIOR_SANITIZER) - SET (ENABLED_SANITIZER true) - ENDIF () - - IF (${ENABLED_SANITIZER}) - SET (PREPROCESSOR_DEFS_EXTRA ${PREPROCESSOR_DEFS_EXTRA} _SANITIZERS) - if (${RUNTIME_STATIC_LINK}) - set (CMAKE_EXE_LINKER_FLAGS_EXTRA ${CMAKE_EXE_LINKER_FLAGS_EXTRA} -static-libsan) - else () - set (CMAKE_EXE_LINKER_FLAGS_EXTRA ${CMAKE_EXE_LINKER_FLAGS_EXTRA} -shared-libsan) - endif () - ENDIF () - - - #-- Store compiler flags common to all builds. - - SET (cxx_local_opts_warnings - -Werror - -Wall -Wextra -Wno-unknown-pragmas -Wno-switch -Wno-implicit-fallthrough - -Wno-parentheses -Wno-misleading-indentation -Wno-conversion-null -Wno-unused-result - -Wno-format-security # TODO: disable that when we'll have time to fix every printf format issue - - # clang -specific: - # -fforce-emit-vtables - ) - SET (cxx_local_opts - -std=c++20 -fexceptions -fnon-call-exceptions - -pipe -ffast-math - -mno-ms-bitfields - # -mno-ms-bitfields is needed to fix structure packing; - # -pthread unused here? we only need to specify that to the linker? - -Wno-format-security # TODO: disable that when we'll have time to fix every printf format issue - - # clang-specific: - # - - # Flags supported by GCC but not by Clang: -fno-expensive-optimizations, -Wno-error=maybe-uninitialized - ) - set (cxx_compiler_options_common ${cxx_local_opts_warnings} ${cxx_local_opts} ${CXX_FLAGS_EXTRA}) - - - #-- Apply compiler flags, only the ones specific per build type. - - # -fno-omit-frame-pointer disables a good optimization which may corrupt the debugger stack trace. - SET (COMPILE_OPTIONS_EXTRA) - IF (ENABLED_SANITIZER OR TARGET spheresvr_debug) - SET (COMPILE_OPTIONS_EXTRA -fno-omit-frame-pointer -fno-inline) - ENDIF () - IF (TARGET spheresvr_release) - TARGET_COMPILE_OPTIONS ( spheresvr_release PUBLIC -O3 -flto=full -fvirtual-function-elimination ${COMPILE_OPTIONS_EXTRA}) - #[[ + set(cxx_compiler_options_common ${cxx_local_opts_warnings} ${cxx_local_opts} ${CXX_FLAGS_EXTRA}) + + #-- Apply compiler flags, only the ones specific per build type. + + # -fno-omit-frame-pointer disables a good optimization which may corrupt the debugger stack trace. + set(COMPILE_OPTIONS_EXTRA) + if(ENABLED_SANITIZER OR TARGET spheresvr_debug) + set(COMPILE_OPTIONS_EXTRA -fno-omit-frame-pointer -fno-inline) + endif() + if(TARGET spheresvr_release) + target_compile_options( + spheresvr_release + PUBLIC -O3 -flto=full -fvirtual-function-elimination ${COMPILE_OPTIONS_EXTRA} + ) + #[[ IF (NOT ${CLANG_USE_GCC_LINKER}) if (${RUNTIME_STATIC_LINK}) TARGET_COMPILE_OPTIONS ( spheresvr_release PUBLIC /MT ) @@ -141,14 +153,17 @@ function (toolchain_exe_stuff_common) endif () endif () ]] - ENDIF () - IF (TARGET spheresvr_nightly) - IF (ENABLED_SANITIZER) - TARGET_COMPILE_OPTIONS ( spheresvr_nightly PUBLIC -ggdb3 -O1 ${COMPILE_OPTIONS_EXTRA} ) - ELSE () - TARGET_COMPILE_OPTIONS ( spheresvr_nightly PUBLIC -O3 -flto=full -fvirtual-function-elimination ${COMPILE_OPTIONS_EXTRA} ) - ENDIF () - #[[ + endif() + if(TARGET spheresvr_nightly) + if(ENABLED_SANITIZER) + target_compile_options(spheresvr_nightly PUBLIC -ggdb3 -O1 ${COMPILE_OPTIONS_EXTRA}) + else() + target_compile_options( + spheresvr_nightly + PUBLIC -O3 -flto=full -fvirtual-function-elimination ${COMPILE_OPTIONS_EXTRA} + ) + endif() + #[[ IF (NOT ${CLANG_USE_GCC_LINKER}) if (${RUNTIME_STATIC_LINK}) TARGET_COMPILE_OPTIONS ( spheresvr_nightly PUBLIC /MT ) @@ -157,10 +172,10 @@ function (toolchain_exe_stuff_common) endif () endif () ]] - ENDIF () - IF (TARGET spheresvr_debug) - TARGET_COMPILE_OPTIONS ( spheresvr_debug PUBLIC -ggdb3 -Og ) - #[[ + endif() + if(TARGET spheresvr_debug) + target_compile_options(spheresvr_debug PUBLIC -ggdb3 -Og) + #[[ IF (NOT ${CLANG_USE_GCC_LINKER}) if (${RUNTIME_STATIC_LINK}) TARGET_COMPILE_OPTIONS ( spheresvr_debug PUBLIC /MTd ) @@ -169,22 +184,21 @@ function (toolchain_exe_stuff_common) endif () endif () ]] - ENDIF () - + endif() - #-- Store common linker flags. + #-- Store common linker flags. - IF (${USE_MSAN}) - SET (CMAKE_EXE_LINKER_FLAGS_EXTRA ${CMAKE_EXE_LINKER_FLAGS_EXTRA} -pie) - ENDIF() + if(${USE_MSAN}) + set(CMAKE_EXE_LINKER_FLAGS_EXTRA ${CMAKE_EXE_LINKER_FLAGS_EXTRA} -pie) + endif() - set (cxx_linker_options_common ${CMAKE_EXE_LINKER_FLAGS_EXTRA}) - if (${CLANG_USE_GCC_LINKER}) - set (cxx_linker_options_common ${cxx_linker_options_common} -pthread -dynamic -Wl,--fatal-warnings) - if (${RUNTIME_STATIC_LINK}) - set (cxx_linker_options_common ${cxx_linker_options_common} -static-libstdc++ -static-libgcc) # no way to statically link against libc? maybe we can on windows? - endif () -#[[ + set(cxx_linker_options_common ${CMAKE_EXE_LINKER_FLAGS_EXTRA}) + if(${CLANG_USE_GCC_LINKER}) + set(cxx_linker_options_common ${cxx_linker_options_common} -pthread -dynamic -Wl,--fatal-warnings) + if(${RUNTIME_STATIC_LINK}) + set(cxx_linker_options_common ${cxx_linker_options_common} -static-libstdc++ -static-libgcc) # no way to statically link against libc? maybe we can on windows? + endif() + #[[ else () if (${RUNTIME_STATIC_LINK}) set (cxx_linker_options_common ${cxx_linker_options_common} /MTd ) @@ -192,61 +206,58 @@ function (toolchain_exe_stuff_common) set (cxx_linker_options_common ${cxx_linker_options_common} /MDd ) endif () ]] - endif () - - #-- Store common define macros. - - set(cxx_compiler_definitions_common - ${PREPROCESSOR_DEFS_EXTRA} - _EXCEPTIONS_DEBUG - # _EXCEPTIONS_DEBUG: Enable advanced exceptions catching. Consumes some more resources, but is very useful for debug - # on a running environment. Also it makes sphere more stable since exceptions are local. - _CRT_SECURE_NO_WARNINGS - # _CRT_SECURE_NO_WARNINGS: Temporary setting to do not spam so much in the build proccess while we get rid of -W4 warnings and, after it, -Wall. - _WINSOCK_DEPRECATED_NO_WARNINGS - # _WINSOCK_DEPRECATED_NO_WARNINGS: Removing warnings until the code gets updated or reviewed. - ) - if (NOT ${CMAKE_NO_GIT_REVISION}) - set(cxx_compiler_definitions_common ${cxx_compiler_definitions_common} _GITVERSION) - endif () - - - #-- Apply define macros, only the ones specific per build type. - - IF (TARGET spheresvr_release) - target_compile_definitions ( spheresvr_release PUBLIC NDEBUG THREAD_TRACK_CALLSTACK ) - ENDIF () - IF (TARGET spheresvr_nightly) - target_compile_definitions ( spheresvr_nightly PUBLIC NDEBUG THREAD_TRACK_CALLSTACK _NIGHTLYBUILD ) - ENDIF () - IF (TARGET spheresvr_debug) - target_compile_definitions ( spheresvr_debug PUBLIC _DEBUG THREAD_TRACK_CALLSTACK _PACKETDUMP ) - IF (USE_ASAN AND NOT CLANG_USE_GCC_LINKER) - target_compile_definitions ( spheresvr_debug PUBLIC _HAS_ITERATOR_DEBUGGING=0 _ITERATOR_DEBUG_LEVEL=0 ) - ENDIF() - ENDIF () - - - #-- Apply linker options, only the ones specific per build type. - - #if (NOT ${CLANG_USE_GCC_LINKER}) - # IF (TARGET spheresvr_release) - # target_link_options ( spheresvr_release PUBLIC "LINKER:SHELL:" ) - # ENDIF () - # IF (TARGET spheresvr_nightly) - # target_link_options ( spheresvr_nightly PUBLIC "LINKER:SHELL:" ) - # ENDIF () - # IF (TARGET spheresvr_debug) - # target_link_options ( spheresvr_debug PUBLIC "LINKER:/DEBUG" ) - # ENDIF () - #endif () - - - #-- Now add back the common compiler options, preprocessor macros, linker targets and options. - - if (NOT ${CLANG_USE_GCC_LINKER}) - set (libs_prefix lib) -#[[ + endif() + + #-- Store common define macros. + + set(cxx_compiler_definitions_common + ${PREPROCESSOR_DEFS_EXTRA} + _EXCEPTIONS_DEBUG + # _EXCEPTIONS_DEBUG: Enable advanced exceptions catching. Consumes some more resources, but is very useful for debug + # on a running environment. Also it makes sphere more stable since exceptions are local. + _CRT_SECURE_NO_WARNINGS + # _CRT_SECURE_NO_WARNINGS: Temporary setting to do not spam so much in the build proccess while we get rid of -W4 warnings and, after it, -Wall. + _WINSOCK_DEPRECATED_NO_WARNINGS + # _WINSOCK_DEPRECATED_NO_WARNINGS: Removing warnings until the code gets updated or reviewed. + ) + if(NOT ${CMAKE_NO_GIT_REVISION}) + set(cxx_compiler_definitions_common ${cxx_compiler_definitions_common} _GITVERSION) + endif() + + #-- Apply define macros, only the ones specific per build type. + + if(TARGET spheresvr_release) + target_compile_definitions(spheresvr_release PUBLIC NDEBUG THREAD_TRACK_CALLSTACK) + endif() + if(TARGET spheresvr_nightly) + target_compile_definitions(spheresvr_nightly PUBLIC NDEBUG THREAD_TRACK_CALLSTACK _NIGHTLYBUILD) + endif() + if(TARGET spheresvr_debug) + target_compile_definitions(spheresvr_debug PUBLIC _DEBUG THREAD_TRACK_CALLSTACK _PACKETDUMP) + if(USE_ASAN AND NOT CLANG_USE_GCC_LINKER) + target_compile_definitions(spheresvr_debug PUBLIC _HAS_ITERATOR_DEBUGGING=0 _ITERATOR_DEBUG_LEVEL=0) + endif() + endif() + + #-- Apply linker options, only the ones specific per build type. + + #if (NOT ${CLANG_USE_GCC_LINKER}) + # IF (TARGET spheresvr_release) + # target_link_options ( spheresvr_release PUBLIC "LINKER:SHELL:" ) + # ENDIF () + # IF (TARGET spheresvr_nightly) + # target_link_options ( spheresvr_nightly PUBLIC "LINKER:SHELL:" ) + # ENDIF () + # IF (TARGET spheresvr_debug) + # target_link_options ( spheresvr_debug PUBLIC "LINKER:/DEBUG" ) + # ENDIF () + #endif () + + #-- Now add back the common compiler options, preprocessor macros, linker targets and options. + + if(NOT ${CLANG_USE_GCC_LINKER}) + set(libs_prefix lib) + #[[ if (ENABLED_SANITIZER) # one should add to the linker path its LLVM lib folder... if (ARCH_BITS EQUAL 64) @@ -272,21 +283,19 @@ function (toolchain_exe_stuff_common) endif() endif () ]] - endif() - set (libs_to_link_against ${libs_to_link_against} ws2_32 ${libs_prefix}mariadb) - - foreach(tgt ${TARGETS}) - target_compile_options (${tgt} PRIVATE ${cxx_compiler_options_common}) - target_compile_definitions (${tgt} PRIVATE ${cxx_compiler_definitions_common}) - target_link_options (${tgt} PRIVATE LINKER:${cxx_linker_options_common}) - target_link_libraries (${tgt} PRIVATE ${libs_to_link_against}) - endforeach() - - - #-- Set different output folders for each build type - # (When we'll have support for multi-target builds...) - #SET_TARGET_PROPERTIES(spheresvr PROPERTIES RUNTIME_OUTPUT_RELEASE "${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/Release" ) - #SET_TARGET_PROPERTIES(spheresvr PROPERTIES RUNTIME_OUTPUT_DEBUG "${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/Debug" ) - #SET_TARGET_PROPERTIES(spheresvr PROPERTIES RUNTIME_OUTPUT_NIGHTLY "${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/Nightly" ) - + endif() + set(libs_to_link_against ${libs_to_link_against} ws2_32 ${libs_prefix}mariadb) + + foreach(tgt ${TARGETS}) + target_compile_options(${tgt} PRIVATE ${cxx_compiler_options_common}) + target_compile_definitions(${tgt} PRIVATE ${cxx_compiler_definitions_common}) + target_link_options(${tgt} PRIVATE LINKER:${cxx_linker_options_common}) + target_link_libraries(${tgt} PRIVATE ${libs_to_link_against}) + endforeach() + + #-- Set different output folders for each build type + # (When we'll have support for multi-target builds...) + #SET_TARGET_PROPERTIES(spheresvr PROPERTIES RUNTIME_OUTPUT_RELEASE "${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/Release" ) + #SET_TARGET_PROPERTIES(spheresvr PROPERTIES RUNTIME_OUTPUT_DEBUG "${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/Debug" ) + #SET_TARGET_PROPERTIES(spheresvr PROPERTIES RUNTIME_OUTPUT_NIGHTLY "${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/Nightly" ) endfunction() diff --git a/cmake/toolchains/include/Windows-GNU_common.inc.cmake b/cmake/toolchains/include/Windows-GNU_common.inc.cmake index 3a5fd6cf9..52a4c0379 100644 --- a/cmake/toolchains/include/Windows-GNU_common.inc.cmake +++ b/cmake/toolchains/include/Windows-GNU_common.inc.cmake @@ -1,32 +1,28 @@ -SET (TOOLCHAIN_LOADED 1) +set(TOOLCHAIN_LOADED 1) +function(toolchain_after_project_common) + enable_language(RC) + include("${CMAKE_SOURCE_DIR}/cmake/CMakeDetectArch.cmake") +endfunction() -function (toolchain_after_project_common) - ENABLE_LANGUAGE(RC) - include ("${CMAKE_SOURCE_DIR}/cmake/CMakeDetectArch.cmake") -endfunction () - - -function (toolchain_exe_stuff_common) - - #-- Configure the Windows application type. - - # Subsystem is already managed by is_win32_app_linker. GCC doesn't need us to specify the entry point. - #IF (${WIN32_SPAWN_CONSOLE}) - # add_link_options ("LINKER:SHELL:-mconsole") - # SET (PREPROCESSOR_DEFS_EXTRA _WINDOWS_CONSOLE) - ##ELSE () - ## add_link_options ("LINKER:SHELL:-mwindows") - #ENDIF () +function(toolchain_exe_stuff_common) + #-- Configure the Windows application type. + # Subsystem is already managed by is_win32_app_linker. GCC doesn't need us to specify the entry point. + #IF (${WIN32_SPAWN_CONSOLE}) + # add_link_options ("LINKER:SHELL:-mconsole") + # SET (PREPROCESSOR_DEFS_EXTRA _WINDOWS_CONSOLE) + ##ELSE () + ## add_link_options ("LINKER:SHELL:-mwindows") + #ENDIF () - #-- Validate sanitizers options and store them between the common compiler flags. + #-- Validate sanitizers options and store them between the common compiler flags. - SET (ENABLED_SANITIZER false) - IF (${USE_ASAN}) - MESSAGE (FATAL_ERROR "MinGW-GCC doesn't yet support ASAN") - SET (USE_ASAN false) - #[[ + set(ENABLED_SANITIZER false) + if(${USE_ASAN}) + message(FATAL_ERROR "MinGW-GCC doesn't yet support ASAN") + set(USE_ASAN false) + #[[ SET (CXX_FLAGS_EXTRA ${CXX_FLAGS_EXTRA} -fsanitize=address -fno-sanitize-recover=address #-fsanitize-cfi # cfi: control flow integrity, not currently supported by GCC (even on Linux) -fsanitize-address-use-after-scope -fsanitize=pointer-compare -fsanitize=pointer-subtract @@ -40,30 +36,30 @@ function (toolchain_exe_stuff_common) #-fsanitize-trap=all ) ]] - #set (CMAKE_EXE_LINKER_FLAGS_EXTRA ${CMAKE_EXE_LINKER_FLAGS_EXTRA} -fsanitize=address $<$:-static-libasan>) - #SET (PREPROCESSOR_DEFS_EXTRA ${PREPROCESSOR_DEFS_EXTRA} ADDRESS_SANITIZER) - #SET (ENABLED_SANITIZER true) - ENDIF () - IF (${USE_MSAN}) - MESSAGE (FATAL_ERROR "MinGW-GCC doesn't yet support MSAN") - SET (USE_MSAN false) - #SET (CXX_FLAGS_EXTRA ${CXX_FLAGS_EXTRA} -fsanitize=memory -fsanitize-memory-track-origins=2 -fPIE) - #set (CMAKE_EXE_LINKER_FLAGS_EXTRA ${CMAKE_EXE_LINKER_FLAGS_EXTRA} -fsanitize=memory )#$<$:-static-libmsan>) - #SET (PREPROCESSOR_DEFS_EXTRA ${PREPROCESSOR_DEFS_EXTRA} MEMORY_SANITIZER) - #SET (ENABLED_SANITIZER true) - ENDIF () - IF (${USE_LSAN}) - MESSAGE (FATAL_ERROR "MinGW-GCC doesn't yet support LSAN") - SET (USE_LSAN false) - #SET (CXX_FLAGS_EXTRA ${CXX_FLAGS_EXTRA} -fsanitize=leak) - #set (CMAKE_EXE_LINKER_FLAGS_EXTRA ${CMAKE_EXE_LINKER_FLAGS_EXTRA} -fsanitize=leak #$<$:-static-liblsan>) - #SET (PREPROCESSOR_DEFS_EXTRA ${PREPROCESSOR_DEFS_EXTRA} LEAK_SANITIZER) - #SET (ENABLED_SANITIZER true) - ENDIF () - IF (${USE_UBSAN}) - MESSAGE (FATAL_ERROR "MinGW-GCC doesn't yet support UBSAN") - SET (USE_UBSAN false) - #[[ + #set (CMAKE_EXE_LINKER_FLAGS_EXTRA ${CMAKE_EXE_LINKER_FLAGS_EXTRA} -fsanitize=address $<$:-static-libasan>) + #SET (PREPROCESSOR_DEFS_EXTRA ${PREPROCESSOR_DEFS_EXTRA} ADDRESS_SANITIZER) + #SET (ENABLED_SANITIZER true) + endif() + if(${USE_MSAN}) + message(FATAL_ERROR "MinGW-GCC doesn't yet support MSAN") + set(USE_MSAN false) + #SET (CXX_FLAGS_EXTRA ${CXX_FLAGS_EXTRA} -fsanitize=memory -fsanitize-memory-track-origins=2 -fPIE) + #set (CMAKE_EXE_LINKER_FLAGS_EXTRA ${CMAKE_EXE_LINKER_FLAGS_EXTRA} -fsanitize=memory )#$<$:-static-libmsan>) + #SET (PREPROCESSOR_DEFS_EXTRA ${PREPROCESSOR_DEFS_EXTRA} MEMORY_SANITIZER) + #SET (ENABLED_SANITIZER true) + endif() + if(${USE_LSAN}) + message(FATAL_ERROR "MinGW-GCC doesn't yet support LSAN") + set(USE_LSAN false) + #SET (CXX_FLAGS_EXTRA ${CXX_FLAGS_EXTRA} -fsanitize=leak) + #set (CMAKE_EXE_LINKER_FLAGS_EXTRA ${CMAKE_EXE_LINKER_FLAGS_EXTRA} -fsanitize=leak #$<$:-static-liblsan>) + #SET (PREPROCESSOR_DEFS_EXTRA ${PREPROCESSOR_DEFS_EXTRA} LEAK_SANITIZER) + #SET (ENABLED_SANITIZER true) + endif() + if(${USE_UBSAN}) + message(FATAL_ERROR "MinGW-GCC doesn't yet support UBSAN") + set(USE_UBSAN false) + #[[ SET (UBSAN_FLAGS -fsanitize=undefined,float-divide-by-zero -fno-sanitize=enum @@ -72,109 +68,119 @@ function (toolchain_exe_stuff_common) #-fsanitize=implicit-conversion, local-bounds ) ]] - #SET (CXX_FLAGS_EXTRA ${CXX_FLAGS_EXTRA} ${UBSAN_FLAGS} -fsanitize=return,vptr) - #set (CMAKE_EXE_LINKER_FLAGS_EXTRA ${CMAKE_EXE_LINKER_FLAGS_EXTRA} -fsanitize=undefined #$<$:-static-libubsan>) - #SET (PREPROCESSOR_DEFS_EXTRA ${PREPROCESSOR_DEFS_EXTRA} UNDEFINED_BEHAVIOR_SANITIZER) - #SET (ENABLED_SANITIZER true) - ENDIF () - - #IF (${ENABLED_SANITIZER}) - # SET (PREPROCESSOR_DEFS_EXTRA ${PREPROCESSOR_DEFS_EXTRA} _SANITIZERS) - #ENDIF () - - - #-- Store compiler flags common to all builds. - - set (cxx_local_opts_warnings - -Werror - -Wall -Wextra -Wno-nonnull-compare -Wno-unknown-pragmas -Wno-switch -Wno-implicit-fallthrough - -Wno-parentheses -Wno-misleading-indentation -Wno-conversion-null -Wno-unused-result - -Wno-format-security # TODO: disable that when we'll have time to fix every printf format issue - ) - set (cxx_local_opts - -std=c++20 -pthread -fexceptions -fnon-call-exceptions -mno-ms-bitfields - # -mno-ms-bitfields is needed to fix structure packing - -pipe -ffast-math - ) - - set (cxx_compiler_options_common ${cxx_local_opts_warnings} ${cxx_local_opts} ${CXX_FLAGS_EXTRA}) - - - #-- Apply compiler flags, only the ones specific per build type. - - # -fno-omit-frame-pointer disables a good optimization which may corrupt the debugger stack trace. - SET (COMPILE_OPTIONS_EXTRA) - IF (ENABLED_SANITIZER OR TARGET spheresvr_debug) - SET (COMPILE_OPTIONS_EXTRA -fno-omit-frame-pointer -fno-inline) - ENDIF () - IF (TARGET spheresvr_release) - TARGET_COMPILE_OPTIONS ( spheresvr_release PUBLIC -s -O3 ${COMPILE_OPTIONS_EXTRA}) - ENDIF () - IF (TARGET spheresvr_nightly) - IF (ENABLED_SANITIZER) - TARGET_COMPILE_OPTIONS ( spheresvr_nightly PUBLIC -ggdb3 -O1 ${COMPILE_OPTIONS_EXTRA}) - ELSE () - TARGET_COMPILE_OPTIONS ( spheresvr_nightly PUBLIC -O3 ${COMPILE_OPTIONS_EXTRA}) - ENDIF () - ENDIF () - IF (TARGET spheresvr_debug) - TARGET_COMPILE_OPTIONS ( spheresvr_debug PUBLIC -ggdb3 -Og ${COMPILE_OPTIONS_EXTRA}) - ENDIF () - - - #-- Store common linker flags. - - IF (${USE_MSAN}) - SET (CMAKE_EXE_LINKER_FLAGS_EXTRA ${CMAKE_EXE_LINKER_FLAGS_EXTRA} -pie) - ENDIF() - set (cxx_linker_options_common ${CMAKE_EXE_LINKER_FLAGS_EXTRA} -pthread -dynamic -Wl,--fatal-warnings - $<$: -static-libstdc++ -static-libgcc> # no way to statically link against libc? maybe we can on windows? - ) - - - #-- Store common define macros. - - set (cxx_compiler_definitions_common - ${PREPROCESSOR_DEFS_EXTRA} - $<$>:_GITVERSION> - _EXCEPTIONS_DEBUG - # _EXCEPTIONS_DEBUG: Enable advanced exceptions catching. Consumes some more resources, but is very useful for debug - # on a running environment. Also it makes sphere more stable since exceptions are local. - _CRT_SECURE_NO_WARNINGS - # _CRT_SECURE_NO_WARNINGS: Temporary setting to do not spam so much in the build proccess while we get rid of -W4 warnings and, after it, -Wall. - _WINSOCK_DEPRECATED_NO_WARNINGS - # _WINSOCK_DEPRECATED_NO_WARNINGS: Removing warnings until the code gets updated or reviewed. - ) - - - #-- Apply define macros, only the ones specific per build type. - - IF (TARGET spheresvr_release) - TARGET_COMPILE_DEFINITIONS ( spheresvr_release PUBLIC NDEBUG THREAD_TRACK_CALLSTACK ) - ENDIF () - IF (TARGET spheresvr_nightly) - TARGET_COMPILE_DEFINITIONS ( spheresvr_nightly PUBLIC NDEBUG THREAD_TRACK_CALLSTACK _NIGHTLYBUILD ) - ENDIF () - IF (TARGET spheresvr_debug) - TARGET_COMPILE_DEFINITIONS ( spheresvr_debug PUBLIC _DEBUG THREAD_TRACK_CALLSTACK _PACKETDUMP ) - ENDIF () - - - #-- Now apply the common compiler options, preprocessor macros, linker options. - - foreach(tgt ${TARGETS}) - target_compile_options (${tgt} PRIVATE ${cxx_compiler_options_common}) - target_compile_definitions (${tgt} PRIVATE ${cxx_compiler_definitions_common}) - target_link_options (${tgt} PRIVATE ${cxx_linker_options_common}) - target_link_libraries (${tgt} PRIVATE mariadb ws2_32) - endforeach() - - - - #-- Set different output folders for each build type - # (When we'll have support for multi-target builds...) - #SET_TARGET_PROPERTIES(spheresvr PROPERTIES RUNTIME_OUTPUT_RELEASE "${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/Release" ) - #SET_TARGET_PROPERTIES(spheresvr PROPERTIES RUNTIME_OUTPUT_DEBUG "${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/Debug" ) - #SET_TARGET_PROPERTIES(spheresvr PROPERTIES RUNTIME_OUTPUT_NIGHTLY "${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/Nightly" ) + #SET (CXX_FLAGS_EXTRA ${CXX_FLAGS_EXTRA} ${UBSAN_FLAGS} -fsanitize=return,vptr) + #set (CMAKE_EXE_LINKER_FLAGS_EXTRA ${CMAKE_EXE_LINKER_FLAGS_EXTRA} -fsanitize=undefined #$<$:-static-libubsan>) + #SET (PREPROCESSOR_DEFS_EXTRA ${PREPROCESSOR_DEFS_EXTRA} UNDEFINED_BEHAVIOR_SANITIZER) + #SET (ENABLED_SANITIZER true) + endif() + + #IF (${ENABLED_SANITIZER}) + # SET (PREPROCESSOR_DEFS_EXTRA ${PREPROCESSOR_DEFS_EXTRA} _SANITIZERS) + #ENDIF () + + #-- Store compiler flags common to all builds. + + set(cxx_local_opts_warnings + -Werror + -Wall + -Wextra + -Wno-nonnull-compare + -Wno-unknown-pragmas + -Wno-switch + -Wno-implicit-fallthrough + -Wno-parentheses + -Wno-misleading-indentation + -Wno-conversion-null + -Wno-unused-result + -Wno-format-security # TODO: disable that when we'll have time to fix every printf format issue + ) + set(cxx_local_opts + -std=c++20 + -pthread + -fexceptions + -fnon-call-exceptions + -mno-ms-bitfields + # -mno-ms-bitfields is needed to fix structure packing + -pipe + -ffast-math + ) + + set(cxx_compiler_options_common ${cxx_local_opts_warnings} ${cxx_local_opts} ${CXX_FLAGS_EXTRA}) + + #-- Apply compiler flags, only the ones specific per build type. + + # -fno-omit-frame-pointer disables a good optimization which may corrupt the debugger stack trace. + set(COMPILE_OPTIONS_EXTRA) + if(ENABLED_SANITIZER OR TARGET spheresvr_debug) + set(COMPILE_OPTIONS_EXTRA -fno-omit-frame-pointer -fno-inline) + endif() + if(TARGET spheresvr_release) + target_compile_options(spheresvr_release PUBLIC -s -O3 ${COMPILE_OPTIONS_EXTRA}) + endif() + if(TARGET spheresvr_nightly) + if(ENABLED_SANITIZER) + target_compile_options(spheresvr_nightly PUBLIC -ggdb3 -O1 ${COMPILE_OPTIONS_EXTRA}) + else() + target_compile_options(spheresvr_nightly PUBLIC -O3 ${COMPILE_OPTIONS_EXTRA}) + endif() + endif() + if(TARGET spheresvr_debug) + target_compile_options(spheresvr_debug PUBLIC -ggdb3 -Og ${COMPILE_OPTIONS_EXTRA}) + endif() + + #-- Store common linker flags. + + if(${USE_MSAN}) + set(CMAKE_EXE_LINKER_FLAGS_EXTRA ${CMAKE_EXE_LINKER_FLAGS_EXTRA} -pie) + endif() + set(cxx_linker_options_common + ${CMAKE_EXE_LINKER_FLAGS_EXTRA} + -pthread + -dynamic + -Wl,--fatal-warnings + $<$: + -static-libstdc++ + -static-libgcc> # no way to statically link against libc? maybe we can on windows? + ) + + #-- Store common define macros. + + set(cxx_compiler_definitions_common + ${PREPROCESSOR_DEFS_EXTRA} + $<$>:_GITVERSION> + _EXCEPTIONS_DEBUG + # _EXCEPTIONS_DEBUG: Enable advanced exceptions catching. Consumes some more resources, but is very useful for debug + # on a running environment. Also it makes sphere more stable since exceptions are local. + _CRT_SECURE_NO_WARNINGS + # _CRT_SECURE_NO_WARNINGS: Temporary setting to do not spam so much in the build proccess while we get rid of -W4 warnings and, after it, -Wall. + _WINSOCK_DEPRECATED_NO_WARNINGS + # _WINSOCK_DEPRECATED_NO_WARNINGS: Removing warnings until the code gets updated or reviewed. + ) + #-- Apply define macros, only the ones specific per build type. + + if(TARGET spheresvr_release) + target_compile_definitions(spheresvr_release PUBLIC NDEBUG THREAD_TRACK_CALLSTACK) + endif() + if(TARGET spheresvr_nightly) + target_compile_definitions(spheresvr_nightly PUBLIC NDEBUG THREAD_TRACK_CALLSTACK _NIGHTLYBUILD) + endif() + if(TARGET spheresvr_debug) + target_compile_definitions(spheresvr_debug PUBLIC _DEBUG THREAD_TRACK_CALLSTACK _PACKETDUMP) + endif() + + #-- Now apply the common compiler options, preprocessor macros, linker options. + + foreach(tgt ${TARGETS}) + target_compile_options(${tgt} PRIVATE ${cxx_compiler_options_common}) + target_compile_definitions(${tgt} PRIVATE ${cxx_compiler_definitions_common}) + target_link_options(${tgt} PRIVATE ${cxx_linker_options_common}) + target_link_libraries(${tgt} PRIVATE mariadb ws2_32) + endforeach() + + #-- Set different output folders for each build type + # (When we'll have support for multi-target builds...) + #SET_TARGET_PROPERTIES(spheresvr PROPERTIES RUNTIME_OUTPUT_RELEASE "${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/Release" ) + #SET_TARGET_PROPERTIES(spheresvr PROPERTIES RUNTIME_OUTPUT_DEBUG "${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/Debug" ) + #SET_TARGET_PROPERTIES(spheresvr PROPERTIES RUNTIME_OUTPUT_NIGHTLY "${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/Nightly" ) endfunction() diff --git a/lib/CMakeLists.txt b/lib/CMakeLists.txt index ae2f6f9d5..7aa07d072 100644 --- a/lib/CMakeLists.txt +++ b/lib/CMakeLists.txt @@ -1,4 +1,3 @@ - add_subdirectory(bcrypt) add_subdirectory(cdrc) add_subdirectory(flat_containers) @@ -10,54 +9,60 @@ add_subdirectory(regex) #add_subdirectory(simde) add_subdirectory(twofish) -if (${LIB_LIBEV_BUILD}) - add_subdirectory(libev) -# else find_package... +if(${LIB_LIBEV_BUILD}) + add_subdirectory(libev) + # else find_package... endif() -if (${LIB_SQLITE_BUILD}) - add_subdirectory(sqlite) -# else find_package... +if(${LIB_SQLITE_BUILD}) + add_subdirectory(sqlite) + # else find_package... endif() -if (${LIB_ZLIB_BUILD}) - add_subdirectory(zlib) -# else find_package... +if(${LIB_ZLIB_BUILD}) + add_subdirectory(zlib) + # else find_package... endif() +foreach(tgt ${TARGETS}) + # Link to projects defined as interface libraries. + target_link_libraries( + ${tgt} + INTERFACE + flat_containers # header only lib + INTERFACE + mariadb_connector_c # true interface for the precompiled external library + INTERFACE + object_ptr # header only lib + INTERFACE + parallel_hashmap # header only lib + INTERFACE + rand # header only lib + INTERFACE + regex # header only lib + ) -foreach (tgt ${TARGETS}) - # Link to projects defined as interface libraries. - target_link_libraries(${tgt} - INTERFACE flat_containers # header only lib - INTERFACE mariadb_connector_c # true interface for the precompiled external library - INTERFACE object_ptr # header only lib - INTERFACE parallel_hashmap # header only lib - INTERFACE rand # header only lib - INTERFACE regex # header only lib - ) - - # workaround, INCLUDE_DIRECTORIES aren't propagated to projects linking interface libraries... - target_include_directories(${tgt} - PRIVATE $ - PRIVATE $ - PRIVATE $ - PRIVATE $ - PRIVATE $ - PRIVATE $ - ) - - # import the compile_definitions defined by the INTERFACE targets - target_compile_definitions(${tgt} PUBLIC ${INTERFACE_COMPILE_DEFINITIONS}) + # workaround, INCLUDE_DIRECTORIES aren't propagated to projects linking interface libraries... + target_include_directories( + ${tgt} + PRIVATE $ + PRIVATE $ + PRIVATE $ + PRIVATE $ + PRIVATE $ + PRIVATE $ + ) - # Link to (and import include directories) those clasic (.c/.h) libraries. - target_link_libraries(${tgt} PRIVATE bcrypt twofish) # cdrc (not needed for now) - if (${LIB_LIBEV_BUILD}) - target_link_libraries(${tgt} PRIVATE libev) - endif() - if (${LIB_SQLITE_BUILD}) - target_link_libraries(${tgt} PRIVATE sqlite) - endif() - if (${LIB_ZLIB_BUILD}) - target_link_libraries(${tgt} PRIVATE zlib) - endif() -endforeach () + # import the compile_definitions defined by the INTERFACE targets + target_compile_definitions(${tgt} PUBLIC ${INTERFACE_COMPILE_DEFINITIONS}) + # Link to (and import include directories) those clasic (.c/.h) libraries. + target_link_libraries(${tgt} PRIVATE bcrypt twofish) # cdrc (not needed for now) + if(${LIB_LIBEV_BUILD}) + target_link_libraries(${tgt} PRIVATE libev) + endif() + if(${LIB_SQLITE_BUILD}) + target_link_libraries(${tgt} PRIVATE sqlite) + endif() + if(${LIB_ZLIB_BUILD}) + target_link_libraries(${tgt} PRIVATE zlib) + endif() +endforeach() diff --git a/lib/bcrypt/CMakeLists.txt b/lib/bcrypt/CMakeLists.txt index 18ce7745a..7d330d600 100644 --- a/lib/bcrypt/CMakeLists.txt +++ b/lib/bcrypt/CMakeLists.txt @@ -1,7 +1,7 @@ -cmake_minimum_required (VERSION 3.19) +cmake_minimum_required(VERSION 3.19) project(bcrypt C) -set (lib_SOURCES +set(lib_SOURCES bcrypt/crypt_blowfish.c bcrypt/crypt_blowfish.h bcrypt/crypt_gensalt.c @@ -13,12 +13,12 @@ set (lib_SOURCES add_library(bcrypt STATIC ${lib_SOURCES}) # make the headers available in the include path (accessible with < >). -target_include_directories (bcrypt PUBLIC .) +target_include_directories(bcrypt PUBLIC .) # add to the proper directories in the solution explorer (eg. Visual Studio) -source_group (lib\\bcrypt FILES ${lib_SOURCES}) +source_group(lib\\bcrypt FILES ${lib_SOURCES}) # set compiler flags include("../lib_build_flags_common_c.cmake") -target_compile_options (bcrypt PRIVATE ${c_compiler_options_common}) -target_compile_definitions (bcrypt PRIVATE ${c_compiler_definitions_common}) -target_link_options (bcrypt PRIVATE ${c_linker_options_common}) +target_compile_options(bcrypt PRIVATE ${c_compiler_options_common}) +target_compile_definitions(bcrypt PRIVATE ${c_compiler_definitions_common}) +target_link_options(bcrypt PRIVATE ${c_linker_options_common}) diff --git a/lib/cdrc/CMakeLists.txt b/lib/cdrc/CMakeLists.txt index 9105cee9c..783698d6a 100644 --- a/lib/cdrc/CMakeLists.txt +++ b/lib/cdrc/CMakeLists.txt @@ -1,7 +1,7 @@ -cmake_minimum_required (VERSION 3.19) +cmake_minimum_required(VERSION 3.19) project(cdrc CXX) -set (lib_SOURCES +set(lib_SOURCES cdrc/atomic_rc_ptr.h cdrc/atomic_weak_ptr.h cdrc/marked_arc_ptr.h @@ -10,31 +10,22 @@ set (lib_SOURCES cdrc/weak_ptr.h cdrc/weak_snapshot_ptr.h ) -set (lib_custom_SOURCES - cdrc/custom/rand.cpp - cdrc/custom/rand.h - cdrc/custom/threadid.cpp - cdrc/custom/threadid.h -) +set(lib_custom_SOURCES cdrc/custom/rand.cpp cdrc/custom/rand.h cdrc/custom/threadid.cpp cdrc/custom/threadid.h) # add to the proper directories in the solution explorer (eg. Visual Studio) -source_group (lib\\cdrc FILES ${lib_SOURCES}) -source_group (lib\\cdrc\\custom FILES ${lib_custom_SOURCES}) +source_group(lib\\cdrc FILES ${lib_SOURCES}) +source_group(lib\\cdrc\\custom FILES ${lib_custom_SOURCES}) add_library(cdrc STATIC ${lib_SOURCES} ${lib_custom_SOURCES}) # set compiler flags -if (MSVC) - set(my_comp_options - /wd4244 - /wd4267 - /wd4324 - ) -endif () +if(MSVC) + set(my_comp_options /wd4244 /wd4267 /wd4324) +endif() include("../lib_build_flags_common_c.cmake") -target_compile_options (cdrc PRIVATE ${c_compiler_options_common} ${my_comp_options}) -target_link_options (cdrc PRIVATE ${c_linker_options_common}) +target_compile_options(cdrc PRIVATE ${c_compiler_options_common} ${my_comp_options}) +target_link_options(cdrc PRIVATE ${c_linker_options_common}) # make the headers available in the include path (accessible with < >). -target_include_directories (cdrc PUBLIC "${CMAKE_CURRENT_SOURCE_DIR}") +target_include_directories(cdrc PUBLIC "${CMAKE_CURRENT_SOURCE_DIR}") diff --git a/lib/flat_containers/CMakeLists.txt b/lib/flat_containers/CMakeLists.txt index 919ffbdbf..766e73f2b 100644 --- a/lib/flat_containers/CMakeLists.txt +++ b/lib/flat_containers/CMakeLists.txt @@ -1,7 +1,7 @@ -cmake_minimum_required (VERSION 3.19) +cmake_minimum_required(VERSION 3.19) project(flat_containers CXX) -set (lib_SOURCES +set(lib_SOURCES flat_containers/flat_map.hpp flat_containers/flat_multimap.hpp flat_containers/flat_multiset.hpp @@ -9,11 +9,11 @@ set (lib_SOURCES ) # add to the proper directories in the solution explorer (eg. Visual Studio) -source_group (lib\\flat_containers FILES ${lib_SOURCES}) +source_group(lib\\flat_containers FILES ${lib_SOURCES}) # create the target. equivalent to add_executable, but for libraries add_library(flat_containers INTERFACE ${lib_SOURCES}) #set_target_properties(flat_containers PROPERTIES LINKER_LANGUAGE CXX) # make the headers available in the include path (accessible with < >). -target_include_directories (flat_containers INTERFACE "${CMAKE_CURRENT_SOURCE_DIR}") +target_include_directories(flat_containers INTERFACE "${CMAKE_CURRENT_SOURCE_DIR}") diff --git a/lib/lib_build_flags_common_c.cmake b/lib/lib_build_flags_common_c.cmake index 70e4e06c8..b47cecd90 100644 --- a/lib/lib_build_flags_common_c.cmake +++ b/lib/lib_build_flags_common_c.cmake @@ -1,9 +1,10 @@ -set (ENABLED_SANITIZER FALSE) -if (${USE_ASAN} OR ${USE_MSAN} OR ${USE_LSAN} OR ${USE_UBSAN}) - set (ENABLED_SANITIZER TRUE) +set(ENABLED_SANITIZER FALSE) +if(${USE_ASAN} OR ${USE_MSAN} OR ${USE_LSAN} OR ${USE_UBSAN}) + set(ENABLED_SANITIZER TRUE) endif() -if (MSVC) +if(MSVC) + # gersemi: off set (c_compiler_options_common /O2 /EHsc /GA /Gw /Gy /GF /GR- /GS- $<$: $,/MT,/MD> $<$:/Zi>> @@ -15,27 +16,26 @@ if (MSVC) $<$: /OPT:REF,ICF /LTCG:ON /NODEFAULTLIB:libcmtd> $<$: /DEBUG /LTCG:OFF /NODEFAULTLIB:libcmt> ) + # gersemi: on +else(MSVC) + set(c_compiler_options_common + -pipe + -fexceptions + -fnon-call-exceptions + -O3 + $<$:-ggdb3> + ) -else (MSVC) - set (c_compiler_options_common - -pipe -fexceptions -fnon-call-exceptions - -O3 - $<$:-ggdb3> - ) - - if (${CMAKE_C_COMPILER_ID} STREQUAL GNU) - set (c_compiler_options_common ${c_compiler_options_common} - -fno-expensive-optimizations - ) - endif () - - #set (c_compiler_definitions_common ${c_compiler_definitions_common} - #) + if(${CMAKE_C_COMPILER_ID} STREQUAL GNU) + set(c_compiler_options_common ${c_compiler_options_common} -fno-expensive-optimizations) + endif() - #set (c_linker_options_common ${c_linker_options_common} - #) + #set (c_compiler_definitions_common ${c_compiler_definitions_common} + #) - #if (${CMAKE_C_COMPILER_ID} STREQUAL Clang) -#endif() + #set (c_linker_options_common ${c_linker_options_common} + #) + #if (${CMAKE_C_COMPILER_ID} STREQUAL Clang) + #endif() endif() diff --git a/lib/libev/CMakeLists.txt b/lib/libev/CMakeLists.txt index b60ac8499..c74db4f04 100644 --- a/lib/libev/CMakeLists.txt +++ b/lib/libev/CMakeLists.txt @@ -1,10 +1,10 @@ -cmake_minimum_required (VERSION 3.19) +cmake_minimum_required(VERSION 3.19) project(libev C) # Generate config.h file for libev (if we are using it) -INCLUDE ("configure.cmake") +include("configure.cmake") -set (lib_SOURCES +set(lib_SOURCES wrapper_ev.c libev/config.h libev/ev++.h @@ -22,27 +22,25 @@ set (lib_SOURCES ) # add to the proper directories in the solution explorer (eg. Visual Studio) -source_group (lib\\libev FILES ${lib_SOURCES}) +source_group(lib\\libev FILES ${lib_SOURCES}) # create the target. equivalent to add_executable, but for libraries -add_library (libev STATIC ${lib_SOURCES}) +add_library(libev STATIC ${lib_SOURCES}) # make the headers available in the include path (accessible with < >). -target_include_directories (libev PUBLIC .) +target_include_directories(libev PUBLIC .) # set compiler flags include("../lib_build_flags_common_c.cmake") -if (${CMAKE_CXX_COMPILER_ID} STREQUAL Clang) - set (c_compiler_options_common - ${c_compiler_options_common} -Wno-extern-initializer - ) -elseif (${CMAKE_CXX_COMPILER_ID} STREQUAL GNU) - set (c_compiler_options_common +if(${CMAKE_CXX_COMPILER_ID} STREQUAL Clang) + set(c_compiler_options_common ${c_compiler_options_common} -Wno-extern-initializer) +elseif(${CMAKE_CXX_COMPILER_ID} STREQUAL GNU) + set(c_compiler_options_common ${c_compiler_options_common} #-Wno-error=extern-initializer # doesn't exist... yet? - -w # suppress all the warnings, since gcc doesn't have -Wno-extern-initializer + -w # suppress all the warnings, since gcc doesn't have -Wno-extern-initializer ) -endif () -target_compile_options (libev PRIVATE ${c_compiler_options_common}) -target_compile_definitions (libev PRIVATE ${c_compiler_definitions_common}) -target_link_options (libev PRIVATE ${c_linker_options_common}) +endif() +target_compile_options(libev PRIVATE ${c_compiler_options_common}) +target_compile_definitions(libev PRIVATE ${c_compiler_definitions_common}) +target_link_options(libev PRIVATE ${c_linker_options_common}) diff --git a/lib/libev/configure.cmake b/lib/libev/configure.cmake index 3c9111b02..068fc0185 100644 --- a/lib/libev/configure.cmake +++ b/lib/libev/configure.cmake @@ -1,48 +1,47 @@ #Copypaste from https://github.com/LuaDist/libev/blob/master/cmake/configure.cmake -message (STATUS "Generating config.h for LibEV... (may require some time)") - -include ( CheckFunctionExists ) -include ( CheckIncludeFiles ) -set (CMAKE_REQUIRED_QUIET 1) # We don't want to pollute the log with the log msgs with check_include_files and check_function_exists - -check_include_files ( dlfcn.h HAVE_DLFCN_H ) -check_include_files ( inttypes.h HAVE_INTTYPES_H ) -check_include_files ( memory.h HAVE_MEMORY_H ) -check_include_files ( poll.h HAVE_POLL_H ) -check_include_files ( port.h HAVE_PORT_H ) -check_include_files ( stdint.h HAVE_STDINT_H ) -check_include_files ( stdlib.h HAVE_STDLIB_H ) -check_include_files ( strings.h HAVE_STRINGS_H ) -check_include_files ( string.h HAVE_STRING_H ) -check_include_files ( "sys/epoll.h" HAVE_SYS_EPOLL_H ) -check_include_files ( "sys/eventfd.h" HAVE_SYS_EVENTFD_H ) -check_include_files ( "sys/event.h" HAVE_SYS_EVENT_H ) -check_include_files ( "sys/inotify.h" HAVE_SYS_INOTIFY_H ) -check_include_files ( "sys/select.h" HAVE_SYS_SELECT_H ) -check_include_files ( "sys/signalfd.h" HAVE_SYS_SIGNALFD_H ) -check_include_files ( "sys/stat.h" HAVE_SYS_STAT_H ) -check_include_files ( "sys/types.h" HAVE_SYS_TYPES_H ) -check_include_files ( unistd.h HAVE_UNISTD_H ) - -check_function_exists ( clock_gettime HAVE_CLOCK_GETTIME ) -check_function_exists ( epoll_ctl HAVE_EPOLL_CTL ) -check_function_exists ( eventfd HAVE_EVENTFD ) -check_function_exists ( floor HAVE_FLOOR ) -check_function_exists ( inotify_init HAVE_INOTIFY_INIT ) -check_function_exists ( kqueue HAVE_KQUEUE ) -check_function_exists ( nanosleep HAVE_NANOSLEEP ) -check_function_exists ( poll HAVE_POLL ) -check_function_exists ( port_create HAVE_PORT_CREATE ) -check_function_exists ( select HAVE_SELECT ) -check_function_exists ( signalfd HAVE_SIGNALFD ) - -find_library ( HAVE_LIBRT rt ) +message(STATUS "Generating config.h for LibEV... (may require some time)") + +include(CheckFunctionExists) +include(CheckIncludeFiles) +set(CMAKE_REQUIRED_QUIET 1) # We don't want to pollute the log with the log msgs with check_include_files and check_function_exists + +check_include_files(dlfcn.h HAVE_DLFCN_H) +check_include_files(inttypes.h HAVE_INTTYPES_H) +check_include_files(memory.h HAVE_MEMORY_H) +check_include_files(poll.h HAVE_POLL_H) +check_include_files(port.h HAVE_PORT_H) +check_include_files(stdint.h HAVE_STDINT_H) +check_include_files(stdlib.h HAVE_STDLIB_H) +check_include_files(strings.h HAVE_STRINGS_H) +check_include_files(string.h HAVE_STRING_H) +check_include_files("sys/epoll.h" HAVE_SYS_EPOLL_H) +check_include_files("sys/eventfd.h" HAVE_SYS_EVENTFD_H) +check_include_files("sys/event.h" HAVE_SYS_EVENT_H) +check_include_files("sys/inotify.h" HAVE_SYS_INOTIFY_H) +check_include_files("sys/select.h" HAVE_SYS_SELECT_H) +check_include_files("sys/signalfd.h" HAVE_SYS_SIGNALFD_H) +check_include_files("sys/stat.h" HAVE_SYS_STAT_H) +check_include_files("sys/types.h" HAVE_SYS_TYPES_H) +check_include_files(unistd.h HAVE_UNISTD_H) + +check_function_exists(clock_gettime HAVE_CLOCK_GETTIME) +check_function_exists(epoll_ctl HAVE_EPOLL_CTL) +check_function_exists(eventfd HAVE_EVENTFD) +check_function_exists(floor HAVE_FLOOR) +check_function_exists(inotify_init HAVE_INOTIFY_INIT) +check_function_exists(kqueue HAVE_KQUEUE) +check_function_exists(nanosleep HAVE_NANOSLEEP) +check_function_exists(poll HAVE_POLL) +check_function_exists(port_create HAVE_PORT_CREATE) +check_function_exists(select HAVE_SELECT) +check_function_exists(signalfd HAVE_SIGNALFD) + +find_library(HAVE_LIBRT rt) # Tweaks -set ( HAVE_CLOCK_SYSCALL ${HAVE_CLOCK_GETTIME} ) +set(HAVE_CLOCK_SYSCALL ${HAVE_CLOCK_GETTIME}) -CONFIGURE_FILE ("${CMAKE_CURRENT_LIST_DIR}/config.h.in" - "${CMAKE_CURRENT_LIST_DIR}/libev/config.h" ) +configure_file("${CMAKE_CURRENT_LIST_DIR}/config.h.in" "${CMAKE_CURRENT_LIST_DIR}/libev/config.h") -message (STATUS "Done.") +message(STATUS "Done.") diff --git a/lib/mariadb_connector_c/CMakeLists.txt b/lib/mariadb_connector_c/CMakeLists.txt index dbfbdcfee..460c5090b 100644 --- a/lib/mariadb_connector_c/CMakeLists.txt +++ b/lib/mariadb_connector_c/CMakeLists.txt @@ -1,20 +1,17 @@ -cmake_minimum_required (VERSION 3.19) +cmake_minimum_required(VERSION 3.19) project(mariadb_connector C) # we do not build the library here, only provide the headers for a precompiled one. #include("lib_compiler_flags_common_c.cmake") # Configure MariaDB C Connector source headers -include ("mysql/configure.cmake") +include("mysql/configure.cmake") -set (lib_SOURCES - mysql/config.h - mysql/mysql.h -) +set(lib_SOURCES mysql/config.h mysql/mysql.h) # create the target. equivalent to add_executable, but for libraries add_library(mariadb_connector INTERFACE ${lib_SOURCES}) # make the headers available in the include path (accessible with < >). -target_include_directories (mariadb_connector INTERFACE .) +target_include_directories(mariadb_connector INTERFACE .) # add to the proper directories in the solution explorer (eg. Visual Studio) -source_group (lib\\mariadb_connector_c FILES ${lib_SOURCES}) +source_group(lib\\mariadb_connector_c FILES ${lib_SOURCES}) diff --git a/lib/mariadb_connector_c/mysql/configure.cmake b/lib/mariadb_connector_c/mysql/configure.cmake index 8163e5391..3982dbf97 100644 --- a/lib/mariadb_connector_c/mysql/configure.cmake +++ b/lib/mariadb_connector_c/mysql/configure.cmake @@ -1,37 +1,48 @@ -SET(MARIADB_CLIENT_VERSION_MAJOR "10") -SET(MARIADB_CLIENT_VERSION_MINOR "8") -SET(MARIADB_CLIENT_VERSION_PATCH "7") -SET(MARIADB_CLIENT_VERSION_EXTRA "") - -SET(MARIADB_CLIENT_VERSION "${MARIADB_CLIENT_VERSION_MAJOR}.${MARIADB_CLIENT_VERSION_MINOR}.${MARIADB_CLIENT_VERSION_PATCH}${MARIADB_CLIENT_VERSION_EXTRA}") -SET(MARIADB_BASE_VERSION "mariadb-${MARIADB_CLIENT_VERSION_MAJOR}.${MARIADB_CLIENT_VERSION_MINOR}") -MATH(EXPR MARIADB_VERSION_ID "${MARIADB_CLIENT_VERSION_MAJOR} * 10000 + +set(MARIADB_CLIENT_VERSION_MAJOR "10") +set(MARIADB_CLIENT_VERSION_MINOR "8") +set(MARIADB_CLIENT_VERSION_PATCH "7") +set(MARIADB_CLIENT_VERSION_EXTRA "") + +set(MARIADB_CLIENT_VERSION + "${MARIADB_CLIENT_VERSION_MAJOR}.${MARIADB_CLIENT_VERSION_MINOR}.${MARIADB_CLIENT_VERSION_PATCH}${MARIADB_CLIENT_VERSION_EXTRA}" +) +set(MARIADB_BASE_VERSION "mariadb-${MARIADB_CLIENT_VERSION_MAJOR}.${MARIADB_CLIENT_VERSION_MINOR}") +math( + EXPR + MARIADB_VERSION_ID + "${MARIADB_CLIENT_VERSION_MAJOR} * 10000 + ${MARIADB_CLIENT_VERSION_MINOR} * 100 + - ${MARIADB_CLIENT_VERSION_PATCH}") - -SET(CPACK_PACKAGE_VERSION_MAJOR 3) -SET(CPACK_PACKAGE_VERSION_MINOR 3) -SET(CPACK_PACKAGE_VERSION_PATCH 4) - -SET(CPACK_PACKAGE_VERSION "${CPACK_PACKAGE_VERSION_MAJOR}.${CPACK_PACKAGE_VERSION_MINOR}.${CPACK_PACKAGE_VERSION_PATCH}") -MATH(EXPR MARIADB_PACKAGE_VERSION_ID "${CPACK_PACKAGE_VERSION_MAJOR} * 10000 + + ${MARIADB_CLIENT_VERSION_PATCH}" +) + +set(CPACK_PACKAGE_VERSION_MAJOR 3) +set(CPACK_PACKAGE_VERSION_MINOR 3) +set(CPACK_PACKAGE_VERSION_PATCH 4) + +set(CPACK_PACKAGE_VERSION + "${CPACK_PACKAGE_VERSION_MAJOR}.${CPACK_PACKAGE_VERSION_MINOR}.${CPACK_PACKAGE_VERSION_PATCH}" +) +math( + EXPR + MARIADB_PACKAGE_VERSION_ID + "${CPACK_PACKAGE_VERSION_MAJOR} * 10000 + ${CPACK_PACKAGE_VERSION_MINOR} * 100 + - ${CPACK_PACKAGE_VERSION_PATCH}") - -IF (NOT MARIADB_PORT) - SET(MARIADB_PORT 3306) -ENDIF () -IF(NOT MARIADB_UNIX_ADDR) - SET(MARIADB_UNIX_ADDR "/tmp/mysql.sock") -ENDIF() + ${CPACK_PACKAGE_VERSION_PATCH}" +) -SET (PROTOCOL_VERSION 10) # we adapted new password option from PHP's mysqlnd ! +if(NOT MARIADB_PORT) + set(MARIADB_PORT 3306) +endif() +if(NOT MARIADB_UNIX_ADDR) + set(MARIADB_UNIX_ADDR "/tmp/mysql.sock") +endif() -IF (NOT DEFAULT_CHARSET) - SET (DEFAULT_CHARSET "utf8mb4") -ENDIF () +set(PROTOCOL_VERSION 10) # we adapted new password option from PHP's mysqlnd ! +if(NOT DEFAULT_CHARSET) + set(DEFAULT_CHARSET "utf8mb4") +endif() -CONFIGURE_FILE(${CMAKE_CURRENT_LIST_DIR}/ma_config.h.in ${CMAKE_CURRENT_LIST_DIR}/ma_config.h) -CONFIGURE_FILE(${CMAKE_CURRENT_LIST_DIR}/ma_config.h.in ${CMAKE_CURRENT_LIST_DIR}/config.h) -CONFIGURE_FILE(${CMAKE_CURRENT_LIST_DIR}/mariadb_version.h.in ${CMAKE_CURRENT_LIST_DIR}/mariadb_version.h) +configure_file(${CMAKE_CURRENT_LIST_DIR}/ma_config.h.in ${CMAKE_CURRENT_LIST_DIR}/ma_config.h) +configure_file(${CMAKE_CURRENT_LIST_DIR}/ma_config.h.in ${CMAKE_CURRENT_LIST_DIR}/config.h) +configure_file(${CMAKE_CURRENT_LIST_DIR}/mariadb_version.h.in ${CMAKE_CURRENT_LIST_DIR}/mariadb_version.h) diff --git a/lib/object_ptr/CMakeLists.txt b/lib/object_ptr/CMakeLists.txt index 3acfdc369..a714b7342 100644 --- a/lib/object_ptr/CMakeLists.txt +++ b/lib/object_ptr/CMakeLists.txt @@ -1,15 +1,13 @@ -cmake_minimum_required (VERSION 3.19) +cmake_minimum_required(VERSION 3.19) project(object_ptr CXX) # provide the headers headers. -set (lib_SOURCES - object_ptr/object_ptr.hpp -) +set(lib_SOURCES object_ptr/object_ptr.hpp) # create the target. equivalent to add_executable, but for libraries add_library(object_ptr INTERFACE ${lib_SOURCES}) # make the headers available in the include path (accessible with < >). -target_include_directories (object_ptr INTERFACE .) +target_include_directories(object_ptr INTERFACE .) # add to the proper directories in the solution explorer (eg. Visual Studio) -source_group (lib\\object_ptr FILES ${lib_SOURCES}) +source_group(lib\\object_ptr FILES ${lib_SOURCES}) diff --git a/lib/parallel_hashmap/CMakeLists.txt b/lib/parallel_hashmap/CMakeLists.txt index e7e359bac..b7475f31d 100644 --- a/lib/parallel_hashmap/CMakeLists.txt +++ b/lib/parallel_hashmap/CMakeLists.txt @@ -1,7 +1,7 @@ -cmake_minimum_required (VERSION 3.19) +cmake_minimum_required(VERSION 3.19) project(parallel_hashmap CXX) -set (lib_SOURCES +set(lib_SOURCES parallel_hashmap/btree.h #parallel_hashmap/meminfo.h parallel_hashmap/phmap.h @@ -17,9 +17,9 @@ set (lib_SOURCES add_library(parallel_hashmap INTERFACE ${lib_SOURCES}) # make the headers available in the include path (accessible with < >). -target_include_directories (parallel_hashmap INTERFACE .) +target_include_directories(parallel_hashmap INTERFACE .) # add to the proper directories in the solution explorer (eg. Visual Studio) -source_group (lib\\parallel_hashmap FILES ${lib_SOURCES}) +source_group(lib\\parallel_hashmap FILES ${lib_SOURCES}) #target_compile_definitions(parallel_hashmap INTERFACE # $<$: ADDRESS_SANITIZER> diff --git a/lib/rand/CMakeLists.txt b/lib/rand/CMakeLists.txt index 591eee0fc..2a9433403 100644 --- a/lib/rand/CMakeLists.txt +++ b/lib/rand/CMakeLists.txt @@ -1,16 +1,14 @@ -cmake_minimum_required (VERSION 3.19) +cmake_minimum_required(VERSION 3.19) project(rand CXX) -set (lib_SOURCES - rand/xorshift.hpp -) +set(lib_SOURCES rand/xorshift.hpp) # add to the proper directories in the solution explorer (eg. Visual Studio) -source_group (lib\\rand FILES ${lib_SOURCES}) +source_group(lib\\rand FILES ${lib_SOURCES}) # create the target. equivalent to add_executable, but for libraries add_library(rand INTERFACE ${lib_SOURCES}) #set_target_properties(rand PROPERTIES LINKER_LANGUAGE CXX) # make the headers available in the include path (accessible with < >). -target_include_directories (rand INTERFACE "${CMAKE_CURRENT_SOURCE_DIR}") +target_include_directories(rand INTERFACE "${CMAKE_CURRENT_SOURCE_DIR}") diff --git a/lib/regex/CMakeLists.txt b/lib/regex/CMakeLists.txt index 7f700c6a2..5818eb212 100644 --- a/lib/regex/CMakeLists.txt +++ b/lib/regex/CMakeLists.txt @@ -1,14 +1,12 @@ -cmake_minimum_required (VERSION 3.19) +cmake_minimum_required(VERSION 3.19) project(regex CXX) -set (lib_SOURCES - regex/deelx.h -) +set(lib_SOURCES regex/deelx.h) # create the target. equivalent to add_executable, but for libraries add_library(regex INTERFACE ${lib_SOURCES}) # make the headers available in the include path (accessible with < >). -target_include_directories (regex INTERFACE .) +target_include_directories(regex INTERFACE .) # add to the proper directories in the solution explorer (eg. Visual Studio) -source_group (lib\\regex FILES ${lib_SOURCES}) +source_group(lib\\regex FILES ${lib_SOURCES}) diff --git a/lib/sqlite/CMakeLists.txt b/lib/sqlite/CMakeLists.txt index d01fac06e..ccca6be37 100644 --- a/lib/sqlite/CMakeLists.txt +++ b/lib/sqlite/CMakeLists.txt @@ -1,22 +1,19 @@ -cmake_minimum_required (VERSION 3.19) +cmake_minimum_required(VERSION 3.19) project(sqlite C) -set (lib_SOURCES - sqlite/sqlite3.c - sqlite/sqlite3.h -) +set(lib_SOURCES sqlite/sqlite3.c sqlite/sqlite3.h) # add to the proper directories in the solution explorer (eg. Visual Studio) -source_group (lib\\sqlite FILES ${lib_SOURCES}) +source_group(lib\\sqlite FILES ${lib_SOURCES}) # create the target. equivalent to add_executable, but for libraries -add_library (sqlite STATIC ${lib_SOURCES}) +add_library(sqlite STATIC ${lib_SOURCES}) # make the headers available in the include path (accessible with < >). -target_include_directories (sqlite PUBLIC .) +target_include_directories(sqlite PUBLIC .) # set compiler flags include("../lib_build_flags_common_c.cmake") -target_compile_options (sqlite PRIVATE ${c_compiler_options_common}) -target_compile_definitions (sqlite PRIVATE ${c_compiler_definitions_common}) -target_link_options (sqlite PRIVATE ${c_linker_options_common}) +target_compile_options(sqlite PRIVATE ${c_compiler_options_common}) +target_compile_definitions(sqlite PRIVATE ${c_compiler_definitions_common}) +target_link_options(sqlite PRIVATE ${c_linker_options_common}) diff --git a/lib/twofish/CMakeLists.txt b/lib/twofish/CMakeLists.txt index c9f7baf2a..59e5d001e 100644 --- a/lib/twofish/CMakeLists.txt +++ b/lib/twofish/CMakeLists.txt @@ -1,23 +1,19 @@ -cmake_minimum_required (VERSION 3.19) +cmake_minimum_required(VERSION 3.19) project(twofish C) -set (lib_SOURCES - twofish/twofish.h - twofish/twofish_aux.h - twofish/twofish.c -) +set(lib_SOURCES twofish/twofish.h twofish/twofish_aux.h twofish/twofish.c) # add to the proper directories in the solution explorer (eg. Visual Studio) -source_group (lib\\twofish FILES ${lib_SOURCES}) +source_group(lib\\twofish FILES ${lib_SOURCES}) # create the target. equivalent to add_executable, but for libraries -add_library (twofish STATIC ${lib_SOURCES}) +add_library(twofish STATIC ${lib_SOURCES}) # make the headers available in the include path (accessible with < >). -target_include_directories (twofish PUBLIC .) +target_include_directories(twofish PUBLIC .) # set compiler flags include("../lib_build_flags_common_c.cmake") -target_compile_options (twofish PRIVATE ${c_compiler_options_common}) -target_compile_definitions (twofish PRIVATE ${c_compiler_definitions_common}) -target_link_options (twofish PRIVATE ${c_linker_options_common}) +target_compile_options(twofish PRIVATE ${c_compiler_options_common}) +target_compile_definitions(twofish PRIVATE ${c_compiler_definitions_common}) +target_link_options(twofish PRIVATE ${c_linker_options_common}) diff --git a/lib/zlib/CMakeLists.txt b/lib/zlib/CMakeLists.txt index fb8aea13d..8327aefda 100644 --- a/lib/zlib/CMakeLists.txt +++ b/lib/zlib/CMakeLists.txt @@ -1,7 +1,7 @@ -cmake_minimum_required (VERSION 3.19) +cmake_minimum_required(VERSION 3.19) project(zlib C) -set (lib_SOURCES +set(lib_SOURCES zlib/adler32.c zlib/compress.c zlib/crc32.c @@ -30,20 +30,18 @@ set (lib_SOURCES zlib/zutil.h ) -source_group (lib\\zlib FILES - ${lib_SOURCES} -) +source_group(lib\\zlib FILES ${lib_SOURCES}) # make the headers available in the include path (accessible with < >). -add_library (zlib STATIC ${lib_SOURCES}) +add_library(zlib STATIC ${lib_SOURCES}) # add to the proper directories in the solution explorer (eg. Visual Studio) -target_include_directories (zlib PUBLIC .) +target_include_directories(zlib PUBLIC .) # set compiler flags include("../lib_build_flags_common_c.cmake") -target_compile_options (zlib PRIVATE ${c_compiler_options_common}) -target_compile_definitions (zlib PRIVATE ${c_compiler_definitions_common}) -if (MSVC) - target_compile_definitions (zlib PRIVATE _CRT_SECURE_NO_WARNINGS _CRT_NONSTDC_NO_WARNINGS) -endif () -target_link_options (zlib PRIVATE ${c_linker_options_common}) +target_compile_options(zlib PRIVATE ${c_compiler_options_common}) +target_compile_definitions(zlib PRIVATE ${c_compiler_definitions_common}) +if(MSVC) + target_compile_definitions(zlib PRIVATE _CRT_SECURE_NO_WARNINGS _CRT_NONSTDC_NO_WARNINGS) +endif() +target_link_options(zlib PRIVATE ${c_linker_options_common}) diff --git a/src/CMakeSources.cmake b/src/CMakeSources.cmake index 056a8ac7a..dfb228074 100644 --- a/src/CMakeSources.cmake +++ b/src/CMakeSources.cmake @@ -1,559 +1,552 @@ # Main program files: threads, console... -SET (sphere_SRCS -src/sphere/asyncdb.cpp -src/sphere/asyncdb.h -src/sphere/containers.h -src/sphere/ConsoleInterface.cpp -src/sphere/ConsoleInterface.h -src/sphere/ProfileData.cpp -src/sphere/ProfileData.h -src/sphere/ProfileTask.cpp -src/sphere/ProfileTask.h -src/sphere/threads.cpp -src/sphere/threads.h -src/sphere/ntservice.cpp -src/sphere/ntservice.h -src/sphere/ntwindow.cpp -src/sphere/ntwindow.h -src/sphere/UnixTerminal.cpp -src/sphere/UnixTerminal.h +set(sphere_SRCS + src/sphere/asyncdb.cpp + src/sphere/asyncdb.h + src/sphere/containers.h + src/sphere/ConsoleInterface.cpp + src/sphere/ConsoleInterface.h + src/sphere/ProfileData.cpp + src/sphere/ProfileData.h + src/sphere/ProfileTask.cpp + src/sphere/ProfileTask.h + src/sphere/threads.cpp + src/sphere/threads.h + src/sphere/ntservice.cpp + src/sphere/ntservice.h + src/sphere/ntwindow.cpp + src/sphere/ntwindow.h + src/sphere/UnixTerminal.cpp + src/sphere/UnixTerminal.h ) -SOURCE_GROUP (sphere FILES ${sphere_SRCS}) +source_group(sphere FILES ${sphere_SRCS}) # Network management files -SET (network_SRCS -src/network/CClientIterator.cpp -src/network/CClientIterator.h -src/network/CIPHistoryManager.cpp -src/network/CIPHistoryManager.h -src/network/CNetState.cpp -src/network/CNetState.h -src/network/CNetworkInput.cpp -src/network/CNetworkInput.h -src/network/CNetworkManager.cpp -src/network/CNetworkManager.h -src/network/CNetworkOutput.cpp -src/network/CNetworkOutput.h -src/network/CNetworkThread.cpp -src/network/CNetworkThread.h -src/network/CPacketManager.cpp -src/network/CPacketManager.h -src/network/CSocket.cpp -src/network/CSocket.h -src/network/linuxev.cpp -src/network/linuxev.h -src/network/net_datatypes.h -src/network/net_datatypes.cpp -src/network/packet.cpp -src/network/packet.h -src/network/receive.cpp -src/network/receive.h -src/network/send.cpp -src/network/send.h -src/network/PingServer.cpp -src/network/PingServer.h +set(network_SRCS + src/network/CClientIterator.cpp + src/network/CClientIterator.h + src/network/CIPHistoryManager.cpp + src/network/CIPHistoryManager.h + src/network/CNetState.cpp + src/network/CNetState.h + src/network/CNetworkInput.cpp + src/network/CNetworkInput.h + src/network/CNetworkManager.cpp + src/network/CNetworkManager.h + src/network/CNetworkOutput.cpp + src/network/CNetworkOutput.h + src/network/CNetworkThread.cpp + src/network/CNetworkThread.h + src/network/CPacketManager.cpp + src/network/CPacketManager.h + src/network/CSocket.cpp + src/network/CSocket.h + src/network/linuxev.cpp + src/network/linuxev.h + src/network/net_datatypes.h + src/network/net_datatypes.cpp + src/network/packet.cpp + src/network/packet.h + src/network/receive.cpp + src/network/receive.h + src/network/send.cpp + src/network/send.h + src/network/PingServer.cpp + src/network/PingServer.h ) -SOURCE_GROUP (network FILES ${network_SRCS}) +source_group(network FILES ${network_SRCS}) # Login encryption handling -SET (crypto_SRCS -src/common/crypto/CBCrypt.cpp -src/common/crypto/CBCrypt.h -src/common/crypto/CCrypto.cpp -src/common/crypto/CCrypto.h -src/common/crypto/CCryptoBlowFish.cpp -src/common/crypto/CCryptoLogin.cpp -src/common/crypto/CCryptoKeyCalc.cpp -src/common/crypto/CCryptoKeyCalc.h -src/common/crypto/CCryptoMD5Interface.cpp -src/common/crypto/CCryptoTwoFishInterface.cpp -src/common/crypto/CHuffman.cpp -src/common/crypto/CHuffman.h -src/common/crypto/CMD5.cpp -src/common/crypto/CMD5.h -src/common/crypto/crypto_common.h +set(crypto_SRCS + src/common/crypto/CBCrypt.cpp + src/common/crypto/CBCrypt.h + src/common/crypto/CCrypto.cpp + src/common/crypto/CCrypto.h + src/common/crypto/CCryptoBlowFish.cpp + src/common/crypto/CCryptoLogin.cpp + src/common/crypto/CCryptoKeyCalc.cpp + src/common/crypto/CCryptoKeyCalc.h + src/common/crypto/CCryptoMD5Interface.cpp + src/common/crypto/CCryptoTwoFishInterface.cpp + src/common/crypto/CHuffman.cpp + src/common/crypto/CHuffman.h + src/common/crypto/CMD5.cpp + src/common/crypto/CMD5.h + src/common/crypto/crypto_common.h ) -SOURCE_GROUP (common\\crypto FILES ${crypto_SRCS}) +source_group(common\\crypto FILES ${crypto_SRCS}) # Handle UO Client files -SET (uofiles_SRCS -src/game/uo_files/CUOHuesRec.h -src/game/uo_files/CUOHuesRec.cpp -src/game/uo_files/CUOIndexRec.h -src/game/uo_files/CUOIndexRec.cpp -src/game/uo_files/CUOItemInfo.h -src/game/uo_files/CUOItemInfo.cpp -src/game/uo_files/CUOItemTypeRec.h -src/game/uo_files/CUOMapBlock.h -src/game/uo_files/CUOMapList.h -src/game/uo_files/CUOMapList.cpp -src/game/uo_files/CUOMapMeter.h -src/game/uo_files/CUOMapMeter.cpp -src/game/uo_files/CUOMobtypes.h -src/game/uo_files/CUOMobtypes.cpp -src/game/uo_files/CUOMultiItemRec.h -src/game/uo_files/CUOMultiItemRec.cpp -src/game/uo_files/CUOStaticItemRec.h -src/game/uo_files/CUOStaticItemRec.cpp -src/game/uo_files/CUOTerrainInfo.h -src/game/uo_files/CUOTerrainInfo.cpp -src/game/uo_files/CUOTerrainTypeRec.h -src/game/uo_files/CUOTiledata.h -src/game/uo_files/CUOTiledata.cpp -src/game/uo_files/CUOVersionBlock.h -src/game/uo_files/CUOVersionBlock.cpp -src/game/uo_files/uofiles_enums.h -src/game/uo_files/uofiles_enums_itemid.h -src/game/uo_files/uofiles_enums_creid.h -src/game/uo_files/uofiles_macros.h -src/game/uo_files/uofiles_types.h +set(uofiles_SRCS + src/game/uo_files/CUOHuesRec.h + src/game/uo_files/CUOHuesRec.cpp + src/game/uo_files/CUOIndexRec.h + src/game/uo_files/CUOIndexRec.cpp + src/game/uo_files/CUOItemInfo.h + src/game/uo_files/CUOItemInfo.cpp + src/game/uo_files/CUOItemTypeRec.h + src/game/uo_files/CUOMapBlock.h + src/game/uo_files/CUOMapList.h + src/game/uo_files/CUOMapList.cpp + src/game/uo_files/CUOMapMeter.h + src/game/uo_files/CUOMapMeter.cpp + src/game/uo_files/CUOMobtypes.h + src/game/uo_files/CUOMobtypes.cpp + src/game/uo_files/CUOMultiItemRec.h + src/game/uo_files/CUOMultiItemRec.cpp + src/game/uo_files/CUOStaticItemRec.h + src/game/uo_files/CUOStaticItemRec.cpp + src/game/uo_files/CUOTerrainInfo.h + src/game/uo_files/CUOTerrainInfo.cpp + src/game/uo_files/CUOTerrainTypeRec.h + src/game/uo_files/CUOTiledata.h + src/game/uo_files/CUOTiledata.cpp + src/game/uo_files/CUOVersionBlock.h + src/game/uo_files/CUOVersionBlock.cpp + src/game/uo_files/uofiles_enums.h + src/game/uo_files/uofiles_enums_itemid.h + src/game/uo_files/uofiles_enums_creid.h + src/game/uo_files/uofiles_macros.h + src/game/uo_files/uofiles_types.h ) -SOURCE_GROUP (game\\uo_files FILES ${uofiles_SRCS}) +source_group(game\\uo_files FILES ${uofiles_SRCS}) # Files containing 'background work' -SET (common_SRCS -src/common/sqlite/SQLite.cpp -src/common/sqlite/SQLite.h -src/common/assertion.h -src/common/basic_threading.h -src/common/CCacheableScriptFile.cpp -src/common/CCacheableScriptFile.h -src/common/CDataBase.cpp -src/common/CDataBase.h -src/common/CException.cpp -src/common/CException.h -src/common/CExpression.cpp -src/common/CExpression.h -src/common/CFloatMath.cpp -src/common/CFloatMath.h -src/common/CLocalVarsExtra.cpp -src/common/CLocalVarsExtra.h -src/common/CLog.cpp -src/common/CLog.h -src/common/CServerMap.cpp -src/common/CServerMap.h -src/common/CUID.cpp -src/common/CUID.h -src/common/common.cpp -src/common/common.h -src/common/CPointBase.cpp -src/common/CPointBase.h -src/common/CRect.cpp -src/common/CRect.h -src/common/CScript.cpp -src/common/CScript.h -src/common/CScriptContexts.cpp -src/common/CScriptContexts.h -src/common/CScriptObj.cpp -src/common/CScriptObj.h -src/common/CScriptTriggerArgs.cpp -src/common/CScriptTriggerArgs.h -src/common/CSFileObj.cpp -src/common/CSFileObj.h -src/common/CSFileObjContainer.cpp -src/common/CSFileObjContainer.h -src/common/CSVFile.cpp -src/common/CSVFile.h -src/common/CTextConsole.cpp -src/common/CTextConsole.h -src/common/CUOClientVersion.cpp -src/common/CUOClientVersion.h -src/common/CUOInstall.cpp -src/common/CUOInstall.h -src/common/CVarDefMap.cpp -src/common/CVarDefMap.h -src/common/datatypes.h -src/common/ListDefContMap.cpp -src/common/ListDefContMap.h -src/common/os_unix.h -src/common/os_windows.h -src/common/sphereproto.h -src/common/sphereversion.h -src/common/target_info.h +set(common_SRCS + src/common/sqlite/SQLite.cpp + src/common/sqlite/SQLite.h + src/common/assertion.h + src/common/basic_threading.h + src/common/CCacheableScriptFile.cpp + src/common/CCacheableScriptFile.h + src/common/CDataBase.cpp + src/common/CDataBase.h + src/common/CException.cpp + src/common/CException.h + src/common/CExpression.cpp + src/common/CExpression.h + src/common/CFloatMath.cpp + src/common/CFloatMath.h + src/common/CLocalVarsExtra.cpp + src/common/CLocalVarsExtra.h + src/common/CLog.cpp + src/common/CLog.h + src/common/CServerMap.cpp + src/common/CServerMap.h + src/common/CUID.cpp + src/common/CUID.h + src/common/common.cpp + src/common/common.h + src/common/CPointBase.cpp + src/common/CPointBase.h + src/common/CRect.cpp + src/common/CRect.h + src/common/CScript.cpp + src/common/CScript.h + src/common/CScriptContexts.cpp + src/common/CScriptContexts.h + src/common/CScriptObj.cpp + src/common/CScriptObj.h + src/common/CScriptTriggerArgs.cpp + src/common/CScriptTriggerArgs.h + src/common/CSFileObj.cpp + src/common/CSFileObj.h + src/common/CSFileObjContainer.cpp + src/common/CSFileObjContainer.h + src/common/CSVFile.cpp + src/common/CSVFile.h + src/common/CTextConsole.cpp + src/common/CTextConsole.h + src/common/CUOClientVersion.cpp + src/common/CUOClientVersion.h + src/common/CUOInstall.cpp + src/common/CUOInstall.h + src/common/CVarDefMap.cpp + src/common/CVarDefMap.h + src/common/datatypes.h + src/common/ListDefContMap.cpp + src/common/ListDefContMap.h + src/common/os_unix.h + src/common/os_windows.h + src/common/sphereproto.h + src/common/sphereversion.h + src/common/target_info.h ) -SOURCE_GROUP (common FILES ${common_SRCS}) +source_group(common FILES ${common_SRCS}) -SET (resource_SRCS -src/common/resource/CResourceDef.cpp -src/common/resource/CResourceDef.h -src/common/resource/CResourceHolder.cpp -src/common/resource/CResourceHolder.h -src/common/resource/CResourceID.cpp -src/common/resource/CResourceID.h -src/common/resource/CResourceHash.cpp -src/common/resource/CResourceHash.h -src/common/resource/CResourceLink.cpp -src/common/resource/CResourceLink.h -src/common/resource/CResourceLock.cpp -src/common/resource/CResourceLock.h -src/common/resource/CResourceRef.cpp -src/common/resource/CResourceRef.h -src/common/resource/CResourceScript.cpp -src/common/resource/CResourceScript.h -src/common/resource/CResourceSortedArrays.cpp -src/common/resource/CResourceSortedArrays.h -src/common/resource/CResourceQty.cpp -src/common/resource/CResourceQty.h -src/common/resource/CValueDefs.cpp -src/common/resource/CValueDefs.h +set(resource_SRCS + src/common/resource/CResourceDef.cpp + src/common/resource/CResourceDef.h + src/common/resource/CResourceHolder.cpp + src/common/resource/CResourceHolder.h + src/common/resource/CResourceID.cpp + src/common/resource/CResourceID.h + src/common/resource/CResourceHash.cpp + src/common/resource/CResourceHash.h + src/common/resource/CResourceLink.cpp + src/common/resource/CResourceLink.h + src/common/resource/CResourceLock.cpp + src/common/resource/CResourceLock.h + src/common/resource/CResourceRef.cpp + src/common/resource/CResourceRef.h + src/common/resource/CResourceScript.cpp + src/common/resource/CResourceScript.h + src/common/resource/CResourceSortedArrays.cpp + src/common/resource/CResourceSortedArrays.h + src/common/resource/CResourceQty.cpp + src/common/resource/CResourceQty.h + src/common/resource/CValueDefs.cpp + src/common/resource/CValueDefs.h ) -SOURCE_GROUP (common\\resource FILES ${resource_SRCS}) +source_group(common\\resource FILES ${resource_SRCS}) -SET (resourcesections_SRCS -src/common/resource/sections/CDialogDef.cpp -src/common/resource/sections/CDialogDef.h -src/common/resource/sections/CItemTypeDef.cpp -src/common/resource/sections/CItemTypeDef.h -src/common/resource/sections/CRandGroupDef.cpp -src/common/resource/sections/CRandGroupDef.h -src/common/resource/sections/CRegionResourceDef.cpp -src/common/resource/sections/CRegionResourceDef.h -src/common/resource/sections/CResourceNamedDef.cpp -src/common/resource/sections/CResourceNamedDef.h -src/common/resource/sections/CSkillClassDef.cpp -src/common/resource/sections/CSkillClassDef.h -src/common/resource/sections/CSkillDef.cpp -src/common/resource/sections/CSkillDef.h -src/common/resource/sections/CSpellDef.cpp -src/common/resource/sections/CSpellDef.h -src/common/resource/sections/CWebPageDef.cpp -src/common/resource/sections/CWebPageDef.h +set(resourcesections_SRCS + src/common/resource/sections/CDialogDef.cpp + src/common/resource/sections/CDialogDef.h + src/common/resource/sections/CItemTypeDef.cpp + src/common/resource/sections/CItemTypeDef.h + src/common/resource/sections/CRandGroupDef.cpp + src/common/resource/sections/CRandGroupDef.h + src/common/resource/sections/CRegionResourceDef.cpp + src/common/resource/sections/CRegionResourceDef.h + src/common/resource/sections/CResourceNamedDef.cpp + src/common/resource/sections/CResourceNamedDef.h + src/common/resource/sections/CSkillClassDef.cpp + src/common/resource/sections/CSkillClassDef.h + src/common/resource/sections/CSkillDef.cpp + src/common/resource/sections/CSkillDef.h + src/common/resource/sections/CSpellDef.cpp + src/common/resource/sections/CSpellDef.h + src/common/resource/sections/CWebPageDef.cpp + src/common/resource/sections/CWebPageDef.h ) -SOURCE_GROUP (common\\resource\\sections FILES ${resourcesections_SRCS}) +source_group(common\\resource\\sections FILES ${resourcesections_SRCS}) # Sphere library files -SET (spherelibrary_SRCS -src/common/sphere_library/CSAssoc.cpp -src/common/sphere_library/CSAssoc.h -src/common/sphere_library/CSFile.cpp -src/common/sphere_library/CSFile.h -src/common/sphere_library/CSFileList.cpp -src/common/sphere_library/CSFileList.h -src/common/sphere_library/CSFileText.cpp -src/common/sphere_library/CSFileText.h -src/common/sphere_library/CSMemBlock.cpp -src/common/sphere_library/CSMemBlock.h -src/common/sphere_library/CSObjArray.h -src/common/sphere_library/CSObjCont.cpp -src/common/sphere_library/CSObjCont.h -src/common/sphere_library/CSObjContRec.h -src/common/sphere_library/CSObjList.cpp -src/common/sphere_library/CSObjList.h -src/common/sphere_library/CSObjListRec.h -src/common/sphere_library/CSObjSortArray.h -src/common/sphere_library/CSPtrTypeArray.h -src/common/sphere_library/CSReferenceCount.h -src/common/sphere_library/CSTypedArray.h -src/common/sphere_library/CSQueue.cpp -src/common/sphere_library/CSQueue.h -src/common/sphere_library/CSRand.cpp -src/common/sphere_library/CSRand.h -src/common/sphere_library/CSString.cpp -src/common/sphere_library/CSString.h -src/common/sphere_library/CSTime.cpp -src/common/sphere_library/CSTime.h -src/common/sphere_library/CSWindow.cpp -src/common/sphere_library/CSWindow.h -src/common/sphere_library/scontainer_ops.h -src/common/sphere_library/sfastmath.h -src/common/sphere_library/smap.h -src/common/sphere_library/smutex.h -src/common/sphere_library/smutex.cpp -src/common/sphere_library/squeues.h -src/common/sphere_library/sresetevents.cpp -src/common/sphere_library/sresetevents.h -src/common/sphere_library/ssorted_vector.h -src/common/sphere_library/sptr.h -src/common/sphere_library/sptr_containers.h -src/common/sphere_library/sstacks.h -src/common/sphere_library/sstring.cpp -src/common/sphere_library/sstring.h -src/common/sphere_library/sstringobjs.cpp -src/common/sphere_library/sstringobjs.h -src/common/sphere_library/stypecast.h +set(spherelibrary_SRCS + src/common/sphere_library/CSAssoc.cpp + src/common/sphere_library/CSAssoc.h + src/common/sphere_library/CSFile.cpp + src/common/sphere_library/CSFile.h + src/common/sphere_library/CSFileList.cpp + src/common/sphere_library/CSFileList.h + src/common/sphere_library/CSFileText.cpp + src/common/sphere_library/CSFileText.h + src/common/sphere_library/CSMemBlock.cpp + src/common/sphere_library/CSMemBlock.h + src/common/sphere_library/CSObjArray.h + src/common/sphere_library/CSObjCont.cpp + src/common/sphere_library/CSObjCont.h + src/common/sphere_library/CSObjContRec.h + src/common/sphere_library/CSObjList.cpp + src/common/sphere_library/CSObjList.h + src/common/sphere_library/CSObjListRec.h + src/common/sphere_library/CSObjSortArray.h + src/common/sphere_library/CSPtrTypeArray.h + src/common/sphere_library/CSReferenceCount.h + src/common/sphere_library/CSTypedArray.h + src/common/sphere_library/CSQueue.cpp + src/common/sphere_library/CSQueue.h + src/common/sphere_library/CSRand.cpp + src/common/sphere_library/CSRand.h + src/common/sphere_library/CSString.cpp + src/common/sphere_library/CSString.h + src/common/sphere_library/CSTime.cpp + src/common/sphere_library/CSTime.h + src/common/sphere_library/CSWindow.cpp + src/common/sphere_library/CSWindow.h + src/common/sphere_library/scontainer_ops.h + src/common/sphere_library/sfastmath.h + src/common/sphere_library/smap.h + src/common/sphere_library/smutex.h + src/common/sphere_library/smutex.cpp + src/common/sphere_library/squeues.h + src/common/sphere_library/sresetevents.cpp + src/common/sphere_library/sresetevents.h + src/common/sphere_library/ssorted_vector.h + src/common/sphere_library/sptr.h + src/common/sphere_library/sptr_containers.h + src/common/sphere_library/sstacks.h + src/common/sphere_library/sstring.cpp + src/common/sphere_library/sstring.h + src/common/sphere_library/sstringobjs.cpp + src/common/sphere_library/sstringobjs.h + src/common/sphere_library/stypecast.h ) -SOURCE_GROUP (common\\sphere_library FILES ${spherelibrary_SRCS}) +source_group(common\\sphere_library FILES ${spherelibrary_SRCS}) # Main game files. -SET (game_SRCS -src/game/CBase.cpp -src/game/CBase.h -src/game/CContainer.cpp -src/game/CContainer.h -src/game/CComponent.cpp -src/game/CComponent.h -src/game/CComponentProps.cpp -src/game/CComponentProps.h -src/game/CEntity.cpp -src/game/CEntity.h -src/game/CEntityProps.cpp -src/game/CEntityProps.h -src/game/CObjBase.cpp -src/game/CObjBase.h -src/game/CObjBaseTemplate.cpp -src/game/CObjBaseTemplate.h -src/game/CPathFinder.cpp -src/game/CPathFinder.h -src/game/CRegion.cpp -src/game/CRegion.h -src/game/CRegionBase.cpp -src/game/CRegionBase.h -src/game/CResourceCalc.cpp -src/game/CScriptProfiler.h -src/game/CSector.cpp -src/game/CSector.h -src/game/CSectorEnviron.h -src/game/CSectorEnviron.cpp -src/game/CSectorTemplate.cpp -src/game/CSectorTemplate.h -src/game/CSectorList.cpp -src/game/CSectorList.h -src/game/CServer.cpp -src/game/CServer.h -src/game/CServerConfig.cpp -src/game/CServerConfig.h -src/game/CServerDef.cpp -src/game/CServerDef.h -src/game/CServerTime.cpp -src/game/CServerTime.h -src/game/CStartLoc.h -src/game/CTeleport.cpp -src/game/CTeleport.h -src/game/CTimedFunction.cpp -src/game/CTimedFunction.h -src/game/CTimedFunctionHandler.cpp -src/game/CTimedFunctionHandler.h -src/game/CTimedObject.cpp -src/game/CTimedObject.h -src/game/CWorld.cpp -src/game/CWorld.h -src/game/CWorldCache.cpp -src/game/CWorldCache.h -src/game/CWorldClock.cpp -src/game/CWorldClock.h -src/game/CWorldComm.cpp -src/game/CWorldComm.h -src/game/CWorldGameTime.cpp -src/game/CWorldGameTime.h -src/game/CWorldImport.cpp -src/game/CWorldMap.cpp -src/game/CWorldMap.h -src/game/CWorldSearch.cpp -src/game/CWorldSearch.h -src/game/CWorldTicker.cpp -src/game/CWorldTicker.h -src/game/CWorldTickingList.cpp -src/game/CWorldTickingList.h -src/game/CWorldTimedFunctions.cpp -src/game/CWorldTimedFunctions.h -src/game/game_enums.h -src/game/game_macros.h -src/game/spheresvr.cpp -src/game/spheresvr.h -src/game/triggers.h -src/game/triggers.cpp +set(game_SRCS + src/game/CBase.cpp + src/game/CBase.h + src/game/CContainer.cpp + src/game/CContainer.h + src/game/CComponent.cpp + src/game/CComponent.h + src/game/CComponentProps.cpp + src/game/CComponentProps.h + src/game/CEntity.cpp + src/game/CEntity.h + src/game/CEntityProps.cpp + src/game/CEntityProps.h + src/game/CObjBase.cpp + src/game/CObjBase.h + src/game/CObjBaseTemplate.cpp + src/game/CObjBaseTemplate.h + src/game/CPathFinder.cpp + src/game/CPathFinder.h + src/game/CRegion.cpp + src/game/CRegion.h + src/game/CRegionBase.cpp + src/game/CRegionBase.h + src/game/CResourceCalc.cpp + src/game/CScriptProfiler.h + src/game/CSector.cpp + src/game/CSector.h + src/game/CSectorEnviron.h + src/game/CSectorEnviron.cpp + src/game/CSectorTemplate.cpp + src/game/CSectorTemplate.h + src/game/CSectorList.cpp + src/game/CSectorList.h + src/game/CServer.cpp + src/game/CServer.h + src/game/CServerConfig.cpp + src/game/CServerConfig.h + src/game/CServerDef.cpp + src/game/CServerDef.h + src/game/CServerTime.cpp + src/game/CServerTime.h + src/game/CStartLoc.h + src/game/CTeleport.cpp + src/game/CTeleport.h + src/game/CTimedFunction.cpp + src/game/CTimedFunction.h + src/game/CTimedFunctionHandler.cpp + src/game/CTimedFunctionHandler.h + src/game/CTimedObject.cpp + src/game/CTimedObject.h + src/game/CWorld.cpp + src/game/CWorld.h + src/game/CWorldCache.cpp + src/game/CWorldCache.h + src/game/CWorldClock.cpp + src/game/CWorldClock.h + src/game/CWorldComm.cpp + src/game/CWorldComm.h + src/game/CWorldGameTime.cpp + src/game/CWorldGameTime.h + src/game/CWorldImport.cpp + src/game/CWorldMap.cpp + src/game/CWorldMap.h + src/game/CWorldSearch.cpp + src/game/CWorldSearch.h + src/game/CWorldTicker.cpp + src/game/CWorldTicker.h + src/game/CWorldTickingList.cpp + src/game/CWorldTickingList.h + src/game/CWorldTimedFunctions.cpp + src/game/CWorldTimedFunctions.h + src/game/game_enums.h + src/game/game_macros.h + src/game/spheresvr.cpp + src/game/spheresvr.h + src/game/triggers.h + src/game/triggers.cpp ) -SOURCE_GROUP (game FILES ${game_SRCS}) +source_group(game FILES ${game_SRCS}) -SET (items_SRCS -src/game/items/CItem.cpp -src/game/items/CItem.h -src/game/items/CItemBase.cpp -src/game/items/CItemBase.h -src/game/items/CItemCommCrystal.cpp -src/game/items/CItemCommCrystal.h -src/game/items/CItemContainer.cpp -src/game/items/CItemContainer.h -src/game/items/CItemCorpse.cpp -src/game/items/CItemCorpse.h -src/game/items/CItemMap.cpp -src/game/items/CItemMap.h -src/game/items/CItemMemory.cpp -src/game/items/CItemMemory.h -src/game/items/CItemMessage.cpp -src/game/items/CItemMessage.h -src/game/items/CItemMulti.cpp -src/game/items/CItemMulti.h -src/game/items/CItemMultiCustom.cpp -src/game/items/CItemMultiCustom.h -src/game/items/CItemPlant.cpp -src/game/items/CItemScript.cpp -src/game/items/CItemScript.h -src/game/items/CItemShip.cpp -src/game/items/CItemShip.h -src/game/items/CItemScript.cpp -src/game/items/CItemScript.h -src/game/items/CItemStone.cpp -src/game/items/CItemStone.h -src/game/items/CItemVendable.cpp -src/game/items/CItemVendable.h -src/game/items/item_types.h +set(items_SRCS + src/game/items/CItem.cpp + src/game/items/CItem.h + src/game/items/CItemBase.cpp + src/game/items/CItemBase.h + src/game/items/CItemCommCrystal.cpp + src/game/items/CItemCommCrystal.h + src/game/items/CItemContainer.cpp + src/game/items/CItemContainer.h + src/game/items/CItemCorpse.cpp + src/game/items/CItemCorpse.h + src/game/items/CItemMap.cpp + src/game/items/CItemMap.h + src/game/items/CItemMemory.cpp + src/game/items/CItemMemory.h + src/game/items/CItemMessage.cpp + src/game/items/CItemMessage.h + src/game/items/CItemMulti.cpp + src/game/items/CItemMulti.h + src/game/items/CItemMultiCustom.cpp + src/game/items/CItemMultiCustom.h + src/game/items/CItemPlant.cpp + src/game/items/CItemScript.cpp + src/game/items/CItemScript.h + src/game/items/CItemShip.cpp + src/game/items/CItemShip.h + src/game/items/CItemScript.cpp + src/game/items/CItemScript.h + src/game/items/CItemStone.cpp + src/game/items/CItemStone.h + src/game/items/CItemVendable.cpp + src/game/items/CItemVendable.h + src/game/items/item_types.h ) -SOURCE_GROUP (game\\items FILES ${items_SRCS}) +source_group(game\\items FILES ${items_SRCS}) -SET (chars_SRCS -src/game/chars/CCharAct.cpp -src/game/chars/CCharBase.cpp -src/game/chars/CChar.cpp -src/game/chars/CChar.h -src/game/chars/CCharAttacker.cpp -src/game/chars/CCharBase.h -src/game/chars/CCharFight.cpp -src/game/chars/CCharLOS.cpp -src/game/chars/CCharMemory.cpp -src/game/chars/CCharNotoriety.cpp -src/game/chars/CCharNPC.cpp -src/game/chars/CCharNPC.h -src/game/chars/CCharNPCAct.cpp -src/game/chars/CCharNPCAct_Fight.cpp -src/game/chars/CCharNPCAct_Magic.cpp -src/game/chars/CCharNPCAct_Vendor.cpp -src/game/chars/CCharNPCPet.cpp -src/game/chars/CCharNPCStatus.cpp -src/game/chars/CCharPlayer.cpp -src/game/chars/CCharPlayer.h -src/game/chars/CCharRefArray.h -src/game/chars/CCharRefArray.cpp -src/game/chars/CCharSkill.cpp -src/game/chars/CCharSpell.cpp -src/game/chars/CCharStat.cpp -src/game/chars/CCharStatus.cpp -src/game/chars/CCharUse.cpp -src/game/chars/CStoneMember.h -src/game/chars/CStoneMember.cpp +set(chars_SRCS + src/game/chars/CCharAct.cpp + src/game/chars/CCharBase.cpp + src/game/chars/CChar.cpp + src/game/chars/CChar.h + src/game/chars/CCharAttacker.cpp + src/game/chars/CCharBase.h + src/game/chars/CCharFight.cpp + src/game/chars/CCharLOS.cpp + src/game/chars/CCharMemory.cpp + src/game/chars/CCharNotoriety.cpp + src/game/chars/CCharNPC.cpp + src/game/chars/CCharNPC.h + src/game/chars/CCharNPCAct.cpp + src/game/chars/CCharNPCAct_Fight.cpp + src/game/chars/CCharNPCAct_Magic.cpp + src/game/chars/CCharNPCAct_Vendor.cpp + src/game/chars/CCharNPCPet.cpp + src/game/chars/CCharNPCStatus.cpp + src/game/chars/CCharPlayer.cpp + src/game/chars/CCharPlayer.h + src/game/chars/CCharRefArray.h + src/game/chars/CCharRefArray.cpp + src/game/chars/CCharSkill.cpp + src/game/chars/CCharSpell.cpp + src/game/chars/CCharStat.cpp + src/game/chars/CCharStatus.cpp + src/game/chars/CCharUse.cpp + src/game/chars/CStoneMember.h + src/game/chars/CStoneMember.cpp ) -SOURCE_GROUP (game\\chars FILES ${chars_SRCS}) +source_group(game\\chars FILES ${chars_SRCS}) -SET (clients_SRCS -src/game/clients/CAccount.cpp -src/game/clients/CAccount.h -src/game/clients/CChat.cpp -src/game/clients/CChat.h -src/game/clients/CChatChannel.cpp -src/game/clients/CChatChannel.h -src/game/clients/CChatChanMember.cpp -src/game/clients/CChatChanMember.h -src/game/clients/CClient.cpp -src/game/clients/CClientDialog.cpp -src/game/clients/CClientEvent.cpp -src/game/clients/CClient.h -src/game/clients/CClientLog.cpp -src/game/clients/CClientMsg.cpp -src/game/clients/CClientMsg_AOSTooltip.cpp -src/game/clients/CClientTarg.cpp -src/game/clients/CClientTooltip.h -src/game/clients/CClientTooltip.cpp -src/game/clients/CClientUse.cpp -src/game/clients/CGlobalChatChanMember.cpp -src/game/clients/CGlobalChatChanMember.h -src/game/clients/CGMPage.cpp -src/game/clients/CGMPage.h -src/game/clients/CParty.cpp -src/game/clients/CParty.h +set(clients_SRCS + src/game/clients/CAccount.cpp + src/game/clients/CAccount.h + src/game/clients/CChat.cpp + src/game/clients/CChat.h + src/game/clients/CChatChannel.cpp + src/game/clients/CChatChannel.h + src/game/clients/CChatChanMember.cpp + src/game/clients/CChatChanMember.h + src/game/clients/CClient.cpp + src/game/clients/CClientDialog.cpp + src/game/clients/CClientEvent.cpp + src/game/clients/CClient.h + src/game/clients/CClientLog.cpp + src/game/clients/CClientMsg.cpp + src/game/clients/CClientMsg_AOSTooltip.cpp + src/game/clients/CClientTarg.cpp + src/game/clients/CClientTooltip.h + src/game/clients/CClientTooltip.cpp + src/game/clients/CClientUse.cpp + src/game/clients/CGlobalChatChanMember.cpp + src/game/clients/CGlobalChatChanMember.h + src/game/clients/CGMPage.cpp + src/game/clients/CGMPage.h + src/game/clients/CParty.cpp + src/game/clients/CParty.h ) -SOURCE_GROUP (game\\clients FILES ${clients_SRCS}) +source_group(game\\clients FILES ${clients_SRCS}) -SET (components_SRCS -src/game/components/subcomponents/CFactionDef.cpp -src/game/components/subcomponents/CFactionDef.h -src/game/components/CCChampion.cpp -src/game/components/CCChampion.h -src/game/components/CCItemDamageable.cpp -src/game/components/CCItemDamageable.h -src/game/components/CCMultiMovable.cpp -src/game/components/CCMultiMovable.h -src/game/components/CCPropsChar.cpp -src/game/components/CCPropsChar.h -src/game/components/CCPropsItem.cpp -src/game/components/CCPropsItem.h -src/game/components/CCPropsItemChar.cpp -src/game/components/CCPropsItemChar.h -src/game/components/CCPropsItemEquippable.cpp -src/game/components/CCPropsItemEquippable.h -src/game/components/CCPropsItemWeapon.cpp -src/game/components/CCPropsItemWeapon.h -src/game/components/CCPropsItemWeaponRanged.cpp -src/game/components/CCPropsItemWeaponRanged.h -src/game/components/CCSpawn.cpp -src/game/components/CCSpawn.h +set(components_SRCS + src/game/components/subcomponents/CFactionDef.cpp + src/game/components/subcomponents/CFactionDef.h + src/game/components/CCChampion.cpp + src/game/components/CCChampion.h + src/game/components/CCItemDamageable.cpp + src/game/components/CCItemDamageable.h + src/game/components/CCMultiMovable.cpp + src/game/components/CCMultiMovable.h + src/game/components/CCPropsChar.cpp + src/game/components/CCPropsChar.h + src/game/components/CCPropsItem.cpp + src/game/components/CCPropsItem.h + src/game/components/CCPropsItemChar.cpp + src/game/components/CCPropsItemChar.h + src/game/components/CCPropsItemEquippable.cpp + src/game/components/CCPropsItemEquippable.h + src/game/components/CCPropsItemWeapon.cpp + src/game/components/CCPropsItemWeapon.h + src/game/components/CCPropsItemWeaponRanged.cpp + src/game/components/CCPropsItemWeaponRanged.h + src/game/components/CCSpawn.cpp + src/game/components/CCSpawn.h ) -SOURCE_GROUP (game\\components FILES ${components_SRCS}) +source_group(game\\components FILES ${components_SRCS}) # CrashDump files -SET (crashdump_SRCS -src/common/crashdump/crashdump.cpp -src/common/crashdump/crashdump.h -src/common/crashdump/mingwdbghelp.h +set(crashdump_SRCS + src/common/crashdump/crashdump.cpp + src/common/crashdump/crashdump.h + src/common/crashdump/mingwdbghelp.h ) -SOURCE_GROUP (common\\crashdump FILES ${crashdump_SRCS}) +source_group(common\\crashdump FILES ${crashdump_SRCS}) # Table definitions -SET (tables_SRCS -src/tables/CBaseBaseDef_props.tbl -src/tables/CChar_functions.tbl -src/tables/CChar_props.tbl -src/tables/CCharBase_props.tbl -src/tables/CCharNpc_props.tbl -src/tables/CCharPlayer_functions.tbl -src/tables/CCharPlayer_props.tbl -src/tables/CClient_functions.tbl -src/tables/CClient_props.tbl -src/tables/CCPropsChar_props.tbl -src/tables/CCPropsItem_props.tbl -src/tables/CCPropsItemChar_props.tbl -src/tables/CCPropsItemEquippable_props.tbl -src/tables/CCPropsItemWeapon_props.tbl -src/tables/CCPropsItemWeaponRanged_props.tbl -src/tables/CSFileObj_functions.tbl -src/tables/CSFileObj_props.tbl -src/tables/CSFileObjContainer_functions.tbl -src/tables/CSFileObjContainer_props.tbl -src/tables/CItem_functions.tbl -src/tables/CItem_props.tbl -src/tables/CItemBase_props.tbl -src/tables/CItemStone_functions.tbl -src/tables/CItemStone_props.tbl -src/tables/classnames.tbl -src/tables/CObjBase_functions.tbl -src/tables/CObjBase_props.tbl -src/tables/CParty_functions.tbl -src/tables/CParty_props.tbl -src/tables/CScriptObj_functions.tbl -src/tables/CSector_functions.tbl -src/tables/CStoneMember_functions.tbl -src/tables/CStoneMember_props.tbl -src/tables/defmessages.tbl -src/tables/triggers.tbl +set(tables_SRCS + src/tables/CBaseBaseDef_props.tbl + src/tables/CChar_functions.tbl + src/tables/CChar_props.tbl + src/tables/CCharBase_props.tbl + src/tables/CCharNpc_props.tbl + src/tables/CCharPlayer_functions.tbl + src/tables/CCharPlayer_props.tbl + src/tables/CClient_functions.tbl + src/tables/CClient_props.tbl + src/tables/CCPropsChar_props.tbl + src/tables/CCPropsItem_props.tbl + src/tables/CCPropsItemChar_props.tbl + src/tables/CCPropsItemEquippable_props.tbl + src/tables/CCPropsItemWeapon_props.tbl + src/tables/CCPropsItemWeaponRanged_props.tbl + src/tables/CSFileObj_functions.tbl + src/tables/CSFileObj_props.tbl + src/tables/CSFileObjContainer_functions.tbl + src/tables/CSFileObjContainer_props.tbl + src/tables/CItem_functions.tbl + src/tables/CItem_props.tbl + src/tables/CItemBase_props.tbl + src/tables/CItemStone_functions.tbl + src/tables/CItemStone_props.tbl + src/tables/classnames.tbl + src/tables/CObjBase_functions.tbl + src/tables/CObjBase_props.tbl + src/tables/CParty_functions.tbl + src/tables/CParty_props.tbl + src/tables/CScriptObj_functions.tbl + src/tables/CSector_functions.tbl + src/tables/CStoneMember_functions.tbl + src/tables/CStoneMember_props.tbl + src/tables/defmessages.tbl + src/tables/triggers.tbl ) -SOURCE_GROUP (tables FILES ${tables_SRCS}) +source_group(tables FILES ${tables_SRCS}) -SET (app_resources_SRCS -src/resources/SphereSvr.rc -) +set(app_resources_SRCS src/resources/SphereSvr.rc) # Misc doc and *.ini files -SET (docs_TEXT -Changelog.txt -src/sphere.ini -src/sphereCrypt.ini -) - +set(docs_TEXT Changelog.txt src/sphere.ini src/sphereCrypt.ini) -SET (SPHERE_SOURCES - ${game_SRCS} - ${items_SRCS} - ${chars_SRCS} - ${clients_SRCS} - ${components_SRCS} - ${uofiles_SRCS} - ${common_SRCS} - ${resource_SRCS} - ${resourcesections_SRCS} - ${network_SRCS} - ${crypto_SRCS} - ${sphere_SRCS} - ${crashdump_SRCS} - ${spherelibrary_SRCS} - ${tables_SRCS} - ${app_resources_SRCS} +set(SPHERE_SOURCES + ${game_SRCS} + ${items_SRCS} + ${chars_SRCS} + ${clients_SRCS} + ${components_SRCS} + ${uofiles_SRCS} + ${common_SRCS} + ${resource_SRCS} + ${resourcesections_SRCS} + ${network_SRCS} + ${crypto_SRCS} + ${sphere_SRCS} + ${crashdump_SRCS} + ${spherelibrary_SRCS} + ${tables_SRCS} + ${app_resources_SRCS} ) diff --git a/src/CompilerFlags.cmake b/src/CompilerFlags.cmake index 1d934b437..f48f2bf42 100644 --- a/src/CompilerFlags.cmake +++ b/src/CompilerFlags.cmake @@ -1,54 +1,71 @@ - # TODO: CITE ANTLR -if (CMAKE_CXX_COMPILER_ID MATCHES "GNU") - - # Pedantic error flags - set (PEDANTIC_COMPILE_FLAGS - -pedantic-errors -Wall -Wextra -pedantic - -Wundef - -Wmissing-include-dirs - -Wredundant-decls -Wwrite-strings -Wpointer-arith - -Wformat=2 -Wno-format-nonliteral - -Wcast-qual -Wcast-align -Wconversion - -Wctor-dtor-privacy -Wdisabled-optimization - -Winvalid-pch -Woverloaded-virtual - -Wno-ctor-dtor-privacy - ) - #if (NOT CMAKE_CXX_COMPILER_VERSION VERSION_LESS 4.6) - set(PEDANTIC_COMPILE_FLAGS ${PEDANTIC_COMPILE_FLAGS} - -Wno-dangling-else -Wno-unused-local-typedefs) - #endif () - #if (NOT CMAKE_CXX_COMPILER_VERSION VERSION_LESS 5.0) - set(PEDANTIC_COMPILE_FLAGS ${PEDANTIC_COMPILE_FLAGS} -Wdouble-promotion - -Wtrampolines -Wzero-as-null-pointer-constant -Wuseless-cast - -Wvector-operation-performance -Wsized-deallocation -Wshadow) - #endif () - #if (NOT CMAKE_CXX_COMPILER_VERSION VERSION_LESS 6.0) - set(PEDANTIC_COMPILE_FLAGS ${PEDANTIC_COMPILE_FLAGS} -Wshift-overflow=2 - -Wnull-dereference -Wduplicated-cond) - #endif () - set(WERROR_FLAG -Werror) -endif () - - -if (CMAKE_CXX_COMPILER_ID MATCHES "Clang") - # Pedantic error flags - set(PEDANTIC_COMPILE_FLAGS -Wall -Wextra -pedantic -Wconversion -Wundef - -Wdeprecated -Wweak-vtables -Wshadow - -Wno-gnu-zero-variadic-macro-arguments) - check_cxx_compiler_flag(-Wzero-as-null-pointer-constant HAS_NULLPTR_WARNING) - if (HAS_NULLPTR_WARNING) - set(PEDANTIC_COMPILE_FLAGS ${PEDANTIC_COMPILE_FLAGS} - -Wzero-as-null-pointer-constant) - endif () - set(WERROR_FLAG -Werror) -endif () - +if(CMAKE_CXX_COMPILER_ID MATCHES "GNU") + # Pedantic error flags + set(PEDANTIC_COMPILE_FLAGS + -pedantic-errors + -Wall + -Wextra + -pedantic + -Wundef + -Wmissing-include-dirs + -Wredundant-decls + -Wwrite-strings + -Wpointer-arith + -Wformat=2 + -Wno-format-nonliteral + -Wcast-qual + -Wcast-align + -Wconversion + -Wctor-dtor-privacy + -Wdisabled-optimization + -Winvalid-pch + -Woverloaded-virtual + -Wno-ctor-dtor-privacy + ) + #if (NOT CMAKE_CXX_COMPILER_VERSION VERSION_LESS 4.6) + set(PEDANTIC_COMPILE_FLAGS ${PEDANTIC_COMPILE_FLAGS} -Wno-dangling-else -Wno-unused-local-typedefs) + #endif () + #if (NOT CMAKE_CXX_COMPILER_VERSION VERSION_LESS 5.0) + set(PEDANTIC_COMPILE_FLAGS + ${PEDANTIC_COMPILE_FLAGS} + -Wdouble-promotion + -Wtrampolines + -Wzero-as-null-pointer-constant + -Wuseless-cast + -Wvector-operation-performance + -Wsized-deallocation + -Wshadow + ) + #endif () + #if (NOT CMAKE_CXX_COMPILER_VERSION VERSION_LESS 6.0) + set(PEDANTIC_COMPILE_FLAGS ${PEDANTIC_COMPILE_FLAGS} -Wshift-overflow=2 -Wnull-dereference -Wduplicated-cond) + #endif () + set(WERROR_FLAG -Werror) +endif() -if (MSVC) - # Pedantic error flags - set(PEDANTIC_COMPILE_FLAGS /W3) - set(WERROR_FLAG /WX) +if(CMAKE_CXX_COMPILER_ID MATCHES "Clang") + # Pedantic error flags + set(PEDANTIC_COMPILE_FLAGS + -Wall + -Wextra + -pedantic + -Wconversion + -Wundef + -Wdeprecated + -Wweak-vtables + -Wshadow + -Wno-gnu-zero-variadic-macro-arguments + ) + check_cxx_compiler_flag(-Wzero-as-null-pointer-constant HAS_NULLPTR_WARNING) + if(HAS_NULLPTR_WARNING) + set(PEDANTIC_COMPILE_FLAGS ${PEDANTIC_COMPILE_FLAGS} -Wzero-as-null-pointer-constant) + endif() + set(WERROR_FLAG -Werror) +endif() -endif () +if(MSVC) + # Pedantic error flags + set(PEDANTIC_COMPILE_FLAGS /W3) + set(WERROR_FLAG /WX) +endif() diff --git a/utilities/format_cmake.sh b/utilities/cmake_format_gersemi.sh similarity index 82% rename from utilities/format_cmake.sh rename to utilities/cmake_format_gersemi.sh index 9151cab66..69c493e96 100644 --- a/utilities/format_cmake.sh +++ b/utilities/cmake_format_gersemi.sh @@ -7,9 +7,12 @@ if [ "$#" -ne 1 ]; then fi action=$1 +project_root_dir="$(git rev-parse --show-toplevel)" + +# Define the gersemi command; change the execution folder in order to make it read .gersemirc +gersemi_cmd='env PWD="$project_root_dir" gersemi -i "{}"' +#gersemi_cmd='gersemi -i "{}" --list-expansion favour-inlining --no-warn-about-unknown-commands' -# Define the gersemi command -gersemi_cmd='gersemi -i "{}" --list-expansion favour-inlining --no-warn-about-unknown-commands' #looks like cmake-format is unmantained #cmake-format CMakeLists.txt --separate-ctrl-name-with-space --separate-fn-name-with-space --dangle-parens --max-subgroups-hwrap=2 --max-pargs-hwrap=4 --max-rows-cmdline=120 @@ -30,7 +33,7 @@ format_files() { case $action in --all) # Find all *.cmake files and CMakeLists.txt - files=$(find "$(git rev-parse --show-toplevel)" \ + files=$(find "$project_root_dir" \ -type d -name 'CMakeFiles' -prune -o \ -type d -name 'build' -prune -o \ -type d -name '.*' -prune -o \ @@ -47,7 +50,7 @@ case $action in files=$( git diff --name-only HEAD~1 HEAD | grep -E '\.cmake$|CMakeLists\.txt$' ) ;; *) - echo "Invalid option. Use '--all' or '--changed'." + echo "Invalid option." exit 1 ;; esac From 8dece16d96e5859bd9f63c1607c775cd2c22ddb8 Mon Sep 17 00:00:00 2001 From: cbnolok Date: Sun, 8 Sep 2024 14:48:12 +0200 Subject: [PATCH 25/86] CMake files (cmake_format_gersemi.sh): added tab conversion to 4 spaces also for commented lines. --- CMakeLists.txt | 8 +- cmake/toolchains/Linux-Clang-AArch64.cmake | 8 +- cmake/toolchains/Linux-Clang-native.cmake | 8 +- cmake/toolchains/Linux-Clang-x86.cmake | 8 +- cmake/toolchains/Linux-Clang-x86_64.cmake | 8 +- cmake/toolchains/Linux-GNU-AArch64.cmake | 8 +- cmake/toolchains/Linux-GNU-native.cmake | 8 +- cmake/toolchains/Linux-GNU-x86.cmake | 8 +- cmake/toolchains/Linux-GNU-x86_64.cmake | 8 +- cmake/toolchains/OSX-AppleClang-AArch64.cmake | 8 +- cmake/toolchains/OSX-AppleClang-native.cmake | 8 +- cmake/toolchains/OSX-AppleClang-x86_64.cmake | 8 +- cmake/toolchains/Windows-Clang-native.cmake | 20 +-- cmake/toolchains/Windows-Clang-x86.cmake | 12 +- cmake/toolchains/Windows-Clang-x86_64.cmake | 12 +- cmake/toolchains/Windows-GNU-native.cmake | 12 +- cmake/toolchains/Windows-GNU-x86.cmake | 12 +- cmake/toolchains/Windows-GNU-x86_64.cmake | 12 +- cmake/toolchains/Windows-MSVC.cmake | 34 ++--- .../include/Linux-Clang_common.inc.cmake | 12 +- .../include/Linux-GNU_common.inc.cmake | 10 +- .../include/OSX-AppleClang_common.inc.cmake | 14 +- .../include/Windows-Clang_common.inc.cmake | 142 +++++++++--------- .../include/Windows-GNU_common.inc.cmake | 40 ++--- lib/lib_build_flags_common_c.cmake | 22 +-- utilities/cmake_format_gersemi.sh | 11 +- 26 files changed, 235 insertions(+), 226 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 89e3b41b6..50dfda537 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,4 +1,4 @@ -# Main config # +# Main config # cmake_minimum_required(VERSION 3.19) set(CMAKE_SUPPRESS_REGENERATION TRUE) # Supress the ZERO_CHECK generation @@ -161,7 +161,7 @@ if(SINGLE_TARGET) spheresvr_release ${is_win32_app_linker} ${SPHERE_SOURCES} - # ${docs_TEXT} + # ${docs_TEXT} ) set_target_properties(spheresvr_release PROPERTIES OUTPUT_NAME SphereSvrX${ARCH_BITS}_release) endif() @@ -171,7 +171,7 @@ if(SINGLE_TARGET) spheresvr_nightly ${is_win32_app_linker} ${SPHERE_SOURCES} - # ${docs_TEXT} + # ${docs_TEXT} ) set_target_properties(spheresvr_nightly PROPERTIES OUTPUT_NAME SphereSvrX${ARCH_BITS}_nightly) endif() @@ -181,7 +181,7 @@ if(SINGLE_TARGET) spheresvr_debug ${is_win32_app_linker} ${SPHERE_SOURCES} - # ${docs_TEXT} + # ${docs_TEXT} ) set_target_properties(spheresvr_debug PROPERTIES OUTPUT_NAME SphereSvrX${ARCH_BITS}_debug) endif() diff --git a/cmake/toolchains/Linux-Clang-AArch64.cmake b/cmake/toolchains/Linux-Clang-AArch64.cmake index a0cad0d7b..c2cd70ecc 100644 --- a/cmake/toolchains/Linux-Clang-AArch64.cmake +++ b/cmake/toolchains/Linux-Clang-AArch64.cmake @@ -21,7 +21,7 @@ endfunction() function(toolchain_after_project) message(STATUS "Toolchain: Linux-Clang-AArch64.cmake.") # Do not set CMAKE_SYSTEM_NAME if compiling for the same OS, otherwise CMAKE_CROSSCOMPILING will be set to TRUE - #SET(CMAKE_SYSTEM_NAME "Linux" CACHE INTERNAL "" FORCE) + #SET(CMAKE_SYSTEM_NAME "Linux" CACHE INTERNAL "" FORCE) set(CMAKE_SYSTEM_PROCESSOR "aarch64" CACHE INTERNAL "" FORCE) set(CMAKE_RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/bin-aarch64" PARENT_SCOPE) #set(ARCH_BITS 64 CACHE INTERNAL "" FORCE) # provide it @@ -62,7 +62,7 @@ function(toolchain_exe_stuff) toolchain_exe_stuff_common() # Propagate global variables set in toolchain_exe_stuff_common to the upper scope - #SET (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${C_ARCH_OPTS}" PARENT_SCOPE) - #SET (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${CXX_ARCH_OPTS}" PARENT_SCOPE) - #SET (CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS}" PARENT_SCOPE) + #SET (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${C_ARCH_OPTS}" PARENT_SCOPE) + #SET (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${CXX_ARCH_OPTS}" PARENT_SCOPE) + #SET (CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS}" PARENT_SCOPE) endfunction() diff --git a/cmake/toolchains/Linux-Clang-native.cmake b/cmake/toolchains/Linux-Clang-native.cmake index c4f2792bd..cbcded7d1 100644 --- a/cmake/toolchains/Linux-Clang-native.cmake +++ b/cmake/toolchains/Linux-Clang-native.cmake @@ -12,7 +12,7 @@ endfunction() function(toolchain_after_project) message(STATUS "Toolchain: Linux-Clang-native.cmake.") # Do not set CMAKE_SYSTEM_NAME if compiling for the same OS, otherwise CMAKE_CROSSCOMPILING will be set to TRUE - #SET(CMAKE_SYSTEM_NAME "Linux" CACHE INTERNAL "" FORCE) # target OS + #SET(CMAKE_SYSTEM_NAME "Linux" CACHE INTERNAL "" FORCE) # target OS if(CMAKE_SIZEOF_VOID_P EQUAL 8) set(CMAKE_RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/bin-native64" PARENT_SCOPE) else() @@ -55,7 +55,7 @@ function(toolchain_exe_stuff) toolchain_exe_stuff_common() # Propagate global variables set in toolchain_exe_stuff_common to the upper scope - #SET (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${C_ARCH_OPTS}" PARENT_SCOPE) - #SET (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${CXX_ARCH_OPTS}" PARENT_SCOPE) - #SET (CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS}" PARENT_SCOPE) + #SET (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${C_ARCH_OPTS}" PARENT_SCOPE) + #SET (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${CXX_ARCH_OPTS}" PARENT_SCOPE) + #SET (CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS}" PARENT_SCOPE) endfunction() diff --git a/cmake/toolchains/Linux-Clang-x86.cmake b/cmake/toolchains/Linux-Clang-x86.cmake index 335c522ce..cf3a1c5ed 100644 --- a/cmake/toolchains/Linux-Clang-x86.cmake +++ b/cmake/toolchains/Linux-Clang-x86.cmake @@ -23,7 +23,7 @@ endfunction() function(toolchain_after_project) message(STATUS "Toolchain: Linux-Clang-x86.cmake.") # Do not set CMAKE_SYSTEM_NAME if compiling for the same OS, otherwise CMAKE_CROSSCOMPILING will be set to TRUE - #SET(CMAKE_SYSTEM_NAME "Linux" CACHE INTERNAL "" FORCE) # target OS + #SET(CMAKE_SYSTEM_NAME "Linux" CACHE INTERNAL "" FORCE) # target OS set(CMAKE_SYSTEM_PROCESSOR "x86" CACHE INTERNAL "" FORCE) # target arch set(CMAKE_RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/bin-x86" PARENT_SCOPE) #set(ARCH_BITS 32 CACHE INTERNAL "" FORCE) # provide it @@ -81,7 +81,7 @@ function(toolchain_exe_stuff) toolchain_exe_stuff_common() # Propagate global variables set in toolchain_exe_stuff_common to the upper scope - #SET (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${C_ARCH_OPTS}" PARENT_SCOPE) - #SET (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${CXX_ARCH_OPTS}" PARENT_SCOPE) - #SET (CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS}" PARENT_SCOPE) + #SET (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${C_ARCH_OPTS}" PARENT_SCOPE) + #SET (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${CXX_ARCH_OPTS}" PARENT_SCOPE) + #SET (CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS}" PARENT_SCOPE) endfunction() diff --git a/cmake/toolchains/Linux-Clang-x86_64.cmake b/cmake/toolchains/Linux-Clang-x86_64.cmake index 562738bbd..fdc1fbe84 100644 --- a/cmake/toolchains/Linux-Clang-x86_64.cmake +++ b/cmake/toolchains/Linux-Clang-x86_64.cmake @@ -23,7 +23,7 @@ endfunction() function(toolchain_after_project) message(STATUS "Toolchain: Linux-Clang-x86_64.cmake.") # Do not set CMAKE_SYSTEM_NAME if compiling for the same OS, otherwise CMAKE_CROSSCOMPILING will be set to TRUE - #SET(CMAKE_SYSTEM_NAME "Linux" CACHE INTERNAL "" FORCE) # target OS + #SET(CMAKE_SYSTEM_NAME "Linux" CACHE INTERNAL "" FORCE) # target OS set(CMAKE_SYSTEM_PROCESSOR "x86_64" CACHE INTERNAL "" FORCE) # target arch set(CMAKE_RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/bin-x86_64" PARENT_SCOPE) set(ARCH_BITS 64 CACHE INTERNAL "" FORCE) # provide it @@ -65,7 +65,7 @@ function(toolchain_exe_stuff) toolchain_exe_stuff_common() # Propagate global variables set in toolchain_exe_stuff_common to the upper scope - #SET (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${C_ARCH_OPTS}" PARENT_SCOPE) - #SET (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${CXX_ARCH_OPTS}" PARENT_SCOPE) - #SET (CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS}" PARENT_SCOPE) + #SET (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${C_ARCH_OPTS}" PARENT_SCOPE) + #SET (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${CXX_ARCH_OPTS}" PARENT_SCOPE) + #SET (CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS}" PARENT_SCOPE) endfunction() diff --git a/cmake/toolchains/Linux-GNU-AArch64.cmake b/cmake/toolchains/Linux-GNU-AArch64.cmake index ae5da2bd6..bb908928e 100644 --- a/cmake/toolchains/Linux-GNU-AArch64.cmake +++ b/cmake/toolchains/Linux-GNU-AArch64.cmake @@ -24,7 +24,7 @@ endfunction() function(toolchain_after_project) message(STATUS "Toolchain: Linux-GNU-AArch64.cmake.") # Do not set CMAKE_SYSTEM_NAME if compiling for the same OS, otherwise CMAKE_CROSSCOMPILING will be set to TRUE - #SET(CMAKE_SYSTEM_NAME "Linux" CACHE INTERNAL "" FORCE) + #SET(CMAKE_SYSTEM_NAME "Linux" CACHE INTERNAL "" FORCE) set(CMAKE_SYSTEM_PROCESSOR "aarch64" CACHE INTERNAL "" FORCE) set(CMAKE_RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/bin-aarch64" CACHE INTERNAL "" FORCE) set(ARCH_BITS 64 CACHE INTERNAL "" FORCE) # provide it @@ -65,7 +65,7 @@ function(toolchain_exe_stuff) toolchain_exe_stuff_common() # Propagate global variables set in toolchain_exe_stuff_common to the upper scope - #SET (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${C_ARCH_OPTS}" PARENT_SCOPE) - #SET (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${CXX_ARCH_OPTS}" PARENT_SCOPE) - #SET (CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS}" PARENT_SCOPE) + #SET (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${C_ARCH_OPTS}" PARENT_SCOPE) + #SET (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${CXX_ARCH_OPTS}" PARENT_SCOPE) + #SET (CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS}" PARENT_SCOPE) endfunction() diff --git a/cmake/toolchains/Linux-GNU-native.cmake b/cmake/toolchains/Linux-GNU-native.cmake index 322dcff3b..c998ceecd 100644 --- a/cmake/toolchains/Linux-GNU-native.cmake +++ b/cmake/toolchains/Linux-GNU-native.cmake @@ -12,7 +12,7 @@ endfunction() function(toolchain_after_project) message(STATUS "Toolchain: Linux-GNU-native.cmake.") # Do not set CMAKE_SYSTEM_NAME if compiling for the same OS, otherwise CMAKE_CROSSCOMPILING will be set to TRUE - #SET(CMAKE_SYSTEM_NAME "Linux" CACHE INTERNAL "" FORCE) # target OS + #SET(CMAKE_SYSTEM_NAME "Linux" CACHE INTERNAL "" FORCE) # target OS if(CMAKE_SIZEOF_VOID_P EQUAL 8) set(CMAKE_RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/bin-native64" PARENT_SCOPE) else() @@ -46,7 +46,7 @@ function(toolchain_exe_stuff) toolchain_exe_stuff_common() # Propagate global variables set in toolchain_exe_stuff_common to the upper scope - #SET (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${C_ARCH_OPTS}" PARENT_SCOPE) - #SET (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${CXX_ARCH_OPTS}" PARENT_SCOPE) - #SET (CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS}" PARENT_SCOPE) + #SET (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${C_ARCH_OPTS}" PARENT_SCOPE) + #SET (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${CXX_ARCH_OPTS}" PARENT_SCOPE) + #SET (CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS}" PARENT_SCOPE) endfunction() diff --git a/cmake/toolchains/Linux-GNU-x86.cmake b/cmake/toolchains/Linux-GNU-x86.cmake index a20c4fb0e..aa2f38f57 100644 --- a/cmake/toolchains/Linux-GNU-x86.cmake +++ b/cmake/toolchains/Linux-GNU-x86.cmake @@ -27,7 +27,7 @@ endfunction() function(toolchain_after_project) message(STATUS "Toolchain: Linux-GNU-x86.cmake.") # Do not set CMAKE_SYSTEM_NAME if compiling for the same OS, otherwise CMAKE_CROSSCOMPILING will be set to TRUE - #SET(CMAKE_SYSTEM_NAME "Linux" CACHE INTERNAL "" FORCE) + #SET(CMAKE_SYSTEM_NAME "Linux" CACHE INTERNAL "" FORCE) set(CMAKE_SYSTEM_PROCESSOR "x86" CACHE INTERNAL "" FORCE) set(CMAKE_RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/bin-x86" PARENT_SCOPE) #set(ARCH_BITS 32 CACHE INTERNAL "" FORCE) # provide it @@ -84,7 +84,7 @@ function(toolchain_exe_stuff) toolchain_exe_stuff_common() # Propagate global variables set in toolchain_exe_stuff_common to the upper scope - #SET (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${C_ARCH_OPTS}" PARENT_SCOPE) - #SET (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${CXX_ARCH_OPTS}" PARENT_SCOPE) - #SET (CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS}" PARENT_SCOPE) + #SET (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${C_ARCH_OPTS}" PARENT_SCOPE) + #SET (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${CXX_ARCH_OPTS}" PARENT_SCOPE) + #SET (CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS}" PARENT_SCOPE) endfunction() diff --git a/cmake/toolchains/Linux-GNU-x86_64.cmake b/cmake/toolchains/Linux-GNU-x86_64.cmake index bb399e508..170c9454f 100644 --- a/cmake/toolchains/Linux-GNU-x86_64.cmake +++ b/cmake/toolchains/Linux-GNU-x86_64.cmake @@ -27,7 +27,7 @@ endfunction() function(toolchain_after_project) message(STATUS "Toolchain: Linux-GNU-x86_64.cmake.") # Do not set CMAKE_SYSTEM_NAME if compiling for the same OS, otherwise CMAKE_CROSSCOMPILING will be set to TRUE - #SET(CMAKE_SYSTEM_NAME "Linux" CACHE INTERNAL "" FORCE) # target os + #SET(CMAKE_SYSTEM_NAME "Linux" CACHE INTERNAL "" FORCE) # target os set(CMAKE_SYSTEM_PROCESSOR "x86_64" CACHE INTERNAL "" FORCE) # target arch set(CMAKE_RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/bin-x86_64" PARENT_SCOPE) #set(ARCH_BITS 64 CACHE INTERNAL "" FORCE) # provide it @@ -68,7 +68,7 @@ function(toolchain_exe_stuff) toolchain_exe_stuff_common() # Propagate global variables set in toolchain_exe_stuff_common to the upper scope - #SET (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${C_ARCH_OPTS}" PARENT_SCOPE) - #SET (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${CXX_ARCH_OPTS}" PARENT_SCOPE) - #SET (CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS}" PARENT_SCOPE) + #SET (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${C_ARCH_OPTS}" PARENT_SCOPE) + #SET (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${CXX_ARCH_OPTS}" PARENT_SCOPE) + #SET (CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS}" PARENT_SCOPE) endfunction() diff --git a/cmake/toolchains/OSX-AppleClang-AArch64.cmake b/cmake/toolchains/OSX-AppleClang-AArch64.cmake index 860371728..cd19f8216 100644 --- a/cmake/toolchains/OSX-AppleClang-AArch64.cmake +++ b/cmake/toolchains/OSX-AppleClang-AArch64.cmake @@ -15,7 +15,7 @@ endfunction() function(toolchain_after_project) message(STATUS "Toolchain: OSX-AppleClang-AArch64.cmake.") # Do not set CMAKE_SYSTEM_NAME if compiling for the same OS, otherwise CMAKE_CROSSCOMPILING will be set to TRUE - #SET(CMAKE_SYSTEM_NAME "Darwin" CACHE INTERNAL "" FORCE) + #SET(CMAKE_SYSTEM_NAME "Darwin" CACHE INTERNAL "" FORCE) set(CMAKE_SYSTEM_PROCESSOR "aarch64" CACHE INTERNAL "" FORCE) set(CMAKE_RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/bin-aarch64" PARENT_SCOPE) #set(ARCH_BITS 64 CACHE INTERNAL "" FORCE) # provide it @@ -31,7 +31,7 @@ function(toolchain_exe_stuff) toolchain_exe_stuff_common() # Propagate global variables set in toolchain_exe_stuff_common to the upper scope - #SET (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${C_ARCH_OPTS}" PARENT_SCOPE) - #SET (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${CXX_ARCH_OPTS}" PARENT_SCOPE) - #SET (CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS}" PARENT_SCOPE) + #SET (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${C_ARCH_OPTS}" PARENT_SCOPE) + #SET (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${CXX_ARCH_OPTS}" PARENT_SCOPE) + #SET (CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS}" PARENT_SCOPE) endfunction() diff --git a/cmake/toolchains/OSX-AppleClang-native.cmake b/cmake/toolchains/OSX-AppleClang-native.cmake index 39ca1784b..801679ab6 100644 --- a/cmake/toolchains/OSX-AppleClang-native.cmake +++ b/cmake/toolchains/OSX-AppleClang-native.cmake @@ -15,7 +15,7 @@ endfunction() function(toolchain_after_project) message(STATUS "Toolchain: OSX-AppleClang-native.cmake.") # Do not set CMAKE_SYSTEM_NAME if compiling for the same OS, otherwise CMAKE_CROSSCOMPILING will be set to TRUE - #SET(CMAKE_SYSTEM_NAME "Darwin" CACHE INTERNAL "" FORCE) + #SET(CMAKE_SYSTEM_NAME "Darwin" CACHE INTERNAL "" FORCE) if(CMAKE_SIZEOF_VOID_P EQUAL 8) set(CMAKE_RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/bin-native64" PARENT_SCOPE) else() @@ -34,7 +34,7 @@ function(toolchain_exe_stuff) toolchain_exe_stuff_common() # Propagate global variables set in toolchain_exe_stuff_common to the upper scope - #SET (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${C_ARCH_OPTS}" PARENT_SCOPE) - #SET (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${CXX_ARCH_OPTS}" PARENT_SCOPE) - #SET (CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS}" PARENT_SCOPE) + #SET (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${C_ARCH_OPTS}" PARENT_SCOPE) + #SET (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${CXX_ARCH_OPTS}" PARENT_SCOPE) + #SET (CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS}" PARENT_SCOPE) endfunction() diff --git a/cmake/toolchains/OSX-AppleClang-x86_64.cmake b/cmake/toolchains/OSX-AppleClang-x86_64.cmake index a15a68ac3..a0d352499 100644 --- a/cmake/toolchains/OSX-AppleClang-x86_64.cmake +++ b/cmake/toolchains/OSX-AppleClang-x86_64.cmake @@ -16,7 +16,7 @@ endfunction() function(toolchain_after_project) message(STATUS "Toolchain: OSX-AppleClang-x86_64.cmake.") # Do not set CMAKE_SYSTEM_NAME if compiling for the same OS, otherwise CMAKE_CROSSCOMPILING will be set to TRUE - #SET(CMAKE_SYSTEM_NAME "Darwin" CACHE INTERNAL "" FORCE) + #SET(CMAKE_SYSTEM_NAME "Darwin" CACHE INTERNAL "" FORCE) set(CMAKE_SYSTEM_PROCESSOR "x86_64" CACHE INTERNAL "" FORCE) set(CMAKE_RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/bin-x86_64" PARENT_SCOPE) #set(ARCH_BITS 64 CACHE INTERNAL "" FORCE) # provide it @@ -32,7 +32,7 @@ function(toolchain_exe_stuff) toolchain_exe_stuff_common() # Propagate global variables set in toolchain_exe_stuff_common to the upper scope - #SET (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${C_ARCH_OPTS}" PARENT_SCOPE) - #SET (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${CXX_ARCH_OPTS}" PARENT_SCOPE) - #SET (CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS}" PARENT_SCOPE) + #SET (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${C_ARCH_OPTS}" PARENT_SCOPE) + #SET (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${CXX_ARCH_OPTS}" PARENT_SCOPE) + #SET (CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS}" PARENT_SCOPE) endfunction() diff --git a/cmake/toolchains/Windows-Clang-native.cmake b/cmake/toolchains/Windows-Clang-native.cmake index ba396e5e4..1f5c4e262 100644 --- a/cmake/toolchains/Windows-Clang-native.cmake +++ b/cmake/toolchains/Windows-Clang-native.cmake @@ -9,7 +9,7 @@ function(toolchain_force_compiler) set(CMAKE_CXX_COMPILER "clang++" CACHE STRING "C++ compiler" FORCE) # In order to enable ninja to be verbose - #set(CMAKE_VERBOSE_MAKEFILE ON CACHE BOOL "ON") + #set(CMAKE_VERBOSE_MAKEFILE ON CACHE BOOL "ON") if(CLANG_USE_GCC_LINKER) # Not working, see CLANG_USE_GCC_LINKER option. Use MSVC. @@ -22,7 +22,7 @@ endfunction() function(toolchain_after_project) message(STATUS "Toolchain: Windows-Clang-native.cmake.") # Do not set CMAKE_SYSTEM_NAME if compiling for the same OS, otherwise CMAKE_CROSSCOMPILING will be set to TRUE - #SET(CMAKE_SYSTEM_NAME "Windows" INTERNAL "" FORCE) + #SET(CMAKE_SYSTEM_NAME "Windows" INTERNAL "" FORCE) if(CMAKE_SIZEOF_VOID_P EQUAL 8) set(CMAKE_RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/bin-native64" PARENT_SCOPE) else() @@ -31,10 +31,10 @@ function(toolchain_after_project) toolchain_after_project_common() # To enable RC language, to compile Windows Resource files - #SET (CLANG_TARGET "--target=x86_64-pc-windows-${CLANG_VENDOR}") - #SET (C_ARCH_OPTS "-march=native ${CLANG_TARGET}") - #SET (CXX_ARCH_OPTS "-march=native ${CLANG_TARGET}") - #SET (RC_FLAGS "${CLANG_TARGET}") + #SET (CLANG_TARGET "--target=x86_64-pc-windows-${CLANG_VENDOR}") + #SET (C_ARCH_OPTS "-march=native ${CLANG_TARGET}") + #SET (CXX_ARCH_OPTS "-march=native ${CLANG_TARGET}") + #SET (RC_FLAGS "${CLANG_TARGET}") # TODO: fix the target, maybe using CMAKE_HOST_SYSTEM_PROCESSOR ? link_directories("lib/_bin/{ARCH}/mariadb/") @@ -46,8 +46,8 @@ function(toolchain_exe_stuff) toolchain_exe_stuff_common() # Propagate global variables set in toolchain_exe_stuff_common to the upper scope - #SET (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${C_ARCH_OPTS}" PARENT_SCOPE) - #SET (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${CXX_ARCH_OPTS}" PARENT_SCOPE) - #SET (CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS}" PARENT_SCOPE) - #SET (CMAKE_RC_FLAGS "${RC_FLAGS}" PARENT_SCOPE) + #SET (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${C_ARCH_OPTS}" PARENT_SCOPE) + #SET (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${CXX_ARCH_OPTS}" PARENT_SCOPE) + #SET (CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS}" PARENT_SCOPE) + #SET (CMAKE_RC_FLAGS "${RC_FLAGS}" PARENT_SCOPE) endfunction() diff --git a/cmake/toolchains/Windows-Clang-x86.cmake b/cmake/toolchains/Windows-Clang-x86.cmake index a6a139946..8d24d467f 100644 --- a/cmake/toolchains/Windows-Clang-x86.cmake +++ b/cmake/toolchains/Windows-Clang-x86.cmake @@ -9,7 +9,7 @@ function(toolchain_force_compiler) set(CMAKE_CXX_COMPILER "clang++" CACHE STRING "C++ compiler" FORCE) # In order to enable ninja to be verbose - #set(CMAKE_VERBOSE_MAKEFILE ON CACHE BOOL "ON") + #set(CMAKE_VERBOSE_MAKEFILE ON CACHE BOOL "ON") if(CLANG_USE_GCC_LINKER) # Not working, see CLANG_USE_GCC_LINKER option. Use MSVC. @@ -22,7 +22,7 @@ endfunction() function(toolchain_after_project) message(STATUS "Toolchain: Windows-Clang-x86.cmake.") # Do not set CMAKE_SYSTEM_NAME if compiling for the same OS, otherwise CMAKE_CROSSCOMPILING will be set to TRUE - #SET(CMAKE_SYSTEM_NAME "Windows" CACHE INTERNAL "" FORCE) + #SET(CMAKE_SYSTEM_NAME "Windows" CACHE INTERNAL "" FORCE) set(CMAKE_SYSTEM_PROCESSOR "x86" CACHE INTERNAL "" FORCE) set(CMAKE_RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/bin-x86" PARENT_SCOPE) #set(ARCH_BITS 32 CACHE INTERNAL "" FORCE) # provide it @@ -40,10 +40,10 @@ function(toolchain_exe_stuff) toolchain_exe_stuff_common() # Propagate global variables set in toolchain_exe_stuff_common to the upper scope - #SET (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${C_ARCH_OPTS}" PARENT_SCOPE) - #SET (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${CXX_ARCH_OPTS}" PARENT_SCOPE) - #SET (CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS}" PARENT_SCOPE) - #SET (CMAKE_RC_FLAGS "${RC_FLAGS}" PARENT_SCOPE) + #SET (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${C_ARCH_OPTS}" PARENT_SCOPE) + #SET (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${CXX_ARCH_OPTS}" PARENT_SCOPE) + #SET (CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS}" PARENT_SCOPE) + #SET (CMAKE_RC_FLAGS "${RC_FLAGS}" PARENT_SCOPE) # Set different output folders for each build type set_target_properties(spheresvr PROPERTIES RUNTIME_OUTPUT_RELEASE "${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/Release") diff --git a/cmake/toolchains/Windows-Clang-x86_64.cmake b/cmake/toolchains/Windows-Clang-x86_64.cmake index 84e9ae72a..36392f5dc 100644 --- a/cmake/toolchains/Windows-Clang-x86_64.cmake +++ b/cmake/toolchains/Windows-Clang-x86_64.cmake @@ -9,7 +9,7 @@ function(toolchain_force_compiler) set(CMAKE_CXX_COMPILER "clang++" CACHE STRING "C++ compiler" FORCE) # In order to enable ninja to be verbose - #set(CMAKE_VERBOSE_MAKEFILE ON CACHE BOOL "ON") + #set(CMAKE_VERBOSE_MAKEFILE ON CACHE BOOL "ON") if(CLANG_USE_GCC_LINKER) # Not working, see CLANG_USE_GCC_LINKER option. Use MSVC. @@ -22,7 +22,7 @@ endfunction() function(toolchain_after_project) message(STATUS "Toolchain: Windows-Clang-x86_64.cmake.") # Do not set CMAKE_SYSTEM_NAME if compiling for the same OS, otherwise CMAKE_CROSSCOMPILING will be set to TRUE - #SET(CMAKE_SYSTEM_NAME "Windows" CACHE INTERNAL "" FORCE) + #SET(CMAKE_SYSTEM_NAME "Windows" CACHE INTERNAL "" FORCE) set(CMAKE_SYSTEM_PROCESSOR "x86_64" CACHE INTERNAL "" FORCE) set(CMAKE_RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/bin-x86_64" PARENT_SCOPE) #set(ARCH_BITS 64 CACHE INTERNAL "" FORCE) # provide it @@ -45,8 +45,8 @@ function(toolchain_exe_stuff) toolchain_exe_stuff_common() # Propagate global variables set in toolchain_exe_stuff_common to the upper scope - #SET (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${C_ARCH_OPTS}" PARENT_SCOPE) - #SET (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${CXX_ARCH_OPTS}" PARENT_SCOPE) - #SET (CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS}" PARENT_SCOPE) - #SET (CMAKE_RC_FLAGS "${RC_FLAGS}" PARENT_SCOPE) + #SET (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${C_ARCH_OPTS}" PARENT_SCOPE) + #SET (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${CXX_ARCH_OPTS}" PARENT_SCOPE) + #SET (CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS}" PARENT_SCOPE) + #SET (CMAKE_RC_FLAGS "${RC_FLAGS}" PARENT_SCOPE) endfunction() diff --git a/cmake/toolchains/Windows-GNU-native.cmake b/cmake/toolchains/Windows-GNU-native.cmake index 173772020..de9e072b8 100644 --- a/cmake/toolchains/Windows-GNU-native.cmake +++ b/cmake/toolchains/Windows-GNU-native.cmake @@ -9,13 +9,13 @@ function(toolchain_force_compiler) set(CMAKE_CXX_COMPILER "g++" CACHE STRING "C++ compiler" FORCE) # In order to enable ninja to be verbose - #set(CMAKE_VERBOSE_MAKEFILE ON CACHE BOOL "ON") + #set(CMAKE_VERBOSE_MAKEFILE ON CACHE BOOL "ON") endfunction() function(toolchain_after_project) message(STATUS "Toolchain: Windows-GNU-native.cmake.") # Do not set CMAKE_SYSTEM_NAME if compiling for the same OS, otherwise CMAKE_CROSSCOMPILING will be set to TRUE - #SET(CMAKE_SYSTEM_NAME "Windows" CACHE INTERNAL "" FORCE) + #SET(CMAKE_SYSTEM_NAME "Windows" CACHE INTERNAL "" FORCE) if(CMAKE_SIZEOF_VOID_P EQUAL 8) set(CMAKE_RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/bin-native64" PARENT_SCOPE) else() @@ -33,8 +33,8 @@ function(toolchain_exe_stuff) toolchain_exe_stuff_common() # Propagate global variables set in toolchain_exe_stuff_common to the upper scope - #SET (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${C_ARCH_OPTS}" PARENT_SCOPE) - #SET (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${CXX_ARCH_OPTS}" PARENT_SCOPE) - #SET (CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS}" PARENT_SCOPE) - #SET (CMAKE_RC_FLAGS "${CMAKE_RC_FLAGS}" PARENT_SCOPE) + #SET (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${C_ARCH_OPTS}" PARENT_SCOPE) + #SET (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${CXX_ARCH_OPTS}" PARENT_SCOPE) + #SET (CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS}" PARENT_SCOPE) + #SET (CMAKE_RC_FLAGS "${CMAKE_RC_FLAGS}" PARENT_SCOPE) endfunction() diff --git a/cmake/toolchains/Windows-GNU-x86.cmake b/cmake/toolchains/Windows-GNU-x86.cmake index 4c056f300..de440beba 100644 --- a/cmake/toolchains/Windows-GNU-x86.cmake +++ b/cmake/toolchains/Windows-GNU-x86.cmake @@ -9,13 +9,13 @@ function(toolchain_force_compiler) set(CMAKE_CXX_COMPILER "g++" CACHE STRING "C++ compiler" FORCE) # In order to enable ninja to be verbose - #set(CMAKE_VERBOSE_MAKEFILE ON CACHE BOOL "ON") + #set(CMAKE_VERBOSE_MAKEFILE ON CACHE BOOL "ON") endfunction() function(toolchain_after_project) message(STATUS "Toolchain: Windows-GNU-x86.cmake.") # Do not set CMAKE_SYSTEM_NAME if compiling for the same OS, otherwise CMAKE_CROSSCOMPILING will be set to TRUE - #SET(CMAKE_SYSTEM_NAME "Windows" CACHE INTERNAL "" FORCE) + #SET(CMAKE_SYSTEM_NAME "Windows" CACHE INTERNAL "" FORCE) set(CMAKE_SYSTEM_PROCESSOR "x86" CACHE INTERNAL "" FORCE) set(CMAKE_RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/bin_x86" PARENT_SCOPE) #set(ARCH_BITS 32 CACHE INTERNAL "" FORCE) # provide it @@ -32,8 +32,8 @@ function(toolchain_exe_stuff) toolchain_exe_stuff_common() # Propagate global variables set in toolchain_exe_stuff_common to the upper scope - #SET (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${C_ARCH_OPTS}" PARENT_SCOPE) - #SET (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${CXX_ARCH_OPTS}" PARENT_SCOPE) - #SET (CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS}" PARENT_SCOPE) - #SET (CMAKE_RC_FLAGS "${RC_FLAGS}" PARENT_SCOPE) + #SET (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${C_ARCH_OPTS}" PARENT_SCOPE) + #SET (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${CXX_ARCH_OPTS}" PARENT_SCOPE) + #SET (CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS}" PARENT_SCOPE) + #SET (CMAKE_RC_FLAGS "${RC_FLAGS}" PARENT_SCOPE) endfunction() diff --git a/cmake/toolchains/Windows-GNU-x86_64.cmake b/cmake/toolchains/Windows-GNU-x86_64.cmake index f3291237d..b85339500 100644 --- a/cmake/toolchains/Windows-GNU-x86_64.cmake +++ b/cmake/toolchains/Windows-GNU-x86_64.cmake @@ -9,13 +9,13 @@ function(toolchain_force_compiler) set(CMAKE_CXX_COMPILER "g++" CACHE STRING "C++ compiler" FORCE) # In order to enable ninja to be verbose - #set(CMAKE_VERBOSE_MAKEFILE ON CACHE BOOL "ON") + #set(CMAKE_VERBOSE_MAKEFILE ON CACHE BOOL "ON") endfunction() function(toolchain_after_project) message(STATUS "Toolchain: Windows-GNU-x86_64.cmake.") # Do not set CMAKE_SYSTEM_NAME if compiling for the same OS, otherwise CMAKE_CROSSCOMPILING will be set to TRUE - #SET(CMAKE_SYSTEM_NAME "Windows" CACHE INTERNAL "" FORCE) + #SET(CMAKE_SYSTEM_NAME "Windows" CACHE INTERNAL "" FORCE) set(CMAKE_SYSTEM_PROCESSOR "x86_64" CACHE INTERNAL "" FORCE) set(CMAKE_RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/bin-x86_64" PARENT_SCOPE) #set(ARCH_BITS 64 CACHE INTERNAL "" FORCE) # provide it @@ -32,8 +32,8 @@ function(toolchain_exe_stuff) toolchain_exe_stuff_common() # Propagate global variables set in toolchain_exe_stuff_common to the upper scope - #SET (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${C_ARCH_OPTS}" PARENT_SCOPE) - #SET (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${CXX_ARCH_OPTS}" PARENT_SCOPE) - #SET (CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS}" PARENT_SCOPE) - #SET (CMAKE_RC_FLAGS "${RC_FLAGS}" PARENT_SCOPE) + #SET (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${C_ARCH_OPTS}" PARENT_SCOPE) + #SET (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${CXX_ARCH_OPTS}" PARENT_SCOPE) + #SET (CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS}" PARENT_SCOPE) + #SET (CMAKE_RC_FLAGS "${RC_FLAGS}" PARENT_SCOPE) endfunction() diff --git a/cmake/toolchains/Windows-MSVC.cmake b/cmake/toolchains/Windows-MSVC.cmake index 8ac30f1b5..9b37d0743 100644 --- a/cmake/toolchains/Windows-MSVC.cmake +++ b/cmake/toolchains/Windows-MSVC.cmake @@ -2,11 +2,11 @@ set(TOOLCHAIN_LOADED 1) function(toolchain_force_compiler) # Already managed by the generator. - #SET (CMAKE_C_COMPILER "...cl.exe" CACHE STRING "C compiler" FORCE) - #SET (CMAKE_CXX_COMPILER "...cl.exe" CACHE STRING "C++ compiler" FORCE) + #SET (CMAKE_C_COMPILER "...cl.exe" CACHE STRING "C compiler" FORCE) + #SET (CMAKE_CXX_COMPILER "...cl.exe" CACHE STRING "C++ compiler" FORCE) message(STATUS "Toolchain: Windows-MSVC.cmake.") - #SET(CMAKE_SYSTEM_NAME "Windows" CACHE INTERNAL "" FORCE) + #SET(CMAKE_SYSTEM_NAME "Windows" CACHE INTERNAL "" FORCE) endfunction() function(toolchain_after_project) @@ -38,7 +38,7 @@ function(toolchain_exe_stuff) add_link_options("LINKER:/ENTRY:WinMainCRTStartup") # Handled by is_win32_app_linker -> "LINKER:/SUBSYSTEM:CONSOLE" set(PREPROCESSOR_DEFS_EXTRA _WINDOWS_CONSOLE) #ELSE () - # add_link_options ("LINKER:/ENTRY:WinMainCRTStartup") # Handled by is_win32_app_linker -> "LINKER: /SUBSYSTEM:WINDOWS" + # add_link_options ("LINKER:/ENTRY:WinMainCRTStartup") # Handled by is_win32_app_linker -> "LINKER: /SUBSYSTEM:WINDOWS" endif() #-- Validate sanitizers options and store them between the common compiler flags. @@ -106,13 +106,13 @@ function(toolchain_exe_stuff) set(CMAKE_CXX_FLAGS_DEBUG_INIT "" INTERNAL) # gersemi: off - target_compile_options(spheresvr PRIVATE - ${cxx_compiler_flags_common} - $<$: $,/MT,/MD> /EHa /Oy /GL /GA /Gw /Gy /GF $,/O1 /Zi,/O2>> - $<$: $,/MT,/MD> /EHa /Oy /GL /GA /Gw /Gy /GF $,/O1 /Zi,/O2>> - $<$: $,/MTd,/MDd> /EHsc /Oy- /ob1 /Od /Gs $,/Zi,/ZI>> - # ASan (and compilation for ARM arch) doesn't support edit and continue option (ZI) - ) + target_compile_options(spheresvr PRIVATE + ${cxx_compiler_flags_common} + $<$: $,/MT,/MD> /EHa /Oy /GL /GA /Gw /Gy /GF $,/O1 /Zi,/O2>> + $<$: $,/MT,/MD> /EHa /Oy /GL /GA /Gw /Gy /GF $,/O1 /Zi,/O2>> + $<$: $,/MTd,/MDd> /EHsc /Oy- /ob1 /Od /Gs $,/Zi,/ZI>> + # ASan (and compilation for ARM arch) doesn't support edit and continue option (ZI) + ) # gersemi: on if("${ARCH}" STREQUAL "x86_64") @@ -125,13 +125,13 @@ function(toolchain_exe_stuff) set(CMAKE_EXE_LINKER_FLAGS_NIGHTLY CACHE INTERNAL ${CMAKE_EXE_LINKER_FLAGS_RELEASE} "") # gersemi: off - target_link_options(spheresvr PRIVATE + target_link_options(spheresvr PRIVATE /WX # treat all warnings as errors - $<$: ${EXE_LINKER_EXTRA} /NODEFAULTLIB:libcmtd /OPT:REF,ICF /LTCG /INCREMENTAL:NO> - $<$: ${EXE_LINKER_EXTRA} /NODEFAULTLIB:libcmtd /OPT:REF,ICF /LTCG /INCREMENTAL:NO> - $<$: ${EXE_LINKER_EXTRA} /NODEFAULTLIB:libcmt /SAFESEH:NO /DEBUG /LTCG:OFF - $,/INCREMENTAL:NO /EDITANDCONTINUE:NO,/INCREMENTAL /EDITANDCONTINUE> > - ) + $<$: ${EXE_LINKER_EXTRA} /NODEFAULTLIB:libcmtd /OPT:REF,ICF /LTCG /INCREMENTAL:NO> + $<$: ${EXE_LINKER_EXTRA} /NODEFAULTLIB:libcmtd /OPT:REF,ICF /LTCG /INCREMENTAL:NO> + $<$: ${EXE_LINKER_EXTRA} /NODEFAULTLIB:libcmt /SAFESEH:NO /DEBUG /LTCG:OFF + $,/INCREMENTAL:NO /EDITANDCONTINUE:NO,/INCREMENTAL /EDITANDCONTINUE> > + ) # gersemi: on # MSVC doesn't yet have an option to statically link against *san sanitizer libraries. # /INCREMENTAL and /EDITANDCONTINUE not compatible with a MSVC Asan build. diff --git a/cmake/toolchains/include/Linux-Clang_common.inc.cmake b/cmake/toolchains/include/Linux-Clang_common.inc.cmake index 986b79646..b01126c8c 100644 --- a/cmake/toolchains/include/Linux-Clang_common.inc.cmake +++ b/cmake/toolchains/include/Linux-Clang_common.inc.cmake @@ -113,14 +113,14 @@ See comments in the toolchain and: https://github.com/google/sanitizers/wiki/Mem #separate_arguments(cxx_compiler_options_common) # GCC flags not supported by clang: - # Warnings: "-Wno-nonnull-compare -Wno-maybe-uninitialized" - # Other: "-fno-expensive-optimizations" + # Warnings: "-Wno-nonnull-compare -Wno-maybe-uninitialized" + # Other: "-fno-expensive-optimizations" # MemorySanitizer: it doesn't work out of the box. It needs to be linked to an MSAN-instrumented build of libc++ and libc++abi. # This means: one should build them from LLVM source... # https://github.com/google/sanitizers/wiki/MemorySanitizerLibcxxHowTo #IF (${USE_MSAN}) - # SET (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -stdlib=libc++") + # SET (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -stdlib=libc++") #ENDIF() # Use "-stdlib=libstdc++" to link against GCC c/c++ libs (this is done by default) # To use LLVM libc++ use "-stdlib=libc++", but you need to install it separately @@ -200,7 +200,7 @@ See comments in the toolchain and: https://github.com/google/sanitizers/wiki/Mem #-- Set different output folders for each build type # (When we'll have support for multi-target builds...) - #SET_TARGET_PROPERTIES(spheresvr PROPERTIES RUNTIME_OUTPUT_RELEASE "${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/Release" ) - #SET_TARGET_PROPERTIES(spheresvr PROPERTIES RUNTIME_OUTPUT_DEBUG "${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/Debug" ) - #SET_TARGET_PROPERTIES(spheresvr PROPERTIES RUNTIME_OUTPUT_NIGHTLY "${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/Nightly" ) + #SET_TARGET_PROPERTIES(spheresvr PROPERTIES RUNTIME_OUTPUT_RELEASE "${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/Release" ) + #SET_TARGET_PROPERTIES(spheresvr PROPERTIES RUNTIME_OUTPUT_DEBUG "${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/Debug" ) + #SET_TARGET_PROPERTIES(spheresvr PROPERTIES RUNTIME_OUTPUT_NIGHTLY "${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/Nightly" ) endfunction() diff --git a/cmake/toolchains/include/Linux-GNU_common.inc.cmake b/cmake/toolchains/include/Linux-GNU_common.inc.cmake index c483926c8..240602418 100644 --- a/cmake/toolchains/include/Linux-GNU_common.inc.cmake +++ b/cmake/toolchains/include/Linux-GNU_common.inc.cmake @@ -48,8 +48,8 @@ function(toolchain_exe_stuff_common) if(${USE_MSAN}) message(FATAL_ERROR "Linux GCC doesn't yet support MSAN") set(USE_MSAN false) - #SET (CXX_FLAGS_EXTRA ${CXX_FLAGS_EXTRA} -fsanitize=memory -fsanitize-memory-track-origins=2 -fPIE) - #set (CMAKE_EXE_LINKER_FLAGS_EXTRA ${CMAKE_EXE_LINKER_FLAGS_EXTRA} -fsanitize=memory )#$<$:-static-libmsan>) + #SET (CXX_FLAGS_EXTRA ${CXX_FLAGS_EXTRA} -fsanitize=memory -fsanitize-memory-track-origins=2 -fPIE) + #set (CMAKE_EXE_LINKER_FLAGS_EXTRA ${CMAKE_EXE_LINKER_FLAGS_EXTRA} -fsanitize=memory )#$<$:-static-libmsan>) #SET (PREPROCESSOR_DEFS_EXTRA ${PREPROCESSOR_DEFS_EXTRA} MEMORY_SANITIZER) #SET (ENABLED_SANITIZER true) endif() @@ -182,7 +182,7 @@ function(toolchain_exe_stuff_common) #-- Set different output folders for each build type # (When we'll have support for multi-target builds...) - #SET_TARGET_PROPERTIES(spheresvr PROPERTIES RUNTIME_OUTPUT_RELEASE "${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/Release" ) - #SET_TARGET_PROPERTIES(spheresvr PROPERTIES RUNTIME_OUTPUT_DEBUG "${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/Debug" ) - #SET_TARGET_PROPERTIES(spheresvr PROPERTIES RUNTIME_OUTPUT_NIGHTLY "${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/Nightly" ) + #SET_TARGET_PROPERTIES(spheresvr PROPERTIES RUNTIME_OUTPUT_RELEASE "${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/Release" ) + #SET_TARGET_PROPERTIES(spheresvr PROPERTIES RUNTIME_OUTPUT_DEBUG "${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/Debug" ) + #SET_TARGET_PROPERTIES(spheresvr PROPERTIES RUNTIME_OUTPUT_NIGHTLY "${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/Nightly" ) endfunction() diff --git a/cmake/toolchains/include/OSX-AppleClang_common.inc.cmake b/cmake/toolchains/include/OSX-AppleClang_common.inc.cmake index 914e3247a..29dcbf1bd 100644 --- a/cmake/toolchains/include/OSX-AppleClang_common.inc.cmake +++ b/cmake/toolchains/include/OSX-AppleClang_common.inc.cmake @@ -112,8 +112,8 @@ function(toolchain_exe_stuff_common) set(cxx_compiler_options_common ${cxx_local_opts_warnings} ${cxx_local_opts} ${CXX_FLAGS_EXTRA}) # GCC flags not supported by clang: - # Warnings: "-Wno-nonnull-compare -Wno-maybe-uninitialized" - # Other: "-fno-expensive-optimizations" + # Warnings: "-Wno-nonnull-compare -Wno-maybe-uninitialized" + # Other: "-fno-expensive-optimizations" #-- Apply compiler flags, only the ones specific per build type. @@ -154,10 +154,10 @@ function(toolchain_exe_stuff_common) #-- Apply linker flags, only the ones specific per build type. # -s got deprecated, we could directly call 'strip' #IF (TARGET spheresvr_release) - # target_link_options (spheresvr_release PRIVATE -s) + # target_link_options (spheresvr_release PRIVATE -s) #ENDIF () #IF (TARGET spheresvr_nightly AND NOT ${ENABLED_SANITIZER}) - # target_link_options (spheresvr_nightly PRIVATE -s) + # target_link_options (spheresvr_nightly PRIVATE -s) #ENDIF () #-- Store common define macros. @@ -193,7 +193,7 @@ function(toolchain_exe_stuff_common) #-- Set different output folders for each build type # (When we'll have support for multi-target builds...) - #SET_TARGET_PROPERTIES(spheresvr PROPERTIES RUNTIME_OUTPUT_RELEASE "${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/Release" ) - #SET_TARGET_PROPERTIES(spheresvr PROPERTIES RUNTIME_OUTPUT_DEBUG "${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/Debug" ) - #SET_TARGET_PROPERTIES(spheresvr PROPERTIES RUNTIME_OUTPUT_NIGHTLY "${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/Nightly" ) + #SET_TARGET_PROPERTIES(spheresvr PROPERTIES RUNTIME_OUTPUT_RELEASE "${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/Release" ) + #SET_TARGET_PROPERTIES(spheresvr PROPERTIES RUNTIME_OUTPUT_DEBUG "${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/Debug" ) + #SET_TARGET_PROPERTIES(spheresvr PROPERTIES RUNTIME_OUTPUT_NIGHTLY "${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/Nightly" ) endfunction() diff --git a/cmake/toolchains/include/Windows-Clang_common.inc.cmake b/cmake/toolchains/include/Windows-Clang_common.inc.cmake index aa481a011..6ad0e3639 100644 --- a/cmake/toolchains/include/Windows-Clang_common.inc.cmake +++ b/cmake/toolchains/include/Windows-Clang_common.inc.cmake @@ -57,9 +57,9 @@ function(toolchain_exe_stuff_common) if(${USE_MSAN}) message(FATAL_ERROR "Windows Clang doesn't yet support MSAN") set(USE_MSAN false) - #SET (CXX_FLAGS_EXTRA ${CXX_FLAGS_EXTRA} -fsanitize=memory -fsanitize-memory-track-origins=2 -fPIE) + #SET (CXX_FLAGS_EXTRA ${CXX_FLAGS_EXTRA} -fsanitize=memory -fsanitize-memory-track-origins=2 -fPIE) #IF (${CLANG_USE_GCC_LINKER}) - #set (CMAKE_EXE_LINKER_FLAGS_EXTRA ${CMAKE_EXE_LINKER_FLAGS_EXTRA} -fsanitize=memory) + #set (CMAKE_EXE_LINKER_FLAGS_EXTRA ${CMAKE_EXE_LINKER_FLAGS_EXTRA} -fsanitize=memory) #ENDIF #SET (PREPROCESSOR_DEFS_EXTRA ${PREPROCESSOR_DEFS_EXTRA} MEMORY_SANITIZER) #SET (ENABLED_SANITIZER true) @@ -67,9 +67,9 @@ function(toolchain_exe_stuff_common) if(${USE_LSAN}) message(FATAL_ERROR "Windows Clang doesn't yet support LSAN") set(USE_LSAN false) - #SET (CXX_FLAGS_EXTRA ${CXX_FLAGS_EXTRA} -fsanitize=leak) + #SET (CXX_FLAGS_EXTRA ${CXX_FLAGS_EXTRA} -fsanitize=leak) #IF (${CLANG_USE_GCC_LINKER}) - #set (CMAKE_EXE_LINKER_FLAGS_EXTRA ${CMAKE_EXE_LINKER_FLAGS_EXTRA} -fsanitize=leak) + #set (CMAKE_EXE_LINKER_FLAGS_EXTRA ${CMAKE_EXE_LINKER_FLAGS_EXTRA} -fsanitize=leak) #ENDIF #SET (PREPROCESSOR_DEFS_EXTRA ${PREPROCESSOR_DEFS_EXTRA} LEAK_SANITIZER) #SET (ENABLED_SANITIZER true) @@ -84,7 +84,7 @@ function(toolchain_exe_stuff_common) ) set(CXX_FLAGS_EXTRA ${CXX_FLAGS_EXTRA} ${UBSAN_FLAGS} -fsanitize=return) #IF (${CLANG_USE_GCC_LINKER}) - #set (CMAKE_EXE_LINKER_FLAGS_EXTRA ${CMAKE_EXE_LINKER_FLAGS_EXTRA} -fsanitize=undefined) + #set (CMAKE_EXE_LINKER_FLAGS_EXTRA ${CMAKE_EXE_LINKER_FLAGS_EXTRA} -fsanitize=undefined) #ENDIF set(PREPROCESSOR_DEFS_EXTRA ${PREPROCESSOR_DEFS_EXTRA} UNDEFINED_BEHAVIOR_SANITIZER) set(ENABLED_SANITIZER true) @@ -145,14 +145,14 @@ function(toolchain_exe_stuff_common) PUBLIC -O3 -flto=full -fvirtual-function-elimination ${COMPILE_OPTIONS_EXTRA} ) #[[ - IF (NOT ${CLANG_USE_GCC_LINKER}) - if (${RUNTIME_STATIC_LINK}) - TARGET_COMPILE_OPTIONS ( spheresvr_release PUBLIC /MT ) - else () - TARGET_COMPILE_OPTIONS ( spheresvr_release PUBLIC /MD ) - endif () - endif () - ]] + IF (NOT ${CLANG_USE_GCC_LINKER}) + if (${RUNTIME_STATIC_LINK}) + TARGET_COMPILE_OPTIONS ( spheresvr_release PUBLIC /MT ) + else () + TARGET_COMPILE_OPTIONS ( spheresvr_release PUBLIC /MD ) + endif () + endif () + ]] endif() if(TARGET spheresvr_nightly) if(ENABLED_SANITIZER) @@ -164,26 +164,26 @@ function(toolchain_exe_stuff_common) ) endif() #[[ - IF (NOT ${CLANG_USE_GCC_LINKER}) - if (${RUNTIME_STATIC_LINK}) - TARGET_COMPILE_OPTIONS ( spheresvr_nightly PUBLIC /MT ) - else () - TARGET_COMPILE_OPTIONS ( spheresvr_nightly PUBLIC /MD ) - endif () - endif () - ]] + IF (NOT ${CLANG_USE_GCC_LINKER}) + if (${RUNTIME_STATIC_LINK}) + TARGET_COMPILE_OPTIONS ( spheresvr_nightly PUBLIC /MT ) + else () + TARGET_COMPILE_OPTIONS ( spheresvr_nightly PUBLIC /MD ) + endif () + endif () + ]] endif() if(TARGET spheresvr_debug) target_compile_options(spheresvr_debug PUBLIC -ggdb3 -Og) #[[ - IF (NOT ${CLANG_USE_GCC_LINKER}) - if (${RUNTIME_STATIC_LINK}) - TARGET_COMPILE_OPTIONS ( spheresvr_debug PUBLIC /MTd ) - else () - TARGET_COMPILE_OPTIONS ( spheresvr_debug PUBLIC /MDd ) - endif () - endif () - ]] + IF (NOT ${CLANG_USE_GCC_LINKER}) + if (${RUNTIME_STATIC_LINK}) + TARGET_COMPILE_OPTIONS ( spheresvr_debug PUBLIC /MTd ) + else () + TARGET_COMPILE_OPTIONS ( spheresvr_debug PUBLIC /MDd ) + endif () + endif () + ]] endif() #-- Store common linker flags. @@ -199,12 +199,12 @@ function(toolchain_exe_stuff_common) set(cxx_linker_options_common ${cxx_linker_options_common} -static-libstdc++ -static-libgcc) # no way to statically link against libc? maybe we can on windows? endif() #[[ - else () - if (${RUNTIME_STATIC_LINK}) - set (cxx_linker_options_common ${cxx_linker_options_common} /MTd ) - else () - set (cxx_linker_options_common ${cxx_linker_options_common} /MDd ) - endif () + else () + if (${RUNTIME_STATIC_LINK}) + set (cxx_linker_options_common ${cxx_linker_options_common} /MTd ) + else () + set (cxx_linker_options_common ${cxx_linker_options_common} /MDd ) + endif () ]] endif() @@ -242,15 +242,15 @@ function(toolchain_exe_stuff_common) #-- Apply linker options, only the ones specific per build type. #if (NOT ${CLANG_USE_GCC_LINKER}) - # IF (TARGET spheresvr_release) - # target_link_options ( spheresvr_release PUBLIC "LINKER:SHELL:" ) - # ENDIF () - # IF (TARGET spheresvr_nightly) - # target_link_options ( spheresvr_nightly PUBLIC "LINKER:SHELL:" ) - # ENDIF () - # IF (TARGET spheresvr_debug) - # target_link_options ( spheresvr_debug PUBLIC "LINKER:/DEBUG" ) - # ENDIF () + # IF (TARGET spheresvr_release) + # target_link_options ( spheresvr_release PUBLIC "LINKER:SHELL:" ) + # ENDIF () + # IF (TARGET spheresvr_nightly) + # target_link_options ( spheresvr_nightly PUBLIC "LINKER:SHELL:" ) + # ENDIF () + # IF (TARGET spheresvr_debug) + # target_link_options ( spheresvr_debug PUBLIC "LINKER:/DEBUG" ) + # ENDIF () #endif () #-- Now add back the common compiler options, preprocessor macros, linker targets and options. @@ -258,30 +258,30 @@ function(toolchain_exe_stuff_common) if(NOT ${CLANG_USE_GCC_LINKER}) set(libs_prefix lib) #[[ - if (ENABLED_SANITIZER) - # one should add to the linker path its LLVM lib folder... - if (ARCH_BITS EQUAL 64) - if (TARGET spheresvr_release) - target_link_libraries(spheresvr_release PUBLIC clang_rt.asan_dll_thunk-x86_64) #clang_rt.asan_dynamic-x86_64) - endif () - if (TARGET spheresvr_nightly) - target_link_libraries(spheresvr_nightly PUBLIC clang_rt.asan_dll_thunk-x86_64) #clang_rt.asan_dynamic-x86_64) - endif () - if (TARGET spheresvr_debug) - target_link_libraries(spheresvr_debug PUBLIC clang_rt.asan_dll_thunk-x86_64) #clang_rt.asan_dbg_dynamic-x86_64) - endif () - else () - if (TARGET spheresvr_release) - target_link_libraries(spheresvr_release PUBLIC clang_rt.asan_dll_thunk-i386) #clang_rt.asan_dynamic-x86) - endif () - if (TARGET spheresvr_nightly) - target_link_libraries(spheresvr_nightly PUBLIC clang_rt.asan_dll_thunk-i386) #clang_rt.asan_dynamic-x86) - endif () - if (TARGET spheresvr_debug) - target_link_libraries(spheresvr_debug PUBLIC clang_rt.asan_dll_thunk-i386) #clang_rt.asan_dbg_dynamic-x86) - endif () - endif() - endif () + if (ENABLED_SANITIZER) + # one should add to the linker path its LLVM lib folder... + if (ARCH_BITS EQUAL 64) + if (TARGET spheresvr_release) + target_link_libraries(spheresvr_release PUBLIC clang_rt.asan_dll_thunk-x86_64) #clang_rt.asan_dynamic-x86_64) + endif () + if (TARGET spheresvr_nightly) + target_link_libraries(spheresvr_nightly PUBLIC clang_rt.asan_dll_thunk-x86_64) #clang_rt.asan_dynamic-x86_64) + endif () + if (TARGET spheresvr_debug) + target_link_libraries(spheresvr_debug PUBLIC clang_rt.asan_dll_thunk-x86_64) #clang_rt.asan_dbg_dynamic-x86_64) + endif () + else () + if (TARGET spheresvr_release) + target_link_libraries(spheresvr_release PUBLIC clang_rt.asan_dll_thunk-i386) #clang_rt.asan_dynamic-x86) + endif () + if (TARGET spheresvr_nightly) + target_link_libraries(spheresvr_nightly PUBLIC clang_rt.asan_dll_thunk-i386) #clang_rt.asan_dynamic-x86) + endif () + if (TARGET spheresvr_debug) + target_link_libraries(spheresvr_debug PUBLIC clang_rt.asan_dll_thunk-i386) #clang_rt.asan_dbg_dynamic-x86) + endif () + endif() + endif () ]] endif() set(libs_to_link_against ${libs_to_link_against} ws2_32 ${libs_prefix}mariadb) @@ -295,7 +295,7 @@ function(toolchain_exe_stuff_common) #-- Set different output folders for each build type # (When we'll have support for multi-target builds...) - #SET_TARGET_PROPERTIES(spheresvr PROPERTIES RUNTIME_OUTPUT_RELEASE "${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/Release" ) - #SET_TARGET_PROPERTIES(spheresvr PROPERTIES RUNTIME_OUTPUT_DEBUG "${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/Debug" ) - #SET_TARGET_PROPERTIES(spheresvr PROPERTIES RUNTIME_OUTPUT_NIGHTLY "${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/Nightly" ) + #SET_TARGET_PROPERTIES(spheresvr PROPERTIES RUNTIME_OUTPUT_RELEASE "${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/Release" ) + #SET_TARGET_PROPERTIES(spheresvr PROPERTIES RUNTIME_OUTPUT_DEBUG "${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/Debug" ) + #SET_TARGET_PROPERTIES(spheresvr PROPERTIES RUNTIME_OUTPUT_NIGHTLY "${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/Nightly" ) endfunction() diff --git a/cmake/toolchains/include/Windows-GNU_common.inc.cmake b/cmake/toolchains/include/Windows-GNU_common.inc.cmake index 52a4c0379..80f706afa 100644 --- a/cmake/toolchains/include/Windows-GNU_common.inc.cmake +++ b/cmake/toolchains/include/Windows-GNU_common.inc.cmake @@ -10,10 +10,10 @@ function(toolchain_exe_stuff_common) # Subsystem is already managed by is_win32_app_linker. GCC doesn't need us to specify the entry point. #IF (${WIN32_SPAWN_CONSOLE}) - # add_link_options ("LINKER:SHELL:-mconsole") - # SET (PREPROCESSOR_DEFS_EXTRA _WINDOWS_CONSOLE) + # add_link_options ("LINKER:SHELL:-mconsole") + # SET (PREPROCESSOR_DEFS_EXTRA _WINDOWS_CONSOLE) ##ELSE () - ## add_link_options ("LINKER:SHELL:-mwindows") + ## add_link_options ("LINKER:SHELL:-mwindows") #ENDIF () #-- Validate sanitizers options and store them between the common compiler flags. @@ -23,7 +23,7 @@ function(toolchain_exe_stuff_common) message(FATAL_ERROR "MinGW-GCC doesn't yet support ASAN") set(USE_ASAN false) #[[ - SET (CXX_FLAGS_EXTRA ${CXX_FLAGS_EXTRA} + SET (CXX_FLAGS_EXTRA ${CXX_FLAGS_EXTRA} -fsanitize=address -fno-sanitize-recover=address #-fsanitize-cfi # cfi: control flow integrity, not currently supported by GCC (even on Linux) -fsanitize-address-use-after-scope -fsanitize=pointer-compare -fsanitize=pointer-subtract # Flags for additional instrumentation not strictly needing asan to be enabled @@ -36,23 +36,23 @@ function(toolchain_exe_stuff_common) #-fsanitize-trap=all ) ]] - #set (CMAKE_EXE_LINKER_FLAGS_EXTRA ${CMAKE_EXE_LINKER_FLAGS_EXTRA} -fsanitize=address $<$:-static-libasan>) + #set (CMAKE_EXE_LINKER_FLAGS_EXTRA ${CMAKE_EXE_LINKER_FLAGS_EXTRA} -fsanitize=address $<$:-static-libasan>) #SET (PREPROCESSOR_DEFS_EXTRA ${PREPROCESSOR_DEFS_EXTRA} ADDRESS_SANITIZER) #SET (ENABLED_SANITIZER true) endif() if(${USE_MSAN}) message(FATAL_ERROR "MinGW-GCC doesn't yet support MSAN") set(USE_MSAN false) - #SET (CXX_FLAGS_EXTRA ${CXX_FLAGS_EXTRA} -fsanitize=memory -fsanitize-memory-track-origins=2 -fPIE) - #set (CMAKE_EXE_LINKER_FLAGS_EXTRA ${CMAKE_EXE_LINKER_FLAGS_EXTRA} -fsanitize=memory )#$<$:-static-libmsan>) + #SET (CXX_FLAGS_EXTRA ${CXX_FLAGS_EXTRA} -fsanitize=memory -fsanitize-memory-track-origins=2 -fPIE) + #set (CMAKE_EXE_LINKER_FLAGS_EXTRA ${CMAKE_EXE_LINKER_FLAGS_EXTRA} -fsanitize=memory )#$<$:-static-libmsan>) #SET (PREPROCESSOR_DEFS_EXTRA ${PREPROCESSOR_DEFS_EXTRA} MEMORY_SANITIZER) #SET (ENABLED_SANITIZER true) endif() if(${USE_LSAN}) message(FATAL_ERROR "MinGW-GCC doesn't yet support LSAN") set(USE_LSAN false) - #SET (CXX_FLAGS_EXTRA ${CXX_FLAGS_EXTRA} -fsanitize=leak) - #set (CMAKE_EXE_LINKER_FLAGS_EXTRA ${CMAKE_EXE_LINKER_FLAGS_EXTRA} -fsanitize=leak #$<$:-static-liblsan>) + #SET (CXX_FLAGS_EXTRA ${CXX_FLAGS_EXTRA} -fsanitize=leak) + #set (CMAKE_EXE_LINKER_FLAGS_EXTRA ${CMAKE_EXE_LINKER_FLAGS_EXTRA} -fsanitize=leak #$<$:-static-liblsan>) #SET (PREPROCESSOR_DEFS_EXTRA ${PREPROCESSOR_DEFS_EXTRA} LEAK_SANITIZER) #SET (ENABLED_SANITIZER true) endif() @@ -61,21 +61,21 @@ function(toolchain_exe_stuff_common) set(USE_UBSAN false) #[[ SET (UBSAN_FLAGS - -fsanitize=undefined,float-divide-by-zero - -fno-sanitize=enum - # Unsupported (yet?) by GCC 13 - #-fsanitize=unsigned-integer-overflow #Unlike signed integer overflow, this is not undefined behavior, but it is often unintentional. + -fsanitize=undefined,float-divide-by-zero + -fno-sanitize=enum + # Unsupported (yet?) by GCC 13 + #-fsanitize=unsigned-integer-overflow #Unlike signed integer overflow, this is not undefined behavior, but it is often unintentional. #-fsanitize=implicit-conversion, local-bounds - ) + ) ]] - #SET (CXX_FLAGS_EXTRA ${CXX_FLAGS_EXTRA} ${UBSAN_FLAGS} -fsanitize=return,vptr) - #set (CMAKE_EXE_LINKER_FLAGS_EXTRA ${CMAKE_EXE_LINKER_FLAGS_EXTRA} -fsanitize=undefined #$<$:-static-libubsan>) + #SET (CXX_FLAGS_EXTRA ${CXX_FLAGS_EXTRA} ${UBSAN_FLAGS} -fsanitize=return,vptr) + #set (CMAKE_EXE_LINKER_FLAGS_EXTRA ${CMAKE_EXE_LINKER_FLAGS_EXTRA} -fsanitize=undefined #$<$:-static-libubsan>) #SET (PREPROCESSOR_DEFS_EXTRA ${PREPROCESSOR_DEFS_EXTRA} UNDEFINED_BEHAVIOR_SANITIZER) #SET (ENABLED_SANITIZER true) endif() #IF (${ENABLED_SANITIZER}) - # SET (PREPROCESSOR_DEFS_EXTRA ${PREPROCESSOR_DEFS_EXTRA} _SANITIZERS) + # SET (PREPROCESSOR_DEFS_EXTRA ${PREPROCESSOR_DEFS_EXTRA} _SANITIZERS) #ENDIF () #-- Store compiler flags common to all builds. @@ -180,7 +180,7 @@ function(toolchain_exe_stuff_common) #-- Set different output folders for each build type # (When we'll have support for multi-target builds...) - #SET_TARGET_PROPERTIES(spheresvr PROPERTIES RUNTIME_OUTPUT_RELEASE "${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/Release" ) - #SET_TARGET_PROPERTIES(spheresvr PROPERTIES RUNTIME_OUTPUT_DEBUG "${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/Debug" ) - #SET_TARGET_PROPERTIES(spheresvr PROPERTIES RUNTIME_OUTPUT_NIGHTLY "${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/Nightly" ) + #SET_TARGET_PROPERTIES(spheresvr PROPERTIES RUNTIME_OUTPUT_RELEASE "${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/Release" ) + #SET_TARGET_PROPERTIES(spheresvr PROPERTIES RUNTIME_OUTPUT_DEBUG "${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/Debug" ) + #SET_TARGET_PROPERTIES(spheresvr PROPERTIES RUNTIME_OUTPUT_NIGHTLY "${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/Nightly" ) endfunction() diff --git a/lib/lib_build_flags_common_c.cmake b/lib/lib_build_flags_common_c.cmake index b47cecd90..623a30f26 100644 --- a/lib/lib_build_flags_common_c.cmake +++ b/lib/lib_build_flags_common_c.cmake @@ -5,17 +5,17 @@ endif() if(MSVC) # gersemi: off - set (c_compiler_options_common - /O2 /EHsc /GA /Gw /Gy /GF /GR- /GS- - $<$: $,/MT,/MD> $<$:/Zi>> - $<$: $,/MT,/MD> $<$:/Zi>> - $<$: $,/MTd,/MDd> $,/Zi,/ZI>> - ) - set (c_linker_options_common - $<$: /OPT:REF,ICF /LTCG:ON /NODEFAULTLIB:libcmtd> - $<$: /OPT:REF,ICF /LTCG:ON /NODEFAULTLIB:libcmtd> - $<$: /DEBUG /LTCG:OFF /NODEFAULTLIB:libcmt> - ) + set (c_compiler_options_common + /O2 /EHsc /GA /Gw /Gy /GF /GR- /GS- + $<$: $,/MT,/MD> $<$:/Zi>> + $<$: $,/MT,/MD> $<$:/Zi>> + $<$: $,/MTd,/MDd> $,/Zi,/ZI>> + ) + set (c_linker_options_common + $<$: /OPT:REF,ICF /LTCG:ON /NODEFAULTLIB:libcmtd> + $<$: /OPT:REF,ICF /LTCG:ON /NODEFAULTLIB:libcmtd> + $<$: /DEBUG /LTCG:OFF /NODEFAULTLIB:libcmt> + ) # gersemi: on else(MSVC) set(c_compiler_options_common diff --git a/utilities/cmake_format_gersemi.sh b/utilities/cmake_format_gersemi.sh index 69c493e96..c115c78f9 100644 --- a/utilities/cmake_format_gersemi.sh +++ b/utilities/cmake_format_gersemi.sh @@ -13,6 +13,9 @@ project_root_dir="$(git rev-parse --show-toplevel)" gersemi_cmd='env PWD="$project_root_dir" gersemi -i "{}"' #gersemi_cmd='gersemi -i "{}" --list-expansion favour-inlining --no-warn-about-unknown-commands' +# Replace tabs with 4 spaces +sed_cmd='sed -i "s/\t/ /g" "{}"' + #looks like cmake-format is unmantained #cmake-format CMakeLists.txt --separate-ctrl-name-with-space --separate-fn-name-with-space --dangle-parens --max-subgroups-hwrap=2 --max-pargs-hwrap=4 --max-rows-cmdline=120 @@ -23,10 +26,16 @@ format_files() { if [ -f "{}" ]; then echo "Formatting {}" '"$gersemi_cmd"' + '"$sed_cmd"' else - echo "{} does not exist" + echo "{} does not exist?" fi ' + #if git diff --exit-code "{}" > /dev/null; then + # result="$result CHANGED" + #else + # result="$result unchanged" + #fi } # Case to determine the files based on the action From 56a67698cf47853c8a560468bd4c0ab77f68fcff Mon Sep 17 00:00:00 2001 From: cbnolok Date: Sun, 8 Sep 2024 16:41:18 +0200 Subject: [PATCH 26/86] Fixed dorigin, regression in previous refactoring and fixes. --- src/common/resource/sections/CDialogDef.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/common/resource/sections/CDialogDef.cpp b/src/common/resource/sections/CDialogDef.cpp index 0a6fceb81..f59e75719 100644 --- a/src/common/resource/sections/CDialogDef.cpp +++ b/src/common/resource/sections/CDialogDef.cpp @@ -150,7 +150,7 @@ bool CDialogDef::r_Verb( CScript & s, CTextConsole * pSrc ) // some command on t GETNONWHITESPACE(ptcArgs); }; - const auto _CalcRelative = [](lptstr& ptcArgs, int iCoordBase) -> int + const auto _CalcRelative = [](lptstr& ptcArgs, int &iCoordBase) -> int { int c; if ( *ptcArgs == '-' && IsSpace(ptcArgs[1])) From f670e252759a9af0d211e261160164585e86e09f Mon Sep 17 00:00:00 2001 From: cbnolok Date: Sun, 8 Sep 2024 17:24:23 +0200 Subject: [PATCH 27/86] Add bash script to run clang-format. Minor changes to .clang-format. --- .clang-format | 5 +- utilities/run_clang-format.sh | 67 +++++++++++++++++++ ...format_gersemi.sh => run_gersemi_cmake.sh} | 0 3 files changed, 70 insertions(+), 2 deletions(-) create mode 100644 utilities/run_clang-format.sh rename utilities/{cmake_format_gersemi.sh => run_gersemi_cmake.sh} (100%) diff --git a/.clang-format b/.clang-format index 6e789c574..700faebeb 100644 --- a/.clang-format +++ b/.clang-format @@ -11,8 +11,8 @@ ColumnLimit: 160 ##-- Alignment AlignAfterOpenBracket: AlwaysBreak -AlignConsecutiveAssignments: false -AlignConsecutiveDeclarations: false +AlignConsecutiveAssignments: true +AlignConsecutiveDeclarations: true #AlignEscapedNewlinesLeft: false AlignTrailingComments: true @@ -63,6 +63,7 @@ BreakStringLiterals: false ##-- Indentation IndentCaseBlocks: false IndentCaseLabels: true +IndentExternBlock: AfterExternBlock IndentGotoLabels: true IndentPPDirectives: AfterHash LambdaBodyIndentation: Signature diff --git a/utilities/run_clang-format.sh b/utilities/run_clang-format.sh new file mode 100644 index 000000000..2755261c4 --- /dev/null +++ b/utilities/run_clang-format.sh @@ -0,0 +1,67 @@ +#!/bin/bash + +# Check if a parameter is provided +if [ "$#" -ne 1 ]; then + echo "Usage: $0 [--all|--changed|--last-commit] [--autocommit]" + exit 1 +fi + +parallel_jobs=$(nproc) +action=$1 +project_root_dir="$(git rev-parse --show-toplevel)" + +# Define the command; change the execution folder in order to make it read .clang-format +gersemi_cmd='env PWD="$project_root_dir" clang-format -i "{}"' + +# Function to format files +format_files() { + echo "$1" | \ + xargs -P $parallel_jobs -I {} sh -c ' + if [ -f "{}" ]; then + echo "Formatting {}" + '"$gersemi_cmd"' + '"$sed_cmd"' + else + echo "{} does not exist?" + fi + ' + #if git diff --exit-code "{}" > /dev/null; then + # result="$result CHANGED" + #else + # result="$result unchanged" + #fi +} + +# Case to determine the files based on the action +case $action in + --all) + # Find all *.cmake files and CMakeLists.txt + files=$(find "$project_root_dir"/src \ + -type f \( -name "*.cpp" -o -name "*.h" -o -name "*.hpp" \) -print) + ;; + --changed) + # Get modified and staged files (combined) + unstaged_files=$(git diff --name-only) + staged_files=$(git diff --cached --name-only) + files=$( (echo "$unstaged_files" && echo "$staged_files") | sort | uniq | grep -E '\.cpp$|\.h$|\.hpp$') + ;; + --last-commit) + # Get only the files modified by the last commit + files=$( git diff --name-only HEAD~1 HEAD | grep -E '\.cpp$|\.h$|\.hpp$' ) + ;; + *) + echo "Invalid option." + exit 1 + ;; +esac + +# Call the formatting function +format_files "$files" + +# Check if --autocommit flag is passed +if [[ "$2" == "--autocommit" ]]; then + echo "$files" | xargs git add + #git commit --amend --no-edit + git commit --no-edit -m "Auto commit: re-formatted cmake files." + echo "Previous commit amended with the staged files." +fi diff --git a/utilities/cmake_format_gersemi.sh b/utilities/run_gersemi_cmake.sh similarity index 100% rename from utilities/cmake_format_gersemi.sh rename to utilities/run_gersemi_cmake.sh From 2981b76da983a0b4965aae38c9ab93a9643e8e2f Mon Sep 17 00:00:00 2001 From: cbnolok Date: Sun, 8 Sep 2024 21:20:42 +0200 Subject: [PATCH 28/86] Add .clang-tidy stub. --- .clang-tidy | 43 +++++++++++++++++++++++++++++++++++ lib/.cmake-tidy | 2 ++ src/game/CWorldImport.cpp | 2 +- src/network/net_datatypes.cpp | 14 ++++++------ src/network/net_datatypes.h | 4 ++-- 5 files changed, 55 insertions(+), 10 deletions(-) create mode 100644 .clang-tidy create mode 100644 lib/.cmake-tidy diff --git a/.clang-tidy b/.clang-tidy new file mode 100644 index 000000000..c8d1127c8 --- /dev/null +++ b/.clang-tidy @@ -0,0 +1,43 @@ +Checks: > + #-*, + bugprone-*, + cppcoreguidelines-*, + clang-analyzer-*, + hicpp-*, + misc-*, + modernize-*, + performance-*, + portability-*, + readability-* + #-misc-non-private-member-variables-in-classes, + #-readability-named-parameter, + #-readability-braces-around-statements, + #-readability-magic-numbers + +# Turn all the warnings from the checks above into errors. +#WarningsAsErrors: "*" + +CheckOptions: + - key: 'clang-analyzer-core.NonNullParamChecker:assert_like_macro' + value: 'DEBUG_ASSERT,ASSERT,PERSISTANT_ASSERT' + - { key: readability-identifier-naming.NamespaceCase, value: lower_case } + - { key: readability-identifier-naming.ClassCase, value: CamelCase } + - { key: readability-identifier-naming.StructCase, value: CamelCase } + - { key: readability-identifier-naming.TemplateParameterCase, value: CamelCase } + - { key: readability-identifier-naming.FunctionCase, value: camelBack } + - { key: readability-identifier-naming.VariableCase, value: lower_case } + - { key: readability-identifier-naming.PrivateMemberPrefix, value: m_ } + - { key: readability-identifier-naming.ProtectedMemberPrefix, value: m_ } + - { key: readability-identifier-naming.MacroDefinitionCase, value: UPPER_CASE } + - { key: readability-identifier-naming.EnumConstantCase, value: UPPER_CASE} + - { key: readability-identifier-naming.EnumConstantPrefix, value: k } + - { key: readability-identifier-naming.ScopedEnumConstantCase, value: CamelCase } + - { key: readability-identifier-naming.ScopedEnumConstantPrefix, value: k } + - { key: readability-identifier-naming.ConstexprVariableCase, value: CamelCase } + - { key: readability-identifier-naming.ConstexprVariablePrefix, value: k } + - { key: readability-identifier-naming.GlobalConstantCase, value: CamelCase } + - { key: readability-identifier-naming.GlobalConstantPrefix, value: k } + - { key: readability-identifier-naming.MemberConstantCase, value: CamelCase } + - { key: readability-identifier-naming.MemberConstantPrefix, value: k } + - { key: readability-identifier-naming.StaticConstantCase, value: CamelCase } + - { key: readability-identifier-naming.StaticConstantPrefix, value: k } diff --git a/lib/.cmake-tidy b/lib/.cmake-tidy new file mode 100644 index 000000000..2f122e331 --- /dev/null +++ b/lib/.cmake-tidy @@ -0,0 +1,2 @@ +# Disable all checks in this folder. +Checks: '-*' diff --git a/src/game/CWorldImport.cpp b/src/game/CWorldImport.cpp index 2ad5f3a3c..e7109120c 100644 --- a/src/game/CWorldImport.cpp +++ b/src/game/CWorldImport.cpp @@ -416,7 +416,7 @@ bool CImportFile::ImportWSC( CScript & s, word wModeFlags, short dx, short dy ) m_pCurSer->m_layer = static_cast(atoi(pArg)); continue; } - else if (pItem == nullptr) + if (pItem == nullptr) { DEBUG_ERR(( "Import:Found '%s' before ID.\n", s.GetKey())); continue; diff --git a/src/network/net_datatypes.cpp b/src/network/net_datatypes.cpp index ef9066312..57223fd99 100644 --- a/src/network/net_datatypes.cpp +++ b/src/network/net_datatypes.cpp @@ -32,7 +32,7 @@ ndword& ndword::operator = (dword val) noexcept } -static int CvtSystemToUTF16(wchar& wChar, lpctstr pInp, int iSizeInBytes) noexcept +static int CvtSystemToUTF16(wchar& wChar, lpctstr pInp, int iSizeInBytes) { // Convert a UTF8 encoded string to a single unicode char. // RETURN: The length used from input string. < iSizeInBytes @@ -43,7 +43,7 @@ static int CvtSystemToUTF16(wchar& wChar, lpctstr pInp, int iSizeInBytes) noexce // 3 16 1110bbbb 10bbbbbb 10bbbbbb // 4 21 11110bbb 10bbbbbb 10bbbbbb 10bbbbbb - byte ch = *pInp; + byte ch = (byte)*pInp; ASSERT(ch >= 0x80); // needs special UTF8 decoding. int iBytes; @@ -75,7 +75,7 @@ static int CvtSystemToUTF16(wchar& wChar, lpctstr pInp, int iSizeInBytes) noexce int iInp = 1; for (; iInp < iBytes; iInp++) { - ch = pInp[iInp]; + ch = (byte)pInp[iInp]; if ((ch & 0xc0) != 0x80) // bad coding. return -1; wCharTmp <<= 6; @@ -86,7 +86,7 @@ static int CvtSystemToUTF16(wchar& wChar, lpctstr pInp, int iSizeInBytes) noexce return iBytes; } -static int CvtUTF16ToSystem(tchar* pOut, int iSizeOutBytes, wchar wChar) noexcept +static int CvtUTF16ToSystem(tchar* pOut, int iSizeOutBytes, wchar wChar) { // Convert a single unicode char to system string. // RETURN: The length < iSizeOutBytes @@ -145,7 +145,7 @@ static int CvtUTF16ToSystem(tchar* pOut, int iSizeOutBytes, wchar wChar) noexcep return iBytes; } -int CvtSystemToNETUTF16(nachar* pOut, int iSizeOutChars, lpctstr pInp, int iSizeInBytes) noexcept +int CvtSystemToNETUTF16(nachar* pOut, int iSizeOutChars, lpctstr pInp, int iSizeInBytes) { // // Convert the system default text format UTF8 to UNICODE @@ -214,7 +214,7 @@ int CvtSystemToNETUTF16(nachar* pOut, int iSizeOutChars, lpctstr pInp, int iSize int iInp = 0; for (; iInp < iSizeInBytes; ) { - byte ch = pInp[iInp]; + byte ch = (byte)pInp[iInp]; if (ch == 0) break; @@ -246,7 +246,7 @@ int CvtSystemToNETUTF16(nachar* pOut, int iSizeOutChars, lpctstr pInp, int iSize return iOut; } -int CvtNETUTF16ToSystem(tchar* pOut, int iSizeOutBytes, const nachar* pInp, int iSizeInChars) noexcept +int CvtNETUTF16ToSystem(tchar* pOut, int iSizeOutBytes, const nachar* pInp, int iSizeInChars) { // ARGS: // iSizeInBytes = space we have (included null char) diff --git a/src/network/net_datatypes.h b/src/network/net_datatypes.h index 7b520ee27..e6633453c 100644 --- a/src/network/net_datatypes.h +++ b/src/network/net_datatypes.h @@ -86,8 +86,8 @@ struct ndword #endif -int CvtSystemToNETUTF16(nachar* pOut, int iSizeOutChars, lpctstr pInp, int iSizeInBytes) noexcept; -int CvtNETUTF16ToSystem(tchar* pOut, int iSizeOutBytes, const nachar* pInp, int iSizeInChars) noexcept; +int CvtSystemToNETUTF16(nachar* pOut, int iSizeOutChars, lpctstr pInp, int iSizeInBytes); +int CvtNETUTF16ToSystem(tchar* pOut, int iSizeOutBytes, const nachar* pInp, int iSizeInChars); #endif // _INC_NET_DATATYPES_H From af5f7d375a15477e45959f8d4e451caf2f99c156 Mon Sep 17 00:00:00 2001 From: cbnolok Date: Mon, 9 Sep 2024 18:51:32 +0200 Subject: [PATCH 29/86] Update .clang-tidy, fixed a couple of linter warnings. --- .clang-tidy | 53 +++++++++++++++++++++---- lib/.cmake-tidy | 2 +- src/common/CException.h | 2 +- src/common/CScriptObj.cpp | 1 + src/common/common.cpp | 2 +- src/common/resource/CResourceHolder.cpp | 2 +- src/common/sphere_library/CSString.cpp | 1 + src/game/CBase.cpp | 2 +- src/game/CBase.h | 2 +- src/game/CObjBase.cpp | 2 +- src/game/CScriptProfiler.h | 2 +- src/game/CServer.cpp | 11 +++-- src/game/chars/CCharUse.cpp | 1 + 13 files changed, 64 insertions(+), 19 deletions(-) diff --git a/.clang-tidy b/.clang-tidy index c8d1127c8..d051527da 100644 --- a/.clang-tidy +++ b/.clang-tidy @@ -1,18 +1,55 @@ +ExcludeHeaderFilterRegex: ^.*(lib\/).* + Checks: > #-*, + # Enable groups: bugprone-*, cppcoreguidelines-*, clang-analyzer-*, - hicpp-*, + ##hicpp-*, misc-*, modernize-*, performance-*, portability-*, - readability-* - #-misc-non-private-member-variables-in-classes, - #-readability-named-parameter, - #-readability-braces-around-statements, - #-readability-magic-numbers + readability-*, + # Disable specific checks/warnings: + -clang-analyzer-security.insecureAPI.strcpy, + -cppcoreguidelines-avoid-c-arrays, + -cppcoreguidelines-avoid-goto, + -cppcoreguidelines-avoid-magic-numbers, + -cppcoreguidelines-no-malloc, + -cppcoreguidelines-init-variables, # false positives + -cppcoreguidelines-owning-memory, + -cppcoreguidelines-prefer-member-initializer, + -cppcoreguidelines-pro-bounds-array-pointer-decay, + -cppcoreguidelines-pro-bounds-pointer-arithmetic, + -cppcoreguidelines-pro-bounds-constant-array-index, + -cppcoreguidelines-pro-type-const-cast, # we have some instances, and we should remove them... + -cppcoreguidelines-pro-type-vararg, + -cppcoreguidelines-pro-type-union-access, + ##-hicpp-use-auto, #duplicate + ##-hicpp-braces-around-statements, + ##-hicpp-vararg, #duplicate + -misc-include-cleaner, + -modernize-avoid-c-arrays, + -modernize-use-auto, + -modernize-use-trailing-return-type, + -modernize-loop-convert, + -readability-braces-around-statements, + -readability-delete-null-pointer, + -readability-else-after-return, + -readability-function-cognitive-complexity, + -readability-identifier-length, + -readability-identifier-naming, + -readability-implicit-bool-conversion, + -readability-magic-numbers, + -readability-misleading-indentation, # to be enabled after the source is properly formatted + -readability-simplify-boolean-expr, + -readability-uppercase-literal-suffix, + ##-misc-non-private-member-variables-in-classes, + ##-readability-named-parameter, + ##-readability-braces-around-statements, + ##-readability-magic-numbers # Turn all the warnings from the checks above into errors. #WarningsAsErrors: "*" @@ -25,12 +62,12 @@ CheckOptions: - { key: readability-identifier-naming.StructCase, value: CamelCase } - { key: readability-identifier-naming.TemplateParameterCase, value: CamelCase } - { key: readability-identifier-naming.FunctionCase, value: camelBack } - - { key: readability-identifier-naming.VariableCase, value: lower_case } + - { key: readability-identifier-naming.VariableCase, value: camelBack } # lower_case - { key: readability-identifier-naming.PrivateMemberPrefix, value: m_ } - { key: readability-identifier-naming.ProtectedMemberPrefix, value: m_ } - { key: readability-identifier-naming.MacroDefinitionCase, value: UPPER_CASE } - { key: readability-identifier-naming.EnumConstantCase, value: UPPER_CASE} - - { key: readability-identifier-naming.EnumConstantPrefix, value: k } + #- { key: readability-identifier-naming.EnumConstantPrefix, value: k } - { key: readability-identifier-naming.ScopedEnumConstantCase, value: CamelCase } - { key: readability-identifier-naming.ScopedEnumConstantPrefix, value: k } - { key: readability-identifier-naming.ConstexprVariableCase, value: CamelCase } diff --git a/lib/.cmake-tidy b/lib/.cmake-tidy index 2f122e331..66d80e2b4 100644 --- a/lib/.cmake-tidy +++ b/lib/.cmake-tidy @@ -1,2 +1,2 @@ # Disable all checks in this folder. -Checks: '-*' +Checks: -* diff --git a/src/common/CException.h b/src/common/CException.h index 3c9919a56..7f2f9a0c8 100644 --- a/src/common/CException.h +++ b/src/common/CException.h @@ -126,7 +126,7 @@ class CAssert : public CSError #define EXC_TRY(a) \ lpctstr inLocalBlock = ""; \ lpctstr inLocalArgs = a; \ - uint inLocalBlockCnt = 0; \ + uint inLocalBlockCnt = 0; /* NOLINT(misc-const-correctness) */ \ bool fCATCHExcept = false; \ UnreferencedParameter(fCATCHExcept); \ try \ diff --git a/src/common/CScriptObj.cpp b/src/common/CScriptObj.cpp index 9731e86f3..0390d7d38 100644 --- a/src/common/CScriptObj.cpp +++ b/src/common/CScriptObj.cpp @@ -969,6 +969,7 @@ bool CScriptObj::r_WriteVal( lpctstr ptcKey, CSString &sVal, CTextConsole * pSrc */ // I think fork will cause problems.. we'll see.. if yes new thread + execlp is required. + // TODO: use posix_spawn int child_pid = vfork(); if ( child_pid < 0 ) { diff --git a/src/common/common.cpp b/src/common/common.cpp index d7b937b8b..9d6f7e4f0 100644 --- a/src/common/common.cpp +++ b/src/common/common.cpp @@ -61,7 +61,7 @@ void CLanguageID::GetStrDef(tchar* pszLang) noexcept { if (!IsDef()) { - strcpy(pszLang, "enu"); + strcpy(pszLang, "enu"); // NOLINT(clang-analyzer-security.insecureAPI.strcpy) } else { diff --git a/src/common/resource/CResourceHolder.cpp b/src/common/resource/CResourceHolder.cpp index 196af300d..d2fe6ec22 100644 --- a/src/common/resource/CResourceHolder.cpp +++ b/src/common/resource/CResourceHolder.cpp @@ -113,7 +113,7 @@ CResourceScript * CResourceHolder::AddResourceFile( lpctstr pszName ) throw CSError(LOGL_ERROR, 0, "Filename too long!"); tchar szName[_MAX_PATH]; - strcpy(szName, pszName); + Str_CopyLimitNull(szName, pszName, sizeof(szName)); tchar szTitle[_MAX_PATH]; lpctstr ptcTitle = CScript::GetFilesTitle(szName); diff --git a/src/common/sphere_library/CSString.cpp b/src/common/sphere_library/CSString.cpp index e2dec70eb..3e96295a9 100644 --- a/src/common/sphere_library/CSString.cpp +++ b/src/common/sphere_library/CSString.cpp @@ -136,6 +136,7 @@ int CSString::Resize(int iNewLength, bool fPreciseSize) pNewData[m_iLength] = '\0'; m_pchData = pNewData; } + ASSERT(m_pchData); m_iLength = iNewLength; m_pchData[m_iLength] = '\0'; return m_iLength; diff --git a/src/game/CBase.cpp b/src/game/CBase.cpp index f11a71045..da66090dd 100644 --- a/src/game/CBase.cpp +++ b/src/game/CBase.cpp @@ -24,7 +24,7 @@ lpctstr const CBaseBaseDef::sm_szLoadKeys[OBC_QTY+1] = }; -CBaseBaseDef::CBaseBaseDef( CResourceID id ) : +CBaseBaseDef::CBaseBaseDef( CResourceID const& id ) : CResourceLink( id ), m_sName(false) { diff --git a/src/game/CBase.h b/src/game/CBase.h index 1cf7e28fc..e9843fe02 100644 --- a/src/game/CBase.h +++ b/src/game/CBase.h @@ -193,7 +193,7 @@ struct CBaseBaseDef : public CResourceLink, public CEntityProps } public: - CBaseBaseDef( CResourceID id ); + CBaseBaseDef( CResourceID const& id ); virtual ~CBaseBaseDef() = default; CBaseBaseDef(const CBaseBaseDef& copy) = delete; diff --git a/src/game/CObjBase.cpp b/src/game/CObjBase.cpp index 435377476..3019f062b 100644 --- a/src/game/CObjBase.cpp +++ b/src/game/CObjBase.cpp @@ -1974,7 +1974,7 @@ bool CObjBase::r_LoadVal( CScript & s ) * So the new timer will be the current time in msecs (SetTimeout) * For older builds, the timer is stored in seconds (SetTimeoutD) */ - if (iPrevBuild && (iPrevBuild >= 2866)) // commit #e08723c54b0a4a3b1601eba6f34a6118891f1313 + if (iPrevBuild >= 2866) // commit #e08723c54b0a4a3b1601eba6f34a6118891f1313 { // If TIMER = 0 was saved it means that at the moment of the worldsave the timer was elapsed but its object could not tick, // since it was waiting a GoAwake() call. Now set the timer to tick asap. diff --git a/src/game/CScriptProfiler.h b/src/game/CScriptProfiler.h index 364897232..4fa0b8958 100644 --- a/src/game/CScriptProfiler.h +++ b/src/game/CScriptProfiler.h @@ -37,7 +37,7 @@ extern struct CScriptProfiler // Time measurement macros for the profiler (use them only for the profiler!) -#define TIME_PROFILE_INIT llong llTicksStart = 0, llTicksEnd = 0 +#define TIME_PROFILE_INIT llong llTicksStart = 0; llong llTicksEnd = 0 #define TIME_PROFILE_START llTicksStart = CSTime::GetMonotonicSysTimeMilli(); #define TIME_PROFILE_END llTicksEnd = CSTime::GetMonotonicSysTimeMilli(); diff --git a/src/game/CServer.cpp b/src/game/CServer.cpp index fd64ff4fe..19115f35d 100644 --- a/src/game/CServer.cpp +++ b/src/game/CServer.cpp @@ -394,7 +394,9 @@ void CServer::ListClients( CTextConsole *pConsole ) const if ( pCharCmd && !pCharCmd->CanDisturb(pChar) ) continue; - snprintf(ptcMsg, Str_TempLength(), "%" PRIx32 ":Acc%c'%s', Char='%s' (IP: %s)\n", pClient->GetSocketID(), chRank, !pAcc ? "null" : pAcc->GetName(), pChar->GetName(), pClient->GetPeerStr()); + snprintf(ptcMsg, Str_TempLength(), + "%" PRIx32 ":Acc%c'%s', Char='%s' (IP: %s)\n", + pClient->GetSocketID(), chRank, (!pAcc ? "null" : pAcc->GetName()), pChar->GetName(), pClient->GetPeerStr()); } else { @@ -415,7 +417,9 @@ void CServer::ListClients( CTextConsole *pConsole ) const break; } - snprintf(ptcMsg, Str_TempLength(), "%" PRIx32 ":Acc%c'%s' (IP: %s) %s\n", pClient->GetSocketID(), chRank, pAcc ? pAcc->GetName() : "", pClient->GetPeerStr(), pszState); + snprintf(ptcMsg, Str_TempLength(), + "%" PRIx32 ":Acc%c'%s' (IP: %s) %s\n", + pClient->GetSocketID(), chRank, (pAcc ? pAcc->GetName() : ""), pClient->GetPeerStr(), pszState); } pConsole->SysMessage(ptcMsg); @@ -497,7 +501,8 @@ bool CServer::OnConsoleCmd( CSString & sText, CTextConsole * pSrc ) switch ( tolower(*ptcKey) ) { case 'a': // areas - ptcKey++; GETNONWHITESPACE( ptcKey ); + ptcKey++; + GETNONWHITESPACE( ptcKey ); if ( !g_World.DumpAreas( pSrc, ptcKey ) ) { if (pSrc != this) diff --git a/src/game/chars/CCharUse.cpp b/src/game/chars/CCharUse.cpp index b4e9ab655..1dc98f43d 100644 --- a/src/game/chars/CCharUse.cpp +++ b/src/game/chars/CCharUse.cpp @@ -204,6 +204,7 @@ void CChar::Use_MoonGate( CItem * pItem ) // What gate are we at ? size_t i = 0; size_t iCount = g_Cfg.m_MoonGates.size(); + ASSERT(iCount != 0); const CPointMap& ptTop = GetTopPoint(); for ( ; i < iCount; ++i ) { From 899b93b721c5f70faddae7c0c64dd1bbec7d6372 Mon Sep 17 00:00:00 2001 From: cbnolok Date: Tue, 10 Sep 2024 12:11:12 +0200 Subject: [PATCH 30/86] Updated f_onserver_connectreq_ex. --- Changelog.txt | 20 ++++++- src/game/CServer.cpp | 8 +-- src/game/CServerConfig.cpp | 4 +- src/game/CServerConfig.h | 2 +- src/game/clients/CClient.cpp | 24 +++++---- src/game/clients/CClient.h | 2 +- src/game/clients/CClientLog.cpp | 6 +-- src/network/CIPHistoryManager.cpp | 48 ++++++++--------- src/network/CIPHistoryManager.h | 18 +++---- src/network/CNetworkManager.cpp | 88 +++++++++++++++++-------------- src/sphere.ini | 6 +-- 11 files changed, 129 insertions(+), 97 deletions(-) diff --git a/Changelog.txt b/Changelog.txt index 295220e34..027ff84ef 100644 --- a/Changelog.txt +++ b/Changelog.txt @@ -3725,6 +3725,8 @@ Added: 'H' shortcut for variables to get the value as hexadecimal. // Maximum time in milliseconds to wait before closing a connection request wich did not make it into a successful login (classic DDoS just asks to connect without doing anything else, or sends garbage data). TimeoutIncompleteConn=5 * 1000 // 5 seconds - Added serv_trig function f_onserver_connectreq_ex, called after an IP exceeds MaxConnectRequestsPerIP: + WARNING: function arguments and returns CHANGED in the 10-09-2024 commit. + ARGS (RO): IP address. ARGN1 (RO): System time in milliseconds since the last connection. ARGN2 (RO): System time in milliseconds of this connection attempt. @@ -3861,7 +3863,7 @@ Added: 'H' shortcut for variables to get the value as hexadecimal. 10-08-2024, Gladie - Fixed: CAN_I_DAMAGEABLE not updating status bar (PR #1259, issues #1248, #1260). -05-09-2024, Nolok +09-09-2024, Nolok WARNING! POTENTIALLY BREAKING CHANGE! Scripts will need to be updated. - Changed: since there was too much data to be stored in the FACTION/SLAYER property, so that it sometimes couldn't fit and caused issues, it has been split in two different properties: @@ -3872,3 +3874,19 @@ Added: 'H' shortcut for variables to get the value as hexadecimal. - Changed: SLAYER now works only on items, FACTION on characters. Before, they were synonyms and could be used on both chars and items to access the same property. - Removed: unused properties SLAYER, SLAYER_LESSER, SLAYER_SUPER, SLAYER_MISC. - Added: log message when a new thread is created or a thread is being renamed. + +10-09-2024, Nolok +Updated: f_onserver_connectreq_ex now is called whenever an ini connection limit is exceeded (pings, max connections...). + Now it stores these parameters: + - ARGS = IP address + - LOCAL.TIME_CUR_CONNECTED_MS (RO) = Monotonic system time when this connection request was handled (milliseconds) + - LOCAL.TIME_LAST_CONNECTED_MS (RO) = Monotonic system time of the previous connection attempt/request (milliseconds) + - LOCAL.PINGS (RO) = Current number of "pings" (connection attempts, the number decays over time) + - LOCAL.CONNECTION_REQUESTS (RO) = Current number of connection requests since i remember of this IP + - LOCAL.ALIVE_CONNECTIONS (RO) = How many active and successiful connections i have with this IP + - LOCAL.PENDING_CONNECTING (RO) = How many active connection attempts or incomplete connections i have to this IP + - LOCAL.BAN_TIMEOUT (RW) = unchanged -> 5 * 60 (default), seconds to keep banned the ip from new connections to the server (permanent if negative). + + RETURN -1: Don't do anything, let the connection pass. + RETURN 1: Only reject the connection. + RETURN 2: Reject and ban the IP for seconds. diff --git a/src/game/CServer.cpp b/src/game/CServer.cpp index 19115f35d..bb5c67dee 100644 --- a/src/game/CServer.cpp +++ b/src/game/CServer.cpp @@ -1571,11 +1571,11 @@ bool CServer::r_Verb( CScript &s, CTextConsole * pSrc ) { if (pSrc != this) { - pSrc->SysMessagef("IP%s blocked\n", history.m_blocked ? " already" : ""); + pSrc->SysMessagef("IP%s blocked\n", (history.m_fBlocked ? " already" : "")); } else { - g_Log.Event(LOGL_EVENT, "IP%s blocked\n", history.m_blocked ? " already" : ""); + g_Log.Event(LOGL_EVENT, "IP%s blocked\n", (history.m_fBlocked ? " already" : "")); } } @@ -1909,11 +1909,11 @@ bool CServer::r_Verb( CScript &s, CTextConsole * pSrc ) HistoryIP& history = g_NetworkManager.getIPHistoryManager().getHistoryForIP(s.GetArgRaw()); if (pSrc != this) { - pSrc->SysMessagef("IP%s unblocked\n", history.m_blocked ? "" : " already"); + pSrc->SysMessagef("IP%s unblocked\n", (history.m_fBlocked ? "" : " already")); } else { - g_Log.Event(LOGL_EVENT, "IP%s unblocked\n", history.m_blocked ? "" : " already"); + g_Log.Event(LOGL_EVENT, "IP%s unblocked\n", (history.m_fBlocked ? "" : " already")); } history.setBlocked(false); } diff --git a/src/game/CServerConfig.cpp b/src/game/CServerConfig.cpp index 456963106..809d625dc 100644 --- a/src/game/CServerConfig.cpp +++ b/src/game/CServerConfig.cpp @@ -310,7 +310,7 @@ CServerConfig::CServerConfig() _uiNetworkThreadPriority= IThread::Disabled; m_fUseAsyncNetwork = 0; m_iNetMaxPings = 15; - m_iNetHistoryTTL = 300; + m_iNetHistoryTTLSeconds = 300; _uiNetMaxPacketsPerTick = 50; _uiNetMaxLengthPerTick = 18'000; m_iNetMaxQueueSize = 75; @@ -919,7 +919,7 @@ const CAssocReg CServerConfig::sm_szLoadKeys[RC_QTY + 1] { "MYSQLPASSWORD", { ELEM_CSTRING, static_castOFFSETOF(CServerConfig,m_sMySqlPass) }}, { "MYSQLTICKS", { ELEM_BOOL, static_castOFFSETOF(CServerConfig,m_fMySqlTicks) }}, { "MYSQLUSER", { ELEM_CSTRING, static_castOFFSETOF(CServerConfig,m_sMySqlUser) }}, - { "NETTTL", { ELEM_INT, static_castOFFSETOF(CServerConfig,m_iNetHistoryTTL) }}, + { "NETTTL", { ELEM_INT, static_castOFFSETOF(CServerConfig, m_iNetHistoryTTLSeconds) }}, { "NETWORKTHREADPRIORITY", { ELEM_MASK_INT,static_castOFFSETOF(CServerConfig,_uiNetworkThreadPriority)}}, { "NETWORKTHREADS", { ELEM_MASK_INT,static_castOFFSETOF(CServerConfig,_uiNetworkThreads) }}, { "NORESROBE", { ELEM_BOOL, static_castOFFSETOF(CServerConfig,m_fNoResRobe) }}, diff --git a/src/game/CServerConfig.h b/src/game/CServerConfig.h index 8e3d8e0a2..768ce123b 100644 --- a/src/game/CServerConfig.h +++ b/src/game/CServerConfig.h @@ -572,7 +572,7 @@ extern class CServerConfig : public CResourceHolder uint _uiNetworkThreadPriority; // priority of network threads int m_fUseAsyncNetwork; // 0=normal send, 1=async send, 2=async send for 4.0.0+ only int m_iNetMaxPings; // max pings before blocking an ip - int m_iNetHistoryTTL; // time to remember an ip + int m_iNetHistoryTTLSeconds; // time to remember an ip uint _uiNetMaxPacketsPerTick; // max packets to send per tick (per queue) uint _uiNetMaxLengthPerTick; // max packet length to send per tick (per queue) (also max length of individual packets) int64 _iMaxSizeClientOut; // Maximum number of bytes a client can send to the server in 10 seconds before being disconnected diff --git a/src/game/clients/CClient.cpp b/src/game/clients/CClient.cpp index 46c6f4df1..9ac40448e 100644 --- a/src/game/clients/CClient.cpp +++ b/src/game/clients/CClient.cpp @@ -31,8 +31,8 @@ CClient::CClient(CNetState* state) // update ip history HistoryIP& history = g_NetworkManager.getIPHistoryManager().getHistoryForIP(GetPeer()); - ++ history.m_connecting; - ++ history.m_connected; + ++ history.m_iPendingConnectionRequests; + ++ history.m_iAliveSuccessfulConnections; m_Crypt.SetClientVerFromOther( g_Serv.m_ClientVersion ); m_pAccount = nullptr; @@ -62,7 +62,7 @@ CClient::CClient(CNetState* state) m_Env.SetInvalid(); g_Log.Event(LOGM_CLIENTS_LOG, "%x:Client connected [Total:%" PRIuSIZE_T "]. IP='%s'. (Connecting/Connected: %d/%d).\n", - GetSocketID(), g_Serv.StatGet(SERV_STAT_CLIENTS), GetPeerStr(), history.m_connecting, history.m_connected); + GetSocketID(), g_Serv.StatGet(SERV_STAT_CLIENTS), GetPeerStr(), history.m_iPendingConnectionRequests, history.m_iAliveSuccessfulConnections); m_zLastMessage[0] = 0; m_zLastObjMessage[0] = 0; @@ -83,17 +83,23 @@ CClient::CClient(CNetState* state) } -CClient::~CClient() +CClient::~CClient() noexcept { - EXC_TRY("Cleanup in destructor"); - ADDTOCALLSTACK("CClient::~CClient"); + EXC_TRY("Cleanup in destructor"); // update ip history HistoryIP& history = g_NetworkManager.getIPHistoryManager().getHistoryForIP(GetPeer()); if ( GetConnectType() != CONNECT_GAME ) - --history.m_connecting; - --history.m_connected; + { + EXC_TRYSUB("m_iPendingConnectionRequests") + + ASSERT(history.m_iPendingConnectionRequests > 0); + -- history.m_iPendingConnectionRequests; + + EXC_CATCHSUB("m_iPendingConnectionRequests"); + } + -- history.m_iAliveSuccessfulConnections; const bool fWasChar = ( m_pChar != nullptr ); @@ -104,7 +110,7 @@ CClient::~CClient() m_pGMPage->ClearHandler(); // Clear session-bound containers (CTAG and TOOLTIP) - m_TagDefs.Clear(); + //m_TagDefs.Clear(); CAccount * pAccount = GetAccount(); if ( pAccount ) diff --git a/src/game/clients/CClient.h b/src/game/clients/CClient.h index e4f9baf26..7d1d27274 100644 --- a/src/game/clients/CClient.h +++ b/src/game/clients/CClient.h @@ -384,7 +384,7 @@ class CClient : public CSObjListRec, public CScriptObj, public CChatChanMember, public: explicit CClient(CNetState* state); - ~CClient(); + ~CClient() noexcept; CClient(const CClient& copy) = delete; CClient& operator=(const CClient& other) = delete; diff --git a/src/game/clients/CClientLog.cpp b/src/game/clients/CClientLog.cpp index e4e18bc12..89597af89 100644 --- a/src/game/clients/CClientLog.cpp +++ b/src/game/clients/CClientLog.cpp @@ -61,7 +61,7 @@ void CClient::SetConnectType( CONNECT_TYPE iType ) { ADDTOCALLSTACK("CClient::SetConnectType"); - auto _IsFullyConnectedType = [](const CONNECT_TYPE typ) -> bool { + auto _IsFullyConnectedType = [](const CONNECT_TYPE typ) noexcept -> bool { switch (typ) { case CONNECT_GAME: @@ -78,7 +78,7 @@ void CClient::SetConnectType( CONNECT_TYPE iType ) if (_IsFullyConnectedType(iType) && !_IsFullyConnectedType(m_iConnectType)) { HistoryIP& history = g_NetworkManager.getIPHistoryManager().getHistoryForIP(GetPeer()); - -- history.m_connecting; + -- history.m_iPendingConnectionRequests; } m_iConnectType = iType; @@ -279,7 +279,7 @@ bool CClient::Login_Relay( uint iRelay ) // Relay player to a selected IP // >= 1.26.00 clients list Gives us a 1 based index for some reason. if ( iRelay > 0 ) - iRelay --; + -- iRelay; CServerRef pServ; if ( iRelay <= 0 ) diff --git a/src/network/CIPHistoryManager.cpp b/src/network/CIPHistoryManager.cpp index 4558c8510..4c037776a 100644 --- a/src/network/CIPHistoryManager.cpp +++ b/src/network/CIPHistoryManager.cpp @@ -5,8 +5,6 @@ #include "CIPHistoryManager.h" #include -#define NETHISTORY_PINGDECAY 60 // time to decay 1 'ping' - /*************************************************************************** * @@ -19,7 +17,7 @@ void HistoryIP::update(void) { // reset ttl - m_ttl = g_Cfg.m_iNetHistoryTTL; + m_iTTLSeconds = g_Cfg.m_iNetHistoryTTLSeconds; } bool HistoryIP::checkPing(void) @@ -27,7 +25,7 @@ bool HistoryIP::checkPing(void) // ip is pinging, check if blocked update(); - return (m_blocked || (m_pings++ >= g_Cfg.m_iNetMaxPings)); + return (m_fBlocked || (m_iPings++ >= g_Cfg.m_iNetMaxPings)); } void HistoryIP::setBlocked(bool isBlocked, int64 timeoutSeconds) @@ -42,12 +40,12 @@ void HistoryIP::setBlocked(bool isBlocked, int64 timeoutSeconds) timeoutSeconds = args.m_iN1; } - m_blocked = isBlocked; + m_fBlocked = isBlocked; if (isBlocked && timeoutSeconds >= 0) - m_blockExpire = CWorldGameTime::GetCurrentTime().GetTimeRaw() + (timeoutSeconds * MSECS_PER_SEC); + m_iBlockExpireMs = CWorldGameTime::GetCurrentTime().GetTimeRaw() + (timeoutSeconds * MSECS_PER_SEC); else - m_blockExpire = 0; + m_iBlockExpireMs = 0; } /*************************************************************************** @@ -79,33 +77,33 @@ void IPHistoryManager::tick(void) for (IPHistoryList::iterator it = m_ips.begin(), end = m_ips.end(); it != end; ++it) { - if (it->m_blocked) + if (it->m_fBlocked) { // blocked ips don't decay, but check if the ban has expired - if (it->m_blockExpire > 0 && (CWorldGameTime::GetCurrentTime().GetTimeRaw() > it->m_blockExpire)) + if (it->m_iBlockExpireMs > 0 && (CWorldGameTime::GetCurrentTime().GetTimeRaw() > it->m_iBlockExpireMs)) it->setBlocked(false); } else if (decayTTL) { - if (it->m_connected == 0 && it->m_connecting == 0) + if (it->m_iAliveSuccessfulConnections == 0 && it->m_iPendingConnectionRequests == 0) { // start to forget about clients who aren't connected - if (it->m_ttl >= 0) - --it->m_ttl; + if (it->m_iTTLSeconds >= 0) + --it->m_iTTLSeconds; } // wait a 5th of TTL between each ping decay, but do not wait less than 30 seconds - if (it->m_pings > 0 && --it->m_pingDecay < 0) + if (it->m_iPings > 0 && --it->m_iPingDecay < 0) { - --it->m_pings; - it->m_pingDecay = NETHISTORY_PINGDECAY; + --it->m_iPings; + it->m_iPingDecay = std::max(30, g_Cfg.m_iNetHistoryTTLSeconds / 5); } } } // clear old ip history std::erase_if(m_ips, [](HistoryIP const& elem) { - return elem.m_ttl < 0; + return elem.m_iTTLSeconds < 0; }); } @@ -123,15 +121,15 @@ HistoryIP& IPHistoryManager::getHistoryForIP(const CSocketAddressIP& ip) noexcep // create a new entry HistoryIP hist = { .m_ip = ip, - .m_pings = 0, - .m_connecting = 0, - .m_connected = 0, - .m_blocked = 0, - .m_ttl = 0, // updated by update() method - .m_connectionAttempts = 0, - .m_timeLastConnectedMs = 0, // set by the caller, if needed - .m_blockExpire = 0, - .m_pingDecay = NETHISTORY_PINGDECAY + .m_fBlocked = 0, + .m_iPingDecay = 30, + .m_iPings = 0, + .m_iConnectionRequests = 0, + .m_iPendingConnectionRequests = 0, + .m_iAliveSuccessfulConnections = 0, + .m_iTTLSeconds = 0, // updated by update() method + .m_iTimeLastConnectedMs = 0, // set by the caller, if needed + .m_iBlockExpireMs = 0, }; hist.update(); diff --git a/src/network/CIPHistoryManager.h b/src/network/CIPHistoryManager.h index 49010ca84..0658a2a78 100644 --- a/src/network/CIPHistoryManager.h +++ b/src/network/CIPHistoryManager.h @@ -20,15 +20,15 @@ struct HistoryIP { CSocketAddressIP m_ip; - int m_pings; - int m_connecting; - int m_connected; - bool m_blocked; - int m_ttl; - int64 m_connectionAttempts; // since i remember of this IP - int64 m_timeLastConnectedMs; - int64 m_blockExpire; - int m_pingDecay; + bool m_fBlocked; + int m_iPingDecay; + int m_iPings; // How many times i tried to connect from this ip. Decays over time. + int m_iConnectionRequests; // Like pings, but doesn't decay, it's forgotten when the IP is forgotten. + int m_iPendingConnectionRequests; + int m_iAliveSuccessfulConnections; + int m_iTTLSeconds; + int64 m_iTimeLastConnectedMs; + int64 m_iBlockExpireMs; void update(void); bool checkPing(void); // IP is blocked -or- too many pings to it? diff --git a/src/network/CNetworkManager.cpp b/src/network/CNetworkManager.cpp index 26421ee38..d38e00fa9 100644 --- a/src/network/CNetworkManager.cpp +++ b/src/network/CNetworkManager.cpp @@ -135,76 +135,86 @@ void CNetworkManager::acceptNewConnection(void) const int maxIp = g_Cfg.m_iConnectingMaxIP; const int climaxIp = g_Cfg.m_iClientsMaxIP; HistoryIP& ip = m_ips.getHistoryForIP(client_addr); - if (ip.m_ttl < g_Cfg.m_iNetHistoryTTL) + if (ip.m_iTTLSeconds < g_Cfg.m_iNetHistoryTTLSeconds) { // This is an IP of interest, i want to remember it for longer. - ip.m_ttl = g_Cfg.m_iNetHistoryTTL; + ip.m_iTTLSeconds = g_Cfg.m_iNetHistoryTTLSeconds; } - const int64 iIpPrevConnectionTime = ip.m_timeLastConnectedMs; - ip.m_timeLastConnectedMs = CSTime::GetMonotonicSysTimeMilli(); - ip.m_connectionAttempts += 1; + const int64 iIpPrevConnectionTime = ip.m_iTimeLastConnectedMs; + ip.m_iTimeLastConnectedMs = CSTime::GetMonotonicSysTimeMilli(); + ip.m_iConnectionRequests += 1; DEBUGNETWORK(("Incoming connection from '%s' [IP history: blocked=%d, ttl=%d, pings=%d, connecting=%d, connected=%d].\n", - ip.m_ip.GetAddrStr(), ip.m_blocked, ip.m_ttl, ip.m_pings, ip.m_connecting, ip.m_connected)); + ip.m_ip.GetAddrStr(), ip.m_fBlocked, ip.m_iTTLSeconds, ip.m_iPings, ip.m_iPendingConnectionRequests, ip.m_iAliveSuccessfulConnections)); - const auto _printIPBlocked = [&ip](void) -> void { + const auto _printIPBlocked = [&ip](void) noexcept -> void { g_Log.Event(LOGM_CLIENTS_LOG | LOGL_ERROR, "Blocked connection from '%s' [IP history: blocked=%d, ttl=%d, pings=%d, connecting=%d, connected=%d].\n", - ip.m_ip.GetAddrStr(), ip.m_blocked, ip.m_ttl, ip.m_pings, ip.m_connecting, ip.m_connected); + ip.m_ip.GetAddrStr(), ip.m_fBlocked, ip.m_iTTLSeconds, ip.m_iPings, ip.m_iPendingConnectionRequests, ip.m_iAliveSuccessfulConnections); }; // check if ip is allowed to connect - if (ip.checkPing() || // check for ip ban - (maxIp > 0 && ip.m_connecting > maxIp) || // check for too many connecting - (climaxIp > 0 && ip.m_connected > climaxIp)) // check for too many connected + if (ip.checkPing() || // check for ip ban and connection attempts (decaying) + (maxIp > 0 && ip.m_iPendingConnectionRequests > maxIp) || // check for too many connecting + (climaxIp > 0 && ip.m_iAliveSuccessfulConnections > climaxIp) ||// check for too many connected + (g_Cfg._iMaxConnectRequestsPerIP > 0) && (ip.m_iConnectionRequests >= g_Cfg._iMaxConnectRequestsPerIP)) // connection attempts (not decaying) { EXC_SET_BLOCK("rejected"); - DEBUGNETWORK(("Closing incoming connection [max ip=%d, clients max ip=%d].\n", maxIp, climaxIp)); + //DEBUGNETWORK(("Closing incoming connection [max ip=%d, clients max ip=%d].\n", maxIp, climaxIp)); CLOSESOCKET(h); _printIPBlocked(); - if (ip.m_blocked) + if (ip.m_fBlocked) g_Log.Event(LOGM_CLIENTS_LOG | LOGL_ERROR, "Reject reason: Blocked IP.\n"); - else if (maxIp && ip.m_connecting > maxIp) - g_Log.Event(LOGM_CLIENTS_LOG | LOGL_ERROR, "Reject reason: CONNECTINGMAXIP reached %d/%d.\n", ip.m_connecting, maxIp); - else if (climaxIp && ip.m_connected > climaxIp) - g_Log.Event(LOGM_CLIENTS_LOG | LOGL_ERROR, "Reject reason: CLIENTMAXIP reached %d/%d.\n", ip.m_connected, climaxIp); - else if (ip.m_pings >= g_Cfg.m_iNetMaxPings) - g_Log.Event(LOGM_CLIENTS_LOG | LOGL_ERROR, "Reject reason: MAXPINGS reached %d/%d.\n", ip.m_pings, g_Cfg.m_iNetMaxPings); + else if (maxIp && ip.m_iPendingConnectionRequests > maxIp) + g_Log.Event(LOGM_CLIENTS_LOG | LOGL_ERROR, "Reject reason: CONNECTINGMAXIP reached %d/%d.\n", ip.m_iPendingConnectionRequests, maxIp); + else if (climaxIp && ip.m_iAliveSuccessfulConnections > climaxIp) + g_Log.Event(LOGM_CLIENTS_LOG | LOGL_ERROR, "Reject reason: CLIENTMAXIP reached %d/%d.\n", ip.m_iAliveSuccessfulConnections, climaxIp); + else if (ip.m_iPings >= g_Cfg.m_iNetMaxPings) + g_Log.Event(LOGM_CLIENTS_LOG | LOGL_ERROR, "Reject reason: MAXPINGS reached %d/%d.\n", ip.m_iPings, g_Cfg.m_iNetMaxPings); + else if (ip.m_iConnectionRequests >= g_Cfg._iMaxConnectRequestsPerIP) + g_Log.Event(LOGM_CLIENTS_LOG | LOGL_ERROR, "Reject reason: MaxConnectRequestsPerIP reached %d/%d.\n", ip.m_iConnectionRequests, g_Cfg._iMaxConnectRequestsPerIP); else g_Log.Event(LOGM_CLIENTS_LOG | LOGL_ERROR, "Reject reason: unclassified.\n"); - return; - } - if ((g_Cfg._iMaxConnectRequestsPerIP > 0) && (ip.m_connectionAttempts >= (int64)g_Cfg._iMaxConnectRequestsPerIP)) - { // Call this special scripted function. CScriptTriggerArgs fargs_ex(client_addr.GetAddrStr()); - fargs_ex.m_iN1 = iIpPrevConnectionTime; - fargs_ex.m_iN2 = ip.m_timeLastConnectedMs; // Current connection time. - fargs_ex.m_iN3 = ip.m_connectionAttempts; + fargs_ex.m_VarsLocal.SetNumNew("TIME_CUR_CONNECTED_MS", ip.m_iTimeLastConnectedMs); + fargs_ex.m_VarsLocal.SetNumNew("TIME_LAST_CONNECTED_MS", iIpPrevConnectionTime); + fargs_ex.m_VarsLocal.SetNumNew("PINGS", ip.m_iPings); + fargs_ex.m_VarsLocal.SetNumNew("CONNECTION_REQUESTS", ip.m_iConnectionRequests); + fargs_ex.m_VarsLocal.SetNumNew("ALIVE_CONNECTIONS", ip.m_iAliveSuccessfulConnections); + fargs_ex.m_VarsLocal.SetNumNew("PENDING_CONNECTING", ip.m_iPendingConnectionRequests); fargs_ex.m_VarsLocal.SetNumNew("BAN_TIMEOUT", 5ll * 60); TRIGRET_TYPE fret = TRIGRET_RET_FALSE; g_Serv.r_Call("f_onserver_connectreq_ex", &g_Serv, &fargs_ex, nullptr, &fret); - if (fret == TRIGRET_RET_TRUE) + if (fret == -1) { - // reject - CLOSESOCKET(h); - - _printIPBlocked(); - g_Log.Event(LOGM_CLIENTS_LOG | LOGL_ERROR, "Reject reason: requested kick via script 'f_onserver_connectreq_ex'.\n"); + // RETURN -1: do not block. + g_Log.Event(LOGM_CLIENTS_LOG | LOGL_ERROR, "Outcome: ignore warnings from 'f_onserver_connectreq_ex'.\n"); } - else if (fret == TRIGRET_RET_DEFAULT) // 2 + else { - // block IP - CLOSESOCKET(h); - ip.setBlocked(true, fargs_ex.m_VarsLocal.GetKeyNum("BAN_TIMEOUT")); + if (fret == TRIGRET_RET_TRUE) + { + // RETURN 1: reject + CLOSESOCKET(h); - _printIPBlocked(); - g_Log.Event(LOGM_CLIENTS_LOG | LOGL_ERROR, "Reject reason: requested kick + IP block allowed by script 'f_onserver_connectreq_ex'.\n"); + g_Log.Event(LOGM_CLIENTS_LOG | LOGL_ERROR, "Outcome: requested kick via script 'f_onserver_connectreq_ex'.\n"); + } + else + { + // RETURN 2 (TRIGRET_RET_DEFAULT) or other: block IP + CLOSESOCKET(h); + ip.setBlocked(true, fargs_ex.m_VarsLocal.GetKeyNum("BAN_TIMEOUT")); + + g_Log.Event(LOGM_CLIENTS_LOG | LOGL_ERROR, "Outcome (default): requested kick + IP block allowed by script 'f_onserver_connectreq_ex'.\n"); + } } + + return; } /* @@ -261,7 +271,7 @@ void CNetworkManager::acceptNewConnection(void) // Call this special scripted function. CScriptTriggerArgs fargs_acquired(client_addr.GetAddrStr()); fargs_acquired.m_iN1 = iIpPrevConnectionTime; - fargs_acquired.m_iN2 = ip.m_timeLastConnectedMs; // Current connection time. + fargs_acquired.m_iN2 = ip.m_iTimeLastConnectedMs; // Current connection time. TRIGRET_TYPE fret = TRIGRET_RET_FALSE; g_Serv.r_Call("f_onserver_connection_acquired", &g_Serv, &fargs_acquired, nullptr, &fret); diff --git a/src/sphere.ini b/src/sphere.ini index e0307c96e..c0cea2587 100644 --- a/src/sphere.ini +++ b/src/sphere.ini @@ -1086,7 +1086,7 @@ DeadSocketTime=5 // Maximum number of packets to send per tick (outgoing) MaxPacketsPerTick=1000 -// Number of connections a client can make before being blocked +// Number of connections a client can make before being blocked (the connection attempt number/ping count decays over time: 1/5 of TTL or 30 seconds if less) MaxPings=15 // Maximum number of packets before lowering packet priorities (0 for no limit) @@ -1103,8 +1103,8 @@ MaxSizeClientOut=80000 // 0 = disabled. Default behavior: disconnect. MaxSizeClientIn=10000 -// Maximum number of connection requests before rejecting/blocking IP (reset after seconds elapsed after last connection attempt). -MaxConnectRequestsPerIP=40 +// Maximum number of connection requests before rejecting/blocking IP (similar to MaxPings but does not decay, it resets only after seconds elapsed since last connection attempt). +MaxConnectRequestsPerIP=50 // Maximum time in milliseconds to wait before closing a connection request wich did not make it into a successful login (classic DDoS just asks to connect without doing anything else, or sends garbage data). TimeoutIncompleteConn=5 * 1000 // 5 seconds From 3719de45da5e117140d4adc611de6d107f1486ff Mon Sep 17 00:00:00 2001 From: cbnolok Date: Tue, 10 Sep 2024 12:11:42 +0200 Subject: [PATCH 31/86] Fixed slayer damage bonus. --- src/game/chars/CCharFight.cpp | 6 +++--- .../components/subcomponents/CFactionDef.cpp | 20 +++++++++++++------ .../components/subcomponents/CFactionDef.h | 9 --------- 3 files changed, 17 insertions(+), 18 deletions(-) diff --git a/src/game/chars/CCharFight.cpp b/src/game/chars/CCharFight.cpp index 9a877570e..4fbda8182 100644 --- a/src/game/chars/CCharFight.cpp +++ b/src/game/chars/CCharFight.cpp @@ -823,7 +823,7 @@ int CChar::OnTakeDamage( int iDmg, CChar * pSrc, DAMAGE_TYPE uiType, int iDmgPhy const CFactionDef *pMyFaction = GetFaction(); if (pMyFaction && !pMyFaction->IsNone()) { - int iDmgBonusPercent = 100; + int iDmgBonusPercent = 0; if (pSrcWeapon) { const CFactionDef *pSrcSlayer = pSrcWeapon->GetSlayer(); @@ -839,7 +839,7 @@ int CChar::OnTakeDamage( int iDmg, CChar * pSrc, DAMAGE_TYPE uiType, int iDmgPhy } } } - if (iDmgBonusPercent == 100) // Couldn't find a weapon, a Slayer flag or a suitable flag for the target... + if (iDmgBonusPercent == 0) // Couldn't find a weapon, a Slayer flag or a suitable flag for the target... { const CItem *pSrcTalisman = pSrc->LayerFind(LAYER_TALISMAN); // then lets try with a Talisman if (pSrcTalisman) @@ -858,7 +858,7 @@ int CChar::OnTakeDamage( int iDmg, CChar * pSrc, DAMAGE_TYPE uiType, int iDmgPhy } } } - if (iDmgBonusPercent != 100) + if (iDmgBonusPercent != 0) { iDmg += (iDmg * iDmgBonusPercent) / 100; } diff --git a/src/game/components/subcomponents/CFactionDef.cpp b/src/game/components/subcomponents/CFactionDef.cpp index 9e2d52220..f07345ce2 100644 --- a/src/game/components/subcomponents/CFactionDef.cpp +++ b/src/game/components/subcomponents/CFactionDef.cpp @@ -125,22 +125,30 @@ bool CFactionDef::HasLesserSlayer() const noexcept return ((GetGroup() != Group::NONE) && (GetSpecies() != Species::NONE) && !HasSuperSlayer()); } +/* +TODO: enable customization of slayer bonus damage? +Until the Stygian Abyss expansion, all Slayers did double damage to applicable monsters. However, following that expansion, Lesser Slayers do triple damage, and Super Slayers still do double damage. +*/ +#define DAMAGE_SLAYER_LESSER 200 // Lesser Slayer does x3 (100 + 200%) damage. +#define DAMAGE_SLAYER_SUPER 100 // Super Slayer does x2 (100 + 100%) damage. +#define DAMAGE_SLAYER_OPPOSITE 100 // Opposite Slayer does x2 (100 + 100%) damage. + int CFactionDef::GetSlayerDamageBonusPercent(const CFactionDef *target) const noexcept { - ADDTOCALLSTACK_DEBUG("CFactionDef::GetSlayerDamageBonus"); + ADDTOCALLSTACK_DEBUG("CFactionDef::GetSlayerDamageBonusPercent"); if (IsLesserSlayerVersus(target)) return DAMAGE_SLAYER_LESSER; - else if (IsSuperSlayerVersus(target)) + if (IsSuperSlayerVersus(target)) return DAMAGE_SLAYER_SUPER; - return 100; + return 0; } int CFactionDef::GetSlayerDamagePenaltyPercent(const CFactionDef * target) const noexcept { - ADDTOCALLSTACK_DEBUG("CFactionDef::GetSlayerDamagePenalty"); + ADDTOCALLSTACK_DEBUG("CFactionDef::GetSlayerDamagePenaltyPercent"); if (HasSuperSlayer() && IsOppositeGroup(target)) - return DAMAGE_SLAYER_OPPOSITE; - return 100; + return - DAMAGE_SLAYER_OPPOSITE; + return 0; } diff --git a/src/game/components/subcomponents/CFactionDef.h b/src/game/components/subcomponents/CFactionDef.h index adbb53ed2..0c7cf6509 100644 --- a/src/game/components/subcomponents/CFactionDef.h +++ b/src/game/components/subcomponents/CFactionDef.h @@ -37,15 +37,6 @@ class CItemBase; */ -/* -TODO: enable customization of slayer bonus damage? -Until the Stygian Abyss expansion, all Slayers did double damage to applicable monsters. However, following that expansion, Lesser Slayers do triple damage, and Super Slayers still do double damage. -*/ -#define DAMAGE_SLAYER_LESSER 300 // Lesser Slayer does x3 (300%) damage. -#define DAMAGE_SLAYER_SUPER 200 // Super Slayer does x2 (200%) damage. -#define DAMAGE_SLAYER_OPPOSITE 200 // Opposite Slayer does x2 (200%) damage. - - /* This class is used to store FACTION for NPCs and SLAYER for items Initially involved in the Slayer system it handles Super Slayer, From 0998d8fd9b594e3882d8cc094fb28384514a5075 Mon Sep 17 00:00:00 2001 From: cbnolok Date: Tue, 10 Sep 2024 12:11:56 +0200 Subject: [PATCH 32/86] Updated .clang-format and .editorconfig --- .clang-format | 2 +- .editorconfig | 14 ++++++++++---- 2 files changed, 11 insertions(+), 5 deletions(-) diff --git a/.clang-format b/.clang-format index 700faebeb..b993d79f0 100644 --- a/.clang-format +++ b/.clang-format @@ -12,7 +12,7 @@ ColumnLimit: 160 ##-- Alignment AlignAfterOpenBracket: AlwaysBreak AlignConsecutiveAssignments: true -AlignConsecutiveDeclarations: true +AlignConsecutiveDeclarations: false #AlignEscapedNewlinesLeft: false AlignTrailingComments: true diff --git a/.editorconfig b/.editorconfig index dc3145a32..1a210abc6 100644 --- a/.editorconfig +++ b/.editorconfig @@ -6,10 +6,16 @@ root = true charset = utf-8 trim_trailing_whitespace = true insert_final_newline = true - # Optional: git will commit as lf, this will only affect local files end_of_line = lf +[*.txt] +charset = utf-8 +trim_trailing_whitespace = true +insert_final_newline = true +indent_style = space +indent_size = 4 + [*.md] trim_trailing_whitespace = false @@ -18,15 +24,15 @@ indent_style = tab [*.{py,yml,sh,cmake}] indent_style = space -indent_size = 2 +indent_size = 4 [*.{py,yml,sh,cmake}.in] indent_style = space -indent_size = 2 +indent_size = 4 [CMakeLists.txt] indent_style = space -indent_size = 2 +indent_size = 4 [*.{c,h,cpp,cxx,hpp}] charset = utf-8 From 0768175c1619761ed39c33a27794c5c045beaec9 Mon Sep 17 00:00:00 2001 From: DavideRei <118212274+DavideRei@users.noreply.github.com> Date: Tue, 10 Sep 2024 15:23:10 +0300 Subject: [PATCH 33/86] Fix PartyAdd context menu (#1283) When you click on a player to open the context menu and the party already exists, the Party Add entry is not showed. This fix the problem --- src/game/clients/CClientEvent.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/game/clients/CClientEvent.cpp b/src/game/clients/CClientEvent.cpp index 1397e3da0..6f58a04b2 100644 --- a/src/game/clients/CClientEvent.cpp +++ b/src/game/clients/CClientEvent.cpp @@ -2693,7 +2693,7 @@ void CClient::Event_AOSPopupMenuRequest( dword uid ) //construct packet after a m_pPopupPacket->addOption(POPUP_PARTY_ADD, 197, POPUPFLAG_COLOR, 0xFFFF); else if (m_pChar->m_pParty != nullptr && m_pChar->m_pParty->IsPartyMaster(m_pChar)) { - if (m_pChar->m_pParty == nullptr) + if (pChar->m_pParty == nullptr) m_pPopupPacket->addOption(POPUP_PARTY_ADD, 197, POPUPFLAG_COLOR, 0xFFFF); else if (pChar->m_pParty == m_pChar->m_pParty) m_pPopupPacket->addOption(POPUP_PARTY_REMOVE, 198, POPUPFLAG_COLOR, 0xFFFF); From 01be47ec0746776389047b595aa1141dcc7034ef Mon Sep 17 00:00:00 2001 From: cbnolok Date: Thu, 12 Sep 2024 17:54:31 +0200 Subject: [PATCH 34/86] Added stricter warning flags for GCC and Clang. Fixed some function calls getting as argument a null pointer instead of a string, and similar issues found with a new warning flag. Also minimal refactoring to CSQLite, encapsulated zlib includes in a zlib namespace. --- .../include/Linux-Clang_common.inc.cmake | 43 +++++++-- .../include/Linux-GNU_common.inc.cmake | 35 ++++++- src/CompilerFlags.cmake | 71 -------------- src/common/CException.cpp | 2 +- src/common/CLog.cpp | 6 ++ src/common/CLog.h | 12 +-- src/common/CScript.h | 15 ++- src/common/CVarDefMap.cpp | 2 + src/common/CVarDefMap.h | 2 +- src/common/ListDefContMap.cpp | 15 ++- src/common/ListDefContMap.h | 10 +- src/common/resource/CResourceDef.cpp | 11 +++ src/common/resource/CResourceDef.h | 22 +---- src/common/resource/CResourceLink.cpp | 2 + src/common/resource/CResourceLink.h | 7 +- src/common/resource/sections/CWebPageDef.cpp | 10 +- src/common/sphere_library/CSAssoc.cpp | 18 ++++ src/common/sphere_library/CSAssoc.h | 15 ++- src/common/sphere_library/CSFileList.cpp | 4 + src/common/sphere_library/CSFileList.h | 11 ++- src/common/sphere_library/CSMemBlock.cpp | 6 +- src/common/sphere_library/CSMemBlock.h | 21 ++-- src/common/sphere_library/CSObjList.cpp | 12 +++ src/common/sphere_library/CSObjListRec.h | 11 +-- src/common/sphere_library/sptr.h | 9 ++ src/common/sphere_library/sstring.cpp | 18 ++-- src/common/sphere_library/sstringobjs.cpp | 4 +- src/common/sphere_library/sstringobjs.h | 4 +- src/common/sqlite/SQLite.cpp | 95 +++++++++++-------- src/common/sqlite/SQLite.h | 39 ++++---- src/game/CComponent.cpp | 2 + src/game/CComponent.h | 2 +- src/game/CComponentProps.cpp | 2 + src/game/CComponentProps.h | 3 +- src/game/CObjBase.cpp | 2 +- src/game/CSectorTemplate.cpp | 10 +- src/game/CSectorTemplate.h | 4 +- src/game/CServerConfig.cpp | 16 ++++ src/game/CServerConfig.h | 4 +- src/game/CWorldImport.cpp | 19 ++-- src/game/CWorldTicker.h | 13 +++ src/game/chars/CChar.cpp | 6 +- src/game/chars/CCharAttacker.cpp | 4 +- src/game/chars/CCharNPC.cpp | 4 +- src/game/chars/CCharSkill.cpp | 6 +- src/game/clients/CClient.cpp | 5 +- src/game/clients/CClientDialog.cpp | 2 +- src/game/clients/CClientLog.cpp | 7 +- src/game/clients/CGlobalChatChanMember.cpp | 1 + src/game/clients/CGlobalChatChanMember.h | 2 +- src/game/clients/CParty.cpp | 2 +- src/game/components/CCMultiMovable.cpp | 2 + src/game/components/CCMultiMovable.h | 4 +- src/network/packet.cpp | 11 +++ src/network/packet.h | 18 ++-- src/network/receive.cpp | 2 +- src/network/send.cpp | 24 +++-- src/network/send.h | 15 +++ src/sphere/UnixTerminal.cpp | 2 +- src/sphere/threads.cpp | 15 ++- src/sphere/threads.h | 7 +- 61 files changed, 448 insertions(+), 300 deletions(-) delete mode 100644 src/CompilerFlags.cmake diff --git a/cmake/toolchains/include/Linux-Clang_common.inc.cmake b/cmake/toolchains/include/Linux-Clang_common.inc.cmake index b01126c8c..cc70368a5 100644 --- a/cmake/toolchains/include/Linux-Clang_common.inc.cmake +++ b/cmake/toolchains/include/Linux-Clang_common.inc.cmake @@ -25,9 +25,11 @@ function(toolchain_exe_stuff_common) if(${USE_ASAN}) set(CXX_FLAGS_EXTRA - ${CXX_FLAGS_EXTRA} # -fsanitize=safe-stack # Can't be used with asan! + ${CXX_FLAGS_EXTRA} + # -fsanitize=safe-stack # Can't be used with asan! -fsanitize=address - -fno-sanitize-recover=address #-fsanitize-cfi # cfi: control flow integrity + -fno-sanitize-recover=address + #-fsanitize-cfi # cfi: control flow integrity -fsanitize-address-use-after-scope -fsanitize=pointer-compare -fsanitize=pointer-subtract @@ -90,16 +92,41 @@ See comments in the toolchain and: https://github.com/google/sanitizers/wiki/Mem -Werror -Wall -Wextra - -Wno-unknown-pragmas + -Wpedantic + + -Wmissing-include-dirs # Warns when an include directory provided with -I does not exist. + -Wformat=2 + #-Wcast-qual # Warns about casts that remove a type's const or volatile qualifier. + #-Wconversion # Temporarily disabled. Warns about implicit type conversions that might change a value, such as narrowing conversions. + -Wdisabled-optimization + #-Winvalid-pch + -Wzero-as-null-pointer-constant + -Wnull-dereference + + # Clang-only + -Wweak-vtables + #-Wmissing-prototypes + #-Wmissing-variable-declarations + + # Unsupported by Clang, but supported by GCC: + #-fno-expensive-optimizations + #-Wtrampolines # Warns when trampolines (a technique to implement nested functions) are generated (don't want this for security reasons). + #-Wvector-operation-performance + #-Wsized-deallocation + #-Wduplicated-cond + #-Wshift-overflow=2 + #-Wno-maybe-uninitialized + #-Wno-nonnull-compare + + # Disable errors: + -Wno-format-nonliteral # Since -Wformat=2 is stricter, you would need to disable this warning. -Wno-switch -Wno-implicit-fallthrough -Wno-parentheses -Wno-misleading-indentation - -Wno-conversion-null -Wno-unused-result -Wno-format-security # TODO: disable that when we'll have time to fix every printf format issue - # clang -specific: - # -fforce-emit-vtables + -Wno-nested-anon-types ) set(cxx_local_opts -std=c++20 @@ -108,13 +135,13 @@ See comments in the toolchain and: https://github.com/google/sanitizers/wiki/Mem -fnon-call-exceptions -pipe -ffast-math + # clang -specific: + # -fforce-emit-vtables ) set(cxx_compiler_options_common ${cxx_local_opts_warnings} ${cxx_local_opts} ${CXX_FLAGS_EXTRA}) #separate_arguments(cxx_compiler_options_common) # GCC flags not supported by clang: - # Warnings: "-Wno-nonnull-compare -Wno-maybe-uninitialized" - # Other: "-fno-expensive-optimizations" # MemorySanitizer: it doesn't work out of the box. It needs to be linked to an MSAN-instrumented build of libc++ and libc++abi. # This means: one should build them from LLVM source... diff --git a/cmake/toolchains/include/Linux-GNU_common.inc.cmake b/cmake/toolchains/include/Linux-GNU_common.inc.cmake index 240602418..aba4acf56 100644 --- a/cmake/toolchains/include/Linux-GNU_common.inc.cmake +++ b/cmake/toolchains/include/Linux-GNU_common.inc.cmake @@ -23,7 +23,8 @@ function(toolchain_exe_stuff_common) set(CXX_FLAGS_EXTRA ${CXX_FLAGS_EXTRA} -fsanitize=address - -fno-sanitize-recover=address #-fsanitize-cfi # cfi: control flow integrity, not supported by GCC + -fno-sanitize-recover=address + #-fsanitize-cfi # cfi: control flow integrity, not supported by GCC -fsanitize-address-use-after-scope -fsanitize=pointer-compare -fsanitize=pointer-subtract @@ -33,7 +34,8 @@ function(toolchain_exe_stuff_common) -fstack-protector-all -fcf-protection=full # GCC 14? - #-fharden-control-flow-redundancy -fhardcfr-check-exceptions + #-fharden-control-flow-redundancy + #-fhardcfr-check-exceptions # Other #-fsanitize-trap=all ) @@ -91,15 +93,38 @@ function(toolchain_exe_stuff_common) -Werror -Wall -Wextra - -Wno-nonnull-compare - -Wno-unknown-pragmas + -Wpedantic + + -Wmissing-include-dirs # Warns when an include directory provided with -I does not exist. + -Wformat=2 + #-Wcast-qual # Warns about casts that remove a type's const or volatile qualifier. + #-Wconversion # Temporarily disabled. Warns about implicit type conversions that might change a value, such as narrowing conversions. + -Wdisabled-optimization + #-Winvalid-pch + -Wzero-as-null-pointer-constant + -Wnull-dereference + -Wduplicated-cond + + # Supported by Clang, but unsupported by GCC: + #-Wweak-vtables + + # Unsupported by Clang, but supported by GCC: + -Wtrampolines # Warns when trampolines (a technique to implement nested functions) are generated (don't want this for security reasons). + -Wvector-operation-performance + -Wsized-deallocation + -Wduplicated-cond + -Wshift-overflow=2 + + # Disable errors: + -Wno-format-nonliteral # Since -Wformat=2 is stricter, you would need to disable this warning. + -Wno-nonnull-compare # GCC only -Wno-switch -Wno-implicit-fallthrough -Wno-parentheses -Wno-misleading-indentation - -Wno-conversion-null -Wno-unused-result -Wno-format-security # TODO: disable that when we'll have time to fix every printf format issue + -Wno-nested-anon-types ) set(cxx_local_opts -std=c++20 diff --git a/src/CompilerFlags.cmake b/src/CompilerFlags.cmake deleted file mode 100644 index f48f2bf42..000000000 --- a/src/CompilerFlags.cmake +++ /dev/null @@ -1,71 +0,0 @@ -# TODO: CITE ANTLR - -if(CMAKE_CXX_COMPILER_ID MATCHES "GNU") - # Pedantic error flags - set(PEDANTIC_COMPILE_FLAGS - -pedantic-errors - -Wall - -Wextra - -pedantic - -Wundef - -Wmissing-include-dirs - -Wredundant-decls - -Wwrite-strings - -Wpointer-arith - -Wformat=2 - -Wno-format-nonliteral - -Wcast-qual - -Wcast-align - -Wconversion - -Wctor-dtor-privacy - -Wdisabled-optimization - -Winvalid-pch - -Woverloaded-virtual - -Wno-ctor-dtor-privacy - ) - #if (NOT CMAKE_CXX_COMPILER_VERSION VERSION_LESS 4.6) - set(PEDANTIC_COMPILE_FLAGS ${PEDANTIC_COMPILE_FLAGS} -Wno-dangling-else -Wno-unused-local-typedefs) - #endif () - #if (NOT CMAKE_CXX_COMPILER_VERSION VERSION_LESS 5.0) - set(PEDANTIC_COMPILE_FLAGS - ${PEDANTIC_COMPILE_FLAGS} - -Wdouble-promotion - -Wtrampolines - -Wzero-as-null-pointer-constant - -Wuseless-cast - -Wvector-operation-performance - -Wsized-deallocation - -Wshadow - ) - #endif () - #if (NOT CMAKE_CXX_COMPILER_VERSION VERSION_LESS 6.0) - set(PEDANTIC_COMPILE_FLAGS ${PEDANTIC_COMPILE_FLAGS} -Wshift-overflow=2 -Wnull-dereference -Wduplicated-cond) - #endif () - set(WERROR_FLAG -Werror) -endif() - -if(CMAKE_CXX_COMPILER_ID MATCHES "Clang") - # Pedantic error flags - set(PEDANTIC_COMPILE_FLAGS - -Wall - -Wextra - -pedantic - -Wconversion - -Wundef - -Wdeprecated - -Wweak-vtables - -Wshadow - -Wno-gnu-zero-variadic-macro-arguments - ) - check_cxx_compiler_flag(-Wzero-as-null-pointer-constant HAS_NULLPTR_WARNING) - if(HAS_NULLPTR_WARNING) - set(PEDANTIC_COMPILE_FLAGS ${PEDANTIC_COMPILE_FLAGS} -Wzero-as-null-pointer-constant) - endif() - set(WERROR_FLAG -Werror) -endif() - -if(MSVC) - # Pedantic error flags - set(PEDANTIC_COMPILE_FLAGS /W3) - set(WERROR_FLAG /WX) -endif() diff --git a/src/common/CException.cpp b/src/common/CException.cpp index e3ad57cd4..94914f706 100644 --- a/src/common/CException.cpp +++ b/src/common/CException.cpp @@ -397,7 +397,7 @@ void _cdecl Signal_Illegal_Instruction(int sig = 0) void _cdecl Signal_Children(int sig = 0) { UnreferencedParameter(sig); - while (waitpid((pid_t)(-1), 0, WNOHANG) > 0) {} + while (waitpid((pid_t)(-1), nullptr, WNOHANG) > 0) {} } #endif diff --git a/src/common/CLog.cpp b/src/common/CLog.cpp index 922fd1323..4236293eb 100644 --- a/src/common/CLog.cpp +++ b/src/common/CLog.cpp @@ -6,6 +6,10 @@ #include "CLog.h" +CEventLog::CEventLog() = default; +CEventLog::~CEventLog() = default; + + int CEventLog::VEvent(dword dwMask, lpctstr pszFormat, ConsoleTextColor iColor, va_list args) noexcept { if (pszFormat == nullptr || pszFormat[0] == '\0') @@ -92,6 +96,8 @@ CLog::CLog() SetFilePath( SPHERE_FILE "log.log" ); // default name to go to. } +CLog::~CLog() = default; + const CScript * CLog::_SetScriptContext( const CScript * pScriptContext ) { const CScript * pOldScript = m_pScriptContext; diff --git a/src/common/CLog.h b/src/common/CLog.h index 810d1dffa..219a472d8 100644 --- a/src/common/CLog.h +++ b/src/common/CLog.h @@ -73,12 +73,11 @@ class CEventLog int _cdecl EventEvent( lpctstr pszFormat, ... ) noexcept __printfargs(2,3); #endif //_DEBUG -public: - CEventLog() = default; + CEventLog(); + virtual ~CEventLog(); -private: - CEventLog(const CEventLog& copy); - CEventLog& operator=(const CEventLog& other); + CEventLog(const CEventLog& copy) = delete; + CEventLog& operator=(const CEventLog& other) = delete; }; @@ -108,7 +107,7 @@ public: const CScriptObj * SetObjectContext( const CScriptObj * pObjectConte protected: bool _OpenLog(lpctstr pszName = nullptr); // name set previously. public: bool OpenLog(lpctstr pszName = nullptr); - bool SetFilePath(lpctstr pszName); + virtual bool SetFilePath(lpctstr pszName) override; lpctstr GetLogDir() const; dword GetLogMask() const; @@ -125,6 +124,7 @@ public: bool OpenLog(lpctstr pszName = nullptr); public: CLog(); + virtual ~CLog() override; CLog(const CLog& copy) = delete; CLog& operator=(const CLog& other) = delete; diff --git a/src/common/CScript.h b/src/common/CScript.h index e703edef1..3caa1e8e4 100644 --- a/src/common/CScript.h +++ b/src/common/CScript.h @@ -65,10 +65,10 @@ class CScriptKey public: CScriptKey(); CScriptKey( tchar * ptcKey, tchar * ptcArg ); - virtual ~CScriptKey() = default; -private: - CScriptKey(const CScriptKey& copy); - CScriptKey& operator=(const CScriptKey& other); + ~CScriptKey() = default; + + CScriptKey(const CScriptKey& copy) = delete; + CScriptKey& operator=(const CScriptKey& other) = delete; }; class CScriptKeyAlloc : public CScriptKey @@ -91,11 +91,10 @@ class CScriptKeyAlloc : public CScriptKey public: CScriptKeyAlloc() = default; - virtual ~CScriptKeyAlloc() = default; + ~CScriptKeyAlloc() = default; -private: - CScriptKeyAlloc(const CScriptKeyAlloc& copy); - CScriptKeyAlloc& operator=(const CScriptKeyAlloc& other); + CScriptKeyAlloc(const CScriptKeyAlloc& copy) = delete; + CScriptKeyAlloc& operator=(const CScriptKeyAlloc& other) = delete; }; diff --git a/src/common/CVarDefMap.cpp b/src/common/CVarDefMap.cpp index 48a4f98b8..3e99fae28 100644 --- a/src/common/CVarDefMap.cpp +++ b/src/common/CVarDefMap.cpp @@ -9,6 +9,8 @@ #include "CVarDefMap.h" +CVarDefCont::~CVarDefCont() = default; + inline static int VarDefCompare(const CVarDefCont* pVar, lpctstr ptcKey) noexcept { return strcmpi(pVar->GetKey(), ptcKey); diff --git a/src/common/CVarDefMap.h b/src/common/CVarDefMap.h index 745934500..0bfa84aad 100644 --- a/src/common/CVarDefMap.h +++ b/src/common/CVarDefMap.h @@ -19,7 +19,7 @@ class CVarDefCont static const char *m_sClassName; CVarDefCont() = default; - virtual ~CVarDefCont() = default; + virtual ~CVarDefCont(); CVarDefCont(const CVarDefCont& copy) = delete; CVarDefCont& operator=(const CVarDefCont& other) = delete; diff --git a/src/common/ListDefContMap.cpp b/src/common/ListDefContMap.cpp index 38b2642ae..8d0d7c68b 100644 --- a/src/common/ListDefContMap.cpp +++ b/src/common/ListDefContMap.cpp @@ -13,7 +13,20 @@ /*************************************************************************** * * -* class CVarDefContNum List element implementation (Number) +* class CListDefContElem List element implementation (base class) +* +* +***************************************************************************/ + +CListDefContElem::CListDefContElem(lpctstr ptcKey) + : m_Key(ptcKey) + {} +CListDefContElem::~CListDefContElem() = default; + +/*************************************************************************** +* +* +* class CListDefContNum List element implementation (Number) * * ***************************************************************************/ diff --git a/src/common/ListDefContMap.h b/src/common/ListDefContMap.h index 17b252d1e..7f5f8995f 100644 --- a/src/common/ListDefContMap.h +++ b/src/common/ListDefContMap.h @@ -17,18 +17,16 @@ class CScript; class CListDefContElem { -private: CSString m_Key; // reference to map key public: static const char *m_sClassName; - explicit CListDefContElem(lpctstr ptcKey) : m_Key(ptcKey) {}; - virtual ~CListDefContElem() = default; + explicit CListDefContElem(lpctstr ptcKey); + virtual ~CListDefContElem(); -private: - CListDefContElem(const CListDefContElem& copy); - CListDefContElem& operator=(const CListDefContElem& other); + CListDefContElem(const CListDefContElem& copy) = delete; + CListDefContElem& operator=(const CListDefContElem& other) = delete; public: inline lpctstr GetKey() const { diff --git a/src/common/resource/CResourceDef.cpp b/src/common/resource/CResourceDef.cpp index 29f066b51..bd127118a 100644 --- a/src/common/resource/CResourceDef.cpp +++ b/src/common/resource/CResourceDef.cpp @@ -10,6 +10,17 @@ #include "CResourceDef.h" +CResourceDef::CResourceDef(const CResourceID& rid, lpctstr pszDefName) : + m_rid(rid), m_pDefName(nullptr) +{ + SetResourceName(pszDefName); +} +CResourceDef::CResourceDef(const CResourceID& rid, const CVarDefContNum * pDefName) : + m_rid(rid), m_pDefName(pDefName) +{ +} +CResourceDef::~CResourceDef() = default; + bool CResourceDef::SetResourceName( lpctstr pszName ) { ADDTOCALLSTACK("CResourceDef::SetResourceName"); diff --git a/src/common/resource/CResourceDef.h b/src/common/resource/CResourceDef.h index 808b07de8..81a6c0227 100644 --- a/src/common/resource/CResourceDef.h +++ b/src/common/resource/CResourceDef.h @@ -26,24 +26,12 @@ class CResourceDef : public CScriptObj public: static const char *m_sClassName; - CResourceDef(const CResourceID& rid, lpctstr pszDefName) : - m_rid(rid), m_pDefName(nullptr) - { - SetResourceName(pszDefName); - } - CResourceDef(const CResourceID& rid, const CVarDefContNum * pDefName = nullptr) : - m_rid(rid), m_pDefName(pDefName) - { - } - virtual ~CResourceDef() - { - // need a virtual for the dynamic_cast to work. - // ?? Attempt to remove m_pDefName ? - } + CResourceDef(const CResourceID& rid, lpctstr pszDefName); + CResourceDef(const CResourceID& rid, const CVarDefContNum * pDefName = nullptr); + virtual ~CResourceDef(); -private: - CResourceDef(const CResourceDef& copy); - CResourceDef& operator=(const CResourceDef& other); + CResourceDef(const CResourceDef& copy) = delete; + CResourceDef& operator=(const CResourceDef& other) = delete; public: inline const CResourceID& GetResourceID() const noexcept diff --git a/src/common/resource/CResourceLink.cpp b/src/common/resource/CResourceLink.cpp index 10b957d1c..009500863 100644 --- a/src/common/resource/CResourceLink.cpp +++ b/src/common/resource/CResourceLink.cpp @@ -23,6 +23,8 @@ CResourceLink::CResourceLink(const CResourceID& rid, const CVarDefContNum * pDef ClearTriggers(); } +CResourceLink::~CResourceLink() = default; + void CResourceLink::ScanSection( RES_TYPE restype ) { ADDTOCALLSTACK("CResourceLink::ScanSection"); diff --git a/src/common/resource/CResourceLink.h b/src/common/resource/CResourceLink.h index 93e942dfa..90124e963 100644 --- a/src/common/resource/CResourceLink.h +++ b/src/common/resource/CResourceLink.h @@ -59,11 +59,10 @@ class CResourceLink : public CResourceDef public: CResourceLink(const CResourceID& rid, const CVarDefContNum * pDef = nullptr); - virtual ~CResourceLink() = default; + virtual ~CResourceLink(); -private: - CResourceLink(const CResourceLink& copy); - CResourceLink& operator=(const CResourceLink& other); + CResourceLink(const CResourceLink& copy) = delete; + CResourceLink& operator=(const CResourceLink& other) = delete; }; #endif // _INC_CRESOURCELINK_H diff --git a/src/common/resource/sections/CWebPageDef.cpp b/src/common/resource/sections/CWebPageDef.cpp index 7a387d87e..9cdaf9035 100644 --- a/src/common/resource/sections/CWebPageDef.cpp +++ b/src/common/resource/sections/CWebPageDef.cpp @@ -37,16 +37,17 @@ lpctstr const CWebPageDef::sm_szVerbKeys[WV_QTY+1] = class CSFileConsole : public CTextConsole { -private: - CSFileConsole(const CSFileConsole& copy); - CSFileConsole& operator=(const CSFileConsole& other); - public: static const char *m_sClassName; CSFileText m_FileOut; public: CSFileConsole() = default; + virtual ~CSFileConsole(); + CSFileConsole(const CSFileConsole& copy) = delete; + CSFileConsole& operator=(const CSFileConsole& other) = delete; + + virtual PLEVEL_TYPE GetPrivLevel() const { return PLEVEL_Admin; @@ -63,6 +64,7 @@ class CSFileConsole : public CTextConsole } }; +CSFileConsole::~CSFileConsole() = default; //******************************************************** // -CWebPageDef diff --git a/src/common/sphere_library/CSAssoc.cpp b/src/common/sphere_library/CSAssoc.cpp index 4f119799b..3831d757f 100644 --- a/src/common/sphere_library/CSAssoc.cpp +++ b/src/common/sphere_library/CSAssoc.cpp @@ -3,6 +3,7 @@ #include "../CExpression.h" #include "../common.h" + //*************************************************************************** // -CValStr @@ -120,3 +121,20 @@ bool CElementDef::GetValStr( const void * pBase, CSString & sVal ) const } return false; } + + +//-- + +// CSObjListRec:: Constructors, Destructor, Assign operator. + +CSStringListRec::CSStringListRec( lpctstr pszVal ) + : CSString( pszVal ) + { } + +CSStringListRec::~CSStringListRec() = default; + +//-- + +// CSObjStringList: Constructors, Destructor, Assign operator. +CSStringList::CSStringList() = default; +CSStringList::~CSStringList() = default; diff --git a/src/common/sphere_library/CSAssoc.h b/src/common/sphere_library/CSAssoc.h index 5e584a285..d129c3088 100644 --- a/src/common/sphere_library/CSAssoc.h +++ b/src/common/sphere_library/CSAssoc.h @@ -10,10 +10,6 @@ #include "CSFile.h" -#ifndef OFFSETOF // stddef.h ? - #define OFFSETOF(TYPE, ELEMENT) ((size_t)&(((TYPE *)0)->ELEMENT)) -#endif - // ----------------------------- // CValStr // ----------------------------- @@ -100,9 +96,9 @@ class CSStringListRec : public CSObjListRec, public CSString public: static const char *m_sClassName; - explicit CSStringListRec( lpctstr pszVal ) : CSString( pszVal ) - { - } + + CSStringListRec( lpctstr pszVal ); + virtual ~CSStringListRec(); CSStringListRec(const CSStringListRec& copy) = delete; CSStringListRec& operator=(const CSStringListRec& other) = delete; @@ -117,8 +113,9 @@ class CSStringList : public CSObjList // obviously a list of strings. { public: static const char *m_sClassName; - CSStringList() = default; - virtual ~CSStringList() = default; + + CSStringList(); + virtual ~CSStringList(); CSStringList(const CSStringList& copy) = delete; CSStringList& operator=(const CSStringList& other) = delete; diff --git a/src/common/sphere_library/CSFileList.cpp b/src/common/sphere_library/CSFileList.cpp index e6f4db934..bf3c46457 100644 --- a/src/common/sphere_library/CSFileList.cpp +++ b/src/common/sphere_library/CSFileList.cpp @@ -13,6 +13,10 @@ #include "../../common/CLog.h" #include "../../sphere/threads.h" + +CSFileList::CSFileList() = default; +CSFileList::~CSFileList() = default; + // Similar to the MFC CFileFind bool CSFileList::ReadFileInfo( lpctstr pszFilePath, time_t & dwDateChange, dword & dwSize ) // static { diff --git a/src/common/sphere_library/CSFileList.h b/src/common/sphere_library/CSFileList.h index ecd4ea48c..5df032e52 100644 --- a/src/common/sphere_library/CSFileList.h +++ b/src/common/sphere_library/CSFileList.h @@ -34,16 +34,17 @@ class CSFileList : public CSStringList int ReadDir( lpctstr pszFilePath, bool bShowError = true ); public: - CSFileList() { }; -private: - /** + CSFileList(); + virtual ~CSFileList(); + + /** * @brief No copy on construction allowed. */ - CSFileList(const CSFileList& copy); + CSFileList(const CSFileList& copy) = delete; /** * @brief No copy allowed. */ - CSFileList& operator=(const CSFileList& other); + CSFileList& operator=(const CSFileList& other) = delete; }; #endif // _INC_CSFILELIST_H diff --git a/src/common/sphere_library/CSMemBlock.cpp b/src/common/sphere_library/CSMemBlock.cpp index cdf3ab821..3e5647050 100644 --- a/src/common/sphere_library/CSMemBlock.cpp +++ b/src/common/sphere_library/CSMemBlock.cpp @@ -49,11 +49,13 @@ void CSMemBlock::MemLink( byte * pData ) // CSMemLenBlock:: Constructors, Destructor, Asign operator. -CSMemLenBlock::CSMemLenBlock() +CSMemLenBlock::CSMemLenBlock() : + m_uiLength(0) { - m_uiLength = 0; } +CSMemLenBlock::~CSMemLenBlock() = default; + // CSMemLenBlock:: Modifiers. void CSMemLenBlock::Alloc( size_t uiSize ) diff --git a/src/common/sphere_library/CSMemBlock.h b/src/common/sphere_library/CSMemBlock.h index 3ba78f865..f38648fa0 100644 --- a/src/common/sphere_library/CSMemBlock.h +++ b/src/common/sphere_library/CSMemBlock.h @@ -18,15 +18,15 @@ class CSMemBlock ///@{ CSMemBlock(); virtual ~CSMemBlock(); -private: - /** + + /** * @brief No copy on construction allowed. */ - CSMemBlock(const CSMemBlock& copy); + CSMemBlock(const CSMemBlock& copy) = delete; /** * @brief No copy allowed. */ - CSMemBlock& operator=(const CSMemBlock& other); + CSMemBlock& operator=(const CSMemBlock& other) = delete; ///@} /** @name Modifiers: */ @@ -82,18 +82,19 @@ class CSMemLenBlock : public CSMemBlock */ ///@{ CSMemLenBlock(); -private: - /** + virtual ~CSMemLenBlock(); + + /** * @brief No copy on construction allowed. */ - CSMemLenBlock(const CSMemLenBlock& copy); + CSMemLenBlock(const CSMemLenBlock& copy) = delete; /** * @brief No copy allowed. */ - CSMemLenBlock& operator=(const CSMemLenBlock& other); + CSMemLenBlock& operator=(const CSMemLenBlock& other) = delete; ///@} -public: - /** @name Modifiers: + + /** @name Modifiers: */ ///@{ /** diff --git a/src/common/sphere_library/CSObjList.cpp b/src/common/sphere_library/CSObjList.cpp index bb6038c68..35fafb63d 100644 --- a/src/common/sphere_library/CSObjList.cpp +++ b/src/common/sphere_library/CSObjList.cpp @@ -3,6 +3,18 @@ #include "../CException.h" +// CSObjListRec:: Constructors, Destructor, Assign operator. + +CSObjListRec::CSObjListRec() noexcept : + m_pParent(nullptr), m_pNext(nullptr), m_pPrev(nullptr) + {} + +CSObjListRec::~CSObjListRec() +{ + RemoveSelf(); +} + + // CSObjListRec:: Capacity. void CSObjListRec::RemoveSelf() diff --git a/src/common/sphere_library/CSObjListRec.h b/src/common/sphere_library/CSObjListRec.h index a83ba2f1e..41ce921d8 100644 --- a/src/common/sphere_library/CSObjListRec.h +++ b/src/common/sphere_library/CSObjListRec.h @@ -27,11 +27,9 @@ class CSObjListRec /** * @brief set references for parent, next and previous to nullptr. */ - CSObjListRec() noexcept : - m_pParent(nullptr), m_pNext(nullptr), m_pPrev(nullptr) - {} + CSObjListRec() noexcept; - virtual inline ~CSObjListRec(); + virtual ~CSObjListRec(); /** * @brief No copies allowed. @@ -81,11 +79,6 @@ class CSObjListRec /* Inline Methods Definitions */ -inline CSObjListRec::~CSObjListRec() -{ - RemoveSelf(); -} - // CSObjListRec:: Capacity. //void CSObjListRec::RemoveSelf() // defined in CSObjList.cpp diff --git a/src/common/sphere_library/sptr.h b/src/common/sphere_library/sptr.h index 3d95e61cd..152c069ae 100644 --- a/src/common/sphere_library/sptr.h +++ b/src/common/sphere_library/sptr.h @@ -1,8 +1,17 @@ #ifndef _INC_SPTR_H #define _INC_SPTR_H +#ifndef _MSVC +# pragma GCC diagnostic push +# pragma GCC diagnostic ignored "-Wzero-as-null-pointer-constant" +#endif + #include +#ifndef _MSVC +#pragma GCC diagnostic pop +#endif + // Sphere Library namespace sl diff --git a/src/common/sphere_library/sstring.cpp b/src/common/sphere_library/sstring.cpp index c4de7b30c..d6bdb13ca 100644 --- a/src/common/sphere_library/sstring.cpp +++ b/src/common/sphere_library/sstring.cpp @@ -8,16 +8,22 @@ #include #pragma warning( push ) #pragma warning ( disable : ALL_CODE_ANALYSIS_WARNINGS ) -#elif defined(__GNUC__) && !defined(__clang__) +#else #pragma GCC diagnostic push - #pragma GCC diagnostic ignored "-Wmaybe-uninitialized" + #pragma GCC diagnostic ignored "-Winvalid-utf8" + #pragma GCC diagnostic ignored "-Wzero-as-null-pointer-constant" + #if defined(__GNUC__) && !defined(__clang__) + # pragma GCC diagnostic ignored "-Wmaybe-uninitialized" + #elif defined(__clang__) + # pragma GCC diagnostic ignored "-Wweak-vtables" + #endif #endif #include #ifdef _MSC_VER #pragma warning( pop ) -#elif defined(__GNUC__) && !defined(__clang__) +#else #pragma GCC diagnostic pop #endif @@ -1830,9 +1836,9 @@ fReadUntilDelimiter(char **buf, size_t *bufsiz, int delimiter, FILE *fp) noexcep char *ptr, *eptr; - if (*buf == NULL || *bufsiz == 0) { + if (*buf == nullptr || *bufsiz == 0) { *bufsiz = BUFSIZ; - if ((*buf = (char*)malloc(*bufsiz)) == NULL) + if ((*buf = (char*)malloc(*bufsiz)) == nullptr) return -1; } @@ -1857,7 +1863,7 @@ fReadUntilDelimiter(char **buf, size_t *bufsiz, int delimiter, FILE *fp) noexcep char *nbuf; size_t nbufsiz = *bufsiz * 2; ssize_t d = ptr - *buf; - if ((nbuf = (char*)realloc(*buf, nbufsiz)) == NULL) + if ((nbuf = (char*)realloc(*buf, nbufsiz)) == nullptr) return -1; *buf = nbuf; *bufsiz = nbufsiz; diff --git a/src/common/sphere_library/sstringobjs.cpp b/src/common/sphere_library/sstringobjs.cpp index dc249228d..951b88923 100644 --- a/src/common/sphere_library/sstringobjs.cpp +++ b/src/common/sphere_library/sstringobjs.cpp @@ -46,10 +46,12 @@ tchar* Str_GetTemp() noexcept */ AbstractString::AbstractString() : - m_buf(0), m_length(0), m_realLength(0) + m_buf(nullptr), m_length(0), m_realLength(0) { } +AbstractString::~AbstractString() = default; + void AbstractString::ensureLengthHeap(size_t newLength) { if (newLength >= m_realLength) diff --git a/src/common/sphere_library/sstringobjs.h b/src/common/sphere_library/sstringobjs.h index 5bf4cd4a7..fddd7e55e 100644 --- a/src/common/sphere_library/sstringobjs.h +++ b/src/common/sphere_library/sstringobjs.h @@ -36,7 +36,7 @@ class AbstractString { public: AbstractString(); - virtual ~AbstractString() = default; + virtual ~AbstractString(); AbstractString(const AbstractString& copy) = delete; AbstractString& operator=(const AbstractString& other) = delete; @@ -132,7 +132,7 @@ class TemporaryString : public AbstractString public: TemporaryString(); - ~TemporaryString(); + virtual ~TemporaryString() override; TemporaryString(const TemporaryString& copy) = delete; TemporaryString& operator=(const TemporaryString& other) = delete; diff --git a/src/common/sqlite/SQLite.cpp b/src/common/sqlite/SQLite.cpp index 004ec53bd..f2fa7078e 100644 --- a/src/common/sqlite/SQLite.cpp +++ b/src/common/sqlite/SQLite.cpp @@ -61,7 +61,7 @@ int CSQLite::QuerySQL( lpctstr strSQL, CVarDefMap & mapQueryResult ) mapQueryResult.Clear(); mapQueryResult.SetNumNew("NUMROWS", 0); - TablePtr retTable = QuerySQLPtr(strSQL); + SQLiteTablePtr retTable = QuerySQLPtr(strSQL); if (retTable.m_pTable == nullptr) goto err_and_ret; @@ -92,11 +92,11 @@ int CSQLite::QuerySQL( lpctstr strSQL, CVarDefMap & mapQueryResult ) return m_iLastError; } -Table CSQLite::QuerySQL( lpctstr strSQL ) +SQLiteTable CSQLite::QuerySQL( lpctstr strSQL ) { if (!IsOpen()) { m_iLastError=SQLITE_ERROR; - return Table(); + return SQLiteTable(); } char ** retStrings = nullptr; @@ -114,7 +114,7 @@ Table CSQLite::QuerySQL( lpctstr strSQL ) sqlite3_free(errmsg); - Table retTable; + SQLiteTable retTable; if (iRows>0) retTable.m_iPos=0; @@ -158,7 +158,7 @@ Table CSQLite::QuerySQL( lpctstr strSQL ) return retTable; } -TablePtr CSQLite::QuerySQLPtr( lpctstr strSQL ) +SQLiteTablePtr CSQLite::QuerySQLPtr( lpctstr strSQL ) { if (!IsOpen()) { @@ -181,7 +181,7 @@ TablePtr CSQLite::QuerySQLPtr( lpctstr strSQL ) sqlite3_free(errmsg); - Table * retTable = new Table(); + SQLiteTable * retTable = new SQLiteTable(); if (iRows>0) retTable->m_iPos=0; @@ -221,7 +221,7 @@ TablePtr CSQLite::QuerySQLPtr( lpctstr strSQL ) sqlite3_free_table(retStrings); m_iLastError=SQLITE_OK; - return TablePtr(retTable); + return SQLiteTablePtr(retTable); } void CSQLite::ConvertUTF8ToVString( const char * strInUTF8MB, stdvstring & strOut ) @@ -553,16 +553,21 @@ bool CSQLite::r_Verb(CScript & s, CTextConsole * pSrc) // Table Class... -lpctstr Table::GetColName( int iCol ) +SQLiteTable::SQLiteTable() : + m_iRows(0), m_iCols(0), m_iPos(-1) +{} +SQLiteTable::~SQLiteTable() = default; + +lpctstr SQLiteTable::GetColName( int iCol ) { if (iCol>=0 && iCol0) { @@ -602,7 +607,7 @@ bool Table::GoPrev() return false; } -bool Table::GoRow(uint iRow) +bool SQLiteTable::GoRow(uint iRow) { if (iRow=m_iCols) return 0; - if (m_iPos<0) return 0; + if (iColIndex<0 || iColIndex>=m_iCols) + return nullptr; + if (m_iPos<0) + return nullptr; + return &m_lstRows[m_iPos][iColIndex][0]; } -lpctstr Table::operator [] (lpctstr lpColName) +lpctstr SQLiteTable::operator [] (lpctstr lpColName) { if (!lpColName) - return 0; + return nullptr; if (m_iPos<0) - return 0; + return nullptr; + for (int i=0; i=m_iCols) - return 0; + return nullptr; if (m_iPos<0) - return 0; + return nullptr; return &m_lstRows[m_iPos][iColIndex][0]; } -void Table::JoinTable(Table & tblJoin) +void SQLiteTable::JoinTable(SQLiteTable & tblJoin) { if (m_iCols==0) { *this=tblJoin; return; } - if (m_iCols!=tblJoin.m_iCols) return; + if (m_iCols!=tblJoin.m_iCols) + return; if (tblJoin.m_iRows>0) { @@ -679,51 +690,53 @@ void Table::JoinTable(Table & tblJoin) } } -TablePtr::TablePtr( ) +//-- + +SQLiteTablePtr::SQLiteTablePtr( ) { m_pTable=nullptr; } -TablePtr::TablePtr( Table * pTable ) +SQLiteTablePtr::SQLiteTablePtr( SQLiteTable * pTable ) { m_pTable = pTable; } -TablePtr::TablePtr( const TablePtr& cTablePtr ) +SQLiteTablePtr::SQLiteTablePtr( const SQLiteTablePtr & cTablePtr ) { m_pTable=cTablePtr.m_pTable; - ((TablePtr *)&cTablePtr)->m_pTable=nullptr; + ((SQLiteTablePtr *)&cTablePtr)->m_pTable=nullptr; } -TablePtr::~TablePtr() +SQLiteTablePtr::~SQLiteTablePtr() { if (m_pTable) delete m_pTable; } -void TablePtr::operator =( const TablePtr& cTablePtr ) +void SQLiteTablePtr::operator =( const SQLiteTablePtr & cTablePtr ) { if (m_pTable) delete m_pTable; m_pTable=cTablePtr.m_pTable; - ((TablePtr *)&cTablePtr)->m_pTable=nullptr; + ((SQLiteTablePtr *)&cTablePtr)->m_pTable=nullptr; } -Table * TablePtr::Detach() +SQLiteTable * SQLiteTablePtr::Detach() { - Table * pTable=m_pTable; + SQLiteTable * pTable=m_pTable; m_pTable=nullptr; return pTable; } -void TablePtr::Attach( Table * pTable ) +void SQLiteTablePtr::Attach( SQLiteTable * pTable ) { if (m_pTable) delete m_pTable; m_pTable=pTable; } -void TablePtr::Destroy() +void SQLiteTablePtr::Destroy() { if (m_pTable) delete m_pTable; diff --git a/src/common/sqlite/SQLite.h b/src/common/sqlite/SQLite.h index 753b815ea..e06b1a910 100644 --- a/src/common/sqlite/SQLite.h +++ b/src/common/sqlite/SQLite.h @@ -27,8 +27,8 @@ typedef vstrlist row; // Forward declarations struct sqlite3; -class Table; -class TablePtr; +class SQLiteTable; +class SQLiteTablePtr; // Main wrapper @@ -49,8 +49,8 @@ class CSQLite : public CScriptObj int GetLastError() const { return m_iLastError; }; void ClearError() { m_iLastError=0; }; // SQLITE_OK = 0 - TablePtr QuerySQLPtr( lpctstr strSQL ); - Table QuerySQL( lpctstr strSQL ); + SQLiteTablePtr QuerySQLPtr( lpctstr strSQL ); + SQLiteTable QuerySQL( lpctstr strSQL ); int QuerySQL( lpctstr strSQL, CVarDefMap & mapQueryResult ); int ExecuteSQL( lpctstr strSQL ); int IsSQLComplete( lpctstr strSQL ); @@ -92,12 +92,13 @@ class CSQLite : public CScriptObj }; // Table class... -class Table +class SQLiteTable { friend class CSQLite; + public: - Table(void){ m_iRows=m_iCols=0; m_iPos=-1; }; - virtual ~Table() {}; + SQLiteTable(); + virtual ~SQLiteTable(); // Gets the number of columns int GetColCount(){ return m_iCols; }; @@ -153,7 +154,7 @@ class Table // Adds the rows from another table to this table // It is the caller's reponsibility to make sure // The two tables are matching - void JoinTable(Table & tblJoin); + void JoinTable(SQLiteTable & tblJoin); private: int m_iRows, m_iCols; @@ -166,52 +167,52 @@ class Table // A class to contain a pointer to a Table class, // Which will spare the user from freeing a pointer. -class TablePtr +class SQLiteTablePtr { public: // Default constructor - TablePtr( ); + SQLiteTablePtr( ); // Construct from a Table* - TablePtr( Table * pTable ); + SQLiteTablePtr( SQLiteTable * pTable ); // Copy constructor. // Will prevent the original TablePtr from deleting the table. // If you have a previous table connected to this class, // you do not have to worry, // it will commit suicide before eating the new table. - TablePtr( const TablePtr& cTablePtr ); + SQLiteTablePtr( const SQLiteTablePtr & cTablePtr ); // Destructor... - virtual ~TablePtr(); + virtual ~SQLiteTablePtr(); // Copy operator. // Will prevent the original TablePtr from deleting the table. // If you have a previous table connected to this class, // you do not have to worry, // it will commit suicide before eating the new table. - void operator =(const TablePtr& cTablePtr); + void operator =(const SQLiteTablePtr & cTablePtr); // Functor operator, will de-reference the m_pTable member. // WARNING: Use with care! Check for non-null m_pTable first! - Table& operator()() { return *m_pTable; }; + SQLiteTable& operator()() { return *m_pTable; }; // bool operator, to check if m_pTable is valid. - operator bool() { return m_pTable != 0; }; + operator bool() { return m_pTable != nullptr; }; // Detaches the class from the Table, // and returns the Table that were just detached... - Table * Detach(); + SQLiteTable * Detach(); // Frees the current Table, and attaches the pTable. - void Attach(Table * pTable); + void Attach(SQLiteTable * pTable); // Frees the current Table. void Destroy(); // Pointer to the table. // I do not see any reason for encapsulating in Get/Set functions. - Table * m_pTable; + SQLiteTable * m_pTable; }; diff --git a/src/game/CComponent.cpp b/src/game/CComponent.cpp index a59881201..c171944ba 100644 --- a/src/game/CComponent.cpp +++ b/src/game/CComponent.cpp @@ -7,6 +7,8 @@ CComponent::CComponent(COMP_TYPE type) noexcept : { } +CComponent::~CComponent() = default; + COMP_TYPE CComponent::GetType() const noexcept { return _iType; diff --git a/src/game/CComponent.h b/src/game/CComponent.h index c527d8375..1a07e19b6 100644 --- a/src/game/CComponent.h +++ b/src/game/CComponent.h @@ -41,7 +41,7 @@ class CComponent CComponent(COMP_TYPE type) noexcept; public: - virtual ~CComponent() = default; + virtual ~CComponent(); COMP_TYPE GetType() const noexcept; /* Script's compatibility diff --git a/src/game/CComponentProps.cpp b/src/game/CComponentProps.cpp index df386ed20..a131158ea 100644 --- a/src/game/CComponentProps.cpp +++ b/src/game/CComponentProps.cpp @@ -3,6 +3,8 @@ #include "CComponentProps.h" +CComponentProps::~CComponentProps() noexcept = default; + bool CComponentProps::BaseCont_GetPropertyNum(const BaseContNum_t* container, PropertyIndex_t iPropIndex, PropertyValNum_t* piOutVal) const { ADDTOCALLSTACK("CComponentProps::GetPropertyNum"); diff --git a/src/game/CComponentProps.h b/src/game/CComponentProps.h index f8cee1db3..5cfadbda4 100644 --- a/src/game/CComponentProps.h +++ b/src/game/CComponentProps.h @@ -48,6 +48,7 @@ class CComponentProps CComponentProps(COMPPROPS_TYPE type) noexcept { _iType = type; } + virtual ~CComponentProps() noexcept; virtual lpctstr GetName() const = 0; virtual PropertyIndex_t GetPropsQty() const = 0; @@ -137,8 +138,6 @@ class CComponentProps static void BaseCont_Write_ContStr(const BaseContStr_t* container, const lpctstr *ptcPropsTable, CScript &s); public: - virtual ~CComponentProps() noexcept = default; - inline COMPPROPS_TYPE GetType() const noexcept { return _iType; } diff --git a/src/game/CObjBase.cpp b/src/game/CObjBase.cpp index 3019f062b..ce66c5612 100644 --- a/src/game/CObjBase.cpp +++ b/src/game/CObjBase.cpp @@ -1187,7 +1187,7 @@ bool CObjBase::r_WriteVal( lpctstr ptcKey, CSString &sVal, CTextConsole * pSrc, } //++count; } - sVal.Format(ptcArg[0], ptcArg[1], ptcArg[2] ? ptcArg[2] : 0, ptcArg[3] ? ptcArg[3] : 0); + sVal.Format(ptcArg[0], ptcArg[1], (ptcArg[2] ? ptcArg[2] : nullptr), (ptcArg[3] ? ptcArg[3] : nullptr)); return true; } break; case OC_DIALOGLIST: diff --git a/src/game/CSectorTemplate.cpp b/src/game/CSectorTemplate.cpp index 5151dc1e0..35281a2a1 100644 --- a/src/game/CSectorTemplate.cpp +++ b/src/game/CSectorTemplate.cpp @@ -14,6 +14,9 @@ //////////////////////////////////////////////////////////////////////// // -CCharsDisconnectList +CCharsDisconnectList::CCharsDisconnectList() = default; +CCharsDisconnectList::~CCharsDisconnectList() = default; + void CCharsDisconnectList::AddCharDisconnected( CChar * pChar ) { ADDTOCALLSTACK("CCharsDisconnectList::AddCharDisconnected"); @@ -25,12 +28,13 @@ void CCharsDisconnectList::AddCharDisconnected( CChar * pChar ) //////////////////////////////////////////////////////////////////////// // -CCharsActiveList -CCharsActiveList::CCharsActiveList() +CCharsActiveList::CCharsActiveList() : + m_iClients(0), m_iTimeLastClient(0) { - m_iTimeLastClient = 0; - m_iClients = 0; } +CCharsActiveList::~CCharsActiveList() = default; + void CCharsActiveList::OnRemoveObj(CSObjContRec* pObjRec ) { ADDTOCALLSTACK("CCharsActiveList::OnRemoveObj"); diff --git a/src/game/CSectorTemplate.h b/src/game/CSectorTemplate.h index cae6dfa38..2b9200ce5 100644 --- a/src/game/CSectorTemplate.h +++ b/src/game/CSectorTemplate.h @@ -23,7 +23,8 @@ struct CSectorObjCont struct CCharsDisconnectList : public CSObjCont, public CSectorObjCont { - CCharsDisconnectList() = default; + CCharsDisconnectList(); + virtual ~CCharsDisconnectList(); CCharsDisconnectList(const CCharsDisconnectList& copy) = delete; CCharsDisconnectList& operator=(const CCharsDisconnectList& other) = delete; @@ -41,6 +42,7 @@ struct CCharsActiveList : public CSObjCont, public CSectorObjCont public: CCharsActiveList(); + ~CCharsActiveList(); CCharsActiveList(const CCharsActiveList& copy) = delete; CCharsActiveList& operator=(const CCharsActiveList& other) = delete; diff --git a/src/game/CServerConfig.cpp b/src/game/CServerConfig.cpp index 809d625dc..a54c7a625 100644 --- a/src/game/CServerConfig.cpp +++ b/src/game/CServerConfig.cpp @@ -33,6 +33,12 @@ #include "spheresvr.h" #include "triggers.h" +#include +#ifndef OFFSETOF +//# define OFFSETOF(TYPE, ELEMENT) (offsetof(TYPE, ELEMENT)) +# define OFFSETOF(TYPE, ELEMENT) ((size_t)&(((TYPE *)0)->ELEMENT)) +#endif + // .ini settings. CServerConfig::CServerConfig() @@ -729,6 +735,12 @@ enum RC_TYPE // NOTE: Need to be alphabetized order +// TODO: use offsetof by cstddef. Though, it requires the class/struct to be a POD type, so we need to encapsulate the values in a separate struct. +#ifdef __GNUC__ + #pragma GCC diagnostic push + #pragma GCC diagnostic ignored "-Wzero-as-null-pointer-constant" +#endif + const CAssocReg CServerConfig::sm_szLoadKeys[RC_QTY + 1] { @@ -1013,6 +1025,10 @@ const CAssocReg CServerConfig::sm_szLoadKeys[RC_QTY + 1] { nullptr, { ELEM_VOID, 0, }} }; +#ifdef __GNUC__ + #pragma GCC diagnostic pop +#endif + bool CServerConfig::r_LoadVal( CScript &s ) { ADDTOCALLSTACK("CServerConfig::r_LoadVal"); diff --git a/src/game/CServerConfig.h b/src/game/CServerConfig.h index 768ce123b..8d67d01d8 100644 --- a/src/game/CServerConfig.h +++ b/src/game/CServerConfig.h @@ -231,6 +231,7 @@ extern class CServerConfig : public CResourceHolder public: static const char *m_sClassName; + int64 m_timePeriodic; // When to perform the next periodic update // Begin INI file options. @@ -376,7 +377,7 @@ extern class CServerConfig : public CResourceHolder bool m_fDisplayPercentAr; // Display the ARMOR value in the tooltip as the % bool m_fDisplayElementalResistance; //Display the Elemental and MAxElemental Resistances on the paperdoll and tooltips (RESFIRE/RESCOLD/RESENERGY/RESPOISON) even if combat flag Elemental Engine is disabled. bool _fMeditationMovementAbort; // Meditation fails if the player moves. - + // Flags for controlling pvp/pvm behaviour of players uint m_iCombatFlags; // combat flags uint m_iMagicFlags; // magic flags @@ -609,7 +610,6 @@ extern class CServerConfig : public CResourceHolder CResourceScript m_scpIni; // Keep this around so we can link to it. CResourceScript m_scpCryptIni; // Encryption keys are in here -public: CResourceScript m_scpTables; // Script's loaded. CSStringSortArray m_ResourceList; // Sections lists. diff --git a/src/game/CWorldImport.cpp b/src/game/CWorldImport.cpp index e7109120c..d9216cdf2 100644 --- a/src/game/CWorldImport.cpp +++ b/src/game/CWorldImport.cpp @@ -22,19 +22,22 @@ struct CImportSer : public CSObjListRec return( m_dwContSer == UID_UNUSED ); } - CImportSer( dword dwSer ) noexcept : - m_dwSer( dwSer ) - { - m_pObj = nullptr; - m_dwContSer = UID_UNUSED; - m_layer = LAYER_NONE; - } - ~CImportSer() noexcept = default; + CImportSer( dword dwSer ) noexcept; + ~CImportSer() noexcept; CImportSer(const CImportSer& copy) = delete; CImportSer& operator=(const CImportSer& other) = delete; }; +CImportSer::CImportSer( dword dwSer ) noexcept : + m_dwSer( dwSer ) +{ + m_pObj = nullptr; + m_dwContSer = UID_UNUSED; + m_layer = LAYER_NONE; +} +CImportSer::~CImportSer() noexcept = default; + struct CImportFile { CObjBase * m_pCurObj; // current entry. diff --git a/src/game/CWorldTicker.h b/src/game/CWorldTicker.h index 50fd92fdb..b78a95c4e 100644 --- a/src/game/CWorldTicker.h +++ b/src/game/CWorldTicker.h @@ -9,6 +9,7 @@ #include "CTimedObject.h" #include +/* Include phmap.h */ #ifdef ADDRESS_SANITIZER #define MYASAN_ #endif @@ -31,8 +32,20 @@ #ifdef __GNUC__ #pragma GCC diagnostic pop #endif +/* End of phmap.h inclusion */ + +/* Include btree.h */ +#ifdef __GNUC__ + #pragma GCC diagnostic push + #pragma GCC diagnostic ignored "-Wzero-as-null-pointer-constant" +#endif + #include +#ifdef __GNUC__ + #pragma GCC diagnostic pop +#endif +/* End of btree.h inclusion */ class CObjBase; diff --git a/src/game/chars/CChar.cpp b/src/game/chars/CChar.cpp index ccf2248a3..c4815c878 100644 --- a/src/game/chars/CChar.cpp +++ b/src/game/chars/CChar.cpp @@ -2616,7 +2616,7 @@ bool CChar::r_WriteVal( lpctstr ptcKey, CSString & sVal, CTextConsole * pSrc, bo --i; } - sVal = 0; + sVal = "0"; delete[] pszFameAt0; return true; } @@ -2712,7 +2712,7 @@ bool CChar::r_WriteVal( lpctstr ptcKey, CSString & sVal, CTextConsole * pSrc, bo --i; } - sVal = 0; + sVal = "0"; delete[] pszKarmaAt0; return true; } @@ -2890,7 +2890,7 @@ bool CChar::r_WriteVal( lpctstr ptcKey, CSString & sVal, CTextConsole * pSrc, bo sVal = IsDisconnected() ? "0" : "1"; return true; } - sVal = 0; + sVal = "0"; return true; case CHC_ISSTUCK: { diff --git a/src/game/chars/CCharAttacker.cpp b/src/game/chars/CCharAttacker.cpp index 7b449d1e2..19d53e45f 100644 --- a/src/game/chars/CCharAttacker.cpp +++ b/src/game/chars/CCharAttacker.cpp @@ -20,7 +20,7 @@ bool CChar::Attacker_Add(CChar * pChar, int threat) } else if (IsTrigUsed(TRIGGER_COMBATSTART)) { - TRIGRET_TYPE tRet = OnTrigger(CTRIG_CombatStart, pChar, 0); + TRIGRET_TYPE tRet = OnTrigger(CTRIG_CombatStart, pChar, nullptr); if (tRet == TRIGRET_RET_TRUE) return false; else @@ -255,7 +255,7 @@ void CChar::Attacker_Clear() { if (m_lastAttackers.empty() || !Fight_IsActive() || !m_Fight_Targ_UID.IsValidUID() || !m_Fight_Targ_UID.CharFind()) { - OnTrigger(CTRIG_CombatEnd, this, 0); + OnTrigger(CTRIG_CombatEnd, this, nullptr); } } diff --git a/src/game/chars/CCharNPC.cpp b/src/game/chars/CCharNPC.cpp index 347111caf..3e1d850fa 100644 --- a/src/game/chars/CCharNPC.cpp +++ b/src/game/chars/CCharNPC.cpp @@ -325,7 +325,7 @@ void CChar::NPC_CreateTrigger() continue; executedEvents.emplace(pLink); - iRet = CScriptObj::OnTriggerScript(s, pszTrigName, this, 0); + iRet = CScriptObj::OnTriggerScript(s, pszTrigName, this, nullptr); if (iRet != TRIGRET_RET_FALSE && iRet != TRIGRET_RET_DEFAULT) return; } @@ -342,7 +342,7 @@ void CChar::NPC_CreateTrigger() continue; executedEvents.emplace(pLink); - iRet = CScriptObj::OnTriggerScript(s, pszTrigName, this, 0); + iRet = CScriptObj::OnTriggerScript(s, pszTrigName, this, nullptr); if (iRet != TRIGRET_RET_FALSE && iRet != TRIGRET_RET_DEFAULT) return; } diff --git a/src/game/chars/CCharSkill.cpp b/src/game/chars/CCharSkill.cpp index f32d016f6..4ee5a9147 100644 --- a/src/game/chars/CCharSkill.cpp +++ b/src/game/chars/CCharSkill.cpp @@ -420,7 +420,7 @@ void CChar::Skill_Experience( SKILL_TYPE skill, int iDifficulty ) if ( Skill_OnTrigger( skill, SKTRIG_GAIN, &pArgs ) == TRIGRET_RET_TRUE ) return; } - pArgs.GetArgNs( 0, &iChance, &iSkillMax ); + pArgs.GetArgNs( nullptr, &iChance, &iSkillMax ); if ( iChance <= 0 ) return; @@ -554,7 +554,7 @@ bool CChar::Skill_UseQuick( SKILL_TYPE skill, int64 difficulty, bool bAllowGain, if ( IsTrigUsed(TRIGGER_SKILLUSEQUICK) ) { ret = Skill_OnCharTrigger( skill, CTRIG_SkillUseQuick, &pArgs ); - pArgs.GetArgNs( 0, &difficulty, &result); + pArgs.GetArgNs( nullptr, &difficulty, &result); if ( ret == TRIGRET_RET_TRUE ) return true; @@ -564,7 +564,7 @@ bool CChar::Skill_UseQuick( SKILL_TYPE skill, int64 difficulty, bool bAllowGain, if ( IsTrigUsed(TRIGGER_USEQUICK) ) { ret = Skill_OnTrigger( skill, SKTRIG_USEQUICK, &pArgs ); - pArgs.GetArgNs( 0, &difficulty, &result ); + pArgs.GetArgNs( nullptr, &difficulty, &result ); if ( ret == TRIGRET_RET_TRUE ) return true; diff --git a/src/game/clients/CClient.cpp b/src/game/clients/CClient.cpp index 9ac40448e..04cbf40df 100644 --- a/src/game/clients/CClient.cpp +++ b/src/game/clients/CClient.cpp @@ -1610,7 +1610,10 @@ bool CClient::r_Verb( CScript & s, CTextConsole * pSrc ) // Execute command from break; } } - SysMessagef( pszArgs[0], pszArgs[1], pszArgs[2] ? pszArgs[2] : 0, pszArgs[3] ? pszArgs[3] : 0); + SysMessagef(pszArgs[0], + pszArgs[1], + pszArgs[2] ? pszArgs[2] : nullptr, + pszArgs[3] ? pszArgs[3] : nullptr); } break; case CV_SMSGU: diff --git a/src/game/clients/CClientDialog.cpp b/src/game/clients/CClientDialog.cpp index 981536aa3..5f95b6a20 100644 --- a/src/game/clients/CClientDialog.cpp +++ b/src/game/clients/CClientDialog.cpp @@ -180,7 +180,7 @@ TRIGRET_TYPE CClient::Dialog_OnButton( const CResourceID& rid, dword dwButtonID, CResourceLock prebutton; if (g_Cfg.ResourceLock(prebutton, CResourceID(RES_DIALOG, rid.GetResIndex(), RES_DIALOG_PREBUTTON))) - stopPrebutton = pObj->OnTriggerRun(prebutton, TRIGRUN_SECTION_TRUE, m_pChar, pArgs, NULL); + stopPrebutton = pObj->OnTriggerRun(prebutton, TRIGRUN_SECTION_TRUE, m_pChar, pArgs, nullptr); if (stopPrebutton != TRIGRET_RET_TRUE) return pObj->OnTriggerRunVal(s, TRIGRUN_SECTION_TRUE, m_pChar, pArgs); diff --git a/src/game/clients/CClientLog.cpp b/src/game/clients/CClientLog.cpp index 89597af89..e0fe9fab4 100644 --- a/src/game/clients/CClientLog.cpp +++ b/src/game/clients/CClientLog.cpp @@ -11,8 +11,9 @@ #include "../CServer.h" #include "CClient.h" +namespace zlib { #include - +} ///////////////////////////////////////////////////////////////// // -CClient stuff. @@ -244,8 +245,8 @@ bool CClient::addRelay( const CServerDef * pServ ) CSString sCustomerID(pServ->GetName()); sCustomerID.Add(GetAccount()->GetName()); - dwCustomerId = ::crc32(0L, Z_NULL, 0); - dwCustomerId = ::crc32(dwCustomerId, reinterpret_cast(sCustomerID.GetBuffer()), (uInt)sCustomerID.GetLength()); + dwCustomerId = zlib::crc32(0L, nullptr, 0); + dwCustomerId = zlib::crc32(dwCustomerId, reinterpret_cast(sCustomerID.GetBuffer()), (zlib::uInt)sCustomerID.GetLength()); GetAccount()->m_TagDefs.SetNum("customerid", dwCustomerId); } diff --git a/src/game/clients/CGlobalChatChanMember.cpp b/src/game/clients/CGlobalChatChanMember.cpp index e06ec2663..a460a3db3 100644 --- a/src/game/clients/CGlobalChatChanMember.cpp +++ b/src/game/clients/CGlobalChatChanMember.cpp @@ -8,6 +8,7 @@ CGlobalChatChanMember::CGlobalChatChanMember() noexcept : { } +CGlobalChatChanMember::~CGlobalChatChanMember() noexcept = default; void CGlobalChatChanMember::SetJID(lpctstr pszJID) { diff --git a/src/game/clients/CGlobalChatChanMember.h b/src/game/clients/CGlobalChatChanMember.h index 24d03f922..a4d5e80c7 100644 --- a/src/game/clients/CGlobalChatChanMember.h +++ b/src/game/clients/CGlobalChatChanMember.h @@ -17,7 +17,7 @@ class CGlobalChatChanMember // This is member of CClient static const char* m_sClassName; CGlobalChatChanMember() noexcept; - virtual ~CGlobalChatChanMember() noexcept = default; + virtual ~CGlobalChatChanMember() noexcept; private: CSString m_strJID; // client Jabber ID diff --git a/src/game/clients/CParty.cpp b/src/game/clients/CParty.cpp index 5fa7edf95..470de2a5a 100644 --- a/src/game/clients/CParty.cpp +++ b/src/game/clients/CParty.cpp @@ -324,7 +324,7 @@ bool CPartyDef::RemoveMember( CUID uidRemove, CUID uidCommand ) } if ( IsTrigUsed(TRIGGER_PARTYLEAVE) ) { - if ( pCharRemove->OnTrigger(CTRIG_PartyLeave, pCharRemove, 0) == TRIGRET_RET_TRUE ) + if ( pCharRemove->OnTrigger(CTRIG_PartyLeave, pCharRemove, nullptr) == TRIGRET_RET_TRUE ) return false; } diff --git a/src/game/components/CCMultiMovable.cpp b/src/game/components/CCMultiMovable.cpp index ddc069b1e..35ee66461 100644 --- a/src/game/components/CCMultiMovable.cpp +++ b/src/game/components/CCMultiMovable.cpp @@ -36,6 +36,8 @@ CCMultiMovable::CCMultiMovable(bool fCanTurn) : _pCaptain = nullptr; } +CCMultiMovable::~CCMultiMovable() = default; + void CCMultiMovable::SetCaptain(CTextConsole * pSrc) { _pCaptain = pSrc; diff --git a/src/game/components/CCMultiMovable.h b/src/game/components/CCMultiMovable.h index be2162038..4967a67ac 100644 --- a/src/game/components/CCMultiMovable.h +++ b/src/game/components/CCMultiMovable.h @@ -25,7 +25,7 @@ class CCMultiMovable public: CCMultiMovable(bool fCanTurn); - virtual ~CCMultiMovable() = default; + virtual ~CCMultiMovable(); //CItem *GetLink() const; bool _OnTick(); @@ -53,4 +53,4 @@ class CCMultiMovable void SetPilot(CChar *pChar); }; -#endif //_INC_CCMULTIMOVABLE_H \ No newline at end of file +#endif //_INC_CCMULTIMOVABLE_H diff --git a/src/network/packet.cpp b/src/network/packet.cpp index 2e2eb33c8..cde1e6475 100644 --- a/src/network/packet.cpp +++ b/src/network/packet.cpp @@ -1222,6 +1222,8 @@ PacketSend::PacketSend(const PacketSend *other) m_position = other->m_position; } +PacketSend::~PacketSend() = default; + void PacketSend::initLength(void) { // DEBUGNETWORK(("Packet %x starts dynamic with pos %d.\n", m_buffer[0], m_position)); @@ -1323,6 +1325,15 @@ bool PacketSend::canSendTo(const CNetState* state) const return true; } +/*************************************************************************** + * + * + * class SimplePacketTransaction Interface for defining a packet transaction + * + * + ***************************************************************************/ + +PacketTransaction::~PacketTransaction() = default; /*************************************************************************** * diff --git a/src/network/packet.h b/src/network/packet.h index ec62055dd..6ba324726 100644 --- a/src/network/packet.h +++ b/src/network/packet.h @@ -160,7 +160,7 @@ class PacketSend : public Packet public: explicit PacketSend(byte id, uint len = 0, Priority priority = PRI_NORMAL); PacketSend(const PacketSend* other); - virtual ~PacketSend() { }; + virtual ~PacketSend(); private: PacketSend& operator=(const PacketSend& other); @@ -199,14 +199,13 @@ class PacketSend : public Packet class PacketTransaction { protected: - PacketTransaction(void) { }; + PacketTransaction(void) = default; -private: - PacketTransaction(const PacketTransaction& copy); - PacketTransaction& operator=(const PacketTransaction& other); + PacketTransaction(const PacketTransaction& copy) = delete; + PacketTransaction& operator=(const PacketTransaction& other) = delete; public: - virtual ~PacketTransaction(void) { }; + virtual ~PacketTransaction(void); virtual PacketSend* front(void) = 0; // get first packet in the transaction virtual void pop(void) = 0; // remove first packet from the transaction @@ -232,11 +231,10 @@ class SimplePacketTransaction : public PacketTransaction public: explicit SimplePacketTransaction(PacketSend* packet) : m_packet(packet) { }; - ~SimplePacketTransaction(void); + virtual ~SimplePacketTransaction(void); -private: - SimplePacketTransaction(const SimplePacketTransaction& copy); - SimplePacketTransaction& operator=(const SimplePacketTransaction& other); + SimplePacketTransaction(const SimplePacketTransaction& copy) = delete; + SimplePacketTransaction& operator=(const SimplePacketTransaction& other) = delete; public: CNetState* getTarget(void) const { return m_packet->getTarget(); } diff --git a/src/network/receive.cpp b/src/network/receive.cpp index b62668f57..53f75dc37 100644 --- a/src/network/receive.cpp +++ b/src/network/receive.cpp @@ -3293,7 +3293,7 @@ bool PacketGargoyleFly::onReceive(CNetState* net) if ( IsTrigUsed(TRIGGER_TOGGLEFLYING) ) { - if ( character->OnTrigger(CTRIG_ToggleFlying,character,0) == TRIGRET_RET_TRUE ) + if ( character->OnTrigger(CTRIG_ToggleFlying, character, nullptr) == TRIGRET_RET_TRUE ) return false; } diff --git a/src/network/send.cpp b/src/network/send.cpp index d20e2e8fa..10feaab7c 100644 --- a/src/network/send.cpp +++ b/src/network/send.cpp @@ -23,8 +23,9 @@ #include "CNetworkManager.h" #include "send.h" +namespace zlib { #include - +} /*************************************************************************** * @@ -1835,6 +1836,9 @@ PacketActionBasic::PacketActionBasic(const CChar* character, ANIM_TYPE_NEW actio writeByte(variation); } +PacketAction::~PacketAction() = default; +PacketActionBasic::~PacketActionBasic() = default; + /*************************************************************************** * * @@ -1850,6 +1854,8 @@ PacketTradeAction::PacketTradeAction(SECURE_TRADE_TYPE action) : PacketSend(XCMD writeByte((byte)action); } +PacketTradeAction::~PacketTradeAction() = default; + void PacketTradeAction::prepareContainerOpen(const CChar *character, const CItem *container1, const CItem *container2) { ADDTOCALLSTACK("PacketTradeAction::prepareContainerOpen"); @@ -3615,10 +3621,10 @@ void PacketGumpDialog::writeCompressedControls(std::vector const* cont ASSERT(controlLengthCurrent == controlLength); - uLong compressLength = ::compressBound(controlLengthCurrent); + zlib::uLong compressLength = zlib::compressBound(controlLengthCurrent); byte* compressBuffer = new byte[compressLength]; - int error = ::compress2(compressBuffer, &compressLength, (byte*)toCompress, controlLengthCurrent, Z_DEFAULT_COMPRESSION); + int error = zlib::compress2(compressBuffer, &compressLength, (byte*)toCompress, controlLengthCurrent, Z_DEFAULT_COMPRESSION); delete[] toCompress; if (error != Z_OK || compressLength <= 0) @@ -3653,10 +3659,10 @@ void PacketGumpDialog::writeCompressedControls(std::vector const* cont uint textsLength = getPosition() - textsPosition; - uLong compressLength = ::compressBound((uLong)textsLength); + zlib::uLong compressLength = zlib::compressBound((zlib::uLong)textsLength); byte* compressBuffer = new byte[compressLength]; - int error = ::compress2(compressBuffer, &compressLength, &m_buffer[textsPosition], (uLong)textsLength, Z_DEFAULT_COMPRESSION); + int error = zlib::compress2(compressBuffer, &compressLength, &m_buffer[textsPosition], (zlib::uLong)textsLength, Z_DEFAULT_COMPRESSION); if (error != Z_OK || compressLength <= 0) { delete[] compressBuffer; @@ -4790,10 +4796,10 @@ bool PacketHouseDesign::writePlaneData(int plane, int itemCount, byte* data, int ADDTOCALLSTACK("PacketHouseDesign::writePlaneData"); // compress data - uLong compressLength = ::compressBound(dataSize); + zlib::uLong compressLength = zlib::compressBound(dataSize); byte* compressBuffer = new byte[compressLength]; - int error = ::compress2(compressBuffer, &compressLength, data, dataSize, Z_DEFAULT_COMPRESSION); + int error = zlib::compress2(compressBuffer, &compressLength, data, dataSize, Z_DEFAULT_COMPRESSION); if ( error != Z_OK ) { // an error occured with this floor, but we should be able to continue to the next without problems @@ -4851,10 +4857,10 @@ void PacketHouseDesign::flushStairData(void) m_stairCount = 0; // compress data - uLong compressLength = ::compressBound(stairSize); + zlib::uLong compressLength = zlib::compressBound(stairSize); byte* compressBuffer = new byte[compressLength]; - int error = ::compress2(compressBuffer, &compressLength, (byte*)m_stairBuffer, stairSize, Z_DEFAULT_COMPRESSION); + int error = zlib::compress2(compressBuffer, &compressLength, (byte*)m_stairBuffer, stairSize, Z_DEFAULT_COMPRESSION); if ( error != Z_OK ) { // an error occured with this block, but we should be able to continue to the next without problems diff --git a/src/network/send.h b/src/network/send.h index 6ccd94566..ddb041f44 100644 --- a/src/network/send.h +++ b/src/network/send.h @@ -31,6 +31,14 @@ class CItemShip; class CClientTooltip; +// TODO: define the virtual destructor of each class with virtual methods in the .cpp file. +// Not doing that makes the compiler emit the virtual table (vtable) in every translation unit, instead +// of having that only in one .cpp file (translation unit) -> the one file where we define the destructor or at least one virtual method. +#ifdef __clang__ + #pragma GCC diagnostic push + #pragma GCC diagnostic ignored "-Wweak-vtables" +#endif + /*************************************************************************** * * @@ -664,12 +672,14 @@ class PacketAction : public PacketSend { public: PacketAction(const CChar* character, ANIM_TYPE action, word repeat, bool backward, byte delay, byte len); + virtual ~PacketAction(); }; class PacketActionBasic : public PacketSend { public: PacketActionBasic(const CChar* character, ANIM_TYPE_NEW action, ANIM_TYPE_NEW subaction, byte variation); + virtual ~PacketActionBasic(); }; /*************************************************************************** @@ -683,6 +693,7 @@ class PacketTradeAction : public PacketSend { public: PacketTradeAction(SECURE_TRADE_TYPE action); + ~PacketTradeAction(); void prepareContainerOpen(const CChar *character, const CItem *container1, const CItem *container2); void prepareReadyChange(const CItemContainer *container1, const CItemContainer *container2); void prepareClose(const CItemContainer *container); @@ -2074,5 +2085,9 @@ class PacketGlobalChat : public PacketSend } }; +#ifdef __clang__ + #pragma GCC diagnostic pop +#endif + #endif // _INC_SEND_H diff --git a/src/sphere/UnixTerminal.cpp b/src/sphere/UnixTerminal.cpp index 4673e7641..d8031e3e2 100644 --- a/src/sphere/UnixTerminal.cpp +++ b/src/sphere/UnixTerminal.cpp @@ -74,7 +74,7 @@ bool UnixTerminal::isReady() tvTimeout.tv_sec = 0; tvTimeout.tv_usec = 1; - if (select(1, &consoleFds, 0, 0, &tvTimeout) <= 0) + if (select(1, &consoleFds, nullptr, nullptr, &tvTimeout) <= 0) return false; // get next character diff --git a/src/sphere/threads.cpp b/src/sphere/threads.cpp index 1ecfd5f85..414c4c7f1 100644 --- a/src/sphere/threads.cpp +++ b/src/sphere/threads.cpp @@ -53,6 +53,12 @@ struct TemporaryStringThreadSafeStateHolder } }; +IThread::IThread() noexcept : + m_threadSystemId(0), m_threadHolderId(-1) + { }; + +// This is needed to prevent weak-vtables warning (puts the vtable in this translation unit instead of every translation unit) +IThread::~IThread() noexcept = default; #ifdef _WIN32 #pragma pack(push, 8) @@ -492,7 +498,8 @@ void AbstractThread::terminate(bool ended) #ifdef _WIN32 _endthreadex(EXIT_SUCCESS); #else - pthread_exit(EXIT_SUCCESS); + //exit(EXIT_SUCCESS) + pthread_exit(nullptr); #endif } } @@ -604,7 +611,11 @@ SPHERE_THREADENTRY_RETNTYPE AbstractThread::runner(void *callerThread) caller->terminate(true); } - return 0; +#ifdef _WIN32 + return 0; +#else + return nullptr; +#endif } bool AbstractThread::isActive() const diff --git a/src/sphere/threads.h b/src/sphere/threads.h index 2c61f6318..e8b305d94 100644 --- a/src/sphere/threads.h +++ b/src/sphere/threads.h @@ -153,6 +153,9 @@ class IThread Disabled = 0xFF // tick never }; + IThread() noexcept; + virtual ~IThread() noexcept; + virtual threadid_t getId() const = 0; virtual const char *getName() const = 0; @@ -198,10 +201,6 @@ class IThread protected: virtual bool shouldExit() noexcept = 0; - -public: - IThread() noexcept : m_threadSystemId(0), m_threadHolderId(-1) { }; - virtual ~IThread() = default; }; From 29e62c1d726b6b96baa83ead6463cde903a607a9 Mon Sep 17 00:00:00 2001 From: cbnolok Date: Fri, 13 Sep 2024 11:38:12 +0200 Subject: [PATCH 35/86] Added .clangd and CMAKE_EXPORT_COMPILE_COMMANDS option. --- .clangd | 12 ++++++++++++ CMakeLists.txt | 5 +++++ 2 files changed, 17 insertions(+) create mode 100644 .clangd diff --git a/.clangd b/.clangd new file mode 100644 index 000000000..f72b2a4c5 --- /dev/null +++ b/.clangd @@ -0,0 +1,12 @@ +CompileFlags: + Add: + - -I!.codelite + - -I!.ctagsd + - -I!.git + - -I!.github + - -I!.kdev4 + - -I!.vscode + - -I!build + - -I!cmake + - -I!lib + - -I!utilities diff --git a/CMakeLists.txt b/CMakeLists.txt index 50dfda537..1eaa86083 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -15,6 +15,11 @@ option( "Statically link inside the executable the runtime libraries? (MSVC, libc/libcc, libstdc++)." FALSE ) +option( + CMAKE_EXPORT_COMPILE_COMMANDS + "Export compiler commands to compile_commands.json" + TRUE +) set(predef_LIB_LIBEV_BUILD FALSE) if(NOT WIN32) From 1291c44e9dc06592587dee35bd1525d4f8ad4751 Mon Sep 17 00:00:00 2001 From: cbnolok Date: Fri, 13 Sep 2024 17:45:12 +0200 Subject: [PATCH 36/86] Fixed: When acquiring a new pet follower, CurFollower incremented by 1 regardless of pet's FollowerSlots value (Issue #1251). Fixed: dynamic FOLLOWERSLOTS property wasn't correctly saved and loaded from a worldsave. Added: FOLLOWER. to reference char followers. Reverted a change on UnixTerminal which caused typed chars showing with some lag. --- Changelog.txt | 7 +- src/game/CObjBase.cpp | 2 - src/game/CTimedFunctionHandler.h | 1 + src/game/CWorldTicker.h | 6 +- src/game/chars/CChar.cpp | 274 +++++++++++++++----------- src/game/chars/CChar.h | 12 +- src/game/chars/CCharNPC.cpp | 10 +- src/game/chars/CCharNPCAct_Vendor.cpp | 2 +- src/game/chars/CCharNPCPet.cpp | 30 +-- src/game/chars/CCharSkill.cpp | 2 +- src/game/chars/CCharSpell.cpp | 2 +- src/game/chars/CCharUse.cpp | 80 +++++--- src/game/clients/CClientEvent.cpp | 1 - src/game/clients/CClientTarg.cpp | 2 +- src/network/send.cpp | 5 +- src/sphere/UnixTerminal.cpp | 2 +- src/tables/CCharNpc_props.tbl | 1 - src/tables/CChar_props.tbl | 1 + 18 files changed, 256 insertions(+), 184 deletions(-) diff --git a/Changelog.txt b/Changelog.txt index 027ff84ef..05f4a6c19 100644 --- a/Changelog.txt +++ b/Changelog.txt @@ -3876,7 +3876,7 @@ Added: 'H' shortcut for variables to get the value as hexadecimal. - Added: log message when a new thread is created or a thread is being renamed. 10-09-2024, Nolok -Updated: f_onserver_connectreq_ex now is called whenever an ini connection limit is exceeded (pings, max connections...). +- Updated: f_onserver_connectreq_ex now is called whenever an ini connection limit is exceeded (pings, max connections...). Now it stores these parameters: - ARGS = IP address - LOCAL.TIME_CUR_CONNECTED_MS (RO) = Monotonic system time when this connection request was handled (milliseconds) @@ -3890,3 +3890,8 @@ Updated: f_onserver_connectreq_ex now is called whenever an ini connection limit RETURN -1: Don't do anything, let the connection pass. RETURN 1: Only reject the connection. RETURN 2: Reject and ban the IP for seconds. + +13-09-2024, Nolok +- Fixed: When acquiring a new pet follower, CurFollower incremented by 1 regardless of pet's FollowerSlots value (Issue #1251). +- Fixed: dynamic FOLLOWERSLOTS property wasn't correctly saved and loaded from a worldsave. +- Added: FOLLOWER. to reference char followers. diff --git a/src/game/CObjBase.cpp b/src/game/CObjBase.cpp index ce66c5612..6086b849c 100644 --- a/src/game/CObjBase.cpp +++ b/src/game/CObjBase.cpp @@ -9,7 +9,6 @@ #include "chars/CChar.h" #include "clients/CClient.h" #include "components/CCChampion.h" -#include "components/CCPropsItemChar.h" #include "components/CCPropsItemWeapon.h" #include "components/CCSpawn.h" #include "components/CCItemDamageable.h" @@ -21,7 +20,6 @@ #include "CWorldTickingList.h" #include "CWorldTimedFunctions.h" #include "CTimedFunction.h" -#include "spheresvr.h" #include "triggers.h" #include "CObjBase.h" diff --git a/src/game/CTimedFunctionHandler.h b/src/game/CTimedFunctionHandler.h index 4651df052..f877512e0 100644 --- a/src/game/CTimedFunctionHandler.h +++ b/src/game/CTimedFunctionHandler.h @@ -8,6 +8,7 @@ #include "../common/sphere_library/CSObjCont.h" #include "../common/CScriptContexts.h" +#include "../common/CScriptObj.h" #include "CTimedFunction.h" diff --git a/src/game/CWorldTicker.h b/src/game/CWorldTicker.h index b78a95c4e..8509489b7 100644 --- a/src/game/CWorldTicker.h +++ b/src/game/CWorldTicker.h @@ -7,7 +7,6 @@ #include "CTimedFunctionHandler.h" #include "CTimedObject.h" -#include /* Include phmap.h */ #ifdef ADDRESS_SANITIZER @@ -15,6 +14,7 @@ #endif #ifdef _WIN32 + #define MYSRWLOCK_ #undef SRWLOCK_INIT #endif #ifdef __GNUC__ @@ -25,9 +25,13 @@ // TODO: undef is TEMPORARY !! There's a bug that needs to be solved #undef ADDRESS_SANITIZER #include + #ifdef MYASAN_ #define ADDRESS_SANITIZER #endif +#ifdef MYSRWLOCK_ +# define SRWLOCK_INIT +#endif #ifdef __GNUC__ #pragma GCC diagnostic pop diff --git a/src/game/chars/CChar.cpp b/src/game/chars/CChar.cpp index c4815c878..f53797d4a 100644 --- a/src/game/chars/CChar.cpp +++ b/src/game/chars/CChar.cpp @@ -5,7 +5,6 @@ #include "../../common/CUID.h" #include "../../common/CRect.h" #include "../../common/CLog.h" -#include "../../sphere/ProfileTask.h" #include "../clients/CAccount.h" #include "../clients/CClient.h" #include "../items/CItem.h" @@ -23,7 +22,6 @@ #include "../CWorldGameTime.h" #include "../CWorldMap.h" #include "../CWorldTickingList.h" -#include "../spheresvr.h" #include "../triggers.h" #include "CChar.h" #include "CCharBase.h" @@ -1247,7 +1245,7 @@ bool CChar::DupeFrom(const CChar * pChar, bool fNewbieItems ) pItem->m_uidLink = myUID; //If the character being duped has an item which linked to himself, set the newly duped character link instead. else if (IsSetOF(OF_PetSlots) && pItem->IsMemoryTypes(MEMORY_IPET) && pTest3 == NPC_PetGetOwner()) { - const short iFollowerSlots = n64_narrow_n16(GetDefNum("FOLLOWERSLOTS", true, 1)); + const short iFollowerSlots = GetFollowerSlots(); //If we have reached the maximum follower slots we remove the ownership of the pet by clearing the memory flag instead of using NPC_PetClearOwners(). if (!pTest3->FollowersUpdate(this, maximum(0, iFollowerSlots))) Memory_ClearTypes(MEMORY_IPET); @@ -2306,6 +2304,23 @@ bool CChar::r_WriteVal( lpctstr ptcKey, CSString & sVal, CTextConsole * pSrc, bo if ( iKeyNum < 0 ) { do_default: + + if (!strnicmp("FOLLOWER", ptcKey, 8)) + { + if (ptcKey[8] == '.') + { + ptcKey += 9; + const uint uiIndex = Exp_GetUVal(ptcKey); + if (uiIndex >= m_followers.size()) + return false; + + CChar* pCharArg = CUID::CharFindFromUID(m_followers[uiIndex].uid); + ASSERT(pCharArg); + if (pCharArg->r_WriteVal(ptcKey, sVal, pSrc, fNoCallParent, fNoCallChildren)) + return true; + } + } + if ( m_pPlayer ) { if ( m_pPlayer->r_WriteVal( this, ptcKey, sVal )) @@ -2338,43 +2353,44 @@ bool CChar::r_WriteVal( lpctstr ptcKey, CSString & sVal, CTextConsole * pSrc, bo CChar * pCharSrc = pSrc->GetChar(); switch ( iKeyNum ) { + case CHC_FOLLOWERSLOTS: + sVal.FormatLLVal(GetFollowerSlots()); + break; + //return as decimal number or 0 if not set case CHC_CURFOLLOWER: { - if (!IsSetEF(EF_FollowerList)) //Using an old system? - { - sVal.FormatLLVal(GetDefNum(ptcKey,false)); - } - else - { - if (strlen(ptcKey) == 11) - { - sVal.FormatULLVal(m_followers.size()); - return true; - } - sVal.FormatVal(0); - ptcKey += 11; - if (*ptcKey == '.') - { - ++ptcKey; - if (!m_followers.empty()) - { - int iIndex = std::max((int)0, Exp_GetVal(ptcKey)); - SKIP_SEPARATORS(ptcKey); - if (iIndex < (int)m_followers.size()) - { - if ((!strnicmp(ptcKey, "UID", 3)) || (*ptcKey == '\0')) - { - CUID uid = m_followers[iIndex]; - sVal.FormatHex(uid.CharFind() ? (dword)uid : 0); - return true; - } - } - } - } - } - return true; - } + if (!IsSetEF(EF_FollowerList)) //Using an old system? + { + sVal.FormatLLVal(GetDefNum(ptcKey,false)); + return true; + } + + if (strlen(ptcKey) == 11) + { + sVal.FormatSVal(GetCurFollowers()); + return true; + } + + sVal.FormatVal(0); + ptcKey += 11; + if (*ptcKey == '.' && !m_followers.empty()) + { + ++ptcKey; + int iIndex = std::max((int)0, Exp_GetVal(ptcKey)); + SKIP_SEPARATORS(ptcKey); + if (iIndex < (int)m_followers.size()) + { + if ((!strnicmp(ptcKey, "UID", 3)) || (*ptcKey == '\0')) + { + CUID const& uid = m_followers[iIndex].uid; + sVal.FormatHex(uid.CharFind() ? (dword)uid : 0); + return true; + } + } + } + return true; + } //On these ones, check BaseDef if not found on dynamic case CHC_MAXFOLLOWER: case CHC_SPELLTIMEOUT: @@ -3346,20 +3362,45 @@ bool CChar::r_LoadVal( CScript & s ) EXC_SET_BLOCK("Keyword"); lpctstr ptcKey = s.GetKey(); - if (!strnicmp("FOLLOWER", ptcKey, 8)) - { - if (ptcKey[8] == '.') - { - ptcKey = ptcKey + 4; - CUID ptcArg = CUID(s.GetArgDWVal()); - m_followers.emplace_back(ptcArg); - return true; - } - } - CHC_TYPE iKeyNum = (CHC_TYPE) FindTableHeadSorted( ptcKey, sm_szLoadKeys, ARRAY_COUNT( sm_szLoadKeys )-1 ); if ( iKeyNum < 0 ) { + if (!strnicmp("FOLLOWER", ptcKey, 8)) + { + if (ptcKey[8] == '.') + { + ptcKey += 9; + // I'm probably loading from a save, or that's a very weird way to add a follower... + // Anyways, i expect the followers to be passed with sequential incremental ids: 0, 1, 2... Not random order. + const uint uiIndex = Exp_GetUVal(ptcKey); + if (uiIndex != m_followers.size()) + return false; + + const CUID uidPet(Exp_GetDWVal(ptcKey)); + const CChar* pCharPet = uidPet.CharFind(); + if (!pCharPet) + return false; + + const bool fExists = + !m_followers.empty() && + m_followers.end() != + std::find_if(m_followers.begin(), m_followers.end(), + [&uidPet](auto const& inp_struct) -> bool { + return inp_struct.uid == uidPet; + }); + if (fExists) + return false; + + m_followers.emplace_back( + FollowerCharData { + .uid = uidPet, + .followerslots = pCharPet->GetFollowerSlots() + }); + + return true; + } + } + if ( m_pPlayer ) { if ( m_pPlayer->r_LoadVal( this, s )) @@ -3422,68 +3463,68 @@ bool CChar::r_LoadVal( CScript & s ) Stats_SetRegenVal(STAT_FOOD, s.GetArgUSVal()); break; + case CHC_FOLLOWERSLOTS: + SetDefNum(s.GetKey(), s.GetArgVal(), false ); + break; + case CHC_CURFOLLOWER: if (!IsSetEF(EF_FollowerList)) { - SetDefNum(s.GetKey(), s.GetArgLLVal(), false); + SetDefNum(s.GetKey(), s.GetArgSVal(), false); UpdateStatsFlag(); break; } - else - { - if (strlen(ptcKey) > 11) - { - ptcKey += 11; - if (*ptcKey == '.') - { - ++ptcKey; - if (!strnicmp(ptcKey, "CLEAR", 5)) - { - if (!m_followers.empty()) - m_followers.clear(); - UpdateStatsFlag(); - return true; - } - else if (!strnicmp(ptcKey, "DELETE", 6) || !strnicmp(ptcKey, "DEL", 3)) - { - if (!m_followers.empty()) - { - CUID uid = (CUID)s.GetArgDWVal(); - for (std::vector::iterator it = m_followers.begin(); it != m_followers.end(); ) - { - if (uid == *it) - it = m_followers.erase(it); - else - ++it; - } - } - return true; - } - else if (!strnicmp(ptcKey, "ADD", 3)) - { - bool fExists = false; - CUID uid = (CUID)s.GetArgDWVal(); - if (!m_followers.empty()) - { - for (std::vector::iterator it = m_followers.begin(); it != m_followers.end(); ) - { - if (uid == *it) - { - fExists = true; - break; - } - else - ++it; - } - } - if (!fExists) - m_followers.emplace_back(uid); - return true; - } - } - } - } + if (strlen(ptcKey) < 12) + return false; + + ptcKey += 11; + if (*ptcKey != '.') + return false; + + ++ptcKey; + if (!strnicmp(ptcKey, "CLEAR", 5)) + { + if (!m_followers.empty()) + m_followers.clear(); + UpdateStatsFlag(); + return true; + } + else if (!strnicmp(ptcKey, "DELETE", 6) || !strnicmp(ptcKey, "DEL", 3)) + { + if (!m_followers.empty()) + { + const CUID uid(s.GetArgDWVal()); + std::erase_if(m_followers, + [&uid](auto const& inp_struct) -> bool + { + return inp_struct.uid == uid; + }); + } + return true; + } + else if (!strnicmp(ptcKey, "ADD", 3)) + { + const CUID uid(s.GetArgDWVal()); + const bool fExists = + !m_followers.empty() && + m_followers.end() != + std::find_if(m_followers.begin(), m_followers.end(), + [&uid](auto const& inp_struct) -> bool { + return inp_struct.uid == uid; + }); + if (!fExists) + { + const CChar* pCharPet = uid.CharFind(); + ASSERT(pCharPet); + m_followers.emplace_back( + FollowerCharData{ + .uid = uid, + .followerslots = pCharPet->GetFollowerSlots() + }); + } + return true; + } return false; case CHC_MAXFOLLOWER: case CHC_TITHING: @@ -3977,11 +4018,12 @@ void CChar::r_Write( CScript & s ) CObjBase::r_Write(s); - for (CUID uid : m_followers) { - dword dUID = (dword)uid; + for (uint i = 0; auto const& fdata : m_followers) { + dword dUID = (dword)fdata.uid; char *pszTag = Str_GetTemp(); - snprintf(pszTag, Str_TempLength(), "FOLLOWER.%d", dUID); + snprintf(pszTag, Str_TempLength(), "FOLLOWER.%u", i); s.WriteKeyHex(pszTag, dUID); + ++ i; } if (iValLastHit != 0) @@ -4244,7 +4286,7 @@ bool CChar::r_Verb( CScript &s, CTextConsole * pSrc ) // Execute command from sc EXC_TRY("Verb"); if ( IsClientActive() && GetClientActive()->r_Verb(s, pSrc) ) - return true; + return true; if (CEntity::r_Verb(s, pSrc)) { @@ -4277,7 +4319,7 @@ bool CChar::r_Verb( CScript &s, CTextConsole * pSrc ) // Execute command from sc fMode = args.m_iN2 > 0 ? true : false; if (iRet == TRIGRET_RET_TRUE) //Block AFK mode switching if RETURN 1 in Trigger. - return true; + break; } if ( fMode != fAFK ) @@ -4377,10 +4419,10 @@ bool CChar::r_Verb( CScript &s, CTextConsole * pSrc ) // Execute command from sc break; case CHV_CURE: { - bool bCureHallucination = false; + bool fCureHallucination = false; if (s.HasArgs()) - bCureHallucination = (bool)s.GetArgVal(); - SetPoisonCure(bCureHallucination); + fCureHallucination = (bool)s.GetArgVal(); + SetPoisonCure(fCureHallucination); } break; case CHV_DISCONNECT: @@ -4418,7 +4460,7 @@ bool CChar::r_Verb( CScript &s, CTextConsole * pSrc ) // Execute command from sc pItem->SetAttr(ATTR_MOVE_NEVER); LayerAdd( pItem, LAYER_HAND2 ); } - return true; + break; case CHV_EQUIPARMOR: return ItemEquipArmor(false); case CHV_EQUIPWEAPON: @@ -4431,7 +4473,7 @@ bool CChar::r_Verb( CScript &s, CTextConsole * pSrc ) // Execute command from sc if (*pszVerbArg == '\0') { UpdateDir(dynamic_cast(pCharSrc)); - return true; + break; } else if (IsStrNumeric(pszVerbArg)) { @@ -4439,7 +4481,7 @@ bool CChar::r_Verb( CScript &s, CTextConsole * pSrc ) // Execute command from sc if (pTowards != nullptr) { UpdateDir(pTowards); - return true; + break; } } else @@ -4449,7 +4491,7 @@ bool CChar::r_Verb( CScript &s, CTextConsole * pSrc ) // Execute command from sc if (pt.IsValidPoint()) { UpdateDir(pt); - return true; + break; } } return false; @@ -4484,7 +4526,7 @@ bool CChar::r_Verb( CScript &s, CTextConsole * pSrc ) // Execute command from sc return false; pObj = pObj->GetTopLevelObj(); Spell_Teleport( pObj->GetTopPoint(), true, false ); - return true; + break; } return false; case CHV_HEAR: diff --git a/src/game/chars/CChar.h b/src/game/chars/CChar.h index ed13ffd9a..9855a0235 100644 --- a/src/game/chars/CChar.h +++ b/src/game/chars/CChar.h @@ -205,8 +205,12 @@ class CChar : public CObjBase, public CContainer, public CTextConsole ushort _uiRange; - - std::vector m_followers; + struct FollowerCharData + { + CUID uid; + short followerslots; + }; + std::vector m_followers; // Args related to specific actions type (m_Act_SkillCurrent) union @@ -1155,7 +1159,9 @@ public: void StatFlag_Mod(uint64 uiStatFlag, bool fMod) noexcept; CChar * Use_Figurine( CItem * pItem, bool fCheckFollowerSlots = true ); CItem * Make_Figurine( const CUID &uidOwner, ITEMID_TYPE id = ITEMID_NOTHING ); CItem * NPC_Shrink(); - bool FollowersUpdate( CChar * pChar, short iFollowerSlots = 0, bool fCheckOnly = false ); + bool FollowersUpdate(CChar * pCharPet, short iPetFollowerSlots = 0, bool fCheckOnly = false ); + short GetFollowerSlots() const; + short GetCurFollowers() const; int ItemPickup( CItem * pItem, word amount ); bool ItemEquip( CItem * pItem, CChar * pCharMsg = nullptr, bool fFromDClick = false ); diff --git a/src/game/chars/CCharNPC.cpp b/src/game/chars/CCharNPC.cpp index 3e1d850fa..5782c5ce6 100644 --- a/src/game/chars/CCharNPC.cpp +++ b/src/game/chars/CCharNPC.cpp @@ -58,9 +58,7 @@ CCharNPC::CCharNPC( CChar * pChar, NPCBRAIN_TYPE NPCBrain ) m_timeRestock = 0; } -CCharNPC::~CCharNPC() -{ -} +CCharNPC::~CCharNPC() = default; bool CCharNPC::r_LoadVal( CChar * pChar, CScript &s ) { @@ -83,9 +81,6 @@ bool CCharNPC::r_LoadVal( CChar * pChar, CScript &s ) if ( !g_Serv.IsLoading() ) pChar->UpdatePropertyFlag(); break; - case CNC_FOLLOWERSLOTS: - pChar->SetDefNum(s.GetKey(), s.GetArgVal(), false ); - break; case CNC_ACTPRI: m_Act_Motivation = (uchar)(s.GetArgVal()); break; @@ -167,9 +162,6 @@ bool CCharNPC::r_WriteVal( CChar * pChar, lpctstr ptcKey, CSString & sVal ) case CNC_BONDED: sVal.FormatVal( m_bonded ); break; - case CNC_FOLLOWERSLOTS: - sVal.FormatLLVal(pChar->GetDefNum(ptcKey, true)); - break; case CNC_ACTPRI: sVal.FormatVal( m_Act_Motivation ); break; diff --git a/src/game/chars/CCharNPCAct_Vendor.cpp b/src/game/chars/CCharNPCAct_Vendor.cpp index e5e83ad24..5c183fedf 100644 --- a/src/game/chars/CCharNPCAct_Vendor.cpp +++ b/src/game/chars/CCharNPCAct_Vendor.cpp @@ -203,7 +203,7 @@ bool CChar::NPC_StablePetRetrieve( CChar * pCharPlayer ) pItem->Delete(); if (IsSetOF(OF_PetSlots)) { - const short iFollowerSlots = (short)pPet->GetDefNum("FOLLOWERSLOTS", true, 1); + const short iFollowerSlots = GetFollowerSlots(); pCharPlayer->FollowersUpdate(pPet, (maximum(0, iFollowerSlots)), false); } ++iCount; diff --git a/src/game/chars/CCharNPCPet.cpp b/src/game/chars/CCharNPCPet.cpp index 9a49405af..c4e64aec0 100644 --- a/src/game/chars/CCharNPCPet.cpp +++ b/src/game/chars/CCharNPCPet.cpp @@ -423,7 +423,7 @@ bool CChar::NPC_OnHearPetCmdTarg( int iCmd, CChar *pSrc, CObjBase *pObj, const C return true; } - bool bSuccess = false; + bool fSuccess = false; CItem *pItemTarg = dynamic_cast(pObj); CChar *pCharTarg = dynamic_cast(pObj); @@ -434,9 +434,9 @@ bool CChar::NPC_OnHearPetCmdTarg( int iCmd, CChar *pSrc, CObjBase *pObj, const C { if ( !pCharTarg || pCharTarg == pSrc || pCharTarg == this ) break; - bSuccess = pCharTarg->OnAttackedBy(pSrc, true); // we know who told them to do this. - if ( bSuccess ) - bSuccess = Fight_Attack(pCharTarg, true); + fSuccess = pCharTarg->OnAttackedBy(pSrc, true); // we know who told them to do this. + if ( fSuccess ) + fSuccess = Fight_Attack(pCharTarg, true); break; } @@ -444,7 +444,7 @@ bool CChar::NPC_OnHearPetCmdTarg( int iCmd, CChar *pSrc, CObjBase *pObj, const C if ( !pCharTarg ) break; m_Act_UID = pCharTarg->GetUID(); - bSuccess = Skill_Start(NPCACT_FOLLOW_TARG); + fSuccess = Skill_Start(NPCACT_FOLLOW_TARG); break; case PC_FRIEND: @@ -465,7 +465,7 @@ bool CChar::NPC_OnHearPetCmdTarg( int iCmd, CChar *pSrc, CObjBase *pObj, const C Memory_AddObjTypes(pCharTarg, MEMORY_FRIEND); m_Act_UID = pCharTarg->GetUID(); - bSuccess = Skill_Start(NPCACT_FOLLOW_TARG); + fSuccess = Skill_Start(NPCACT_FOLLOW_TARG); break; } @@ -487,7 +487,7 @@ bool CChar::NPC_OnHearPetCmdTarg( int iCmd, CChar *pSrc, CObjBase *pObj, const C pMemory->Delete(); m_Act_UID = pSrc->GetUID(); - bSuccess = Skill_Start(NPCACT_FOLLOW_TARG); + fSuccess = Skill_Start(NPCACT_FOLLOW_TARG); break; } @@ -495,7 +495,7 @@ bool CChar::NPC_OnHearPetCmdTarg( int iCmd, CChar *pSrc, CObjBase *pObj, const C if ( !pt.IsValidPoint() ) break; m_Act_p = pt; - bSuccess = Skill_Start(NPCACT_GOTO); + fSuccess = Skill_Start(NPCACT_GOTO); break; case PC_GUARD: @@ -503,7 +503,7 @@ bool CChar::NPC_OnHearPetCmdTarg( int iCmd, CChar *pSrc, CObjBase *pObj, const C break; pCharTarg->SysMessagef(g_Cfg.GetDefaultMsg(DEFMSG_NPC_PET_TARG_GUARD_SUCCESS), GetName()); m_Act_UID = pCharTarg->GetUID(); - bSuccess = Skill_Start(NPCACT_GUARD_TARG); + fSuccess = Skill_Start(NPCACT_GUARD_TARG); break; case PC_TRANSFER: @@ -511,14 +511,14 @@ bool CChar::NPC_OnHearPetCmdTarg( int iCmd, CChar *pSrc, CObjBase *pObj, const C break; if ( IsSetOF(OF_PetSlots) ) { - short iFollowerSlots = (short)GetDefNum("FOLLOWERSLOTS", true, 1); + short iFollowerSlots = GetFollowerSlots(); if ( !pCharTarg->FollowersUpdate(this, (maximum(0, iFollowerSlots)), true) ) { pSrc->SysMessageDefault(DEFMSG_PETSLOTS_TRY_TRANSFER); break; } } - bSuccess = NPC_PetSetOwner( pCharTarg ); + fSuccess = NPC_PetSetOwner( pCharTarg ); break; case PC_PRICE: // "PRICE" the vendor item. @@ -536,8 +536,8 @@ bool CChar::NPC_OnHearPetCmdTarg( int iCmd, CChar *pSrc, CObjBase *pObj, const C } // Make some sound to confirm we heard it - NPC_OnPetCommand(bSuccess, pSrc); - return bSuccess; + NPC_OnPetCommand(fSuccess, pSrc); + return fSuccess; } void CChar::NPC_PetClearOwners() @@ -583,7 +583,7 @@ void CChar::NPC_PetClearOwners() if ( pOwner && IsSetOF(OF_PetSlots) ) { - short iFollowerSlots = (short)GetDefNum("FOLLOWERSLOTS", true, 1); + short iFollowerSlots = GetFollowerSlots(); pOwner->FollowersUpdate(this, -maximum(0, iFollowerSlots)); } } @@ -617,7 +617,7 @@ bool CChar::NPC_PetSetOwner( CChar * pChar ) if ( IsSetOF(OF_PetSlots) ) { - const short iFollowerSlots = (short)GetDefNum("FOLLOWERSLOTS", true, 1); + const short iFollowerSlots = GetFollowerSlots(); pChar->FollowersUpdate(this, maximum(0, iFollowerSlots)); } diff --git a/src/game/chars/CCharSkill.cpp b/src/game/chars/CCharSkill.cpp index 4ee5a9147..36dd42087 100644 --- a/src/game/chars/CCharSkill.cpp +++ b/src/game/chars/CCharSkill.cpp @@ -2277,7 +2277,7 @@ int CChar::Skill_Taming( SKTRIG_TYPE stage ) if (IsSetOF(OF_PetSlots)) { - short iFollowerSlots = (short)pChar->GetDefNum("FOLLOWERSLOTS", true, 1); + short iFollowerSlots = GetFollowerSlots(); if (!FollowersUpdate(pChar, maximum(0, iFollowerSlots), true)) { SysMessageDefault(DEFMSG_PETSLOTS_TRY_TAMING); diff --git a/src/game/chars/CCharSpell.cpp b/src/game/chars/CCharSpell.cpp index b972ae6b1..256711dd2 100644 --- a/src/game/chars/CCharSpell.cpp +++ b/src/game/chars/CCharSpell.cpp @@ -2613,7 +2613,7 @@ CChar * CChar::Spell_Summon_Try(SPELL_TYPE spell, CPointMap ptTarg, CREID_TYPE u if (IsSetOF(OF_PetSlots)) { - short iFollowerSlots = (short)pChar->GetDefNum("FOLLOWERSLOTS", true, 1); + short iFollowerSlots = GetFollowerSlots(); if (!FollowersUpdate(pChar, maximum(0, iFollowerSlots), true)) { SysMessageDefault(DEFMSG_PETSLOTS_TRY_SUMMON); diff --git a/src/game/chars/CCharUse.cpp b/src/game/chars/CCharUse.cpp index 1dc98f43d..a2a8f32ca 100644 --- a/src/game/chars/CCharUse.cpp +++ b/src/game/chars/CCharUse.cpp @@ -12,6 +12,8 @@ #include "../triggers.h" #include "CChar.h" #include "CCharNPC.h" +#include + static constexpr int MASK_RETURN_FOLLOW_LINKS = 0x02; @@ -1149,7 +1151,7 @@ CChar * CChar::Use_Figurine( CItem * pItem, bool fCheckFollowerSlots ) if ( fCheckFollowerSlots && IsSetOF(OF_PetSlots) ) { - const short iFollowerSlots = (short)pPet->GetDefNum("FOLLOWERSLOTS", true, 1); + const short iFollowerSlots = GetFollowerSlots(); if ( !FollowersUpdate(pPet, (maximum(0, iFollowerSlots)), true) ) { SysMessageDefault(DEFMSG_PETSLOTS_TRY_CONTROL); @@ -1172,27 +1174,49 @@ CChar * CChar::Use_Figurine( CItem * pItem, bool fCheckFollowerSlots ) return pPet; } -bool CChar::FollowersUpdate( CChar * pChar, short iFollowerSlots, bool fCheckOnly ) +short CChar::GetFollowerSlots() const +{ + return n64_narrow_n16(GetDefNum("FOLLOWERSLOTS", true, 1)); +} + +short CChar::GetCurFollowers() const +{ + if (!IsSetEF(EF_FollowerList)) + return GetDefNum("CURFOLLOWER", true); + + return std::accumulate( + m_followers.cbegin(), + m_followers.cend(), + (short)0, + [](short accumulator, auto const& input_struct) -> short + { + return accumulator + input_struct.followerslots; + }); +} + +bool CChar::FollowersUpdate(CChar * pCharPet, short iPetFollowerSlots, bool fCheckOnly ) { ADDTOCALLSTACK("CChar::FollowersUpdate"); // Attemp to update followers on this character based on pChar // This is supossed to be called only when OF_PetSlots is enabled, so no need to check it here. + const bool fIgnoreMax = IsPriv(PRIV_GM); + if (!fCheckOnly && IsTrigUsed(TRIGGER_FOLLOWERSUPDATE)) { CScriptTriggerArgs Args; - Args.m_iN1 = (iFollowerSlots >= 0) ? 0 : 1; - Args.m_iN2 = abs(iFollowerSlots); - if (OnTrigger(CTRIG_FollowersUpdate, pChar, &Args) == TRIGRET_RET_TRUE) + Args.m_iN1 = (iPetFollowerSlots >= 0) ? 0 : 1; + Args.m_iN2 = abs(iPetFollowerSlots); + if (OnTrigger(CTRIG_FollowersUpdate, pCharPet, &Args) == TRIGRET_RET_TRUE) return false; if (Args.m_iN1 == 1) { - iFollowerSlots = - n64_narrow_n16(Args.m_iN2); + iPetFollowerSlots = - n64_narrow_n16(Args.m_iN2); } else { - iFollowerSlots = n64_narrow_n16(Args.m_iN2); + iPetFollowerSlots = n64_narrow_n16(Args.m_iN2); } } @@ -1200,44 +1224,48 @@ bool CChar::FollowersUpdate( CChar * pChar, short iFollowerSlots, bool fCheckOnl ASSERT(iMaxFollower >= 0); if (IsSetEF(EF_FollowerList)) { - if (iFollowerSlots >= 0) + if (iPetFollowerSlots >= 0) { - bool fExists = false; - for (std::vector::iterator it = m_followers.begin(); it != m_followers.end();) + bool fCharAlreadyFollower = false; + for (auto const& follower_data : m_followers) { - if (*it == pChar->GetUID()) + if (follower_data.uid == pCharPet->GetUID()) { - fExists = true; + fCharAlreadyFollower = true; break; } - ++it; } - if ((!fExists && (i16_from_usize_checked(m_followers.size()) < iMaxFollower)) || IsPriv(PRIV_GM)) + if (!fCharAlreadyFollower && (fIgnoreMax || (GetCurFollowers() + iPetFollowerSlots <= iMaxFollower))) { if (!fCheckOnly) - m_followers.emplace_back(pChar->GetUID()); + { + m_followers.emplace_back( + FollowerCharData { + .uid = pCharPet->GetUID(), + .followerslots = pCharPet->GetFollowerSlots() + }); + } } else return false; } else if (!fCheckOnly) { - for (std::vector::iterator it = m_followers.begin(); it != m_followers.end();) - { - if (*it == pChar->GetUID()) - it = m_followers.erase(it); - else - ++it; - } + std::erase_if( + m_followers, + [pCharPet](auto const& inp_struct) -> bool { + return inp_struct.uid == pCharPet->GetUID(); + }); } } else { - short iCurFollower = (short)(GetDefNum("CURFOLLOWER", true)); - iCurFollower = iCurFollower + iFollowerSlots; - if (!fCheckOnly) - SetDefNum("CURFOLLOWER", maximum(iCurFollower, 0)); + short iNewCurFollower = GetCurFollowers() + iPetFollowerSlots; + if (!fIgnoreMax && (iNewCurFollower > iMaxFollower)) + return false; + if (!fCheckOnly) + SetDefNum("CURFOLLOWER", maximum(iNewCurFollower, 0)); } if ( !fCheckOnly ) diff --git a/src/game/clients/CClientEvent.cpp b/src/game/clients/CClientEvent.cpp index 6f58a04b2..0bbfb6544 100644 --- a/src/game/clients/CClientEvent.cpp +++ b/src/game/clients/CClientEvent.cpp @@ -14,7 +14,6 @@ #include "../CWorldGameTime.h" #include "../CWorldMap.h" #include "../CWorldSearch.h" -#include "../spheresvr.h" #include "../triggers.h" #include "CClient.h" diff --git a/src/game/clients/CClientTarg.cpp b/src/game/clients/CClientTarg.cpp index cdf940587..846ee258d 100644 --- a/src/game/clients/CClientTarg.cpp +++ b/src/game/clients/CClientTarg.cpp @@ -1610,7 +1610,7 @@ bool CClient::OnTarg_Pet_Stable( CChar * pCharPet ) if ( IsSetOF(OF_PetSlots) ) { - short iFollowerSlots = (short)pCharPet->GetDefNum("FOLLOWERSLOTS", true, 1); + short iFollowerSlots = pCharPet->GetFollowerSlots(); m_pChar->FollowersUpdate(pCharPet,(-maximum(0, iFollowerSlots))); } diff --git a/src/network/send.cpp b/src/network/send.cpp index 10feaab7c..019b4199b 100644 --- a/src/network/send.cpp +++ b/src/network/send.cpp @@ -284,10 +284,7 @@ void PacketObjectStatus::WriteVersionSpecific(const CClient* target, CChar* othe { if (other->m_pPlayer != nullptr) { - if (!IsSetEF(EF_FollowerList)) - writeByte((byte)(other->GetDefNum("CURFOLLOWER", true))); - else - writeByte((byte)(other->m_followers.size())); + writeByte((byte)(other->GetCurFollowers())); writeByte((byte)(other->GetDefNum("MAXFOLLOWER", true))); } else diff --git a/src/sphere/UnixTerminal.cpp b/src/sphere/UnixTerminal.cpp index d8031e3e2..95922628d 100644 --- a/src/sphere/UnixTerminal.cpp +++ b/src/sphere/UnixTerminal.cpp @@ -88,7 +88,7 @@ bool UnixTerminal::isReady() // echo to console fputc(c, stdout); - //fflush(stdout); + fflush(stdout); m_nextChar = static_cast(c); return m_nextChar != '\0'; diff --git a/src/tables/CCharNpc_props.tbl b/src/tables/CCharNpc_props.tbl index ac1d22d38..e4bfe93e8 100644 --- a/src/tables/CCharNpc_props.tbl +++ b/src/tables/CCharNpc_props.tbl @@ -6,7 +6,6 @@ ADD(ACTPRI, "ACTPRI") ADD(BONDED, "BONDED") -ADD(FOLLOWERSLOTS, "FOLLOWERSLOTS") ADD(HOMEDIST, "HOMEDIST") ADD(NEED, "NEED") ADD(NEEDNAME, "NEEDNAME") diff --git a/src/tables/CChar_props.tbl b/src/tables/CChar_props.tbl index e147fb92b..17e05a718 100644 --- a/src/tables/CChar_props.tbl +++ b/src/tables/CChar_props.tbl @@ -40,6 +40,7 @@ ADD(EXP, "EXP") ADD(FAME, "FAME") ADD(FIGHTRANGE, "FIGHTRANGE") ADD(FLAGS, "FLAGS") +ADD(FOLLOWERSLOTS, "FOLLOWERSLOTS") ADD(FONT, "FONT") ADD(FOOD, "FOOD") ADD(GOLD, "GOLD") From 5b03df7671a71d05428fa010472f9181fe59ee3f Mon Sep 17 00:00:00 2001 From: cbnolok Date: Fri, 13 Sep 2024 21:16:21 +0200 Subject: [PATCH 37/86] Fixed exception on Linux when stdin was not a terminal (i.e. debugging from some IDEs or other apps). Set debug build optimization flags again to minimal (Og) Using O1 sometimes combined statements and inlined variables, making line-by-line debugging harder. Updated Windows-GNU toolchain warning flags. --- cmake/toolchains/Windows-MSVC.cmake | 6 ++-- .../include/Linux-Clang_common.inc.cmake | 2 +- .../include/Linux-GNU_common.inc.cmake | 4 +-- .../include/Windows-GNU_common.inc.cmake | 32 ++++++++++++++++--- src/common/CExpression.cpp | 8 ++--- src/common/sphere_library/sptr.h | 6 ++-- src/common/sphere_library/sstring.cpp | 3 +- src/game/CTimedFunctionHandler.cpp | 3 +- src/game/CWorldTicker.cpp | 2 -- src/game/CWorldTicker.h | 8 ++--- src/game/chars/CCharUse.cpp | 2 +- src/sphere/UnixTerminal.cpp | 23 +++++++------ src/sphere/threads.cpp | 5 +-- 13 files changed, 65 insertions(+), 39 deletions(-) diff --git a/cmake/toolchains/Windows-MSVC.cmake b/cmake/toolchains/Windows-MSVC.cmake index 9b37d0743..9af65c851 100644 --- a/cmake/toolchains/Windows-MSVC.cmake +++ b/cmake/toolchains/Windows-MSVC.cmake @@ -108,9 +108,9 @@ function(toolchain_exe_stuff) # gersemi: off target_compile_options(spheresvr PRIVATE ${cxx_compiler_flags_common} - $<$: $,/MT,/MD> /EHa /Oy /GL /GA /Gw /Gy /GF $,/O1 /Zi,/O2>> - $<$: $,/MT,/MD> /EHa /Oy /GL /GA /Gw /Gy /GF $,/O1 /Zi,/O2>> - $<$: $,/MTd,/MDd> /EHsc /Oy- /ob1 /Od /Gs $,/Zi,/ZI>> + $<$: $,/MT,/MD> /EHa /Oy /GL /GA /Gw /Gy /GF $,/O1 /Zi,/O2>> + $<$: $,/MT,/MD> /EHa /Oy /GL /GA /Gw /Gy /GF $,/O1 /Zi,/O2>> + $<$: $,/MTd,/MDd> /EHsc /Oy- /ob1 /Od /Gs $,/Zi,/ZI>> # ASan (and compilation for ARM arch) doesn't support edit and continue option (ZI) ) # gersemi: on diff --git a/cmake/toolchains/include/Linux-Clang_common.inc.cmake b/cmake/toolchains/include/Linux-Clang_common.inc.cmake index cc70368a5..cca7f2c92 100644 --- a/cmake/toolchains/include/Linux-Clang_common.inc.cmake +++ b/cmake/toolchains/include/Linux-Clang_common.inc.cmake @@ -176,7 +176,7 @@ See comments in the toolchain and: https://github.com/google/sanitizers/wiki/Mem endif() endif() if(TARGET spheresvr_debug) - target_compile_options(spheresvr_debug PUBLIC -ggdb3 -O1 ${COMPILE_OPTIONS_EXTRA}) + target_compile_options(spheresvr_debug PUBLIC -ggdb3 -Og ${COMPILE_OPTIONS_EXTRA}) endif() #-- Store common linker flags. diff --git a/cmake/toolchains/include/Linux-GNU_common.inc.cmake b/cmake/toolchains/include/Linux-GNU_common.inc.cmake index aba4acf56..5d5bb1404 100644 --- a/cmake/toolchains/include/Linux-GNU_common.inc.cmake +++ b/cmake/toolchains/include/Linux-GNU_common.inc.cmake @@ -102,7 +102,7 @@ function(toolchain_exe_stuff_common) -Wdisabled-optimization #-Winvalid-pch -Wzero-as-null-pointer-constant - -Wnull-dereference + #-Wnull-dereference # Don't: on GCC 12 causes some false positives... -Wduplicated-cond # Supported by Clang, but unsupported by GCC: @@ -154,7 +154,7 @@ function(toolchain_exe_stuff_common) endif() endif() if(TARGET spheresvr_debug) - target_compile_options(spheresvr_debug PUBLIC -ggdb3 -O1 ${COMPILE_OPTIONS_EXTRA}) + target_compile_options(spheresvr_debug PUBLIC -ggdb3 -Og ${COMPILE_OPTIONS_EXTRA}) endif() #-- Store common linker flags. diff --git a/cmake/toolchains/include/Windows-GNU_common.inc.cmake b/cmake/toolchains/include/Windows-GNU_common.inc.cmake index 80f706afa..41e9253cb 100644 --- a/cmake/toolchains/include/Windows-GNU_common.inc.cmake +++ b/cmake/toolchains/include/Windows-GNU_common.inc.cmake @@ -84,23 +84,45 @@ function(toolchain_exe_stuff_common) -Werror -Wall -Wextra - -Wno-nonnull-compare - -Wno-unknown-pragmas + -Wpedantic + + -Wmissing-include-dirs # Warns when an include directory provided with -I does not exist. + -Wformat=2 + #-Wcast-qual # Warns about casts that remove a type's const or volatile qualifier. + #-Wconversion # Temporarily disabled. Warns about implicit type conversions that might change a value, such as narrowing conversions. + -Wdisabled-optimization + #-Winvalid-pch + -Wzero-as-null-pointer-constant + #-Wnull-dereference # Don't: on GCC 12 causes some false positives... + -Wduplicated-cond + + # Supported by Clang, but unsupported by GCC: + #-Wweak-vtables + + # Unsupported by Clang, but supported by GCC: + -Wtrampolines # Warns when trampolines (a technique to implement nested functions) are generated (don't want this for security reasons). + -Wvector-operation-performance + -Wsized-deallocation + -Wduplicated-cond + -Wshift-overflow=2 + + # Disable errors: + -Wno-format-nonliteral # Since -Wformat=2 is stricter, you would need to disable this warning. + -Wno-nonnull-compare # GCC only -Wno-switch -Wno-implicit-fallthrough -Wno-parentheses -Wno-misleading-indentation - -Wno-conversion-null -Wno-unused-result -Wno-format-security # TODO: disable that when we'll have time to fix every printf format issue + -Wno-nested-anon-types ) set(cxx_local_opts -std=c++20 -pthread -fexceptions -fnon-call-exceptions - -mno-ms-bitfields - # -mno-ms-bitfields is needed to fix structure packing + -mno-ms-bitfields # it's needed to fix structure packing -pipe -ffast-math ) diff --git a/src/common/CExpression.cpp b/src/common/CExpression.cpp index 7b4ad2167..69c6641ff 100644 --- a/src/common/CExpression.cpp +++ b/src/common/CExpression.cpp @@ -437,7 +437,7 @@ llong CExpression::GetSingle( lpctstr & pszArgs ) } else if ( ! _ISCSYMF(pszArgs[0]) ) { - #pragma region maths + //#pragma region maths // MSVC specific // some sort of math op ? switch ( pszArgs[0] ) @@ -471,10 +471,10 @@ llong CExpression::GetSingle( lpctstr & pszArgs ) case '\0': return 0; } -#pragma endregion maths +//#pragma endregion maths // MSVC specific } else - #pragma region intrinsics +//#pragma region intrinsics // MSVC specific { // Symbol or intrinsinc function ? @@ -883,7 +883,7 @@ llong CExpression::GetSingle( lpctstr & pszArgs ) if ( m_VarDefs.GetParseVal( ptcArgsOriginal, &llVal ) ) // DEF. return llVal; } -#pragma endregion intrinsics +//#pragma endregion intrinsics // MSVC specific // hard end ! Error of some sort. if (ptcStartingString[0] != '\0') diff --git a/src/common/sphere_library/sptr.h b/src/common/sphere_library/sptr.h index 152c069ae..66bc169bc 100644 --- a/src/common/sphere_library/sptr.h +++ b/src/common/sphere_library/sptr.h @@ -1,15 +1,15 @@ #ifndef _INC_SPTR_H #define _INC_SPTR_H -#ifndef _MSVC +#ifndef _MSC_VER # pragma GCC diagnostic push # pragma GCC diagnostic ignored "-Wzero-as-null-pointer-constant" #endif #include -#ifndef _MSVC -#pragma GCC diagnostic pop +#ifndef _MSC_VER +# pragma GCC diagnostic pop #endif diff --git a/src/common/sphere_library/sstring.cpp b/src/common/sphere_library/sstring.cpp index d6bdb13ca..6311a1930 100644 --- a/src/common/sphere_library/sstring.cpp +++ b/src/common/sphere_library/sstring.cpp @@ -1,5 +1,5 @@ #include "sstring.h" -#include "../../common/CLog.h" +//#include "../../common/CLog.h" #include "../../sphere/ProfileTask.h" #include "../CExpression.h" @@ -10,6 +10,7 @@ #pragma warning ( disable : ALL_CODE_ANALYSIS_WARNINGS ) #else #pragma GCC diagnostic push + #pragma GCC diagnostic ignored "-Wpragmas" #pragma GCC diagnostic ignored "-Winvalid-utf8" #pragma GCC diagnostic ignored "-Wzero-as-null-pointer-constant" #if defined(__GNUC__) && !defined(__clang__) diff --git a/src/game/CTimedFunctionHandler.cpp b/src/game/CTimedFunctionHandler.cpp index 02984615f..3c57dc1a5 100644 --- a/src/game/CTimedFunctionHandler.cpp +++ b/src/game/CTimedFunctionHandler.cpp @@ -201,7 +201,8 @@ void CTimedFunctionHandler::r_Write( CScript & s ) ADDTOCALLSTACK("CTimedFunctionHandler::r_Write"); for (CSObjContRec* obj : _timedFunctions.GetIterationSafeCont()) { - auto tfObj = static_cast(obj); + auto tfObj = static_cast(obj); + ASSERT(tfObj); const CUID& uid = tfObj->GetUID(); if (uid.IsValidUID()) { diff --git a/src/game/CWorldTicker.cpp b/src/game/CWorldTicker.cpp index 902db9ba6..31c6af85c 100644 --- a/src/game/CWorldTicker.cpp +++ b/src/game/CWorldTicker.cpp @@ -3,12 +3,10 @@ #include "../sphere/ProfileTask.h" #include "chars/CChar.h" #include "items/CItem.h" -#include "items/CItemShip.h" #include "CSector.h" #include "CWorldClock.h" #include "CWorldGameTime.h" #include "CWorldTicker.h" -#include CWorldTicker::CWorldTicker(CWorldClock *pClock) diff --git a/src/game/CWorldTicker.h b/src/game/CWorldTicker.h index 8509489b7..31d84a808 100644 --- a/src/game/CWorldTicker.h +++ b/src/game/CWorldTicker.h @@ -14,7 +14,7 @@ #endif #ifdef _WIN32 - #define MYSRWLOCK_ +// #define MYSRWLOCK_ #undef SRWLOCK_INIT #endif #ifdef __GNUC__ @@ -29,9 +29,9 @@ #ifdef MYASAN_ #define ADDRESS_SANITIZER #endif -#ifdef MYSRWLOCK_ -# define SRWLOCK_INIT -#endif +//#ifdef MYSRWLOCK_ +//# define SRWLOCK_INIT +//#endif #ifdef __GNUC__ #pragma GCC diagnostic pop diff --git a/src/game/chars/CCharUse.cpp b/src/game/chars/CCharUse.cpp index a2a8f32ca..6044f190e 100644 --- a/src/game/chars/CCharUse.cpp +++ b/src/game/chars/CCharUse.cpp @@ -1182,7 +1182,7 @@ short CChar::GetFollowerSlots() const short CChar::GetCurFollowers() const { if (!IsSetEF(EF_FollowerList)) - return GetDefNum("CURFOLLOWER", true); + return n64_narrow_n16(GetDefNum("CURFOLLOWER", true)); return std::accumulate( m_followers.cbegin(), diff --git a/src/sphere/UnixTerminal.cpp b/src/sphere/UnixTerminal.cpp index 95922628d..daa884170 100644 --- a/src/sphere/UnixTerminal.cpp +++ b/src/sphere/UnixTerminal.cpp @@ -163,18 +163,21 @@ void UnixTerminal::prepare() refresh(); // draw screen #else - // save existing attributes - if (tcgetattr(STDIN_FILENO, &m_original) < 0) - throw CSError(LOGL_WARN, 0, "failed to get terminal attributes"); - - // set new terminal attributes - termios term_caps = m_original; - term_caps.c_lflag &= ~ unsigned(ICANON | ECHO); - term_caps.c_cc[VMIN] = 1; + // Am i running Sphere in a terminal? + if (isatty(STDIN_FILENO)) + { + // save existing attributes + if (tcgetattr(STDIN_FILENO, &m_original) < 0) + throw CSError(LOGL_WARN, 0, "failed to get terminal attributes"); - if (tcsetattr(STDIN_FILENO, TCSANOW, &term_caps) < 0) - throw CSError(LOGL_WARN, 0, "failed to set terminal attributes"); + // set new terminal attributes + termios term_caps = m_original; + term_caps.c_lflag &= ~ unsigned(ICANON | ECHO); + term_caps.c_cc[VMIN] = 1; + if (tcsetattr(STDIN_FILENO, TCSANOW, &term_caps) < 0) + throw CSError(LOGL_WARN, 0, "failed to set terminal attributes"); + } setbuf(stdin, nullptr); #endif diff --git a/src/sphere/threads.cpp b/src/sphere/threads.cpp index 414c4c7f1..c15f53f7c 100644 --- a/src/sphere/threads.cpp +++ b/src/sphere/threads.cpp @@ -113,8 +113,9 @@ void IThread::setThreadName(const char* name) auto athr = static_cast(ThreadHolder::get().current()); ASSERT(athr); - g_Log.Event(LOGM_DEBUG|LOGL_EVENT, "Setting thread (ThreadHolder ID %d, internal name '%s') system name: '%s'.\n", - athr->m_threadHolderId, athr->getName(), name_trimmed); + g_Log.Event(LOGF_CONSOLE_ONLY|LOGM_DEBUG|LOGL_EVENT, + "Setting thread (ThreadHolder ID %d, internal name '%s') system name: '%s'.\n", + athr->m_threadHolderId, athr->getName(), name_trimmed); athr->overwriteInternalThreadName(name_trimmed); } From b0584d08fde60ff4593ed324204bee1614e69e7d Mon Sep 17 00:00:00 2001 From: cbnolok Date: Sat, 14 Sep 2024 07:14:35 +0200 Subject: [PATCH 38/86] Renamed a couple of cmake utility files. --- CMakeLists.txt | 4 ++-- cmake/{CMakeDetectArch.cmake => DetectArch.cmake} | 0 ...akeDefaultToolchain.cmake => DetectDefaultToolchain.cmake} | 0 cmake/{CMakeGitStatus.cmake => GitStatus.cmake} | 0 cmake/toolchains/include/Linux-Clang_common.inc.cmake | 2 +- cmake/toolchains/include/Linux-GNU_common.inc.cmake | 2 +- cmake/toolchains/include/OSX-AppleClang_common.inc.cmake | 2 +- cmake/toolchains/include/Windows-Clang_common.inc.cmake | 2 +- cmake/toolchains/include/Windows-GNU_common.inc.cmake | 2 +- 9 files changed, 7 insertions(+), 7 deletions(-) rename cmake/{CMakeDetectArch.cmake => DetectArch.cmake} (100%) rename cmake/{CMakeDefaultToolchain.cmake => DetectDefaultToolchain.cmake} (100%) rename cmake/{CMakeGitStatus.cmake => GitStatus.cmake} (100%) diff --git a/CMakeLists.txt b/CMakeLists.txt index 1eaa86083..0703c2e43 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -101,7 +101,7 @@ endif() # If we have not specified a toolchain, let's detect which one we should use, using the detected arch. if(NOT TOOLCHAIN_LOADED) - include("cmake/CMakeDefaultToolchain.cmake") + include("cmake/DefaultToolchain.cmake") endif() #-- Stuff that needs to be executed after PROJECT but before ADD_EXECUTABLE @@ -204,4 +204,4 @@ add_subdirectory(lib) toolchain_exe_stuff() # stuff to be executed after ADD_EXECUTABLE # Get the Git revision number -include("cmake/CMakeGitStatus.cmake") +include("cmake/GitStatus.cmake") diff --git a/cmake/CMakeDetectArch.cmake b/cmake/DetectArch.cmake similarity index 100% rename from cmake/CMakeDetectArch.cmake rename to cmake/DetectArch.cmake diff --git a/cmake/CMakeDefaultToolchain.cmake b/cmake/DetectDefaultToolchain.cmake similarity index 100% rename from cmake/CMakeDefaultToolchain.cmake rename to cmake/DetectDefaultToolchain.cmake diff --git a/cmake/CMakeGitStatus.cmake b/cmake/GitStatus.cmake similarity index 100% rename from cmake/CMakeGitStatus.cmake rename to cmake/GitStatus.cmake diff --git a/cmake/toolchains/include/Linux-Clang_common.inc.cmake b/cmake/toolchains/include/Linux-Clang_common.inc.cmake index cca7f2c92..c2c6a077c 100644 --- a/cmake/toolchains/include/Linux-Clang_common.inc.cmake +++ b/cmake/toolchains/include/Linux-Clang_common.inc.cmake @@ -1,7 +1,7 @@ set(TOOLCHAIN_LOADED 1) function(toolchain_after_project_common) - include("${CMAKE_SOURCE_DIR}/cmake/CMakeDetectArch.cmake") + include("${CMAKE_SOURCE_DIR}/cmake/DetectArch.cmake") endfunction() function(toolchain_exe_stuff_common) diff --git a/cmake/toolchains/include/Linux-GNU_common.inc.cmake b/cmake/toolchains/include/Linux-GNU_common.inc.cmake index 5d5bb1404..d5110736d 100644 --- a/cmake/toolchains/include/Linux-GNU_common.inc.cmake +++ b/cmake/toolchains/include/Linux-GNU_common.inc.cmake @@ -1,7 +1,7 @@ set(TOOLCHAIN_LOADED 1) function(toolchain_after_project_common) - include("${CMAKE_SOURCE_DIR}/cmake/CMakeDetectArch.cmake") + include("${CMAKE_SOURCE_DIR}/cmake/DetectArch.cmake") endfunction() function(toolchain_exe_stuff_common) diff --git a/cmake/toolchains/include/OSX-AppleClang_common.inc.cmake b/cmake/toolchains/include/OSX-AppleClang_common.inc.cmake index 29dcbf1bd..5e4a74ebf 100644 --- a/cmake/toolchains/include/OSX-AppleClang_common.inc.cmake +++ b/cmake/toolchains/include/OSX-AppleClang_common.inc.cmake @@ -1,7 +1,7 @@ set(TOOLCHAIN_LOADED 1) function(toolchain_after_project_common) - include("${CMAKE_SOURCE_DIR}/cmake/CMakeDetectArch.cmake") + include("${CMAKE_SOURCE_DIR}/cmake/DetectArch.cmake") endfunction() function(toolchain_exe_stuff_common) diff --git a/cmake/toolchains/include/Windows-Clang_common.inc.cmake b/cmake/toolchains/include/Windows-Clang_common.inc.cmake index 6ad0e3639..ac2815981 100644 --- a/cmake/toolchains/include/Windows-Clang_common.inc.cmake +++ b/cmake/toolchains/include/Windows-Clang_common.inc.cmake @@ -8,7 +8,7 @@ option( function(toolchain_after_project_common) enable_language(RC) - include("${CMAKE_SOURCE_DIR}/cmake/CMakeDetectArch.cmake") + include("${CMAKE_SOURCE_DIR}/cmake/DetectArch.cmake") endfunction() function(toolchain_exe_stuff_common) diff --git a/cmake/toolchains/include/Windows-GNU_common.inc.cmake b/cmake/toolchains/include/Windows-GNU_common.inc.cmake index 41e9253cb..d0ab94af1 100644 --- a/cmake/toolchains/include/Windows-GNU_common.inc.cmake +++ b/cmake/toolchains/include/Windows-GNU_common.inc.cmake @@ -2,7 +2,7 @@ set(TOOLCHAIN_LOADED 1) function(toolchain_after_project_common) enable_language(RC) - include("${CMAKE_SOURCE_DIR}/cmake/CMakeDetectArch.cmake") + include("${CMAKE_SOURCE_DIR}/cmake/DetectArch.cmake") endfunction() function(toolchain_exe_stuff_common) From 013287ba17f24b3e80166f13f895373098575852 Mon Sep 17 00:00:00 2001 From: cbnolok Date: Sat, 14 Sep 2024 22:25:29 +0200 Subject: [PATCH 39/86] Huge cleanup of header files, now removing useless includes. Other than removing a lot of clangd/clang-tidy warnings, it should speed up a little compilation. --- CMakeLists.txt | 2 +- cmake/toolchains/Windows-MSVC.cmake | 2 +- src/CMakeSources.cmake | 6 +- src/common/CCacheableScriptFile.h | 6 +- src/common/CDataBase.cpp | 1 + src/common/CDataBase.h | 8 +-- src/common/CException.cpp | 4 +- src/common/CExpression.cpp | 3 +- src/common/CExpression.h | 1 - src/common/CLanguageID.cpp | 67 +++++++++++++++++++ src/common/CLanguageID.h | 26 +++++++ src/common/CLocalVarsExtra.h | 5 +- src/common/CLog.cpp | 2 + src/common/CLog.h | 1 - src/common/CPointBase.cpp | 6 ++ src/common/CPointBase.h | 1 - src/common/CSVFile.cpp | 10 ++- src/common/CSVFile.h | 10 ++- src/common/CScript.cpp | 4 +- src/common/CScript.h | 4 +- src/common/CScriptObj.cpp | 35 ++++++---- src/common/CScriptObj.h | 5 +- src/common/CServerMap.cpp | 33 ++++++--- src/common/CServerMap.h | 35 ++++------ src/common/CTextConsole.cpp | 3 +- src/common/CTextConsole.h | 5 +- src/common/CUID.cpp | 1 + src/common/CUOInstall.cpp | 7 +- src/common/CUOInstall.h | 11 ++- src/common/CVarDefMap.h | 2 +- src/common/ListDefContMap.h | 1 - src/common/common.cpp | 57 +--------------- src/common/crypto/CCryptoTwoFishInterface.cpp | 3 +- src/common/crypto/CMD5.h | 1 - src/common/os_windows.h | 11 ++- src/common/resource/CResourceDef.cpp | 1 - src/common/resource/CResourceHash.h | 1 - src/common/resource/CResourceHolder.cpp | 7 +- src/common/resource/CResourceHolder.h | 8 +-- src/common/resource/CResourceID.h | 3 +- src/common/resource/CResourceQty.cpp | 2 +- src/common/resource/CResourceQty.h | 2 +- src/common/resource/CResourceRef.cpp | 10 ++- src/common/resource/CResourceRef.h | 12 +--- src/common/resource/CResourceScript.h | 7 +- src/common/resource/CResourceSortedArrays.cpp | 1 + src/common/resource/CResourceSortedArrays.h | 5 +- src/common/resource/CValueDefs.cpp | 2 +- src/common/resource/CValueDefs.h | 2 +- .../resource/sections/CRandGroupDef.cpp | 7 +- src/common/resource/sections/CRandGroupDef.h | 7 +- .../resource/sections/CResourceNamedDef.h | 5 +- src/common/resource/sections/CSpellDef.cpp | 7 +- src/common/resource/sections/CSpellDef.h | 3 + src/common/resource/sections/CWebPageDef.cpp | 2 + src/common/resource/sections/CWebPageDef.h | 1 - src/common/sphere_library/CSAssoc.h | 2 +- src/common/sphere_library/CSFileText.cpp | 1 - src/common/sphere_library/CSFileText.h | 7 +- src/common/sphere_library/CSObjCont.cpp | 2 +- src/common/sphere_library/CSObjCont.h | 1 + src/common/sphere_library/CSObjContRec.h | 1 - src/common/sphere_library/CSObjList.h | 1 + src/common/sphere_library/CSObjListRec.h | 1 - src/common/sphere_library/CSReferenceCount.h | 8 +-- src/common/sphere_library/CSTime.cpp | 10 +-- src/common/sphere_library/smutex.cpp | 2 + src/common/sphere_library/smutex.h | 24 +++---- src/common/sphereproto.h | 30 --------- src/game/CBase.cpp | 3 +- src/game/CBase.h | 2 +- src/game/CComponent.cpp | 1 - src/game/CContainer.cpp | 12 ++-- src/game/CContainer.h | 16 +++-- src/game/CEntity.cpp | 5 +- src/game/CEntity.h | 1 - src/game/CEntityProps.cpp | 6 -- src/game/CObjBase.cpp | 4 +- src/game/CObjBase.h | 5 +- src/game/CObjBaseTemplate.cpp | 1 - src/game/CRegion.cpp | 8 +-- src/game/CRegion.h | 2 - src/game/CResourceCalc.cpp | 9 +-- src/game/CScriptProfiler.h | 2 +- src/game/CSector.cpp | 3 +- src/game/CSectorList.cpp | 1 - src/game/CSectorList.h | 1 - src/game/CSectorTemplate.cpp | 4 +- src/game/CSectorTemplate.h | 4 +- src/game/CServer.cpp | 9 +-- src/game/CServerConfig.cpp | 9 ++- src/game/CServerConfig.h | 1 - src/game/CServerDef.cpp | 2 +- src/game/CServerDef.h | 1 + src/game/CServerTime.cpp | 1 + src/game/CTeleport.cpp | 2 +- src/game/CTimedFunction.cpp | 1 - src/game/CTimedFunctionHandler.cpp | 1 - src/game/CWorld.cpp | 3 +- src/game/CWorldClock.cpp | 3 +- src/game/CWorldComm.cpp | 2 +- src/game/CWorldComm.h | 1 + src/game/CWorldImport.cpp | 3 + src/game/CWorldMap.cpp | 1 + src/game/CWorldSearch.cpp | 5 +- src/game/CWorldTickingList.cpp | 1 + src/game/CWorldTickingList.h | 2 + src/game/CWorldTimedFunctions.cpp | 1 + src/game/chars/CChar.cpp | 5 +- src/game/chars/CChar.h | 21 +++--- src/game/chars/CCharAct.cpp | 12 ++-- src/game/chars/CCharAttacker.cpp | 1 + src/game/chars/CCharBase.cpp | 2 + src/game/chars/CCharBase.h | 12 ++-- src/game/chars/CCharFight.cpp | 3 + src/game/chars/CCharLOS.cpp | 3 + src/game/chars/CCharMemory.cpp | 5 +- src/game/chars/CCharNPC.cpp | 1 + src/game/chars/CCharNPCAct.cpp | 5 ++ src/game/chars/CCharNPCAct_Fight.cpp | 4 +- src/game/chars/CCharNPCAct_Magic.cpp | 3 + src/game/chars/CCharNPCAct_Vendor.cpp | 7 +- src/game/chars/CCharNPCPet.cpp | 4 ++ src/game/chars/CCharNPCStatus.cpp | 8 ++- src/game/chars/CCharNotoriety.cpp | 6 +- src/game/chars/CCharPlayer.cpp | 2 + src/game/chars/CCharPlayer.h | 1 - src/game/chars/CCharSkill.cpp | 5 +- src/game/chars/CCharSpell.cpp | 4 ++ src/game/chars/CCharStat.cpp | 4 +- src/game/chars/CCharStatus.cpp | 6 +- src/game/chars/CCharUse.cpp | 3 +- src/game/chars/CStoneMember.cpp | 2 + src/game/chars/CStoneMember.h | 1 + src/game/clients/CAccount.cpp | 2 + src/game/clients/CAccount.h | 11 +-- src/game/clients/CChat.cpp | 2 +- src/game/clients/CChat.h | 8 ++- src/game/clients/CChatChanMember.h | 24 ++++--- src/game/clients/CChatChannel.cpp | 4 +- src/game/clients/CChatChannel.h | 1 + src/game/clients/CClient.cpp | 9 ++- src/game/clients/CClient.h | 16 ++--- src/game/clients/CClientDialog.cpp | 3 +- src/game/clients/CClientEvent.cpp | 3 + src/game/clients/CClientLog.cpp | 1 + src/game/clients/CClientMsg.cpp | 3 + src/game/clients/CClientMsg_AOSTooltip.cpp | 2 + src/game/clients/CClientTarg.cpp | 6 ++ src/game/clients/CClientTooltip.cpp | 7 +- src/game/clients/CClientUse.cpp | 3 + src/game/clients/CGMPage.h | 1 - src/game/clients/CGlobalChatChanMember.cpp | 2 - src/game/clients/CParty.cpp | 3 +- src/game/clients/CParty.h | 1 - src/game/components/CCChampion.cpp | 6 +- src/game/components/CCItemDamageable.cpp | 2 +- src/game/components/CCMultiMovable.cpp | 3 +- src/game/components/CCMultiMovable.h | 11 ++- src/game/components/CCPropsItem.cpp | 3 +- src/game/components/CCPropsItemChar.cpp | 3 +- src/game/components/CCPropsItemEquippable.cpp | 3 +- src/game/components/CCPropsItemWeapon.cpp | 1 + .../components/CCPropsItemWeaponRanged.cpp | 1 + src/game/components/CCSpawn.cpp | 2 + src/game/game_macros.h | 3 +- src/game/items/CItem.cpp | 11 ++- src/game/items/CItem.h | 16 +---- src/game/items/CItemBase.cpp | 26 ++++++- src/game/items/CItemBase.h | 32 +++------ src/game/items/CItemCommCrystal.h | 6 +- src/game/items/CItemContainer.cpp | 3 +- src/game/items/CItemContainer.h | 5 +- src/game/items/CItemCorpse.cpp | 2 +- src/game/items/CItemCorpse.h | 6 +- src/game/items/CItemMap.cpp | 1 + src/game/items/CItemMap.h | 8 +-- src/game/items/CItemMessage.cpp | 1 + src/game/items/CItemMessage.h | 6 +- src/game/items/CItemMulti.cpp | 3 + src/game/items/CItemMultiCustom.cpp | 2 + src/game/items/CItemMultiCustom.h | 7 +- src/game/items/CItemPlant.cpp | 9 +-- src/game/items/CItemShip.cpp | 9 ++- src/game/items/CItemShip.h | 6 +- src/game/items/CItemStone.cpp | 1 + src/game/items/CItemStone.h | 5 +- src/game/items/item_types.h | 3 +- src/game/spheresvr.cpp | 13 ++-- src/game/spheresvr.h | 2 +- src/game/triggers.cpp | 1 - src/game/uo_files/CUOIndexRec.cpp | 1 - src/game/uo_files/CUOIndexRec.h | 3 +- src/game/uo_files/CUOMobtypes.cpp | 1 - src/game/uo_files/CUOMultiItemRec.h | 1 - src/game/uo_files/CUOTiledata.cpp | 3 + src/game/uo_files/CUOVersionBlock.h | 2 +- src/game/uo_files/uofiles_enums.h | 4 +- src/game/uo_files/uofiles_enums_creid.h | 2 + src/game/uo_files/uofiles_enums_itemid.h | 2 +- src/game/uo_files/uofiles_macros.h | 2 - src/network/CClientIterator.cpp | 3 +- src/network/CClientIterator.h | 13 ++-- src/network/CNetworkInput.cpp | 2 +- src/network/CNetworkOutput.h | 2 + src/network/CPacketManager.cpp | 5 +- src/network/CSocket.cpp | 1 + src/network/CSocket.h | 1 - src/network/PingServer.cpp | 2 +- src/network/packet.cpp | 2 +- src/network/receive.cpp | 4 +- src/network/receive.h | 1 - src/network/send.cpp | 20 +++--- src/network/send.h | 2 +- src/resources/SphereSvr.rc | 21 ++++-- src/sphere/ConsoleInterface.h | 2 +- src/sphere/ProfileData.cpp | 5 +- src/sphere/UnixTerminal.cpp | 1 - src/sphere/asyncdb.cpp | 1 - src/sphere/asyncdb.h | 2 + src/sphere/ntservice.cpp | 1 + src/sphere/ntwindow.cpp | 1 + src/sphere/threads.cpp | 7 +- src/sphere/threads.h | 3 - src/tables/classnames.tbl | 9 +++ 225 files changed, 738 insertions(+), 561 deletions(-) create mode 100644 src/common/CLanguageID.cpp create mode 100644 src/common/CLanguageID.h diff --git a/CMakeLists.txt b/CMakeLists.txt index 0703c2e43..cd485cba2 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -101,7 +101,7 @@ endif() # If we have not specified a toolchain, let's detect which one we should use, using the detected arch. if(NOT TOOLCHAIN_LOADED) - include("cmake/DefaultToolchain.cmake") + include("cmake/DetectDefaultToolchain.cmake") endif() #-- Stuff that needs to be executed after PROJECT but before ADD_EXECUTABLE diff --git a/cmake/toolchains/Windows-MSVC.cmake b/cmake/toolchains/Windows-MSVC.cmake index 9af65c851..3088faee3 100644 --- a/cmake/toolchains/Windows-MSVC.cmake +++ b/cmake/toolchains/Windows-MSVC.cmake @@ -18,7 +18,7 @@ function(toolchain_after_project) endif() set(CMAKE_SYSTEM_PROCESSOR "${CMAKE_VS_PLATFORM_NAME}" CACHE INTERNAL "" FORCE) - include("${CMAKE_SOURCE_DIR}/cmake/CMakeDetectArch.cmake") + include("${CMAKE_SOURCE_DIR}/cmake/DetectArch.cmake") message(STATUS "Generating for MSVC platform ${CMAKE_VS_PLATFORM_NAME}.") endfunction() diff --git a/src/CMakeSources.cmake b/src/CMakeSources.cmake index dfb228074..7bf73af39 100644 --- a/src/CMakeSources.cmake +++ b/src/CMakeSources.cmake @@ -116,6 +116,8 @@ set(common_SRCS src/common/sqlite/SQLite.h src/common/assertion.h src/common/basic_threading.h + src/common/common.cpp + src/common/common.h src/common/CCacheableScriptFile.cpp src/common/CCacheableScriptFile.h src/common/CDataBase.cpp @@ -126,6 +128,8 @@ set(common_SRCS src/common/CExpression.h src/common/CFloatMath.cpp src/common/CFloatMath.h + src/common/CLanguageID.cpp + src/common/CLanguageID.h src/common/CLocalVarsExtra.cpp src/common/CLocalVarsExtra.h src/common/CLog.cpp @@ -134,8 +138,6 @@ set(common_SRCS src/common/CServerMap.h src/common/CUID.cpp src/common/CUID.h - src/common/common.cpp - src/common/common.h src/common/CPointBase.cpp src/common/CPointBase.h src/common/CRect.cpp diff --git a/src/common/CCacheableScriptFile.h b/src/common/CCacheableScriptFile.h index 8151da218..3075f5da0 100644 --- a/src/common/CCacheableScriptFile.h +++ b/src/common/CCacheableScriptFile.h @@ -16,9 +16,9 @@ class CCacheableScriptFile : public CSFileText public: CCacheableScriptFile(); ~CCacheableScriptFile(); -private: - CCacheableScriptFile(const CCacheableScriptFile& copy); - CCacheableScriptFile& operator=(const CCacheableScriptFile& other); + + CCacheableScriptFile(const CCacheableScriptFile& copy) = delete; + CCacheableScriptFile& operator=(const CCacheableScriptFile& other) = delete; protected: virtual bool _Open(lpctstr ptcFilename = nullptr, uint uiModeFlags = OF_READ|OF_SHARE_DENY_NONE) override; public: virtual bool Open(lpctstr ptcFilename = nullptr, uint uiModeFlags = OF_READ|OF_SHARE_DENY_NONE) override; diff --git a/src/common/CDataBase.cpp b/src/common/CDataBase.cpp index 58b1cca27..3266a643e 100644 --- a/src/common/CDataBase.cpp +++ b/src/common/CDataBase.cpp @@ -5,6 +5,7 @@ #include "resource/sections/CResourceNamedDef.h" #include "CLog.h" #include "CException.h" +#include "CExpression.h" #include "CScriptTriggerArgs.h" #include "CDataBase.h" diff --git a/src/common/CDataBase.h b/src/common/CDataBase.h index d340fc4cf..ee084ae50 100644 --- a/src/common/CDataBase.h +++ b/src/common/CDataBase.h @@ -10,7 +10,6 @@ #include "sphere_library/smutex.h" #include "CScriptObj.h" #include "CVarDefMap.h" -#include #include #include // mysql standard include @@ -20,8 +19,6 @@ #define MIN_MARIADB_VERSION_ALLOW 30002 -class CVarDefMap; - class CDataBase : public CScriptObj { public: @@ -30,9 +27,8 @@ class CDataBase : public CScriptObj CDataBase(); ~CDataBase(); -private: - CDataBase(const CDataBase& copy); - CDataBase& operator=(const CDataBase& other); + CDataBase(const CDataBase& copy) = delete; + CDataBase& operator=(const CDataBase& other) = delete; public: bool Connect(const char *user, const char *password, const char *base = "", const char *host = "localhost"); diff --git a/src/common/CException.cpp b/src/common/CException.cpp index 94914f706..a29834e7c 100644 --- a/src/common/CException.cpp +++ b/src/common/CException.cpp @@ -4,7 +4,7 @@ #ifndef _WIN32 #include //#include // for pthread_exit -#include +#include #include #include "../game/CServer.h" @@ -52,7 +52,7 @@ void NotifyDebugger() std::abort(); #endif #else - std::raise(SIGINT); + raise(SIGINT); #endif } diff --git a/src/common/CExpression.cpp b/src/common/CExpression.cpp index 69c6641ff..208a57e58 100644 --- a/src/common/CExpression.cpp +++ b/src/common/CExpression.cpp @@ -1,6 +1,7 @@ #include "../game/CServerConfig.h" #include "sphere_library/CSRand.h" -#include "CException.h" +//#include "CException.h" +#include "CLog.h" #include "CExpression.h" #include #include diff --git a/src/common/CExpression.h b/src/common/CExpression.h index 1ea81fc43..05b3db018 100644 --- a/src/common/CExpression.h +++ b/src/common/CExpression.h @@ -10,7 +10,6 @@ #ifndef _INC_CEXPRSSION_H #define _INC_CEXPRSSION_H -#include "sphere_library/CSRand.h" #include "CVarDefMap.h" #include "ListDefContMap.h" diff --git a/src/common/CLanguageID.cpp b/src/common/CLanguageID.cpp new file mode 100644 index 000000000..957610734 --- /dev/null +++ b/src/common/CLanguageID.cpp @@ -0,0 +1,67 @@ +#include "sphere_library/sstringobjs.h" +#include "CLanguageID.h" +#include +#include + + +CLanguageID::CLanguageID() noexcept : + m_codes{} +{} + +CLanguageID::CLanguageID( const char * pszInit ) noexcept +{ + Set( pszInit ); +} + +CLanguageID::CLanguageID(int iDefault) noexcept : + m_codes{} +{ + UnreferencedParameter(iDefault); + ASSERT(iDefault == 0); +} + +bool CLanguageID::IsDef() const noexcept +{ + return ( m_codes[0] != 0 ); +} + +void CLanguageID::GetStrDef(tchar* pszLang) noexcept +{ + if (!IsDef()) + { + strcpy(pszLang, "enu"); // NOLINT(clang-analyzer-security.insecureAPI.strcpy) + } + else + { + memcpy(pszLang, m_codes, 3); + pszLang[3] = '\0'; + } +} + +void CLanguageID::GetStr(tchar* pszLang) const noexcept +{ + memcpy(pszLang, m_codes, 3); + pszLang[3] = '\0'; +} + +lpctstr CLanguageID::GetStr() const +{ + tchar* pszTmp = Str_GetTemp(); + GetStr(pszTmp); + return pszTmp; +} + +bool CLanguageID::Set(lpctstr pszLang) noexcept +{ + // needs not be terminated! + if (pszLang != nullptr) + { + memcpy(m_codes, pszLang, 3); + m_codes[3] = 0; + if (iswalnum(m_codes[0])) + return true; + // not valid ! + } + m_codes[0] = 0; + return false; +} diff --git a/src/common/CLanguageID.h b/src/common/CLanguageID.h new file mode 100644 index 000000000..51c6cc6e3 --- /dev/null +++ b/src/common/CLanguageID.h @@ -0,0 +1,26 @@ +#ifndef _INC_CLANGUAAGEID_H +#define _INC_CLANGUAAGEID_H + +#include "common.h" + +class CLanguageID +{ + // 3 letter code for language. + // ENU,FRA,DEU,etc. (see langcode.iff) + // terminate with a 0 + // 0 = english default. + char m_codes[4]; // UNICODE language pref. ('ENU'=english) + +public: + CLanguageID() noexcept; + CLanguageID( const char * pszInit ) noexcept; + CLanguageID(int iDefault) noexcept; + + bool IsDef() const noexcept; + void GetStrDef(tchar* pszLang) noexcept; + void GetStr(tchar* pszLang) const noexcept; + lpctstr GetStr() const; + bool Set(lpctstr pszLang) noexcept; +}; + +#endif diff --git a/src/common/CLocalVarsExtra.h b/src/common/CLocalVarsExtra.h index 8c7fec182..800f0767b 100644 --- a/src/common/CLocalVarsExtra.h +++ b/src/common/CLocalVarsExtra.h @@ -24,9 +24,8 @@ class CLocalFloatVars CLocalFloatVars() = default; ~CLocalFloatVars() = default; -private: - CLocalFloatVars(const CLocalFloatVars& copy); - CLocalFloatVars& operator=(const CLocalFloatVars& other); + CLocalFloatVars(const CLocalFloatVars& copy) = delete; + CLocalFloatVars& operator=(const CLocalFloatVars& other) = delete; private: //setting, getting bool Set( const char* VarName, const char* VarValue ); diff --git a/src/common/CLog.cpp b/src/common/CLog.cpp index 4236293eb..4e90575ae 100644 --- a/src/common/CLog.cpp +++ b/src/common/CLog.cpp @@ -1,6 +1,8 @@ #include "../sphere/ProfileTask.h" +#include "../sphere/threads.h" #include "../game/CServer.h" +#include "sphere_library/sstringobjs.h" #include "CException.h" #include "CScript.h" #include "CLog.h" diff --git a/src/common/CLog.h b/src/common/CLog.h index 219a472d8..f644e22fe 100644 --- a/src/common/CLog.h +++ b/src/common/CLog.h @@ -9,7 +9,6 @@ #include "sphere_library/CSFileText.h" #include "sphere_library/CSTime.h" #include "../sphere/ConsoleInterface.h" -#include "../sphere/UnixTerminal.h" #include // ----------------------------- diff --git a/src/common/CPointBase.cpp b/src/common/CPointBase.cpp index 0c2f0a8ec..7f969a217 100644 --- a/src/common/CPointBase.cpp +++ b/src/common/CPointBase.cpp @@ -1,5 +1,8 @@ #include "../common/sphere_library/scontainer_ops.h" +#include "../common/CExpression.h" #include "../game/items/CItem.h" +#include "../game/uo_files/CUOMultiItemRec.h" +#include "../game/uo_files/CUOStaticItemRec.h" #include "../game/CSector.h" #include "../game/CServer.h" #include "../game/CWorldMap.h" @@ -9,6 +12,9 @@ #include "CPointBase.h" #include +#include "../game/uo_files/CUOMapList.h" + + static_assert(sizeof(CPointBase) == sizeof(CPointMap), "CPointBase and CPointMap have to have the same size. Was a virtual method added?"); DIR_TYPE GetDirTurn( DIR_TYPE dir, int offset ) diff --git a/src/common/CPointBase.h b/src/common/CPointBase.h index 48707e6b4..4e0670468 100644 --- a/src/common/CPointBase.h +++ b/src/common/CPointBase.h @@ -7,7 +7,6 @@ #define _INC_CPOINTBASE_H #include "../game/uo_files/uofiles_enums.h" -#include "../game/uo_files/CUOMapList.h" #include "../common/common.h" #include diff --git a/src/common/CSVFile.cpp b/src/common/CSVFile.cpp index df11d540e..da0f6c041 100644 --- a/src/common/CSVFile.cpp +++ b/src/common/CSVFile.cpp @@ -1,9 +1,7 @@ #include "../sphere/threads.h" -#include "CException.h" #include "CExpression.h" #include "CSVFile.h" -#include "CScript.h" #include "common.h" CSVFile::CSVFile() @@ -54,8 +52,8 @@ bool CSVFile::_Open(lpctstr ptcFilename, uint uiModeFlags) } // find the types and names of the columns - tchar * ppColumnTypes[MAX_COLUMNS]; - tchar * ppColumnNames[MAX_COLUMNS]; + tchar * ppColumnTypes[kuiMaxColumns]; + tchar * ppColumnNames[kuiMaxColumns]; // first row tells us how many columns there are _iColumnCount = _ReadRowContent(ppColumnTypes, 0); @@ -97,7 +95,7 @@ bool CSVFile::Open(lpctstr ptcFilename, uint uiModeFlags) int CSVFile::_ReadRowContent(tchar ** ppOutput, int rowIndex, int columns) { ADDTOCALLSTACK("CSVFile::_ReadRowContent"); - ASSERT(columns > 0 && columns <= MAX_COLUMNS); + ASSERT(columns > 0 && columns <= i32_from_u32_clamping(kuiMaxColumns)); if ( _GetPosition() != rowIndex ) _Seek(rowIndex, SEEK_SET); @@ -119,7 +117,7 @@ bool CSVFile::_ReadRowContent(int rowIndex, CSVRowData& target) { ADDTOCALLSTACK("CSVFile::_ReadRowContent"); // get row data - tchar * ppRowContent[MAX_COLUMNS]; + tchar * ppRowContent[kuiMaxColumns]; int columns = _ReadRowContent(ppRowContent, rowIndex); if ( columns != _iColumnCount ) return false; diff --git a/src/common/CSVFile.h b/src/common/CSVFile.h index 1d001a43e..a73991b4b 100644 --- a/src/common/CSVFile.h +++ b/src/common/CSVFile.h @@ -9,16 +9,14 @@ #include #include "CCacheableScriptFile.h" -#define MAX_COLUMNS 64 // maximum number of columns in a file - typedef std::map CSVRowData; class CSVFile : public CCacheableScriptFile { -private: - tchar * _pszColumnTypes[MAX_COLUMNS]; - tchar * _pszColumnNames[MAX_COLUMNS]; + static constexpr uint kuiMaxColumns = 64; // maximum number of columns in a file + tchar * _pszColumnTypes[kuiMaxColumns]; + tchar * _pszColumnNames[kuiMaxColumns]; int _iColumnCount; int _iCurrentRow; @@ -38,7 +36,7 @@ private: int _GetCurrentRow() const { return _iCurrentRow; } public: int GetCurrentRow() const; private: - int _ReadRowContent(tchar ** ppOutput, int row, int columns = MAX_COLUMNS); + int _ReadRowContent(tchar ** ppOutput, int row, int columns = kuiMaxColumns); bool _ReadRowContent(int row, CSVRowData& target); int _ReadNextRowContent(tchar ** ppOutput); diff --git a/src/common/CScript.cpp b/src/common/CScript.cpp index 3aea48af9..681b00ff9 100644 --- a/src/common/CScript.cpp +++ b/src/common/CScript.cpp @@ -809,12 +809,12 @@ void CScript::CloseForce() CScript::Close(); } -bool CScript::_SeekContext( CScriptLineContext LineContext ) +bool CScript::_SeekContext(const CScriptLineContext &LineContext ) { m_iLineNum = LineContext.m_iLineNum; return (_Seek( LineContext.m_iOffset, SEEK_SET ) == LineContext.m_iOffset); } -bool CScript::SeekContext( CScriptLineContext LineContext ) +bool CScript::SeekContext( CScriptLineContext const& LineContext ) { MT_UNIQUE_LOCK_RETURN(CScript::_SeekContext(LineContext)); } diff --git a/src/common/CScript.h b/src/common/CScript.h index 3caa1e8e4..855f87fe5 100644 --- a/src/common/CScript.h +++ b/src/common/CScript.h @@ -137,8 +137,8 @@ private: virtual void _Close() override; public: virtual void Close() override; private: virtual int _Seek( int iOffset = 0, int iOrigin = SEEK_SET ) override; public: virtual int Seek( int iOffset = 0, int iOrigin = SEEK_SET ) override; -private: bool _SeekContext( CScriptLineContext LineContext ); -public: bool SeekContext( CScriptLineContext LineContext ); +private: bool _SeekContext( CScriptLineContext const& LineContext ); +public: bool SeekContext( CScriptLineContext const& LineContext ); private: CScriptLineContext _GetContext() const; public: CScriptLineContext GetContext() const; diff --git a/src/common/CScriptObj.cpp b/src/common/CScriptObj.cpp index 0390d7d38..9653393aa 100644 --- a/src/common/CScriptObj.cpp +++ b/src/common/CScriptObj.cpp @@ -1,13 +1,7 @@ -#ifdef _WIN32 - #include -#else - #include - #include // errno - //#include -#endif - #include "../game/chars/CChar.h" +#include "../game/chars/CStoneMember.h" +#include "../game/items/CItem.h" #include "../game/clients/CAccount.h" #include "../game/clients/CClient.h" #include "../game/CScriptProfiler.h" @@ -20,15 +14,25 @@ #include "../sphere/ProfileTask.h" #include "crypto/CBCrypt.h" #include "crypto/CMD5.h" +#include "sphere_library/CSRand.h" #include "resource/sections/CResourceNamedDef.h" #include "resource/CResourceLock.h" #include "CFloatMath.h" #include "CExpression.h" #include "CSFileObjContainer.h" #include "CScriptTriggerArgs.h" +#include + +#ifdef _WIN32 +# include +#else +# include +# include // errno +// #include +#endif -class CStoneMember; +class CStoneMember; enum SREF_TYPE { @@ -976,16 +980,23 @@ bool CScriptObj::r_WriteVal( lpctstr ptcKey, CSString &sVal, CTextConsole * pSrc g_Log.EventError("%s failed when executing '%s'\n", sm_szLoadKeys[index], ptcKey); return false; } - else if ( child_pid == 0 ) + + if ( child_pid == 0 ) { //Don't touch this :P execlp( Arg_ppCmd[0], Arg_ppCmd[0], Arg_ppCmd[1], Arg_ppCmd[2], Arg_ppCmd[3], Arg_ppCmd[4], Arg_ppCmd[5], Arg_ppCmd[6], Arg_ppCmd[7], Arg_ppCmd[8], Arg_ppCmd[9], nullptr ); - g_Log.EventError("%s failed with error %d (\"%s\") when executing '%s'\n", sm_szLoadKeys[index], errno, strerror(errno), ptcKey); + g_Log.EventError( + "%s failed with error %d (\"%s\") when executing '%s'\n", + sm_szLoadKeys[index], errno, strerror(errno), ptcKey); + raise(SIGKILL); - g_Log.EventError("%s failed to handle error. Server is UNSTABLE\n", sm_szLoadKeys[index]); + + g_Log.EventError( + "%s failed to handle error. Server is UNSTABLE\n", + sm_szLoadKeys[index]); while(true) {} // do NOT leave here until the process receives SIGKILL otherwise it will free up resources // it inherited from the main process, which pretty will fuck everything up. Normally this point should never be reached. } diff --git a/src/common/CScriptObj.h b/src/common/CScriptObj.h index a952de5fc..df8b0e095 100644 --- a/src/common/CScriptObj.h +++ b/src/common/CScriptObj.h @@ -166,9 +166,8 @@ class CScriptObj CScriptObj() = default; virtual ~CScriptObj() = default; -private: - CScriptObj(const CScriptObj& copy); - CScriptObj& operator=(const CScriptObj& other); + CScriptObj(const CScriptObj& copy) = delete; + CScriptObj& operator=(const CScriptObj& other) = delete; }; #endif // _INC_CSCRIPTOBJ_H diff --git a/src/common/CServerMap.cpp b/src/common/CServerMap.cpp index 9eb6dcaec..72a684785 100644 --- a/src/common/CServerMap.cpp +++ b/src/common/CServerMap.cpp @@ -5,17 +5,18 @@ #include "CException.h" #include "CUOInstall.h" #include "CServerMap.h" -#include "CRect.h" -#include "../game/uo_files/CUOTerrainInfo.h" #include "../game/uo_files/CUOItemInfo.h" +#include "../game/uo_files/CUOMultiItemRec.h" +#include "../game/uo_files/CUOStaticItemRec.h" +#include "../game/uo_files/CUOTerrainInfo.h" #include "../game/CBase.h" #include "../common/CLog.h" -#include "../game/CObjBase.h" #include "../game/CServerConfig.h" #include "../game/CWorldGameTime.h" #include "../sphere/threads.h" + ////////////////////////////////////////////////////////////////// // -CServerMapBlockingState @@ -349,6 +350,18 @@ int CServerMapDiffBlockArray::CompareKey( dword id, CServerMapDiffBlock* pBase, ////////////////////////////////////////////////////////////////// // -CServerStaticsBlock +CServerStaticsBlock::CServerStaticsBlock() +{ + m_iStatics = 0; + m_pStatics = nullptr; +} + +CServerStaticsBlock::~CServerStaticsBlock() +{ + if ( m_pStatics != nullptr ) + delete[] m_pStatics; +} + void CServerStaticsBlock::LoadStatics( dword ulBlockIndex, int map ) { ADDTOCALLSTACK("CServerStaticsBlock::LoadStatics"); @@ -395,16 +408,18 @@ void CServerStaticsBlock::LoadStatics( uint uiCount, CUOStaticItemRec * pStatics } } -CServerStaticsBlock::CServerStaticsBlock() +const CUOStaticItemRec * CServerStaticsBlock::GetStatic( uint i ) const { - m_iStatics = 0; - m_pStatics = nullptr; + ASSERT( i < m_iStatics ); + return( &m_pStatics[i] ); } -CServerStaticsBlock::~CServerStaticsBlock() +bool CServerStaticsBlock::IsStaticPoint( uint i, int xo, int yo ) const { - if ( m_pStatics != nullptr ) - delete[] m_pStatics; + ASSERT( (xo >= 0) && (xo < UO_BLOCK_SIZE) ); + ASSERT( (yo >= 0) && (yo < UO_BLOCK_SIZE) ); + ASSERT( i < m_iStatics ); + return( (m_pStatics[i].m_x == xo) && (m_pStatics[i].m_y == yo) ); } ////////////////////////////////////////////////////////////////// diff --git a/src/common/CServerMap.h b/src/common/CServerMap.h index 3192bb766..5167a5b36 100644 --- a/src/common/CServerMap.h +++ b/src/common/CServerMap.h @@ -6,12 +6,17 @@ #define _INC_CSERVERMAP_H #include "../game/uo_files/CUOMapBlock.h" -#include "../game/uo_files/CUOStaticItemRec.h" -#include "../game/uo_files/CUOMultiItemRec.h" +#include "../game/uo_files/CUOMapList.h" #include "../game/uo_files/uofiles_macros.h" #include "../game/uo_files/uofiles_types.h" #include "sphere_library/CSObjSortArray.h" -#include "CRect.h" +#include "CPointBase.h" + + +struct CUOStaticItemRec; +struct CUOMultiItemRec_HS; + +// TODO: move some classes out from this file class CCachedMulItem { @@ -28,7 +33,6 @@ class CCachedMulItem CCachedMulItem(const CCachedMulItem& copy) = delete; CCachedMulItem& operator=(const CCachedMulItem& other) = delete; -public: void InitCacheTime(); bool IsTimeValid() const; void HitCacheTime(); @@ -37,13 +41,9 @@ class CCachedMulItem class CServerStaticsBlock { -private: uint m_iStatics; CUOStaticItemRec * m_pStatics; // dyn alloc array block. -public: - void LoadStatics(dword dwBlockIndex, int map); - void LoadStatics(uint uiCount, CUOStaticItemRec * pStatics); public: static const char *m_sClassName; CServerStaticsBlock(); @@ -53,22 +53,15 @@ class CServerStaticsBlock CServerStaticsBlock& operator=(const CServerStaticsBlock& other) = delete; public: + void LoadStatics(dword dwBlockIndex, int map); + void LoadStatics(uint uiCount, CUOStaticItemRec * pStatics); + // These methods are called so frequently but in so few pieces of code that's very important to inline them inline uint GetStaticQty() const { return m_iStatics; } - inline const CUOStaticItemRec * GetStatic( uint i ) const - { - ASSERT( i < m_iStatics ); - return( &m_pStatics[i] ); - } - inline bool IsStaticPoint( uint i, int xo, int yo ) const - { - ASSERT( (xo >= 0) && (xo < UO_BLOCK_SIZE) ); - ASSERT( (yo >= 0) && (yo < UO_BLOCK_SIZE) ); - ASSERT( i < m_iStatics ); - return( (m_pStatics[i].m_x == xo) && (m_pStatics[i].m_y == yo) ); - } + const CUOStaticItemRec * GetStatic( uint i ) const; + bool IsStaticPoint( uint i, int xo, int yo ) const; }; struct CServerMapBlocker @@ -110,7 +103,7 @@ struct CServerMapBlockingState CServerMapBlockingState& operator=(const CServerMapBlockingState& other) = delete; public: - bool CheckTile( uint64 uiItemBlockFlags, int8 zBottom, height_t zheight, dword wID ) noexcept; + bool CheckTile( uint64 uiItemBlockFlags, int8 zBottom, height_t zheight, dword wID ) noexcept; bool CheckTile_Item( uint64 uiItemBlockFlags, int8 zBottom, height_t zheight, dword wID ) noexcept; bool CheckTile_Terrain( uint64 uiItemBlockFlags, int8 z, dword dwID ) noexcept; static lpctstr GetTileName( dword dwID ); diff --git a/src/common/CTextConsole.cpp b/src/common/CTextConsole.cpp index 45fb8b239..b98c301e6 100644 --- a/src/common/CTextConsole.cpp +++ b/src/common/CTextConsole.cpp @@ -3,6 +3,7 @@ #include "../game/chars/CChar.h" #include "../sphere/threads.h" #include "sphere_library/CSAssoc.h" +#include "sphere_library/sstringobjs.h" #include "CTextConsole.h" @@ -144,4 +145,4 @@ void _cdecl CTextConsole::SysMessagef( lpctstr pszFormat, ... ) const va_start( vargs, pszFormat ); VSysMessage( pszFormat, vargs ); va_end( vargs ); -} \ No newline at end of file +} diff --git a/src/common/CTextConsole.h b/src/common/CTextConsole.h index 172804699..5429f4f85 100644 --- a/src/common/CTextConsole.h +++ b/src/common/CTextConsole.h @@ -6,13 +6,12 @@ #ifndef _INC_CTEXTCONSOLE_H #define _INC_CTEXTCONSOLE_H -#include "sphere_library/sstringobjs.h" -#include "common.h" +#include "sphere_library/CSString.h" class CChar; -enum PLEVEL_TYPE // Priviledge (priv) levels. +enum PLEVEL_TYPE : int // Priviledge (priv) levels. { PLEVEL_Guest = 0, // 0 = This is just a guest account. (cannot PK) PLEVEL_Player, // 1 = Player or NPC. diff --git a/src/common/CUID.cpp b/src/common/CUID.cpp index fae5417b8..665829852 100644 --- a/src/common/CUID.cpp +++ b/src/common/CUID.cpp @@ -1,4 +1,5 @@ #include "../game/chars/CChar.h" +#include "../game/items/CItem.h" #include "../game/CWorld.h" #include "CUID.h" diff --git a/src/common/CUOInstall.cpp b/src/common/CUOInstall.cpp index 5fd909e33..2240ced2c 100644 --- a/src/common/CUOInstall.cpp +++ b/src/common/CUOInstall.cpp @@ -1,10 +1,9 @@ - -#include "../common/CLog.h" +#include "../game/uo_files/CUOMultiItemRec.h" #include "../game/CServerConfig.h" #include "../sphere/threads.h" -#include "CUOInstall.h" -#include "common.h" #include "CException.h" +#include "CLog.h" +#include "CUOInstall.h" #include #define MAP_MAX_SUPPORTED_INDEX 6 diff --git a/src/common/CUOInstall.h b/src/common/CUOInstall.h index f4417d531..11328ffd4 100644 --- a/src/common/CUOInstall.h +++ b/src/common/CUOInstall.h @@ -83,9 +83,8 @@ extern struct CUOInstall public: CUOInstall(); -private: - CUOInstall(const CUOInstall& copy); - CUOInstall& operator=(const CUOInstall& other); + CUOInstall(const CUOInstall& copy) = delete; + CUOInstall& operator=(const CUOInstall& other) = delete; } g_Install; /////////////////////////////////////////////////////////////////////////////// @@ -110,9 +109,9 @@ extern class CVerDataMul public: CVerDataMul(); ~CVerDataMul(); -private: - CVerDataMul(const CVerDataMul& copy); - CVerDataMul& operator=(const CVerDataMul& other); + + CVerDataMul(const CVerDataMul& copy) = delete; + CVerDataMul& operator=(const CVerDataMul& other) = delete; } g_VerData; #endif // _INC_CUOINSTALL_H diff --git a/src/common/CVarDefMap.h b/src/common/CVarDefMap.h index 0bfa84aad..5f5bcc039 100644 --- a/src/common/CVarDefMap.h +++ b/src/common/CVarDefMap.h @@ -18,7 +18,7 @@ class CVarDefCont public: static const char *m_sClassName; - CVarDefCont() = default; + CVarDefCont() = default; virtual ~CVarDefCont(); CVarDefCont(const CVarDefCont& copy) = delete; diff --git a/src/common/ListDefContMap.h b/src/common/ListDefContMap.h index 7f5f8995f..db86bc11e 100644 --- a/src/common/ListDefContMap.h +++ b/src/common/ListDefContMap.h @@ -8,7 +8,6 @@ #include #include -#include "common.h" #include "sphere_library/CSString.h" diff --git a/src/common/common.cpp b/src/common/common.cpp index 9d6f7e4f0..e41b313aa 100644 --- a/src/common/common.cpp +++ b/src/common/common.cpp @@ -1,10 +1,6 @@ // contains also some methods/functions declared in os_windows.h and os_unix.h -#include "common.h" -#include "sphereproto.h" -#include // iswalnum - extern "C" { // Put this here as just the starting offset. Needed by Windows crash dump. @@ -14,6 +10,7 @@ extern "C" #ifndef _WIN32 #ifdef _BSD + #include "common.h" #include #include #include @@ -28,6 +25,7 @@ extern "C" #else // _WIN32 + #include "common.h" const OSVERSIONINFO * Sphere_GetOSInfo() noexcept { // NEVER return nullptr ! @@ -46,54 +44,3 @@ extern "C" return &g_osInfo; } #endif // !_WIN32 - - -// TODO: move those in a separate cpp file. - -CLanguageID::CLanguageID(int iDefault) noexcept : - m_codes{} -{ - UnreferencedParameter(iDefault); - ASSERT(iDefault == 0); -} - -void CLanguageID::GetStrDef(tchar* pszLang) noexcept -{ - if (!IsDef()) - { - strcpy(pszLang, "enu"); // NOLINT(clang-analyzer-security.insecureAPI.strcpy) - } - else - { - memcpy(pszLang, m_codes, 3); - pszLang[3] = '\0'; - } -} - -void CLanguageID::GetStr(tchar* pszLang) const noexcept -{ - memcpy(pszLang, m_codes, 3); - pszLang[3] = '\0'; -} - -lpctstr CLanguageID::GetStr() const -{ - tchar* pszTmp = Str_GetTemp(); - GetStr(pszTmp); - return pszTmp; -} - -bool CLanguageID::Set(lpctstr pszLang) noexcept -{ - // needs not be terminated! - if (pszLang != nullptr) - { - memcpy(m_codes, pszLang, 3); - m_codes[3] = 0; - if (iswalnum(m_codes[0])) - return true; - // not valid ! - } - m_codes[0] = 0; - return false; -} diff --git a/src/common/crypto/CCryptoTwoFishInterface.cpp b/src/common/crypto/CCryptoTwoFishInterface.cpp index a1b402039..1a986a986 100644 --- a/src/common/crypto/CCryptoTwoFishInterface.cpp +++ b/src/common/crypto/CCryptoTwoFishInterface.cpp @@ -1,6 +1,7 @@ +#include "../../network/net_datatypes.h" #include "../../sphere/threads.h" -#include "../sphereproto.h" #include "CCrypto.h" +#include extern "C" { #include diff --git a/src/common/crypto/CMD5.h b/src/common/crypto/CMD5.h index 6d335b88b..1cad81592 100644 --- a/src/common/crypto/CMD5.h +++ b/src/common/crypto/CMD5.h @@ -12,7 +12,6 @@ #define _INC_CMD5_H #include "../datatypes.h" -#include class CMD5 { diff --git a/src/common/os_windows.h b/src/common/os_windows.h index c564ef059..9d8b08f31 100644 --- a/src/common/os_windows.h +++ b/src/common/os_windows.h @@ -48,7 +48,16 @@ #define NOTEXTMETRIC #define NOWH -#include +# ifdef _MSC_VER +// Workaround to a possible VS compiler bug: instead of complaining if a macro expands to a "defined" macro, +// it complains if a define macro contains the words "defined" in its name... +# pragma warning(push) +# pragma warning(disable: 5105) +# endif +# include +# ifdef _MSC_VER +# pragma warning(pop) +# endif /* file handling definitions */ diff --git a/src/common/resource/CResourceDef.cpp b/src/common/resource/CResourceDef.cpp index bd127118a..f14941743 100644 --- a/src/common/resource/CResourceDef.cpp +++ b/src/common/resource/CResourceDef.cpp @@ -4,7 +4,6 @@ */ #include "../../sphere/threads.h" -#include "../CVarDefMap.h" #include "../CExpression.h" #include "../CLog.h" #include "CResourceDef.h" diff --git a/src/common/resource/CResourceHash.h b/src/common/resource/CResourceHash.h index f9200af6e..6c6262e59 100644 --- a/src/common/resource/CResourceHash.h +++ b/src/common/resource/CResourceHash.h @@ -6,7 +6,6 @@ #ifndef _INC_CRESOURCEHASH_H #define _INC_CRESOURCEHASH_H -#include "../sphere_library/CSObjSortArray.h" #include "../sphere_library/sptr_containers.h" #include "CResourceID.h" diff --git a/src/common/resource/CResourceHolder.cpp b/src/common/resource/CResourceHolder.cpp index d2fe6ec22..e2c5f355a 100644 --- a/src/common/resource/CResourceHolder.cpp +++ b/src/common/resource/CResourceHolder.cpp @@ -1,16 +1,11 @@ -#include "../../game/chars/CChar.h" -#include "../../game/items/CItem.h" -#include "../../game/triggers.h" -#include "../../game/game_enums.h" -#include "../../game/game_macros.h" #include "../sphere_library/CSFileList.h" #include "../CException.h" +#include "../CExpression.h" #include "../CLog.h" #include "CResourceHolder.h" #include "CResourceHash.h" #include "CResourceScript.h" -#include "CResourceSortedArrays.h" //*************************************************** diff --git a/src/common/resource/CResourceHolder.h b/src/common/resource/CResourceHolder.h index abd276e03..a5c4b40d5 100644 --- a/src/common/resource/CResourceHolder.h +++ b/src/common/resource/CResourceHolder.h @@ -6,15 +6,15 @@ #ifndef _INC_CResourceHolder_H #define _INC_CResourceHolder_H -#include "../sphere_library/CSTime.h" -#include "../CScriptContexts.h" +#include "../sphere_library/CSObjArray.h" +#include "../sphere_library/CSString.h" #include "CResourceDef.h" #include "CResourceHash.h" #include "CResourceLink.h" -#include "CResourceScript.h" -#include "CResourceQty.h" +class CResourceScript; + class CResourceHolder : public CScriptObj { protected: diff --git a/src/common/resource/CResourceID.h b/src/common/resource/CResourceID.h index b887e8b60..ada40c648 100644 --- a/src/common/resource/CResourceID.h +++ b/src/common/resource/CResourceID.h @@ -122,8 +122,9 @@ dword ResGetIndex(dword dwObjUid) noexcept { } -struct CResourceIDBase : public CUID +class CResourceIDBase : public CUID { +public: // Unlike CResourceID, CResourceIDBase has not the "page" part/variable. // Use it to store defnames or UIDs of world objects (items, chars...) or spawns and templates. diff --git a/src/common/resource/CResourceQty.cpp b/src/common/resource/CResourceQty.cpp index 203c842fc..5d03f5458 100644 --- a/src/common/resource/CResourceQty.cpp +++ b/src/common/resource/CResourceQty.cpp @@ -8,8 +8,8 @@ #include "../../game/chars/CChar.h" #include "../../game/CObjBase.h" #include "../../sphere/threads.h" +#include "../CExpression.h" #include "../CLog.h" -#include "CResourceHolder.h" #include "CResourceQty.h" diff --git a/src/common/resource/CResourceQty.h b/src/common/resource/CResourceQty.h index fbe795b58..c265eaa0f 100644 --- a/src/common/resource/CResourceQty.h +++ b/src/common/resource/CResourceQty.h @@ -6,7 +6,7 @@ #ifndef _INC_CRESOURCEQTY_H #define _INC_CRESOURCEQTY_H -#include "../sphere_library/CSTypedArray.h" // Needed for constants +#include "../sphere_library/ssorted_vector.h" #include "CResourceID.h" diff --git a/src/common/resource/CResourceRef.cpp b/src/common/resource/CResourceRef.cpp index e8939441c..500a427ee 100644 --- a/src/common/resource/CResourceRef.cpp +++ b/src/common/resource/CResourceRef.cpp @@ -4,7 +4,6 @@ */ #include "../../game/CServerConfig.h" -#include "../../game/CServer.h" #include "../CException.h" #include "../CScript.h" #include "CResourceRef.h" @@ -207,3 +206,12 @@ void CResourceRefArray::r_Write( CScript & s, lpctstr ptcKey ) const s.WriteKeyStr( ptcKey, GetResourceName( j )); } } + +bool CResourceRefArray::ContainsResourceID( const CResourceID & rid ) const +{ + return FindResourceID(rid) != sl::scont_bad_index(); +} +bool CResourceRefArray::ContainsResourceName( RES_TYPE restype, lpctstr & ptcKey ) const +{ + return FindResourceName(restype, ptcKey) != sl::scont_bad_index(); +} diff --git a/src/common/resource/CResourceRef.h b/src/common/resource/CResourceRef.h index f217c2cc2..6c01a71b4 100644 --- a/src/common/resource/CResourceRef.h +++ b/src/common/resource/CResourceRef.h @@ -7,10 +7,10 @@ #define _INC_CRESOURCEREF_H #include "CResourceLink.h" -#include "CResourceID.h" #include class CSString; +struct CResourceID; class CResourceLink; class CScript; @@ -62,14 +62,8 @@ class CResourceRefArray : public std::vector bool r_LoadVal( CScript & s, RES_TYPE restype ); void r_Write( CScript & s, lpctstr ptcKey ) const; - inline bool ContainsResourceID( const CResourceID & rid ) const - { - return FindResourceID(rid) != sl::scont_bad_index(); - } - inline bool ContainsResourceName( RES_TYPE restype, lpctstr & ptcKey ) const - { - return FindResourceName(restype, ptcKey) != sl::scont_bad_index(); - } + bool ContainsResourceID( const CResourceID & rid ) const; + bool ContainsResourceName( RES_TYPE restype, lpctstr & ptcKey ) const; }; diff --git a/src/common/resource/CResourceScript.h b/src/common/resource/CResourceScript.h index 3710462cd..9fa4da247 100644 --- a/src/common/resource/CResourceScript.h +++ b/src/common/resource/CResourceScript.h @@ -45,11 +45,10 @@ class CResourceScript : public CScript private: bool _CheckForChange(); public: bool CheckForChange(); -private: - CResourceScript(const CResourceScript& copy); - CResourceScript& operator=(const CResourceScript& other); - public: + CResourceScript(const CResourceScript& copy) = delete; + CResourceScript& operator=(const CResourceScript& other) = delete; + bool IsFirstCheck() const noexcept { return (m_dwSize == UINT32_MAX && !m_dateChange.IsTimeValid()); diff --git a/src/common/resource/CResourceSortedArrays.cpp b/src/common/resource/CResourceSortedArrays.cpp index 6af010d28..14cbb63c5 100644 --- a/src/common/resource/CResourceSortedArrays.cpp +++ b/src/common/resource/CResourceSortedArrays.cpp @@ -5,6 +5,7 @@ #include "../sphere_library/CSAssoc.h" #include "../sphere_library/sstring.h" +#include "../../game/items/CItemMulti.h" #include "../CScriptObj.h" #include "CResourceSortedArrays.h" diff --git a/src/common/resource/CResourceSortedArrays.h b/src/common/resource/CResourceSortedArrays.h index e35f7df05..95b6daf70 100644 --- a/src/common/resource/CResourceSortedArrays.h +++ b/src/common/resource/CResourceSortedArrays.h @@ -6,9 +6,12 @@ #ifndef _INC_CRESOURCESORTEDARRAYS_H #define _INC_CRESOURCESORTEDARRAYS_H +#include "../../common/sphere_library/CSObjSortArray.h" #include "../../common/sphere_library/sptr_containers.h" -#include "../CServerMap.h" +#include "../../game/uo_files/uofiles_types.h" +class CScriptObj; +class CUOMulti; struct CValStr; diff --git a/src/common/resource/CValueDefs.cpp b/src/common/resource/CValueDefs.cpp index 2f281a454..fe1def35a 100644 --- a/src/common/resource/CValueDefs.cpp +++ b/src/common/resource/CValueDefs.cpp @@ -1,5 +1,5 @@ #include "../../sphere/threads.h" -#include "../CException.h" +#include "../sphere_library/CSRand.h" #include "../CExpression.h" #include "CValueDefs.h" diff --git a/src/common/resource/CValueDefs.h b/src/common/resource/CValueDefs.h index 5cdb33e52..6d2e3ba2f 100644 --- a/src/common/resource/CValueDefs.h +++ b/src/common/resource/CValueDefs.h @@ -7,7 +7,7 @@ #define _INC_CVALUEDEFS_H #include "../sphere_library/CSTypedArray.h" - +#include "../common.h" /** * @struct CValueRangeDef diff --git a/src/common/resource/sections/CRandGroupDef.cpp b/src/common/resource/sections/CRandGroupDef.cpp index 7341ef79c..f9e6408c0 100644 --- a/src/common/resource/sections/CRandGroupDef.cpp +++ b/src/common/resource/sections/CRandGroupDef.cpp @@ -2,7 +2,9 @@ #include "../../../game/chars/CChar.h" #include "../../../game/CServerConfig.h" #include "../../../game/triggers.h" +#include "../../sphere_library/CSRand.h" #include "../../CException.h" +#include "../../CExpression.h" #include "CRegionResourceDef.h" #include "CRandGroupDef.h" @@ -184,7 +186,10 @@ bool CRandGroupDef::r_WriteVal( lpctstr ptcKey, CSString &sVal, CTextConsole * p tchar *pszTmp = Str_GetTemp(); m_Members.WriteKeys( pszTmp, Str_TempLength(), index, fQtyOnly, fKeyOnly ); if ( fQtyOnly && pszTmp[0] == '\0' ) - strcpy( pszTmp, "0" ); + { + pszTmp[0] = '0'; + pszTmp[1] = '\0'; + } sVal = pszTmp; } diff --git a/src/common/resource/sections/CRandGroupDef.h b/src/common/resource/sections/CRandGroupDef.h index 035d94732..bcfb9f02e 100644 --- a/src/common/resource/sections/CRandGroupDef.h +++ b/src/common/resource/sections/CRandGroupDef.h @@ -21,10 +21,10 @@ */ class CRandGroupDef : public CResourceLink { -private: static lpctstr const sm_szLoadKeys[]; int m_iTotalWeight; CResourceQtyArray m_Members; + private: int CalcTotalWeight(); public: @@ -39,9 +39,8 @@ class CRandGroupDef : public CResourceLink CSString m_sSubsection; // Axis SubSection CSString m_sDescription; // Axis Description -private: - CRandGroupDef(const CRandGroupDef& copy); - CRandGroupDef& operator=(const CRandGroupDef& other); + CRandGroupDef(const CRandGroupDef& copy) = delete; + CRandGroupDef& operator=(const CRandGroupDef& other) = delete; public: virtual bool r_LoadVal( CScript & s ) override; diff --git a/src/common/resource/sections/CResourceNamedDef.h b/src/common/resource/sections/CResourceNamedDef.h index bf950ff7e..18b961b62 100644 --- a/src/common/resource/sections/CResourceNamedDef.h +++ b/src/common/resource/sections/CResourceNamedDef.h @@ -17,9 +17,8 @@ class CResourceNamedDef : public CResourceLink CResourceNamedDef(const CResourceID& rid, lpctstr pszName); virtual ~CResourceNamedDef() = default; -private: - CResourceNamedDef(const CResourceNamedDef& copy); - CResourceNamedDef& operator=(const CResourceNamedDef& other); + CResourceNamedDef(const CResourceNamedDef& copy) = delete; + CResourceNamedDef& operator=(const CResourceNamedDef& other) = delete; public: virtual lpctstr GetName() const override; diff --git a/src/common/resource/sections/CSpellDef.cpp b/src/common/resource/sections/CSpellDef.cpp index 1ab3c0b13..9bc0d5ed8 100644 --- a/src/common/resource/sections/CSpellDef.cpp +++ b/src/common/resource/sections/CSpellDef.cpp @@ -160,7 +160,12 @@ bool CSpellDef::r_WriteVal( lpctstr ptcKey, CSString & sVal, CTextConsole * pSrc tchar *pszTmp = Str_GetTemp(); m_Reags.WriteKeys( pszTmp, Str_TempLength(), index, fQtyOnly, fKeyOnly ); if ( fQtyOnly && pszTmp[0] == '\0' ) - strcpy( pszTmp, "0" ); // Return 0 for empty quantity + { + // Return 0 for empty quantity. + pszTmp[0] = '0'; + pszTmp[1] = '\0'; + } + sVal = pszTmp; } else diff --git a/src/common/resource/sections/CSpellDef.h b/src/common/resource/sections/CSpellDef.h index c786623fc..24dd98e89 100644 --- a/src/common/resource/sections/CSpellDef.h +++ b/src/common/resource/sections/CSpellDef.h @@ -6,8 +6,11 @@ #ifndef _INC_CSPELLDEF_H #define _INC_CSPELLDEF_H +#include "../../../game/uo_files/uofiles_enums.h" #include "../../../game/uo_files/uofiles_enums_itemid.h" #include "../../../game/uo_files/uofiles_types.h" +#include "../../resource/CValueDefs.h" +#include "../../sphere_library/CSString.h" #include "../CResourceQty.h" #include "../CResourceLink.h" diff --git a/src/common/resource/sections/CWebPageDef.cpp b/src/common/resource/sections/CWebPageDef.cpp index 9cdaf9035..9816ad0ef 100644 --- a/src/common/resource/sections/CWebPageDef.cpp +++ b/src/common/resource/sections/CWebPageDef.cpp @@ -1,11 +1,13 @@ #include "../../../game/chars/CChar.h" #include "../../../game/clients/CClient.h" +#include "../../../game/items/CItemStone.h" #include "../../../game/CServer.h" #include "../../../game/CWorld.h" #include "../../../game/CWorldGameTime.h" #include "../../../network/CClientIterator.h" #include "../../sphere_library/CSFileList.h" #include "../../CException.h" +#include "../../CExpression.h" #include "../../sphereversion.h" #include "../CResourceLock.h" #include "CWebPageDef.h" diff --git a/src/common/resource/sections/CWebPageDef.h b/src/common/resource/sections/CWebPageDef.h index c17ec276e..bd4040bbb 100644 --- a/src/common/resource/sections/CWebPageDef.h +++ b/src/common/resource/sections/CWebPageDef.h @@ -8,7 +8,6 @@ #include "../../CTextConsole.h" #include "../CResourceLink.h" -#include "../CValueDefs.h" class CSTime; class CClient; diff --git a/src/common/sphere_library/CSAssoc.h b/src/common/sphere_library/CSAssoc.h index d129c3088..a9cc00688 100644 --- a/src/common/sphere_library/CSAssoc.h +++ b/src/common/sphere_library/CSAssoc.h @@ -6,8 +6,8 @@ #ifndef _INC_CSASSOC_H #define _INC_CSASSOC_H +#include "../sphere_library/CSString.h" #include "CSObjList.h" -#include "CSFile.h" // ----------------------------- diff --git a/src/common/sphere_library/CSFileText.cpp b/src/common/sphere_library/CSFileText.cpp index 1dae1d039..686437c9f 100644 --- a/src/common/sphere_library/CSFileText.cpp +++ b/src/common/sphere_library/CSFileText.cpp @@ -1,5 +1,4 @@ #include "../../sphere/threads.h" -#include "../CLog.h" #include "CSFileText.h" #ifdef _WIN32 diff --git a/src/common/sphere_library/CSFileText.h b/src/common/sphere_library/CSFileText.h index 012337474..f8912cad7 100644 --- a/src/common/sphere_library/CSFileText.h +++ b/src/common/sphere_library/CSFileText.h @@ -6,7 +6,6 @@ #define _INC_CSFILETEXT_H #include "CSFile.h" -#include /** * @brief Text files. Try to be compatible with MFC CFile class. @@ -22,15 +21,15 @@ class CSFileText : public CSFile public: CSFileText(); virtual ~CSFileText(); -private: + /** * @brief No copy on construction allowed. */ - CSFileText(const CSFileText& copy); + CSFileText(const CSFileText& copy) = delete; /** * @brief No copy allowed. */ - CSFileText& operator=(const CSFileText& other); + CSFileText& operator=(const CSFileText& other) = delete; ///@} /** @name File management: */ diff --git a/src/common/sphere_library/CSObjCont.cpp b/src/common/sphere_library/CSObjCont.cpp index 58e5614cd..4ce5e0320 100644 --- a/src/common/sphere_library/CSObjCont.cpp +++ b/src/common/sphere_library/CSObjCont.cpp @@ -1,6 +1,6 @@ -#include "CSObjCont.h" #include "../assertion.h" #include "../CException.h" +#include "CSObjCont.h" #include diff --git a/src/common/sphere_library/CSObjCont.h b/src/common/sphere_library/CSObjCont.h index d007a41b6..e0174b1ab 100644 --- a/src/common/sphere_library/CSObjCont.h +++ b/src/common/sphere_library/CSObjCont.h @@ -7,6 +7,7 @@ #define _INC_CSOBJCONT_H #include "CSObjContRec.h" +#include #include #include // for std::move diff --git a/src/common/sphere_library/CSObjContRec.h b/src/common/sphere_library/CSObjContRec.h index 48d01fd72..83bd81c52 100644 --- a/src/common/sphere_library/CSObjContRec.h +++ b/src/common/sphere_library/CSObjContRec.h @@ -6,7 +6,6 @@ #ifndef _INC_CSOBJCONTREC_H #define _INC_CSOBJCONTREC_H -#include // for nullptr class CSObjCont; diff --git a/src/common/sphere_library/CSObjList.h b/src/common/sphere_library/CSObjList.h index 4d6dfc265..dc0401953 100644 --- a/src/common/sphere_library/CSObjList.h +++ b/src/common/sphere_library/CSObjList.h @@ -7,6 +7,7 @@ #define _INC_CSOBJLIST_H #include "CSObjListRec.h" +#include class CSObjList { diff --git a/src/common/sphere_library/CSObjListRec.h b/src/common/sphere_library/CSObjListRec.h index 41ce921d8..819a07141 100644 --- a/src/common/sphere_library/CSObjListRec.h +++ b/src/common/sphere_library/CSObjListRec.h @@ -6,7 +6,6 @@ #ifndef _INC_CSOBJLISTREC_H #define _INC_CSOBJLISTREC_H -#include // for nullptr class CSObjList; diff --git a/src/common/sphere_library/CSReferenceCount.h b/src/common/sphere_library/CSReferenceCount.h index c698962c8..111519ba4 100644 --- a/src/common/sphere_library/CSReferenceCount.h +++ b/src/common/sphere_library/CSReferenceCount.h @@ -6,10 +6,6 @@ #ifndef _INC_CSREFERENCECOUNT_H #define _INC_CSREFERENCECOUNT_H -#include -#include -//#include - template class CSReferenceCountedOwned; //template @@ -128,6 +124,10 @@ class CSReferenceCountedOwned /* Not yet working +#include +#include +//#include + template class CSReferenceCountedVariant : protected std::variant, CSReferenceCountedOwned> { diff --git a/src/common/sphere_library/CSTime.cpp b/src/common/sphere_library/CSTime.cpp index b2d28dc8a..bc1ee97d4 100644 --- a/src/common/sphere_library/CSTime.cpp +++ b/src/common/sphere_library/CSTime.cpp @@ -4,12 +4,12 @@ // Replace the MFC CTime function. Must be usable with file system. // -#include -#include -#include "CSTime.h" -#include "CSString.h" -#include "../../common/CLog.h" #include "../../sphere/threads.h" +#include "../CLog.h" +#include "sstring.h" +#include "CSTime.h" +#include +//#include // Windows epoch is January 1, 1601 (start of Gregorian calendar cycle) diff --git a/src/common/sphere_library/smutex.cpp b/src/common/sphere_library/smutex.cpp index 011699fae..a6faa28e0 100644 --- a/src/common/sphere_library/smutex.cpp +++ b/src/common/sphere_library/smutex.cpp @@ -1,4 +1,6 @@ +#ifdef _WIN32 #define _WIN32_DCOM +#endif #include "smutex.h" // SimpleMutex:: Constructors, Destructor, Asign operator. diff --git a/src/common/sphere_library/smutex.h b/src/common/sphere_library/smutex.h index 13c673618..29192ab41 100644 --- a/src/common/sphere_library/smutex.h +++ b/src/common/sphere_library/smutex.h @@ -6,13 +6,14 @@ #ifndef _INC_SMUTEX_H #define _INC_SMUTEX_H -#include "../common.h" #ifndef _WIN32 - #include +# include +#else +# include "../common.h" #endif #ifdef _BSD - #define PTHREAD_MUTEX_RECURSIVE_NP PTHREAD_MUTEX_RECURSIVE +# define PTHREAD_MUTEX_RECURSIVE_NP PTHREAD_MUTEX_RECURSIVE #endif @@ -21,6 +22,14 @@ */ class SimpleMutex { +private: +#ifdef _WIN32 + CRITICAL_SECTION m_criticalSection; // Windows API specific mutex. +#else + pthread_mutex_t m_criticalSection; // Unix API specific mutex. + pthread_mutexattr_t m_criticalSectionAttr; // Unix API mutex attr. +#endif + public: /** @name Constructors, Destructor, Asign operator: */ @@ -79,15 +88,6 @@ class SimpleMutex #endif } ///@} - -private: -#ifdef _WIN32 - CRITICAL_SECTION m_criticalSection; // Windows API specific mutex. -#else - pthread_mutex_t m_criticalSection; // Unix API specific mutex. - pthread_mutexattr_t m_criticalSectionAttr; // Unix API mutex attr. -#endif - }; /** diff --git a/src/common/sphereproto.h b/src/common/sphereproto.h index 2f659c7a2..ab1a3aaed 100644 --- a/src/common/sphereproto.h +++ b/src/common/sphereproto.h @@ -7,41 +7,11 @@ #define _INC_SPHEREPROTO_H #include "../network/net_datatypes.h" -#include "../sphere/threads.h" -#include "sphere_library/CSString.h" //---------------------------PROTOCOL DEFS--------------------------- -class CLanguageID -{ - // 3 letter code for language. - // ENU,FRA,DEU,etc. (see langcode.iff) - // terminate with a 0 - // 0 = english default. - char m_codes[4]; // UNICODE language pref. ('ENU'=english) - -public: - CLanguageID() noexcept : - m_codes{} - {} - CLanguageID( const char * pszInit ) noexcept - { - Set( pszInit ); - } - CLanguageID(int iDefault) noexcept; - - bool IsDef() const noexcept - { - return ( m_codes[0] != 0 ); - } - void GetStrDef(tchar* pszLang) noexcept; - void GetStr(tchar* pszLang) const noexcept; - lpctstr GetStr() const; - bool Set(lpctstr pszLang) noexcept; -}; - enum XCMD_TYPE // XCMD_* messages are unique in both directions. { // 0x00 diff --git a/src/game/CBase.cpp b/src/game/CBase.cpp index da66090dd..cd0311d11 100644 --- a/src/game/CBase.cpp +++ b/src/game/CBase.cpp @@ -1,8 +1,7 @@ #include "../common/CException.h" +#include "../common/CExpression.h" #include "../common/common.h" -#include "components/CCPropsItemChar.h" -#include "components/CCPropsItemWeapon.h" #include "CServerConfig.h" #include "CBase.h" #include diff --git a/src/game/CBase.h b/src/game/CBase.h index e9843fe02..52e26582d 100644 --- a/src/game/CBase.h +++ b/src/game/CBase.h @@ -6,8 +6,8 @@ #ifndef _INC_CBASE_H #define _INC_CBASE_H -#include "../common/resource/CResourceHolder.h" #include "../common/resource/CResourceRef.h" +#include "../common/resource/CResourceQty.h" #include "../common/CVarDefMap.h" #include "../common/sphere_library/CSString.h" #include "uo_files/uofiles_types.h" diff --git a/src/game/CComponent.cpp b/src/game/CComponent.cpp index c171944ba..4554859cc 100644 --- a/src/game/CComponent.cpp +++ b/src/game/CComponent.cpp @@ -1,6 +1,5 @@ #include "CComponent.h" -#include "CObjBase.h" CComponent::CComponent(COMP_TYPE type) noexcept : _iType(type) diff --git a/src/game/CContainer.cpp b/src/game/CContainer.cpp index 740efb8a7..aa2e2062a 100644 --- a/src/game/CContainer.cpp +++ b/src/game/CContainer.cpp @@ -1,12 +1,11 @@ +#include "../common/sphere_library/CSRand.h" #include "../common/CException.h" +#include "../common/CExpression.h" #include "../common/CUID.h" #include "../network/send.h" #include "chars/CChar.h" -#include "items/CItem.h" #include "items/CItemContainer.h" -#include "items/CItemVendable.h" -#include "CObjBaseTemplate.h" #include "triggers.h" #include "CContainer.h" @@ -214,7 +213,7 @@ void CContainer::r_WriteContent( CScript &s ) const } } -CItem *CContainer::ContentFind( CResourceID rid, dword dwArg, int iDecendLevels ) const +CItem *CContainer::ContentFind( CResourceID const& rid, dword dwArg, int iDecendLevels ) const { ADDTOCALLSTACK("CContainer::ContentFind"); // send all the items in the container. @@ -244,9 +243,8 @@ CItem *CContainer::ContentFind( CResourceID rid, dword dwArg, int iDecendLevels return nullptr; } -TRIGRET_TYPE CContainer::OnContTriggerForLoop( - CScript &s, CTextConsole *pSrc, CScriptTriggerArgs *pArgs, - CSString *pResult, CScriptLineContext &StartContext, CScriptLineContext &EndContext, CResourceID rid, dword dwArg, int iDecendLevels ) +TRIGRET_TYPE CContainer::OnContTriggerForLoop(CScript &s, CTextConsole *pSrc, CScriptTriggerArgs *pArgs, + CSString *pResult, CScriptLineContext &StartContext, CScriptLineContext &EndContext, const CResourceID &rid, dword dwArg, int iDecendLevels ) { ADDTOCALLSTACK("CContainer::OnContTriggerForLoop"); if ( rid.GetResIndex() != 0 ) diff --git a/src/game/CContainer.h b/src/game/CContainer.h index 530d30ae1..239b21433 100644 --- a/src/game/CContainer.h +++ b/src/game/CContainer.h @@ -7,13 +7,19 @@ #define _INC_CCONTAINER_H #include "../common/sphere_library/CSObjCont.h" -#include "../common/resource/CResourceHolder.h" -#include "../common/CUID.h" -#include "../common/CRect.h" +#include "../common/CScriptObj.h" +class CSString; +class CItem; class CItemContainer; class CObjBase; +struct CPointMap; +struct CScriptLineContext; +class CScriptTriggerArgs; +class CResourceQtyArray; +struct CResourceID; +class CTextConsole; class CContainer : public CSObjCont // This class contains a list of items but may or may not be an item itself. { @@ -127,7 +133,7 @@ class CContainer : public CSObjCont // This class contains a list of items but m * @param iDecendLevels Zero-based index of the decend levels. * @return null if it fails, else a pointer to a CItem. */ - CItem * ContentFind( CResourceID rid, dword dwArg = 0, int iDecendLevels = 255 ) const; + CItem * ContentFind( CResourceID const& rid, dword dwArg = 0, int iDecendLevels = 255 ) const; /** * @fn TRIGRET_TYPE CContainer::OnContTriggerForLoop( CScript &s, CTextConsole * pSrc, CScriptTriggerArgs * pArgs, CSString * pResult, CScriptLineContext & StartContext, CScriptLineContext & EndContext, RESOURCE_ID_BASE rid, dword dwArg = 0, int iDecendLevels = 255 ); @@ -144,7 +150,7 @@ class CContainer : public CSObjCont // This class contains a list of items but m * * @return A TRIGRET_TYPE. */ - TRIGRET_TYPE OnContTriggerForLoop( CScript &s, CTextConsole * pSrc, CScriptTriggerArgs * pArgs, CSString * pResult, CScriptLineContext & StartContext, CScriptLineContext & EndContext, CResourceID rid, dword dwArg = 0, int iDecendLevels = 255 ); + TRIGRET_TYPE OnContTriggerForLoop( CScript &s, CTextConsole * pSrc, CScriptTriggerArgs * pArgs, CSString * pResult, CScriptLineContext & StartContext, CScriptLineContext & EndContext, CResourceID const& rid, dword dwArg = 0, int iDecendLevels = 255 ); /** * @fn TRIGRET_TYPE CContainer::OnGenericContTriggerForLoop( CScript &s, CTextConsole * pSrc, CScriptTriggerArgs * pArgs, CSString * pResult, CScriptLineContext & StartContext, CScriptLineContext & EndContext, int iDecendLevels = 255 ); diff --git a/src/game/CEntity.cpp b/src/game/CEntity.cpp index 08a4ba113..923bbf137 100644 --- a/src/game/CEntity.cpp +++ b/src/game/CEntity.cpp @@ -1,10 +1,9 @@ +#include "../sphere/threads.h" #include "../common/CException.h" #include "../common/CLog.h" +#include "../common/CScript.h" #include "CEntity.h" #include "CComponent.h" -#include "chars/CChar.h" -#include "items/CItem.h" -#include "CObjBase.h" CEntity::CEntity() diff --git a/src/game/CEntity.h b/src/game/CEntity.h index 47d0afa23..2e83551c6 100644 --- a/src/game/CEntity.h +++ b/src/game/CEntity.h @@ -8,7 +8,6 @@ #include #include "CComponent.h" -#include class CEntity { diff --git a/src/game/CEntityProps.cpp b/src/game/CEntityProps.cpp index 44ba8921c..f7575c5cb 100644 --- a/src/game/CEntityProps.cpp +++ b/src/game/CEntityProps.cpp @@ -1,11 +1,5 @@ #include "../common/CLog.h" #include "chars/CChar.h" -#include "components/CCPropsChar.h" -#include "components/CCPropsItem.h" -#include "components/CCPropsItemChar.h" -#include "components/CCPropsItemEquippable.h" -#include "components/CCPropsItemWeapon.h" -#include "components/CCPropsItemWeaponRanged.h" #include "CEntityProps.h" CEntityProps::CEntityProps() diff --git a/src/game/CObjBase.cpp b/src/game/CObjBase.cpp index 6086b849c..fdec42ab5 100644 --- a/src/game/CObjBase.cpp +++ b/src/game/CObjBase.cpp @@ -1,6 +1,7 @@ - +#include "../common/sphere_library/CSRand.h" #include "../common/resource/CResourceLock.h" #include "../common/CException.h" +#include "../common/CExpression.h" #include "../common/sphereversion.h" #include "../common/CLog.h" #include "../network/CClientIterator.h" @@ -8,6 +9,7 @@ #include "../sphere/ProfileTask.h" #include "chars/CChar.h" #include "clients/CClient.h" +#include "clients/CClientTooltip.h" #include "components/CCChampion.h" #include "components/CCPropsItemWeapon.h" #include "components/CCSpawn.h" diff --git a/src/game/CObjBase.h b/src/game/CObjBase.h index c0e485fb2..b94b37b6b 100644 --- a/src/game/CObjBase.h +++ b/src/game/CObjBase.h @@ -6,21 +6,20 @@ #ifndef _INC_COBJBASE_H #define _INC_COBJBASE_H -#include "../common/resource/CResourceHolder.h" #include "../common/resource/CResourceRef.h" +#include "../common/CLanguageID.h" #include "../common/CScriptObj.h" -#include "clients/CClientTooltip.h" #include "CObjBaseTemplate.h" #include "CTimedObject.h" #include "CEntity.h" #include "CBase.h" #include "CServerConfig.h" -#include class PacketSend; class PacketPropertyList; class CCSpawn; +class CClientTooltip; class CSector; class CWorldTicker; diff --git a/src/game/CObjBaseTemplate.cpp b/src/game/CObjBaseTemplate.cpp index a1542fdd6..dedc5512c 100644 --- a/src/game/CObjBaseTemplate.cpp +++ b/src/game/CObjBaseTemplate.cpp @@ -1,5 +1,4 @@ #include "../sphere/threads.h" -#include "uo_files/uofiles_macros.h" #include "CObjBaseTemplate.h" #include "CServerConfig.h" diff --git a/src/game/CRegion.cpp b/src/game/CRegion.cpp index 7ffcef3b4..42a44f355 100644 --- a/src/game/CRegion.cpp +++ b/src/game/CRegion.cpp @@ -1,18 +1,16 @@ // Common for client and server. - #include "../common/resource/sections/CRandGroupDef.h" #include "../common/resource/CResourceLock.h" -#include "../common/CScript.h" +#include "../common/CExpression.h" #include "../network/CClientIterator.h" -#include "../sphere/threads.h" #include "chars/CChar.h" #include "clients/CClient.h" +#include "items/CItem.h" #include "CSector.h" #include "CSectorList.h" #include "CServer.h" - //************************************************************************* // -CRegion @@ -131,7 +129,7 @@ bool CRegion::MakeRegionDefname() lpctstr ptcKey = nullptr; // auxiliary, the key of a similar CVarDef, if any found tchar * pbuf = Str_GetTemp(); tchar * pszDef = pbuf + 2; - strcpy(pbuf, "a_"); + strncpy(pbuf, "a_", Str_TempLength()); lpctstr pszName = GetName(); GETNONWHITESPACE( pszName ); diff --git a/src/game/CRegion.h b/src/game/CRegion.h index c72755abc..fd8db13fc 100644 --- a/src/game/CRegion.h +++ b/src/game/CRegion.h @@ -6,10 +6,8 @@ #ifndef _INC_CREGION_H #define _INC_CREGION_H -#include "../common/resource/CResourceHolder.h" #include "../common/resource/CResourceRef.h" #include "../common/CVarDefMap.h" -#include "CTeleport.h" #include "CRegionBase.h" diff --git a/src/game/CResourceCalc.cpp b/src/game/CResourceCalc.cpp index 03809108f..ad4a78e0c 100644 --- a/src/game/CResourceCalc.cpp +++ b/src/game/CResourceCalc.cpp @@ -1,11 +1,12 @@ // The physics calculations of the world. -#include "CServerConfig.h" -#include "CServerTime.h" +#include "../common/sphere_library/CSRand.h" #include "chars/CChar.h" #include "chars/CCharNPC.h" +#include "../common/CExpression.h" #include "components/CCPropsChar.h" - +#include "items/CItem.h" +#include "CServerConfig.h" //******************************** // Movement @@ -683,4 +684,4 @@ bool CServerConfig::Calc_CurePoisonChance(const CItem* pPoison, int iCureLevel, } return (g_Rand.GetVal(100) <= iCureChance); -} \ No newline at end of file +} diff --git a/src/game/CScriptProfiler.h b/src/game/CScriptProfiler.h index 4fa0b8958..93daf4fe0 100644 --- a/src/game/CScriptProfiler.h +++ b/src/game/CScriptProfiler.h @@ -6,7 +6,7 @@ #ifndef _INC_CSCRIPTPROFILER_H #define _INC_CSCRIPTPROFILER_H -#include "../common/sphere_library/CSTime.h" +#include "../common/common.h" extern struct CScriptProfiler { diff --git a/src/game/CSector.cpp b/src/game/CSector.cpp index d792531e2..bf6402cfe 100644 --- a/src/game/CSector.cpp +++ b/src/game/CSector.cpp @@ -1,5 +1,6 @@ - +#include "../common/sphere_library/CSRand.h" #include "../common/CException.h" +#include "../common/CExpression.h" #include "../common/CLog.h" #include "../sphere/ProfileTask.h" #include "../sphere/ProfileData.h" diff --git a/src/game/CSectorList.cpp b/src/game/CSectorList.cpp index 1f97e80bd..d99514400 100644 --- a/src/game/CSectorList.cpp +++ b/src/game/CSectorList.cpp @@ -1,5 +1,4 @@ #include "../common/sphere_library/sstringobjs.h" -#include "../common/assertion.h" #include "../common/CLog.h" #include "CWorld.h" #include "CSectorList.h" diff --git a/src/game/CSectorList.h b/src/game/CSectorList.h index 840e3c190..7f2bec4d0 100644 --- a/src/game/CSectorList.h +++ b/src/game/CSectorList.h @@ -8,7 +8,6 @@ #include "uo_files/CUOMapList.h" #include "CSector.h" -#include class CSectorList diff --git a/src/game/CSectorTemplate.cpp b/src/game/CSectorTemplate.cpp index 35281a2a1..56fa4da28 100644 --- a/src/game/CSectorTemplate.cpp +++ b/src/game/CSectorTemplate.cpp @@ -1,14 +1,12 @@ -#include -#include "../common/CException.h" #include "../common/CLog.h" #include "../common/CRect.h" #include "../game/CWorld.h" -#include "../sphere/ProfileTask.h" #include "chars/CChar.h" #include "items/CItemShip.h" #include "CSectorList.h" #include "CWorldGameTime.h" #include "CSectorTemplate.h" +#include //////////////////////////////////////////////////////////////////////// diff --git a/src/game/CSectorTemplate.h b/src/game/CSectorTemplate.h index 2b9200ce5..8260e669c 100644 --- a/src/game/CSectorTemplate.h +++ b/src/game/CSectorTemplate.h @@ -11,14 +11,14 @@ #include "../common/CRect.h" #include "CTeleport.h" - +class CChar; class CItem; class CSector; class CTeleport; struct CSectorObjCont { - // Marker class. + // Marker class, consider it as a "tag". }; struct CCharsDisconnectList : public CSObjCont, public CSectorObjCont diff --git a/src/game/CServer.cpp b/src/game/CServer.cpp index bb5c67dee..354749a43 100644 --- a/src/game/CServer.cpp +++ b/src/game/CServer.cpp @@ -1,6 +1,7 @@ #ifdef _WIN32 - #include "../sphere/ntservice.h" // g_Service + #include "../sphere/ntservice.h" // g_Service + #include "../sphere/ntwindow.h" // g_NTWindow #else #include "../sphere/UnixTerminal.h" #include // for setpriority @@ -11,9 +12,8 @@ #endif #include "../common/crypto/CCryptoKeyCalc.h" -#include "../common/sphere_library/CSAssoc.h" -#include "../common/sphere_library/CSFileList.h" #include "../common/CException.h" +#include "../common/CExpression.h" #include "../common/CLog.h" #include "../common/CTextConsole.h" #include "../common/CUOClientVersion.h" @@ -22,12 +22,9 @@ #include "../network/CIPHistoryManager.h" #include "../network/CNetworkManager.h" #include "../sphere/ProfileTask.h" -#include "../sphere/ntwindow.h" #include "chars/CChar.h" #include "clients/CAccount.h" -#include "clients/CChatChannel.h" #include "clients/CClient.h" -#include "items/CItemShip.h" #include "CScriptProfiler.h" #include "CServer.h" #include "CWorld.h" diff --git a/src/game/CServerConfig.cpp b/src/game/CServerConfig.cpp index a54c7a625..b5a56b9e5 100644 --- a/src/game/CServerConfig.cpp +++ b/src/game/CServerConfig.cpp @@ -4,15 +4,15 @@ #include "../common/resource/sections/CRandGroupDef.h" #include "../common/resource/sections/CRegionResourceDef.h" #include "../common/resource/sections/CResourceNamedDef.h" -#include "../common/sphere_library/CSFileList.h" +#include "../common/sphere_library/CSRand.h" #include "../common/CException.h" +#include "../common/CExpression.h" #include "../common/CUOInstall.h" #include "../common/sphereversion.h" #include "../network/CClientIterator.h" #include "../network/CNetworkManager.h" #include "../network/CSocket.h" #include "../sphere/ProfileTask.h" -#include "../sphere/ntwindow.h" #include "clients/CAccount.h" #include "clients/CClient.h" #include "chars/CChar.h" @@ -33,6 +33,10 @@ #include "spheresvr.h" #include "triggers.h" +#ifdef _WIN32 +# include "../sphere/ntwindow.h" // g_NTWindow +#endif + #include #ifndef OFFSETOF //# define OFFSETOF(TYPE, ELEMENT) (offsetof(TYPE, ELEMENT)) @@ -736,6 +740,7 @@ enum RC_TYPE // NOTE: Need to be alphabetized order // TODO: use offsetof by cstddef. Though, it requires the class/struct to be a POD type, so we need to encapsulate the values in a separate struct. +// This hack does happen because this class hasn't virtual methods? Or simply because the compiler is so smart and protects us from ourselves? #ifdef __GNUC__ #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wzero-as-null-pointer-constant" diff --git a/src/game/CServerConfig.h b/src/game/CServerConfig.h index 8d67d01d8..615bb6e99 100644 --- a/src/game/CServerConfig.h +++ b/src/game/CServerConfig.h @@ -16,7 +16,6 @@ #include "../common/resource/CResourceScript.h" #include "../common/resource/CResourceSortedArrays.h" #include "../common/resource/CValueDefs.h" -#include "../common/CExpression.h" #include "../common/CServerMap.h" #include "../common/CTextConsole.h" #include "../common/sphereproto.h" diff --git a/src/game/CServerDef.cpp b/src/game/CServerDef.cpp index e23d12c29..232c7a691 100644 --- a/src/game/CServerDef.cpp +++ b/src/game/CServerDef.cpp @@ -1,11 +1,11 @@ #include "../common/CException.h" +#include "../common/CExpression.h" #include "../common/sphereproto.h" #include "../common/sphereversion.h" #include "../common/CLog.h" #include "../common/CScriptTriggerArgs.h" #include "../sphere/threads.h" -#include "CObjBase.h" #include "CServer.h" #include "CServerConfig.h" #include "CServerDef.h" diff --git a/src/game/CServerDef.h b/src/game/CServerDef.h index b89174c20..120c5332f 100644 --- a/src/game/CServerDef.h +++ b/src/game/CServerDef.h @@ -9,6 +9,7 @@ #include "../network/CSocket.h" #include "../common/crypto/CCrypto.h" #include "../common/sphere_library/CSTime.h" +#include "../common/sphere_library/CSString.h" #include "../common/CScriptObj.h" diff --git a/src/game/CServerTime.cpp b/src/game/CServerTime.cpp index 2378698fd..4e7ef22ce 100644 --- a/src/game/CServerTime.cpp +++ b/src/game/CServerTime.cpp @@ -1,3 +1,4 @@ +#include "../common/CExpression.h" #include "CServerConfig.h" #include "CServerTime.h" diff --git a/src/game/CTeleport.cpp b/src/game/CTeleport.cpp index 1b07a7193..871ce7019 100644 --- a/src/game/CTeleport.cpp +++ b/src/game/CTeleport.cpp @@ -1,7 +1,7 @@ -#include "CTeleport.h" #include "../common/CLog.h" #include "../sphere/threads.h" #include "CSector.h" +#include "CTeleport.h" //************************************************************************ diff --git a/src/game/CTimedFunction.cpp b/src/game/CTimedFunction.cpp index 1e803fbca..da6667d6e 100644 --- a/src/game/CTimedFunction.cpp +++ b/src/game/CTimedFunction.cpp @@ -1,7 +1,6 @@ #include "../common/sphere_library/sstring.h" #include "../common/CLog.h" #include "../sphere/threads.h" -#include "../sphere/ProfileTask.h" #include "CObjBase.h" #include "CServer.h" #include "CTimedFunctionHandler.h" diff --git a/src/game/CTimedFunctionHandler.cpp b/src/game/CTimedFunctionHandler.cpp index 3c57dc1a5..85b4fcd72 100644 --- a/src/game/CTimedFunctionHandler.cpp +++ b/src/game/CTimedFunctionHandler.cpp @@ -1,6 +1,5 @@ #include "../common/CLog.h" #include "../common/CUID.h" -#include "../sphere/ProfileTask.h" #include "CObjBase.h" #include "CServerConfig.h" #include "CServerTime.h" diff --git a/src/game/CWorld.cpp b/src/game/CWorld.cpp index 5abeb62ef..1d09fa9e3 100644 --- a/src/game/CWorld.cpp +++ b/src/game/CWorld.cpp @@ -1,5 +1,5 @@ -#include "../common/CDataBase.h" #include "../common/CException.h" +#include "../common/CExpression.h" #include "../common/sphereversion.h" #include "../network/CClientIterator.h" #include "../network/CNetworkManager.h" @@ -9,6 +9,7 @@ #include "clients/CClient.h" #include "clients/CGMPage.h" #include "items/CItemMulti.h" +#include "items/CItemStone.h" #include "CServer.h" #include "CScriptProfiler.h" #include "CSector.h" diff --git a/src/game/CWorldClock.cpp b/src/game/CWorldClock.cpp index 92918414f..654448595 100644 --- a/src/game/CWorldClock.cpp +++ b/src/game/CWorldClock.cpp @@ -1,7 +1,6 @@ -#include "../common/CException.h" +#include "../common/CLog.h" #include "../sphere/threads.h" #include "CWorldClock.h" -#include #include int64 CWorldClock::GetSystemClock() noexcept // static diff --git a/src/game/CWorldComm.cpp b/src/game/CWorldComm.cpp index dd7a33f1c..d7d3f56a8 100644 --- a/src/game/CWorldComm.cpp +++ b/src/game/CWorldComm.cpp @@ -1,5 +1,5 @@ +#include "../common/sphere_library/CSRand.h" #include "../network/CClientIterator.h" -#include "../common/CLog.h" #include "chars/CChar.h" #include "clients/CClient.h" #include "CWorldComm.h" diff --git a/src/game/CWorldComm.h b/src/game/CWorldComm.h index fe1a0212b..065d101b7 100644 --- a/src/game/CWorldComm.h +++ b/src/game/CWorldComm.h @@ -7,6 +7,7 @@ #define _INC_CWORLDCOMM_H #include "../common/common.h" +#include "../common/CLanguageID.h" #include "../common/sphereproto.h" #include "uo_files/uofiles_enums.h" #include "uo_files/uofiles_types.h" diff --git a/src/game/CWorldImport.cpp b/src/game/CWorldImport.cpp index d9216cdf2..693d4c9d4 100644 --- a/src/game/CWorldImport.cpp +++ b/src/game/CWorldImport.cpp @@ -1,10 +1,13 @@ +#include "../common/CExpression.h" #include "../common/CLog.h" #include "chars/CChar.h" #include "items/CItem.h" +#include "uo_files/uofiles_enums_creid.h" #include "CObjBase.h" #include "CWorld.h" #include "CWorldSearch.h" + struct CImportSer : public CSObjListRec { // Temporary holding structure for new objects being impoted. diff --git a/src/game/CWorldMap.cpp b/src/game/CWorldMap.cpp index b05df9f72..3ca2e35ac 100644 --- a/src/game/CWorldMap.cpp +++ b/src/game/CWorldMap.cpp @@ -10,6 +10,7 @@ #include "chars/CChar.h" #include "items/CItem.h" #include "items/CItemMultiCustom.h" +#include "uo_files/CUOStaticItemRec.h" #include "uo_files/CUOTerrainInfo.h" #include "uo_files/CUOMapList.h" #include "triggers.h" diff --git a/src/game/CWorldSearch.cpp b/src/game/CWorldSearch.cpp index f3f4f1fa5..e811d9e41 100644 --- a/src/game/CWorldSearch.cpp +++ b/src/game/CWorldSearch.cpp @@ -1,10 +1,9 @@ -#include "CWorldSearch.h" -#include "CSector.h" #include "../common/CException.h" #include "../common/CLog.h" #include "../game/chars/CChar.h" #include "../game/items/CItem.h" -#include "../sphere/threads.h" +#include "CSector.h" +#include "CWorldSearch.h" #include static constexpr size_t kuiContainerScaleFactor = 2; diff --git a/src/game/CWorldTickingList.cpp b/src/game/CWorldTickingList.cpp index 119259240..30a29028b 100644 --- a/src/game/CWorldTickingList.cpp +++ b/src/game/CWorldTickingList.cpp @@ -2,6 +2,7 @@ #include "CWorldTicker.h" #include "CWorldTickingList.h" + void CWorldTickingList::AddObjSingle(int64 iTimeout, CTimedObject* pObj, bool fForce) // static { //The lock on pObj should already be acquired by CTimedObject::SetTimeout diff --git a/src/game/CWorldTickingList.h b/src/game/CWorldTickingList.h index 7341566ae..e6f80f0fe 100644 --- a/src/game/CWorldTickingList.h +++ b/src/game/CWorldTickingList.h @@ -5,6 +5,8 @@ #ifndef _INC_CWORLDTICKINGLIST_H #define _INC_CWORLDTICKINGLIST_H +#include "../common/common.h" + class CTimedObject; class CObjBase; class CChar; diff --git a/src/game/CWorldTimedFunctions.cpp b/src/game/CWorldTimedFunctions.cpp index 573efd078..04f27f765 100644 --- a/src/game/CWorldTimedFunctions.cpp +++ b/src/game/CWorldTimedFunctions.cpp @@ -2,6 +2,7 @@ #include "CWorld.h" #include "CWorldTimedFunctions.h" + void CWorldTimedFunctions::ClearUID(const CUID& uid ) // static { g_World._Ticker._TimedFunctions.ClearUID(uid); diff --git a/src/game/chars/CChar.cpp b/src/game/chars/CChar.cpp index f53797d4a..43d7917d2 100644 --- a/src/game/chars/CChar.cpp +++ b/src/game/chars/CChar.cpp @@ -1,7 +1,9 @@ // CChar is either an NPC or a Player. +#include "../../common/sphere_library/CSRand.h" #include "../../common/resource/CResourceLock.h" #include "../../common/CException.h" +#include "../../common/CExpression.h" #include "../../common/CUID.h" #include "../../common/CRect.h" #include "../../common/CLog.h" @@ -12,6 +14,7 @@ #include "../items/CItemMemory.h" #include "../items/CItemShip.h" #include "../items/CItemMulti.h" +#include "../items/CItemStone.h" #include "../components/CCPropsChar.h" #include "../components/CCPropsItemChar.h" #include "../components/CCSpawn.h" @@ -23,9 +26,9 @@ #include "../CWorldMap.h" #include "../CWorldTickingList.h" #include "../triggers.h" -#include "CChar.h" #include "CCharBase.h" #include "CCharNPC.h" +#include "CChar.h" #include diff --git a/src/game/chars/CChar.h b/src/game/chars/CChar.h index 9855a0235..c5a5434d9 100644 --- a/src/game/chars/CChar.h +++ b/src/game/chars/CChar.h @@ -8,22 +8,27 @@ #include "../../common/sphereproto.h" #include "../clients/CParty.h" -#include "../items/CItemContainer.h" -#include "../items/CItemCorpse.h" -#include "../items/CItemMemory.h" -#include "../items/CItemStone.h" -#include "../game_macros.h" +#include "../CContainer.h" #include "../CObjBase.h" #include "../CTimedObject.h" +#include "../game_macros.h" #include "CCharBase.h" #include "CCharPlayer.h" -class CWorldTicker; class CCharNPC; -class CMapBlockingState; class CFactionDef; - +class CItem; +class CItemContainer; +class CItemCorpse; +class CItemMemory; +class CItemVendable; +class CItemStone; +class CMapBlockingState; +class CStoneMember; +class CWorldTicker; +enum MEMORY_TYPE : int; +enum IT_TYPE : int32_t; enum NPCBRAIN_TYPE // General AI type. { diff --git a/src/game/chars/CCharAct.cpp b/src/game/chars/CCharAct.cpp index fbad02be7..d5475a04c 100644 --- a/src/game/chars/CCharAct.cpp +++ b/src/game/chars/CCharAct.cpp @@ -1,15 +1,17 @@ -#include #include "../../common/resource/CResourceLock.h" +#include "../../common/sphere_library/CSRand.h" #include "../../common/CException.h" +#include "../../common/CExpression.h" +#include "../../common/CUOInstall.h" #include "../../network/CClientIterator.h" #include "../../network/send.h" #include "../../sphere/ProfileTask.h" #include "../clients/CClient.h" -#include "../items/CItem.h" +#include "../items/CItemCorpse.h" +#include "../items/CItemMemory.h" #include "../items/CItemMultiCustom.h" #include "../components/CCSpawn.h" #include "../components/CCPropsChar.h" -#include "../components/CCPropsItemChar.h" #include "../components/CCPropsItemEquippable.h" #include "../components/CCPropsItemWeapon.h" #include "../CContainer.h" @@ -19,11 +21,11 @@ #include "../CWorldMap.h" #include "../CWorldSearch.h" #include "../CWorldTickingList.h" -#include "../spheresvr.h" #include "../triggers.h" #include "CChar.h" #include "CCharNPC.h" -#include "../../common/CUOInstall.h" +#include + // "GONAME", "GOTYPE", "GOCHAR" // 0 = object name diff --git a/src/game/chars/CCharAttacker.cpp b/src/game/chars/CCharAttacker.cpp index 19d53e45f..d899bde75 100644 --- a/src/game/chars/CCharAttacker.cpp +++ b/src/game/chars/CCharAttacker.cpp @@ -1,4 +1,5 @@ // Actions specific to an NPC. +#include "../../common/CExpression.h" #include "../clients/CClient.h" #include "../triggers.h" #include "CChar.h" diff --git a/src/game/chars/CCharBase.cpp b/src/game/chars/CCharBase.cpp index 4914a6063..10e1ecc39 100644 --- a/src/game/chars/CCharBase.cpp +++ b/src/game/chars/CCharBase.cpp @@ -4,6 +4,8 @@ #include "../../common/CLog.h" #include "../components/CCPropsChar.h" #include "../components/CCPropsItemChar.h" +#include "../uo_files/uofiles_enums_creid.h" +#include "../uo_files/uofiles_enums_itemid.h" #include "../CServerConfig.h" #include "CCharBase.h" diff --git a/src/game/chars/CCharBase.h b/src/game/chars/CCharBase.h index cf7d10314..b9ab65131 100644 --- a/src/game/chars/CCharBase.h +++ b/src/game/chars/CCharBase.h @@ -6,17 +6,15 @@ #ifndef _INC_CCHARBASE_H #define _INC_CCHARBASE_H -#include "../../common/sphere_library/CSString.h" -#include "../../common/resource/CResourceHolder.h" -#include "../../common/sphereproto.h" -#include "../../common/CScriptObj.h" -#include "../../common/CTextConsole.h" -#include "../uo_files/uofiles_enums_creid.h" #include "../CBase.h" -class CScript; class CFactionDef; +class CScript; +class CSString; +class CTextConsole; +enum CREID_TYPE : uint32_t; +enum ITEMID_TYPE : uint32_t; class CCharBase : public CBaseBaseDef // define basic info about each "TYPE" of monster/creature. { diff --git a/src/game/chars/CCharFight.cpp b/src/game/chars/CCharFight.cpp index 4fbda8182..3ce5c26ba 100644 --- a/src/game/chars/CCharFight.cpp +++ b/src/game/chars/CCharFight.cpp @@ -1,11 +1,14 @@ // Fight/Criminal actions/Noto. +#include "../../common/sphere_library/CSRand.h" +#include "../../common/CExpression.h" #include "../../network/send.h" #include "../clients/CClient.h" #include "../components/CCPropsChar.h" #include "../components/CCPropsItemEquippable.h" #include "../components/CCPropsItemWeapon.h" +#include "../items/CItemMemory.h" #include "../CWorldGameTime.h" #include "../CWorldSearch.h" #include "../triggers.h" diff --git a/src/game/chars/CCharLOS.cpp b/src/game/chars/CCharLOS.cpp index f49421f22..a65c1b719 100644 --- a/src/game/chars/CCharLOS.cpp +++ b/src/game/chars/CCharLOS.cpp @@ -1,4 +1,7 @@ #include "../../common/CLog.h" +#include "../items/CItemMulti.h" +#include "../uo_files/CUOMultiItemRec.h" +#include "../uo_files/CUOStaticItemRec.h" #include "../uo_files/CUOTerrainInfo.h" #include "../CWorldMap.h" #include "../CWorldSearch.h" diff --git a/src/game/chars/CCharMemory.cpp b/src/game/chars/CCharMemory.cpp index 4b32b0ac7..aec3dc846 100644 --- a/src/game/chars/CCharMemory.cpp +++ b/src/game/chars/CCharMemory.cpp @@ -1,8 +1,9 @@ // Actions specific to an NPC. - +#include "../../common/CExpression.h" #include "../../network/send.h" -#include "../clients/CClient.h" +#include "../items/CItemMemory.h" +#include "../items/CItemStone.h" #include "../CWorldGameTime.h" #include "CChar.h" #include "CCharNPC.h" diff --git a/src/game/chars/CCharNPC.cpp b/src/game/chars/CCharNPC.cpp index 5782c5ce6..eaf48d8e3 100644 --- a/src/game/chars/CCharNPC.cpp +++ b/src/game/chars/CCharNPC.cpp @@ -4,6 +4,7 @@ #include "../../common/resource/CResourceLock.h" #include "../../common/CException.h" #include "../clients/CClient.h" +#include "../items/CItemContainer.h" #include "../CServer.h" #include "../triggers.h" #include "CCharNPC.h" diff --git a/src/game/chars/CCharNPCAct.cpp b/src/game/chars/CCharNPCAct.cpp index f9c28d38b..7499958f0 100644 --- a/src/game/chars/CCharNPCAct.cpp +++ b/src/game/chars/CCharNPCAct.cpp @@ -1,10 +1,15 @@ // Actions specific to an NPC. +#include "../../common/sphere_library/CSRand.h" #include "../../common/resource/CResourceLock.h" #include "../../common/CException.h" +#include "../../common/CExpression.h" #include "../../network/receive.h" #include "../clients/CClient.h" +#include "../items/CItemCorpse.h" +#include "../items/CItemMemory.h" +#include "../uo_files/uofiles_enums_creid.h" #include "../CWorldGameTime.h" #include "../CWorldMap.h" #include "../CWorldSearch.h" diff --git a/src/game/chars/CCharNPCAct_Fight.cpp b/src/game/chars/CCharNPCAct_Fight.cpp index 3b9133dc2..041db4ffd 100644 --- a/src/game/chars/CCharNPCAct_Fight.cpp +++ b/src/game/chars/CCharNPCAct_Fight.cpp @@ -1,8 +1,10 @@ // Actions specific to an NPC. +#include "../../common/sphere_library/CSRand.h" #include "../../common/CLog.h" #include "../../common/CScriptTriggerArgs.h" -#include "../../network/receive.h" #include "../components/CCPropsItemWeapon.h" +#include "../items/item_types.h" +#include "../uo_files/uofiles_enums_creid.h" #include "../CPathFinder.h" #include "../triggers.h" #include "CChar.h" diff --git a/src/game/chars/CCharNPCAct_Magic.cpp b/src/game/chars/CCharNPCAct_Magic.cpp index d963de302..1f7f5814d 100644 --- a/src/game/chars/CCharNPCAct_Magic.cpp +++ b/src/game/chars/CCharNPCAct_Magic.cpp @@ -1,6 +1,9 @@ // Actions specific to an NPC. +#include "../../common/sphere_library/CSRand.h" #include "../../common/CScriptTriggerArgs.h" +#include "../items/CItemContainer.h" +#include "../items/CItemMemory.h" #include "../triggers.h" #include "../CWorldMap.h" #include "../CWorldSearch.h" diff --git a/src/game/chars/CCharNPCAct_Vendor.cpp b/src/game/chars/CCharNPCAct_Vendor.cpp index 5c183fedf..6fd99e9ff 100644 --- a/src/game/chars/CCharNPCAct_Vendor.cpp +++ b/src/game/chars/CCharNPCAct_Vendor.cpp @@ -1,10 +1,11 @@ // Actions specific to an NPC. -#include "../../network/receive.h" +#include "../../common/CExpression.h" #include "../clients/CClient.h" +#include "../items/CItemContainer.h" +#include "../items/CItemMemory.h" #include "../CWorldGameTime.h" #include "../CPathFinder.h" -#include "../spheresvr.h" #include "../triggers.h" #include "CChar.h" #include "CCharNPC.h" @@ -306,7 +307,7 @@ bool CChar::NPC_OnTrainPay(CChar *pCharSrc, CItemMemory *pMemory, CItem * pGold) { int iDiffPercent = IMulDiv(wTrainCost, 100, pGold->GetAmount()); uiTrainVal = (ushort)IMulDiv(uiTrainVal,100,iDiffPercent); - wTrainCost = (word)pCharSrc->PayGold(this, (word)minimum(UINT16_MAX, uiTrainVal * uiTrainMult), pGold, PAYGOLD_TRAIN); + /* wTrainCost = (word)*/ pCharSrc->PayGold(this, (word)minimum(UINT16_MAX, uiTrainVal * uiTrainMult), pGold, PAYGOLD_TRAIN); } else if (wGoldAmount == wTrainCost) { diff --git a/src/game/chars/CCharNPCPet.cpp b/src/game/chars/CCharNPCPet.cpp index c4e64aec0..ae2d7d137 100644 --- a/src/game/chars/CCharNPCPet.cpp +++ b/src/game/chars/CCharNPCPet.cpp @@ -1,7 +1,11 @@ // Actions specific to an NPC. +#include "../../common/sphere_library/CSRand.h" +#include "../../common/CExpression.h" #include "../clients/CClient.h" #include "../components/CCSpawn.h" +#include "../items/CItemContainer.h" +#include "../items/CItemMemory.h" #include "../items/CItemVendable.h" #include "../CServerTime.h" #include "../triggers.h" diff --git a/src/game/chars/CCharNPCStatus.cpp b/src/game/chars/CCharNPCStatus.cpp index bda2802d7..83fc88f21 100644 --- a/src/game/chars/CCharNPCStatus.cpp +++ b/src/game/chars/CCharNPCStatus.cpp @@ -1,14 +1,18 @@ // Test things to judge what an NPC might be thinking. (want to do) // But take no actions here. + +#include "../../common/CExpression.h" #include "../../common/CLog.h" +#include "../items/CItemContainer.h" +#include "../items/CItemMemory.h" #include "../items/CItemVendable.h" +#include "../uo_files/uofiles_enums_creid.h" #include "../CWorldGameTime.h" -#include "../CWorldMap.h" #include "../CWorldSearch.h" -#include "../spheresvr.h" #include "CChar.h" #include "CCharNPC.h" + CREID_TYPE CChar::NPC_GetAllyGroupType(CREID_TYPE idTest) // static { ADDTOCALLSTACK("CChar::NPC_GetAllyGroupType"); diff --git a/src/game/chars/CCharNotoriety.cpp b/src/game/chars/CCharNotoriety.cpp index 4c2e3f6af..e5d561103 100644 --- a/src/game/chars/CCharNotoriety.cpp +++ b/src/game/chars/CCharNotoriety.cpp @@ -1,5 +1,9 @@ // Actions specific to an NPC. -#include "../clients/CClient.h" +#include "../../common/CExpression.h" +#include "../../common/CException.h" +#include "../../common/CScriptTriggerArgs.h" +#include "../items/CItemMemory.h" +#include "../items/CItemStone.h" #include "../triggers.h" #include "CChar.h" #include "CCharNPC.h" diff --git a/src/game/chars/CCharPlayer.cpp b/src/game/chars/CCharPlayer.cpp index 3aea3915d..dad515de2 100644 --- a/src/game/chars/CCharPlayer.cpp +++ b/src/game/chars/CCharPlayer.cpp @@ -4,8 +4,10 @@ #include "../../common/resource/sections/CSkillClassDef.h" #include "../../common/CLog.h" #include "../../common/CException.h" +#include "../../common/CExpression.h" #include "../clients/CClient.h" #include "../items/CItemMulti.h" +#include "../items/CItemStone.h" #include "../CServer.h" #include "../CWorld.h" #include "../CWorldGameTime.h" diff --git a/src/game/chars/CCharPlayer.h b/src/game/chars/CCharPlayer.h index 19a0eb08f..cac375775 100644 --- a/src/game/chars/CCharPlayer.h +++ b/src/game/chars/CCharPlayer.h @@ -6,7 +6,6 @@ #ifndef _INC_CCHARPLAYER_H #define _INC_CCHARPLAYER_H -#include "../../common/resource/CResourceHolder.h" #include "../../common/sphereproto.h" #include "../clients/CAccount.h" #include "../CServerConfig.h" diff --git a/src/game/chars/CCharSkill.cpp b/src/game/chars/CCharSkill.cpp index 36dd42087..88b0f4019 100644 --- a/src/game/chars/CCharSkill.cpp +++ b/src/game/chars/CCharSkill.cpp @@ -3,8 +3,12 @@ #include "../../common/resource/sections/CSkillClassDef.h" #include "../../common/resource/sections/CRegionResourceDef.h" #include "../../common/resource/CResourceLock.h" +#include "../../common/sphere_library/CSRand.h" +#include "../../common/CExpression.h" #include "../../common/CLog.h" #include "../clients/CClient.h" +#include "../items/CItemCorpse.h" +#include "../items/CItemMemory.h" #include "../items/CItemVendable.h" #include "../triggers.h" #include "../CServer.h" @@ -12,7 +16,6 @@ #include "../CWorldSearch.h" #include "CChar.h" #include "CCharNPC.h" - #include //---------------------------------------------------------------------- diff --git a/src/game/chars/CCharSpell.cpp b/src/game/chars/CCharSpell.cpp index 256711dd2..e5ed0e7bc 100644 --- a/src/game/chars/CCharSpell.cpp +++ b/src/game/chars/CCharSpell.cpp @@ -1,8 +1,12 @@ +#include "../../common/sphere_library/CSRand.h" +#include "../../common/CExpression.h" #include "../../network/CClientIterator.h" #include "../../network/send.h" #include "../components/CCPropsChar.h" #include "../components/CCPropsItemEquippable.h" #include "../clients/CClient.h" +#include "../items/CItemCorpse.h" +#include "../uo_files/uofiles_enums_creid.h" #include "../CSector.h" #include "../CServer.h" #include "../CWorld.h" diff --git a/src/game/chars/CCharStat.cpp b/src/game/chars/CCharStat.cpp index 9be54887f..9bd654df9 100644 --- a/src/game/chars/CCharStat.cpp +++ b/src/game/chars/CCharStat.cpp @@ -1,8 +1,10 @@ // CChar is either an NPC or a Player. - +#include "../../common/sphere_library/CSRand.h" #include "../../common/resource/sections/CSkillClassDef.h" #include "../../common/CException.h" +#include "../../common/CExpression.h" #include "../../common/CScriptTriggerArgs.h" +#include "../items/CItem.h" #include "../triggers.h" #include "../CServer.h" #include "../CWorldGameTime.h" diff --git a/src/game/chars/CCharStatus.cpp b/src/game/chars/CCharStatus.cpp index 8d25c9fb7..2dd9cfbdd 100644 --- a/src/game/chars/CCharStatus.cpp +++ b/src/game/chars/CCharStatus.cpp @@ -1,17 +1,21 @@ // CChar is either an NPC or a Player. +#include "../../common/CExpression.h" #include "../../common/CLog.h" #include "../components/CCPropsItemEquippable.h" #include "../components/CCPropsItemWeapon.h" #include "../clients/CClient.h" +#include "../items/CItemCorpse.h" #include "../items/CItemMulti.h" +#include "../uo_files/uofiles_enums_creid.h" +#include "../uo_files/CUOStaticItemRec.h" #include "../CServer.h" #include "../CWorldMap.h" -#include "../spheresvr.h" #include "../triggers.h" #include "CChar.h" #include "CCharNPC.h" + bool CChar::IsResourceMatch( const CResourceID& rid, dword dwAmount ) const { ADDTOCALLSTACK("CChar::IsResourceMatch"); diff --git a/src/game/chars/CCharUse.cpp b/src/game/chars/CCharUse.cpp index 6044f190e..6ac60941c 100644 --- a/src/game/chars/CCharUse.cpp +++ b/src/game/chars/CCharUse.cpp @@ -1,5 +1,6 @@ // CChar is either an NPC or a Player. - +#include "../../common/sphere_library/CSRand.h" +#include "../../common/CExpression.h" #include "../clients/CClient.h" #include "../items/CItem.h" #include "../items/CItemCorpse.h" diff --git a/src/game/chars/CStoneMember.cpp b/src/game/chars/CStoneMember.cpp index e5227b6bc..0407dd224 100644 --- a/src/game/chars/CStoneMember.cpp +++ b/src/game/chars/CStoneMember.cpp @@ -1,6 +1,8 @@ #include "../../common/CException.h" +#include "../../common/CExpression.h" #include "../../common/CLog.h" #include "../chars/CChar.h" +#include "../items/CItemStone.h" #include "../CServer.h" #include "CStoneMember.h" diff --git a/src/game/chars/CStoneMember.h b/src/game/chars/CStoneMember.h index 10ffcf94a..d79a10c7e 100644 --- a/src/game/chars/CStoneMember.h +++ b/src/game/chars/CStoneMember.h @@ -7,6 +7,7 @@ #define _INC_CSTONEMEMBER_H #include "../../common/sphere_library/CSObjListRec.h" +#include "../../common/sphere_library/CSString.h" #include "../../common/CScriptObj.h" #include "../../common/CUID.h" diff --git a/src/game/clients/CAccount.cpp b/src/game/clients/CAccount.cpp index 8e40a704d..a7a82c695 100644 --- a/src/game/clients/CAccount.cpp +++ b/src/game/clients/CAccount.cpp @@ -1,6 +1,8 @@ #include "../../common/crypto/CMD5.h" +#include "../../common/sphere_library/CSRand.h" #include "../../common/CLog.h" #include "../../common/CException.h" +#include "../../common/CExpression.h" #include "../../network/CClientIterator.h" #include "../chars/CChar.h" #include "../CServer.h" diff --git a/src/game/clients/CAccount.h b/src/game/clients/CAccount.h index 0d2913bcb..c1e38d5c0 100644 --- a/src/game/clients/CAccount.h +++ b/src/game/clients/CAccount.h @@ -5,13 +5,15 @@ #ifndef _INC_CACCOUNT_H #define _INC_CACCOUNT_H -#include "../../network/CSocket.h" +#include "../../common/resource/CResourceSortedArrays.h" // For CObjNameSortArray #include "../../common/sphere_library/CSString.h" -#include "../../common/sphereproto.h" +#include "../../common/sphere_library/CSTime.h" +#include "../../common/CLanguageID.h" #include "../../common/CScriptObj.h" +#include "../../common/CVarDefMap.h" +#include "../../network/CSocket.h" #include "../chars/CCharRefArray.h" -#include "../CServerConfig.h" -#include "../game_enums.h" +#include #define PRIV_UNUSED0 0x0001 #define PRIV_GM 0x0002 // Acts as a GM (dif from having GM level) @@ -33,6 +35,7 @@ class CClient; +enum PLEVEL_TYPE : int; /** * @brief Single account information. diff --git a/src/game/clients/CChat.cpp b/src/game/clients/CChat.cpp index b9aec96dd..e167118c8 100644 --- a/src/game/clients/CChat.cpp +++ b/src/game/clients/CChat.cpp @@ -1,5 +1,5 @@ #include "../../network/CClientIterator.h" -#include "../chars/CChar.h" +#include "../game_macros.h" #include "../CServer.h" #include "CChat.h" #include "CChatChannel.h" diff --git a/src/game/clients/CChat.h b/src/game/clients/CChat.h index 0cfda724d..130e072b2 100644 --- a/src/game/clients/CChat.h +++ b/src/game/clients/CChat.h @@ -8,8 +8,10 @@ #include "../../common/sphere_library/CSString.h" #include "../../common/sphere_library/sptr_containers.h" -#include "../../common/sphereproto.h" +#include "../../common/CLanguageID.h" +struct naword; +using nachar = naword; class CClient; class CChatChannel; @@ -23,9 +25,9 @@ class CChat CChat() = default; ~CChat() = default; - CChat(const CChat& copy) = delete; - CChat& operator=(const CChat& other) = delete; + CChat(const CChat& copy) = delete; + CChat& operator=(const CChat& other) = delete; static bool IsValidName(lpctstr pszName, bool fPlayer); diff --git a/src/game/clients/CChatChanMember.h b/src/game/clients/CChatChanMember.h index 46fcd0147..2a822f8a7 100644 --- a/src/game/clients/CChatChanMember.h +++ b/src/game/clients/CChatChanMember.h @@ -9,12 +9,17 @@ #include "../../common/sphere_library/CSObjArray.h" #include "../../common/sphere_library/CSString.h" #include "../../common/sphereproto.h" +#include "CChatChannel.h" class CClient; class CChatChanMember { + friend class CChatChannel; + friend class CChat; + // friend CClient; + // This is a member of the CClient. bool m_fChatActive; bool m_fReceiving; @@ -25,17 +30,6 @@ class CChatChanMember static const char *m_sClassName; CSObjArray m_IgnoredMembers; // Player's list of ignored members -private: - friend class CChatChannel; - friend class CChat; - // friend CClient; - bool GetWhoIs() const { return m_fAllowWhoIs; } - void SetWhoIs(bool fAllowWhoIs) { m_fAllowWhoIs = fAllowWhoIs; } - bool IsReceivingAllowed() const { return m_fReceiving; } - lpctstr GetChatName() const; - - size_t FindIgnoringIndex( lpctstr pszName) const; - public: CChatChanMember() noexcept; virtual ~CChatChanMember() noexcept; @@ -70,6 +64,14 @@ class CChatChanMember void ShowCharacterName(); void AddIgnore(lpctstr pszName); void RemoveIgnore(lpctstr pszName); + +private: + bool GetWhoIs() const { return m_fAllowWhoIs; } + void SetWhoIs(bool fAllowWhoIs) { m_fAllowWhoIs = fAllowWhoIs; } + bool IsReceivingAllowed() const { return m_fReceiving; } + lpctstr GetChatName() const; + + size_t FindIgnoringIndex( lpctstr pszName) const; }; #endif // _INC_CCHATCHANMEMBER_H diff --git a/src/game/clients/CChatChannel.cpp b/src/game/clients/CChatChannel.cpp index 96caf2f98..eb1aa77a1 100644 --- a/src/game/clients/CChatChannel.cpp +++ b/src/game/clients/CChatChannel.cpp @@ -483,7 +483,9 @@ size_t CChatChannel::FindMemberIndex(lpctstr pszName) const ADDTOCALLSTACK("CChatChannel::FindMemberIndex"); for (size_t i = 0; i < m_Members.size(); ++i) { - if ( strcmp( m_Members[i]->GetChatName(), pszName) == 0) + lpctstr ptcName = m_Members[i]->GetChatName(); + ASSERT(ptcName); + if ( strcmp( ptcName, pszName) == 0) return i; } return sl::scont_bad_index(); diff --git a/src/game/clients/CChatChannel.h b/src/game/clients/CChatChannel.h index 0c0d66bf0..2d9bd63aa 100644 --- a/src/game/clients/CChatChannel.h +++ b/src/game/clients/CChatChannel.h @@ -9,6 +9,7 @@ #include "../../common/sphere_library/CSString.h" #include "../../common/sphere_library/sptr_containers.h" #include "../../common/sphereproto.h" +#include "../../common/CLanguageID.h" class CChatChanMember; diff --git a/src/game/clients/CClient.cpp b/src/game/clients/CClient.cpp index 04cbf40df..7fc23ab34 100644 --- a/src/game/clients/CClient.cpp +++ b/src/game/clients/CClient.cpp @@ -1,12 +1,12 @@ #include "../../common/resource/sections/CResourceNamedDef.h" +#include "../../common/sphere_library/CSRand.h" #include "../../common/CLog.h" #include "../../common/CException.h" +#include "../../common/CExpression.h" #include "../../common/CUOClientVersion.h" #include "../../network/CClientIterator.h" #include "../../network/CNetworkManager.h" #include "../../network/CIPHistoryManager.h" -#include "../../network/send.h" -#include "../../network/packet.h" #include "../chars/CChar.h" #include "../components/CCSpawn.h" #include "../items/CItemMultiCustom.h" @@ -228,6 +228,11 @@ void CClient::CharDisconnect() m_pChar = nullptr; } +CClient* CClient::GetNext() const +{ + return static_cast (CSObjListRec::GetNext()); +} + bool CClient::IsPriv(word flag) const { // PRIV_GM if (GetAccount() == nullptr) diff --git a/src/game/clients/CClient.h b/src/game/clients/CClient.h index 7d1d27274..d96f64d1b 100644 --- a/src/game/clients/CClient.h +++ b/src/game/clients/CClient.h @@ -9,22 +9,23 @@ #include "../../common/crypto/CCrypto.h" #include "../../common/CScriptTriggerArgs.h" #include "../../common/CTextConsole.h" -#include "../../network/receive.h" #include "../../network/send.h" -#include "../items/CItemBase.h" -#include "../items/CItemContainer.h" #include "../CSectorEnviron.h" #include "../game_enums.h" #include "CAccount.h" -#include "CChat.h" #include "CChatChanMember.h" #include "CGlobalChatChanMember.h" -#include "CClientTooltip.h" #include "CGMPage.h" +class CItemBase; +class CItemContainer; class CItemMap; class CItemMultiCustom; +class CSObjCont; +struct VendorItem; +enum CREID_TYPE : uint32; +enum ITEMID_TYPE : uint32; enum CV_TYPE { @@ -392,10 +393,7 @@ class CClient : public CSObjListRec, public CScriptObj, public CChatChanMember, public: void CharDisconnect(); - CClient* GetNext() const - { - return static_cast (CSObjListRec::GetNext()); - } + CClient* GetNext() const; virtual bool r_GetRef(lpctstr& ptcKey, CScriptObj*& pRef) override; virtual bool r_Verb( CScript & s, CTextConsole * pSrc ) override; // Execute script type command on me diff --git a/src/game/clients/CClientDialog.cpp b/src/game/clients/CClientDialog.cpp index 5f95b6a20..d75c49988 100644 --- a/src/game/clients/CClientDialog.cpp +++ b/src/game/clients/CClientDialog.cpp @@ -1,11 +1,12 @@ #include "../../common/resource/sections/CDialogDef.h" #include "../../common/resource/CResourceLock.h" -#include "../../common/CException.h" +#include "../../common/CExpression.h" #include "../../common/CLog.h" #include "../../network/receive.h" #include "../../network/send.h" #include "../chars/CChar.h" +#include "../items/CItemBase.h" #include "../CServer.h" #include "CClient.h" diff --git a/src/game/clients/CClientEvent.cpp b/src/game/clients/CClientEvent.cpp index 0bbfb6544..3bcef0795 100644 --- a/src/game/clients/CClientEvent.cpp +++ b/src/game/clients/CClientEvent.cpp @@ -1,13 +1,16 @@ #include "../../common/resource/CResourceLock.h" #include "../../common/CException.h" +#include "../../common/CExpression.h" #include "../../network/CClientIterator.h" #include "../../network/receive.h" #include "../../network/send.h" #include "../chars/CChar.h" #include "../chars/CCharNPC.h" +#include "../items/CItemContainer.h" #include "../items/CItemMessage.h" #include "../items/CItemMulti.h" #include "../items/CItemVendable.h" +#include "../uo_files/uofiles_enums_creid.h" #include "../CSector.h" #include "../CServer.h" #include "../CWorld.h" diff --git a/src/game/clients/CClientLog.cpp b/src/game/clients/CClientLog.cpp index e0fe9fab4..f3a84daf8 100644 --- a/src/game/clients/CClientLog.cpp +++ b/src/game/clients/CClientLog.cpp @@ -5,6 +5,7 @@ #include "../../common/sphere_library/CSFileList.h" #include "../../common/CLog.h" #include "../../common/CException.h" +#include "../../common/CExpression.h" #include "../../network/CIPHistoryManager.h" #include "../../network/CNetworkManager.h" #include "../../network/send.h" diff --git a/src/game/clients/CClientMsg.cpp b/src/game/clients/CClientMsg.cpp index 0576c5753..978b5affe 100644 --- a/src/game/clients/CClientMsg.cpp +++ b/src/game/clients/CClientMsg.cpp @@ -2,10 +2,13 @@ // Game server messages. (No login stuff) #include "../../common/resource/CResourceLock.h" +#include "../../common/sphere_library/CSRand.h" #include "../../common/CException.h" +#include "../../common/CExpression.h" #include "../../network/send.h" #include "../chars/CChar.h" #include "../chars/CCharNPC.h" +#include "../items/CItemCorpse.h" #include "../items/CItemMap.h" #include "../items/CItemMessage.h" #include "../items/CItemMultiCustom.h" diff --git a/src/game/clients/CClientMsg_AOSTooltip.cpp b/src/game/clients/CClientMsg_AOSTooltip.cpp index ee75de721..15d3bfc0a 100644 --- a/src/game/clients/CClientMsg_AOSTooltip.cpp +++ b/src/game/clients/CClientMsg_AOSTooltip.cpp @@ -1,5 +1,7 @@ +#include "../../common/CExpression.h" #include "../chars/CChar.h" #include "../chars/CCharNPC.h" +#include "../clients/CClientTooltip.h" #include "../items/CItem.h" #include "../items/CItemStone.h" #include "../components/CCSpawn.h" diff --git a/src/game/clients/CClientTarg.cpp b/src/game/clients/CClientTarg.cpp index 846ee258d..a665de524 100644 --- a/src/game/clients/CClientTarg.cpp +++ b/src/game/clients/CClientTarg.cpp @@ -2,10 +2,16 @@ #include "../../network/send.h" #include "../../common/resource/sections/CItemTypeDef.h" +#include "../../common/sphere_library/CSRand.h" +#include "../../common/CExpression.h" #include "../../common/CLog.h" #include "../chars/CChar.h" +#include "../items/CItemCorpse.h" #include "../items/CItemMulti.h" +#include "../items/CItemStone.h" #include "../items/CItemVendable.h" +#include "../uo_files/CUOStaticItemRec.h" +#include "../uo_files/uofiles_enums_creid.h" #include "../CWorldGameTime.h" #include "../CWorldMap.h" #include "../CWorldSearch.h" diff --git a/src/game/clients/CClientTooltip.cpp b/src/game/clients/CClientTooltip.cpp index a1ff9e1d4..036865271 100644 --- a/src/game/clients/CClientTooltip.cpp +++ b/src/game/clients/CClientTooltip.cpp @@ -1,9 +1,6 @@ - -#include - -#include "../../common/sphere_library/CSString.h" +#include "../../common/sphere_library/sstring.h" #include "CClientTooltip.h" - +#include CClientTooltip::CClientTooltip(dword dwClilocID) { diff --git a/src/game/clients/CClientUse.cpp b/src/game/clients/CClientUse.cpp index e7c230956..2b13591ab 100644 --- a/src/game/clients/CClientUse.cpp +++ b/src/game/clients/CClientUse.cpp @@ -1,8 +1,11 @@ #include "../../common/resource/CResourceLock.h" +#include "../../common/sphere_library/CSRand.h" +#include "../../common/CExpression.h" #include "../../common/CLog.h" #include "../../network/send.h" #include "../chars/CChar.h" +#include "../items/CItemCorpse.h" #include "../items/CItemMap.h" #include "../items/CItemShip.h" #include "../components/CCSpawn.h" diff --git a/src/game/clients/CGMPage.h b/src/game/clients/CGMPage.h index da5440ed7..b22e7d097 100644 --- a/src/game/clients/CGMPage.h +++ b/src/game/clients/CGMPage.h @@ -8,7 +8,6 @@ #include "../../common/sphere_library/CSString.h" #include "../../common/CScriptObj.h" -#include "../../common/CRect.h" #include "../CServerTime.h" #include "CAccount.h" diff --git a/src/game/clients/CGlobalChatChanMember.cpp b/src/game/clients/CGlobalChatChanMember.cpp index a460a3db3..29be2a57b 100644 --- a/src/game/clients/CGlobalChatChanMember.cpp +++ b/src/game/clients/CGlobalChatChanMember.cpp @@ -1,6 +1,4 @@ -#include "../CServer.h" -#include "CClient.h" #include "CGlobalChatChanMember.h" CGlobalChatChanMember::CGlobalChatChanMember() noexcept : diff --git a/src/game/clients/CParty.cpp b/src/game/clients/CParty.cpp index 470de2a5a..0a4dfdf91 100644 --- a/src/game/clients/CParty.cpp +++ b/src/game/clients/CParty.cpp @@ -1,6 +1,7 @@ -#include "../../common/CLog.h" #include "../../common/CException.h" +#include "../../common/CExpression.h" +#include "../../common/CLog.h" #include "../../common/CScriptObj.h" #include "../../network/send.h" #include "../chars/CChar.h" diff --git a/src/game/clients/CParty.h b/src/game/clients/CParty.h index 2203cee13..5182f0a4a 100644 --- a/src/game/clients/CParty.h +++ b/src/game/clients/CParty.h @@ -8,7 +8,6 @@ #include "../../common/sphere_library/CSString.h" #include "../../common/sphere_library/CSObjListRec.h" -#include "../../common/CRect.h" #include "../../common/CScriptObj.h" #include "../../common/CVarDefMap.h" #include "../../common/sphereproto.h" diff --git a/src/game/components/CCChampion.cpp b/src/game/components/CCChampion.cpp index 55bea9ab5..b3b7cf164 100644 --- a/src/game/components/CCChampion.cpp +++ b/src/game/components/CCChampion.cpp @@ -12,16 +12,16 @@ */ #include "../../common/resource/CResourceLock.h" -#include "../../common/CException.h" +#include "../../common/sphere_library/CSRand.h" +#include "../../common/CExpression.h" +#include "../../common/CLog.h" #include "../../common/CScript.h" #include "../chars/CChar.h" #include "../CServer.h" #include "../CWorldGameTime.h" #include "CCChampion.h" // predef header. #include -#include #include -#include #define CANDLESNEXTRED 4 #define MAXSPAWN 2400 diff --git a/src/game/components/CCItemDamageable.cpp b/src/game/components/CCItemDamageable.cpp index 8b89325c8..639a63e24 100644 --- a/src/game/components/CCItemDamageable.cpp +++ b/src/game/components/CCItemDamageable.cpp @@ -1,11 +1,11 @@ #include "CCItemDamageable.h" #include "../CServer.h" -#include "../CObjBase.h" #include "../CWorldGameTime.h" #include "../CWorldSearch.h" #include "../CWorldTickingList.h" #include "../chars/CChar.h" +#include "../items/CItem.h" #include "../clients/CClient.h" diff --git a/src/game/components/CCMultiMovable.cpp b/src/game/components/CCMultiMovable.cpp index 35ee66461..b35062310 100644 --- a/src/game/components/CCMultiMovable.cpp +++ b/src/game/components/CCMultiMovable.cpp @@ -1,10 +1,11 @@ +#include "../../common/sphere_library/CSRand.h" +#include "../../common/CExpression.h" #include "../../network/CClientIterator.h" #include "../../network/send.h" #include "../clients/CClient.h" #include "../chars/CChar.h" #include "../items/CItem.h" #include "../items/CItemMulti.h" -#include "../items/CItemShip.h" #include "../CObjBase.h" #include "../CServer.h" #include "../CWorldMap.h" diff --git a/src/game/components/CCMultiMovable.h b/src/game/components/CCMultiMovable.h index 4967a67ac..996abc31d 100644 --- a/src/game/components/CCMultiMovable.h +++ b/src/game/components/CCMultiMovable.h @@ -1,7 +1,16 @@ #ifndef _INC_CCMULTIMOVABLE_H #define _INC_CCMULTIMOVABLE_H -#include "../CRegion.h" +#include "../../common/common.h" +#include "../uo_files/uofiles_enums.h" + +class CSString; +class CChar; +class CObjBase; +struct CPointMap; +class CRegionWorld; +class CScript; +class CTextConsole; struct ShipSpeed // speed of a ship diff --git a/src/game/components/CCPropsItem.cpp b/src/game/components/CCPropsItem.cpp index 0a2a90426..50f8d76fd 100644 --- a/src/game/components/CCPropsItem.cpp +++ b/src/game/components/CCPropsItem.cpp @@ -1,6 +1,7 @@ #include "CCPropsItem.h" -#include "../items/CItem.h" +#include "../clients/CClientTooltip.h" +#include "../CObjBase.h" lpctstr const CCPropsItem::_ptcPropertyKeys[PROPIT_QTY + 1] = diff --git a/src/game/components/CCPropsItemChar.cpp b/src/game/components/CCPropsItemChar.cpp index 8348fb683..efd0ab25f 100644 --- a/src/game/components/CCPropsItemChar.cpp +++ b/src/game/components/CCPropsItemChar.cpp @@ -1,7 +1,8 @@ #include "CCPropsItemChar.h" -#include "../items/CItem.h" #include "../chars/CChar.h" +#include "../clients/CClientTooltip.h" +#include "../items/CItem.h" lpctstr const CCPropsItemChar::_ptcPropertyKeys[PROPITCH_QTY + 1] = diff --git a/src/game/components/CCPropsItemEquippable.cpp b/src/game/components/CCPropsItemEquippable.cpp index 10edf041f..295445e99 100644 --- a/src/game/components/CCPropsItemEquippable.cpp +++ b/src/game/components/CCPropsItemEquippable.cpp @@ -1,7 +1,8 @@ #include "CCPropsItemEquippable.h" -#include "../items/CItem.h" +#include "../clients/CClientTooltip.h" #include "../chars/CChar.h" +#include "../items/CItem.h" lpctstr const CCPropsItemEquippable::_ptcPropertyKeys[PROPIEQUIP_QTY + 1] = diff --git a/src/game/components/CCPropsItemWeapon.cpp b/src/game/components/CCPropsItemWeapon.cpp index 96c8909b2..3e56e0472 100644 --- a/src/game/components/CCPropsItemWeapon.cpp +++ b/src/game/components/CCPropsItemWeapon.cpp @@ -1,4 +1,5 @@ #include "../../common/sphere_library/CSString.h" +#include "../clients/CClientTooltip.h" #include "../items/CItem.h" #include "CCPropsItemWeapon.h" diff --git a/src/game/components/CCPropsItemWeaponRanged.cpp b/src/game/components/CCPropsItemWeaponRanged.cpp index b05890382..516444ced 100644 --- a/src/game/components/CCPropsItemWeaponRanged.cpp +++ b/src/game/components/CCPropsItemWeaponRanged.cpp @@ -1,4 +1,5 @@ #include "../../common/sphere_library/CSString.h" +//#include "../clients/CClientTooltip.h" #include "../items/CItem.h" #include "CCPropsItemWeaponRanged.h" diff --git a/src/game/components/CCSpawn.cpp b/src/game/components/CCSpawn.cpp index 57cb6fa91..7abcfe81a 100644 --- a/src/game/components/CCSpawn.cpp +++ b/src/game/components/CCSpawn.cpp @@ -1,6 +1,8 @@ #include "../../common/resource/sections/CRandGroupDef.h" +#include "../../common/sphere_library/CSRand.h" #include "../../common/CLog.h" #include "../../common/CException.h" +#include "../../common/CExpression.h" #include "../chars/CChar.h" #include "../chars/CCharNPC.h" #include "../CObjBase.h" diff --git a/src/game/game_macros.h b/src/game/game_macros.h index b429e2343..c6757441c 100644 --- a/src/game/game_macros.h +++ b/src/game/game_macros.h @@ -6,6 +6,7 @@ #ifndef _INC_GAME_MACROS_H #define _INC_GAME_MACROS_H +#include /* Parametric macros */ @@ -70,7 +71,7 @@ #define DAMAGE_THROWN 0x40000 // Damage flag for the throw NPCs action (not the throwing skill!). #define DAMAGE_REACTIVE 0x80000 // Damage reflected by Reactive Armor spell. -typedef uint DAMAGE_TYPE; // describe a type of damage. +typedef uint32_t DAMAGE_TYPE; // describe a type of damage. //--Spellflags diff --git a/src/game/items/CItem.cpp b/src/game/items/CItem.cpp index 07567f5d8..242e9c2a9 100644 --- a/src/game/items/CItem.cpp +++ b/src/game/items/CItem.cpp @@ -1,9 +1,9 @@ - #include "../../common/resource/CResourceLock.h" +#include "../../common/sphere_library/CSRand.h" #include "../../common/CException.h" +#include "../../common/CExpression.h" #include "../../network/CClientIterator.h" #include "../../network/send.h" -#include "../../sphere/ProfileTask.h" #include "../components/CCChampion.h" #include "../components/CCItemDamageable.h" #include "../components/CCSpawn.h" @@ -25,7 +25,6 @@ #include "../triggers.h" #include "CItem.h" #include "CItemCommCrystal.h" -#include "CItemContainer.h" #include "CItemCorpse.h" #include "CItemMap.h" #include "CItemMemory.h" @@ -4059,6 +4058,12 @@ void CItem::SetAnim( ITEMID_TYPE id, int64 iTicksTimeout) Update(); } +CObjBase * CItem::GetContainer() const noexcept { + // What is this CItem contained in ? + // Container should be a CChar or CItemContainer + return (dynamic_cast (GetParent())); +} + const CItem* CItem::GetTopContainer() const { //Get the top container diff --git a/src/game/items/CItem.h b/src/game/items/CItem.h index ad978cc0e..4f046c588 100644 --- a/src/game/items/CItem.h +++ b/src/game/items/CItem.h @@ -6,19 +6,12 @@ #ifndef _INC_CITEM_H #define _INC_CITEM_H -#include "../../common/sphere_library/CSObjCont.h" -#include "../../common/resource/CResourceHolder.h" -#include "../../common/CServerMap.h" -#include "../../common/CRect.h" #include "../components/subcomponents/CFactionDef.h" #include "../CServerTime.h" -#include "../CBase.h" #include "../CObjBase.h" #include "../CObjBaseTemplate.h" -#include "../game_enums.h" #include "../game_macros.h" #include "../CServerConfig.h" -#include "../CEntity.h" #include "CItemBase.h" @@ -34,7 +27,7 @@ class CFactionDef; * * Types of memory a CChar has about a game object. (m_wHue) */ -enum MEMORY_TYPE +enum MEMORY_TYPE : int { MEMORY_NONE = 0, MEMORY_SAWCRIME = 0x0001, // I saw them commit a crime or i was attacked criminally. I can call the guards on them. the crime may not have been against me. @@ -782,12 +775,7 @@ protected: virtual void _SetTimeout(int64 iMsecs) override final; virtual CObjBaseTemplate* GetTopLevelObj() override; virtual const CObjBaseTemplate* GetTopLevelObj() const override; - inline CObjBase * GetContainer() const noexcept { - // What is this CItem contained in ? - // Container should be a CChar or CItemContainer - return (dynamic_cast (GetParent())); - // Called very frequently, worth inlining. - } + CObjBase * GetContainer() const noexcept; CItem * GetTopContainer(); const CItem* GetTopContainer() const; diff --git a/src/game/items/CItemBase.cpp b/src/game/items/CItemBase.cpp index c9e723cc4..ad6fc1cf6 100644 --- a/src/game/items/CItemBase.cpp +++ b/src/game/items/CItemBase.cpp @@ -1,16 +1,25 @@ // define the base types of an item (rather than the instance) + +#include "../../common/resource/CResourceLock.h" #include "../../common/CUOInstall.h" #include "../../common/CLog.h" #include "../../common/CException.h" +#include "../../common/CExpression.h" #include "../../sphere/ProfileTask.h" +#include "../../sphere/threads.h" #include "../components/CCPropsItem.h" #include "../components/CCPropsItemChar.h" #include "../components/CCPropsItemEquippable.h" #include "../components/CCPropsItemWeapon.h" #include "../components/CCPropsItemWeaponRanged.h" -#include "../../common/resource/CResourceLock.h" +#include "../uo_files/uofiles_enums_itemid.h" +#include "../uo_files/uofiles_enums_creid.h" +#include "../uo_files/uofiles_macros.h" +#include "../uo_files/CUOMultiItemRec.h" #include "../uo_files/CUOItemInfo.h" +#include "../uo_files/CUOItemTypeRec.h" +#include "../CServerConfig.h" #include "CItemBase.h" @@ -536,6 +545,11 @@ bool CItemBase::IsID_WaterWash( ITEMID_TYPE id ) noexcept // static return IsID_WaterFish( id ); } +bool CItemBase::IsVisibleLayer( LAYER_TYPE layer ) noexcept // static +{ + return ((layer > LAYER_NONE) && (layer <= LAYER_HORSE) ); +} + bool CItemBase::IsID_Chair( ITEMID_TYPE id ) noexcept // static { // Strangely there is not chair flag in the statics.mul file ??? !!! @@ -1302,7 +1316,10 @@ bool CItemBase::r_WriteVal( lpctstr ptcKey, CSString & sVal, CTextConsole * pSrc else m_SkillMake.WriteNames( pszTmp, Str_TempLength(), index ); if ( fQtyOnly && pszTmp[0] == '\0' ) - strcpy( pszTmp, "0" ); + { + pszTmp[0] = '0'; + pszTmp[1] = '\0'; + } sVal = pszTmp; } else @@ -2299,6 +2316,11 @@ CItemBase * CItemBase::FindItemBase( ITEMID_TYPE id ) // static return pBase; } +bool CItemBase::IsValidDispID( ITEMID_TYPE id ) noexcept // static +{ + // Is this id in the base artwork set ? tile or multi. + return ( id > ITEMID_NOTHING && id < ITEMID_MULTI_MAX ); +} //************************************************** diff --git a/src/game/items/CItemBase.h b/src/game/items/CItemBase.h index cb3c9c333..27f3eaeff 100644 --- a/src/game/items/CItemBase.h +++ b/src/game/items/CItemBase.h @@ -6,16 +6,19 @@ #ifndef _INC_CITEMBASE_H #define _INC_CITEMBASE_H -#include "../../common/resource/CResourceHolder.h" -#include "../uo_files/uofiles_enums_itemid.h" -#include "../uo_files/uofiles_enums_creid.h" -#include "../uo_files/CUOItemTypeRec.h" +#include "../../common/sphere_library/CSTypedArray.h" +#include "../../common/resource/CValueDefs.h" +#include "../../common/CRect.h" #include "../CBase.h" -#include "../CServerConfig.h" #include "item_types.h" +#define WEIGHT_UNITS 10 + class CFactionDef; +struct CUOItemTypeRec_HS; +enum CREID_TYPE : uint32; +enum ITEMID_TYPE : uint32; class CItemBase : public CBaseBaseDef { @@ -259,7 +262,7 @@ class CItemBase : public CBaseBaseDef bool SetMaxAmount(word amount); static CItemBase * FindItemBase( ITEMID_TYPE id ); - inline static bool IsValidDispID( ITEMID_TYPE id ) noexcept; + static bool IsValidDispID( ITEMID_TYPE id ) noexcept; // NOTE: ??? All this stuff should be moved to scripts ! // Classify item by ID @@ -274,7 +277,7 @@ class CItemBase : public CBaseBaseDef static bool IsID_WaterWash( ITEMID_TYPE id ) noexcept; static bool IsID_Chair( ITEMID_TYPE id ) noexcept; - inline static bool IsVisibleLayer( LAYER_TYPE layer ) noexcept; + static bool IsVisibleLayer( LAYER_TYPE layer ) noexcept; static tchar * GetNamePluralize( lpctstr pszNameBase, bool fPluralize ); static bool GetItemData( ITEMID_TYPE id, CUOItemTypeRec_HS * ptile, bool fNameNotNeeded = false ); @@ -327,7 +330,6 @@ class CItemBase : public CBaseBaseDef { return Can( CAN_I_PILE ); } -#define WEIGHT_UNITS 10 word GetWeight() const noexcept; // Get weight in tenths of a stone. byte GetSpeed() const; @@ -461,18 +463,4 @@ class CItemBaseMulti : public CItemBase }; -/* Inline Methods Definitions */ - -bool CItemBase::IsVisibleLayer( LAYER_TYPE layer ) noexcept // static -{ - return ((layer > LAYER_NONE) && (layer <= LAYER_HORSE) ); -} - -bool CItemBase::IsValidDispID( ITEMID_TYPE id ) noexcept // static -{ - // Is this id in the base artwork set ? tile or multi. - return ( id > ITEMID_NOTHING && id < ITEMID_MULTI_MAX ); -} - - #endif // _INC_CITEMBASE_H diff --git a/src/game/items/CItemCommCrystal.h b/src/game/items/CItemCommCrystal.h index 98a37a466..228157e5d 100644 --- a/src/game/items/CItemCommCrystal.h +++ b/src/game/items/CItemCommCrystal.h @@ -16,14 +16,14 @@ class CItemCommCrystal : public CItemVendable protected: static lpctstr const sm_szLoadKeys[]; CResourceRefArray m_Speech; // Speech fragment list (other stuff we know) + public: static const char *m_sClassName; CItemCommCrystal( ITEMID_TYPE id, CItemBase * pItemDef ); virtual ~CItemCommCrystal(); -private: - CItemCommCrystal(const CItemCommCrystal& copy); - CItemCommCrystal& operator=(const CItemCommCrystal& other); + CItemCommCrystal(const CItemCommCrystal& copy) = delete; + CItemCommCrystal& operator=(const CItemCommCrystal& other) = delete; public: virtual void OnMoveFrom() override; diff --git a/src/game/items/CItemContainer.cpp b/src/game/items/CItemContainer.cpp index e329591aa..a6815a256 100644 --- a/src/game/items/CItemContainer.cpp +++ b/src/game/items/CItemContainer.cpp @@ -1,5 +1,6 @@ - +#include "../../common/sphere_library/CSRand.h" #include "../../common/CException.h" +#include "../../common/CExpression.h" #include "../../common/CLog.h" #include "../../network/send.h" #include "../chars/CChar.h" diff --git a/src/game/items/CItemContainer.h b/src/game/items/CItemContainer.h index a5ac7f224..c519228bb 100644 --- a/src/game/items/CItemContainer.h +++ b/src/game/items/CItemContainer.h @@ -30,9 +30,8 @@ class CItemContainer : public CItemVendable, public CContainer CItemContainer( ITEMID_TYPE id, CItemBase * pItemDef ); virtual ~CItemContainer(); -private: - CItemContainer(const CItemContainer& copy); - CItemContainer& operator=(const CItemContainer& other); + CItemContainer(const CItemContainer& copy) = delete; + CItemContainer& operator=(const CItemContainer& other) = delete; public: bool IsWeighed() const; diff --git a/src/game/items/CItemCorpse.cpp b/src/game/items/CItemCorpse.cpp index 6494a4578..75c5b57c0 100644 --- a/src/game/items/CItemCorpse.cpp +++ b/src/game/items/CItemCorpse.cpp @@ -1,10 +1,10 @@ #include "../../common/CException.h" +#include "../../common/CExpression.h" #include "../../common/CLog.h" #include "../../common/sphereproto.h" #include "../chars/CChar.h" #include "../chars/CCharNPC.h" #include "../CWorldGameTime.h" -#include "../CWorldMap.h" #include "../CWorldSearch.h" #include "CItem.h" #include "CItemCorpse.h" diff --git a/src/game/items/CItemCorpse.h b/src/game/items/CItemCorpse.h index 929815264..be3e50e16 100644 --- a/src/game/items/CItemCorpse.h +++ b/src/game/items/CItemCorpse.h @@ -6,7 +6,6 @@ #ifndef _INC_CITEMCORPSE_H #define _INC_CITEMCORPSE_H -#include "../CBase.h" #include "CItemContainer.h" @@ -21,9 +20,8 @@ class CItemCorpse : public CItemContainer CItemCorpse( ITEMID_TYPE id, CItemBase * pItemDef ); virtual ~CItemCorpse(); -private: - CItemCorpse(const CItemCorpse& copy); - CItemCorpse& operator=(const CItemCorpse& other); + CItemCorpse(const CItemCorpse& copy) = delete; + CItemCorpse& operator=(const CItemCorpse& other) = delete; public: bool IsCorpseResurrectable(CChar* pCharHealer, CChar* pCharGhost) const; diff --git a/src/game/items/CItemMap.cpp b/src/game/items/CItemMap.cpp index 847d5e502..c22009fb1 100644 --- a/src/game/items/CItemMap.cpp +++ b/src/game/items/CItemMap.cpp @@ -1,5 +1,6 @@ #include "../../common/CException.h" +#include "../../common/CExpression.h" #include "CItemMap.h" ///////////////////////////////////////////////////////////////////////////// diff --git a/src/game/items/CItemMap.h b/src/game/items/CItemMap.h index 2c37a29c2..90c5fc477 100644 --- a/src/game/items/CItemMap.h +++ b/src/game/items/CItemMap.h @@ -14,8 +14,7 @@ struct CMapPinRec // Pin on a map short m_x; short m_y; -public: - CMapPinRec( short x, short y ) + CMapPinRec( short x, short y ) noexcept : m_x(x), m_y(y) { } @@ -39,9 +38,8 @@ class CItemMap : public CItemVendable CItemMap( ITEMID_TYPE id, CItemBase * pItemDef ); virtual ~CItemMap(); -private: - CItemMap(const CItemMap& copy); - CItemMap& operator=(const CItemMap& other); + CItemMap(const CItemMap& copy) = delete; + CItemMap& operator=(const CItemMap& other) = delete; public: virtual bool IsSameType( const CObjBase * pObj ) const override; diff --git a/src/game/items/CItemMessage.cpp b/src/game/items/CItemMessage.cpp index a068827e1..0e5cfca66 100644 --- a/src/game/items/CItemMessage.cpp +++ b/src/game/items/CItemMessage.cpp @@ -1,5 +1,6 @@ #include "../../common/CException.h" +#include "../../common/CExpression.h" #include "CItemMessage.h" #include "CItemVendable.h" diff --git a/src/game/items/CItemMessage.h b/src/game/items/CItemMessage.h index 0f210e376..2cadefd10 100644 --- a/src/game/items/CItemMessage.h +++ b/src/game/items/CItemMessage.h @@ -28,6 +28,7 @@ class CItemMessage : public CItemVendable static lpctstr const sm_szVerbKeys[]; private: CSObjArray m_sBodyLines; // The main body of the text for bboard message or book. + public: static const char *m_sClassName; CSString m_sAuthor; // Should just have author name ! @@ -37,9 +38,8 @@ class CItemMessage : public CItemVendable CItemMessage( ITEMID_TYPE id, CItemBase * pItemDef ); virtual ~CItemMessage(); -private: - CItemMessage(const CItemMessage& copy); - CItemMessage& operator=(const CItemMessage& other); + CItemMessage(const CItemMessage& copy) = delete; + CItemMessage& operator=(const CItemMessage& other) = delete; public: virtual void r_Write( CScript & s ) override; diff --git a/src/game/items/CItemMulti.cpp b/src/game/items/CItemMulti.cpp index 10da80797..e4b8c7b87 100644 --- a/src/game/items/CItemMulti.cpp +++ b/src/game/items/CItemMulti.cpp @@ -1,8 +1,11 @@ #include "../../common/resource/CResourceLock.h" +#include "../../common/sphere_library/CSRand.h" #include "../../common/CException.h" +#include "../../common/CExpression.h" #include "../../common/sphereproto.h" #include "../chars/CChar.h" #include "../clients/CClient.h" +#include "../items/CItemStone.h" #include "../CServer.h" #include "../CWorld.h" #include "../CWorldMap.h" diff --git a/src/game/items/CItemMultiCustom.cpp b/src/game/items/CItemMultiCustom.cpp index 05ee1aad1..c80080e5a 100644 --- a/src/game/items/CItemMultiCustom.cpp +++ b/src/game/items/CItemMultiCustom.cpp @@ -5,6 +5,7 @@ #include "../../common/resource/sections/CDialogDef.h" #include "../../common/CLog.h" #include "../../common/CException.h" +#include "../../common/CExpression.h" #include "../../common/CUOInstall.h" #include "../../network/send.h" #include "../chars/CChar.h" @@ -13,6 +14,7 @@ #include "../CWorldMap.h" #include "../CWorldSearch.h" #include "../triggers.h" +#include "CItemContainer.h" #include "CItemMultiCustom.h" ///////////////////////////////////////////////////////////////////////////// diff --git a/src/game/items/CItemMultiCustom.h b/src/game/items/CItemMultiCustom.h index 313fb0afa..5839f3542 100644 --- a/src/game/items/CItemMultiCustom.h +++ b/src/game/items/CItemMultiCustom.h @@ -6,8 +6,8 @@ #ifndef _INC_CITEMMULTICUSTOM_H #define _INC_CITEMMULTICUSTOM_H +#include "../uo_files/CUOMultiItemRec.h" #include "CItemMulti.h" -#include "../components/CCMultiMovable.h" class PacketHouseDesign; @@ -39,9 +39,8 @@ class CItemMultiCustom : public CItemMulti CSphereMultiCustom() = default; void LoadFrom(CDesignDetails * pDesign); - private: - CSphereMultiCustom(const CSphereMultiCustom& copy); - CSphereMultiCustom& operator=(const CSphereMultiCustom& other); + CSphereMultiCustom(const CSphereMultiCustom& copy) = delete; + CSphereMultiCustom& operator=(const CSphereMultiCustom& other) = delete; }; private: diff --git a/src/game/items/CItemPlant.cpp b/src/game/items/CItemPlant.cpp index 7378d6672..235f95e83 100644 --- a/src/game/items/CItemPlant.cpp +++ b/src/game/items/CItemPlant.cpp @@ -1,11 +1,12 @@ -#include "CItem.h" -#include "../chars/CChar.h" -#include "../triggers.h" -#include "../CWorldSearch.h" #include "../../common/CScriptTriggerArgs.h" #include "../../common/resource/CResourceID.h" +#include "../../common/CExpression.h" +#include "../chars/CChar.h" +#include "../triggers.h" #include "../CServer.h" +#include "../CWorldSearch.h" +#include "CItem.h" void CItem::Plant_SetTimer() { diff --git a/src/game/items/CItemShip.cpp b/src/game/items/CItemShip.cpp index 67bdffee5..620a02209 100644 --- a/src/game/items/CItemShip.cpp +++ b/src/game/items/CItemShip.cpp @@ -3,11 +3,10 @@ // #include "../../common/CException.h" +#include "../../common/CExpression.h" #include "../chars/CChar.h" #include "../CServer.h" -#include "../CWorldMap.h" #include "../CWorldSearch.h" -#include "../triggers.h" #include "CItemContainer.h" #include "CItemShip.h" #include "CItem.h" @@ -154,7 +153,7 @@ bool CItemShip::r_WriteVal(lpctstr ptcKey, CSString & sVal, CTextConsole * pSrc, { case IMCS_HATCH: { - ptcKey += 5; + //ptcKey += 5; CItem * pItemHold = GetShipHold(); if (pItemHold) sVal.FormatHex(pItemHold->GetUID()); @@ -164,13 +163,13 @@ bool CItemShip::r_WriteVal(lpctstr ptcKey, CSString & sVal, CTextConsole * pSrc, case IMCS_PLANK: { - ptcKey += 6; + //ptcKey += 6; sVal.FormatSTVal(GetShipPlankCount()); } break; case IMCS_TILLER: { - ptcKey += 6; + //ptcKey += 6; const CItem * pTiller = Multi_GetSign(); if (pTiller) sVal.FormatHex(pTiller->GetUID()); diff --git a/src/game/items/CItemShip.h b/src/game/items/CItemShip.h index 157df13b1..1e9765528 100644 --- a/src/game/items/CItemShip.h +++ b/src/game/items/CItemShip.h @@ -7,7 +7,6 @@ #define _INC_CITEMSHIP_H #include "CItemMulti.h" -#include "../components/CCMultiMovable.h" class CItemShip : public CItemMulti @@ -35,9 +34,8 @@ class CItemShip : public CItemMulti CItemShip(ITEMID_TYPE id, CItemBase * pItemDef); virtual ~CItemShip(); -private: - CItemShip(const CItemShip& copy); - CItemShip& operator=(const CItemShip& other); + CItemShip(const CItemShip& copy) = delete; + CItemShip& operator=(const CItemShip& other) = delete; public: virtual bool _OnTick() override; diff --git a/src/game/items/CItemStone.cpp b/src/game/items/CItemStone.cpp index 8b993995b..506f95078 100644 --- a/src/game/items/CItemStone.cpp +++ b/src/game/items/CItemStone.cpp @@ -1,5 +1,6 @@ #include "../../common/CException.h" +#include "../../common/CExpression.h" #include "../../common/CLog.h" #include "../../common/CScriptTriggerArgs.h" #include "../chars/CChar.h" diff --git a/src/game/items/CItemStone.h b/src/game/items/CItemStone.h index 391cba108..aefc184d8 100644 --- a/src/game/items/CItemStone.h +++ b/src/game/items/CItemStone.h @@ -85,9 +85,8 @@ class CItemStone : public CItem, public CSObjList CItemStone( ITEMID_TYPE id, CItemBase * pItemDef ); virtual ~CItemStone(); -private: - CItemStone(const CItemStone& copy); - CItemStone& operator=(const CItemStone& other); + CItemStone(const CItemStone& copy) = delete; + CItemStone& operator=(const CItemStone& other) = delete; public: virtual void r_Write( CScript & s ) override; diff --git a/src/game/items/item_types.h b/src/game/items/item_types.h index 70772629c..64000b465 100644 --- a/src/game/items/item_types.h +++ b/src/game/items/item_types.h @@ -6,8 +6,9 @@ #ifndef _INC_ITEMTYPES_H #define _INC_ITEMTYPES_H +#include -enum IT_TYPE // double click type action. +enum IT_TYPE : int32_t // double click type action. { // NOTE: Never change this list as it will mess up the RES_ITEMDEF or RES_WORLDITEM already stored. // Just add stuff to end. diff --git a/src/game/spheresvr.cpp b/src/game/spheresvr.cpp index 9843543fe..350d633ae 100644 --- a/src/game/spheresvr.cpp +++ b/src/game/spheresvr.cpp @@ -1,6 +1,7 @@ #ifdef _WIN32 #include "../sphere/ntservice.h" // g_Service - #include // getpid() + #include "../sphere/ntwindow.h" + #include // getpid() #else #include "../sphere/UnixTerminal.h" #endif @@ -14,26 +15,24 @@ #include "../network/linuxev.h" #endif +#include "../common/sphere_library/CSRand.h" #include "../common/CLog.h" #include "../common/CException.h" +#include "../common/CExpression.h" #include "../common/CUOInstall.h" -#include "../common/sphereversion.h" // sphere version +#include "../common/sphereversion.h" #include "../network/CNetworkManager.h" #include "../network/PingServer.h" #include "../sphere/asyncdb.h" -#include "../sphere/ntwindow.h" #include "clients/CAccount.h" +#include "CObjBase.h" #include "CScriptProfiler.h" -#include "CSector.h" #include "CServer.h" #include "CWorld.h" #include "spheresvr.h" #include #include -// Headers for InitRuntimeStaticMembers -#include "clients/CClient.h" - // Dynamic allocation of some global stuff std::string g_sServerDescription; diff --git a/src/game/spheresvr.h b/src/game/spheresvr.h index 1633b2561..c71ce3c20 100644 --- a/src/game/spheresvr.h +++ b/src/game/spheresvr.h @@ -6,7 +6,7 @@ #ifndef _INC_SPHERESVR_H #define _INC_SPHERESVR_H -#include "../common/common.h" +#include "../common/sphere_library/CSAssoc.h" #include "../sphere/threads.h" diff --git a/src/game/triggers.cpp b/src/game/triggers.cpp index 760b686c5..ffa50a500 100644 --- a/src/game/triggers.cpp +++ b/src/game/triggers.cpp @@ -3,7 +3,6 @@ #include "CServer.h" #include "triggers.h" -//Trigger function start static constexpr lpctstr kOrderedTrigsNames[] = { #define ADD(_a_) \ diff --git a/src/game/uo_files/CUOIndexRec.cpp b/src/game/uo_files/CUOIndexRec.cpp index 2034c50a0..63bf74de3 100644 --- a/src/game/uo_files/CUOIndexRec.cpp +++ b/src/game/uo_files/CUOIndexRec.cpp @@ -2,7 +2,6 @@ #include "CUOVersionBlock.h" - // CUOIndexRec:: Modifiers. void CUOIndexRec::Init() diff --git a/src/game/uo_files/CUOIndexRec.h b/src/game/uo_files/CUOIndexRec.h index bc99d4516..2ce39725b 100644 --- a/src/game/uo_files/CUOIndexRec.h +++ b/src/game/uo_files/CUOIndexRec.h @@ -7,7 +7,7 @@ #define _INC_CUOINDEXREC_H #include "../../common/common.h" -#include "CUOVersionBlock.h" + // All these structures must be byte packed. #if defined(_WIN32) && defined(_MSC_VER) @@ -19,6 +19,7 @@ #define PACK_NEEDED __attribute__ ((packed)) #endif +struct CUOVersionBlock; /** * 12 byte block = used for table indexes. (staidx0.mul,multi.idx,anim.idx) diff --git a/src/game/uo_files/CUOMobtypes.cpp b/src/game/uo_files/CUOMobtypes.cpp index cffc0a61a..131f4d720 100644 --- a/src/game/uo_files/CUOMobtypes.cpp +++ b/src/game/uo_files/CUOMobtypes.cpp @@ -4,7 +4,6 @@ */ #include "../../sphere/threads.h" -#include "../../common/CException.h" #include "../../common/CExpression.h" #include "../../common/CLog.h" #include "../../common/CUOInstall.h" diff --git a/src/game/uo_files/CUOMultiItemRec.h b/src/game/uo_files/CUOMultiItemRec.h index 2067e5099..421da7c98 100644 --- a/src/game/uo_files/CUOMultiItemRec.h +++ b/src/game/uo_files/CUOMultiItemRec.h @@ -7,7 +7,6 @@ #define _INC_CUOMULTIITEMREC_H #include "../../common/common.h" -#include "uofiles_enums.h" #include "uofiles_enums_itemid.h" // All these structures must be byte packed. diff --git a/src/game/uo_files/CUOTiledata.cpp b/src/game/uo_files/CUOTiledata.cpp index 3bbf4274c..d3af4a5ee 100644 --- a/src/game/uo_files/CUOTiledata.cpp +++ b/src/game/uo_files/CUOTiledata.cpp @@ -7,6 +7,9 @@ #include "../../common/CException.h" #include "../../common/CLog.h" #include "../../common/CUOInstall.h" +#include "CUOTerrainTypeRec.h" +#include "uofiles_enums.h" +#include "uofiles_macros.h" #include "CUOTiledata.h" diff --git a/src/game/uo_files/CUOVersionBlock.h b/src/game/uo_files/CUOVersionBlock.h index 53d43b215..09b2ac2e6 100644 --- a/src/game/uo_files/CUOVersionBlock.h +++ b/src/game/uo_files/CUOVersionBlock.h @@ -7,7 +7,7 @@ #define _INC_CUOVERSIONBLOCK_H #include "../../common/common.h" -#include "uofiles_macros.h" +#include "uofiles_enums.h" #define VERDATA_MAKE_INDEX( f, i ) ((f+1)<< 26 | (i)) diff --git a/src/game/uo_files/uofiles_enums.h b/src/game/uo_files/uofiles_enums.h index 3f30306ca..2653cd8d6 100644 --- a/src/game/uo_files/uofiles_enums.h +++ b/src/game/uo_files/uofiles_enums.h @@ -10,7 +10,7 @@ * @brief Movement type for ships * From packet 0xBF.0x32: 0 = Stop Movement, 1 = One Tile Movement, 2 = Normal Movement */ -enum ShipMovementType +enum ShipMovementType : int { SMT_STOP, // No movement SMT_SLOW, // 1 tile movement @@ -21,7 +21,7 @@ enum ShipMovementType * @Speed type for ships * this has to sync with the outgoing 0xF6 packet */ -enum ShipMovementSpeed +enum ShipMovementSpeed : int { SMS_STOP, // 0x0 = no movement SMS_NORMAL, // 0x01 = one tile diff --git a/src/game/uo_files/uofiles_enums_creid.h b/src/game/uo_files/uofiles_enums_creid.h index cb22346d2..9f3d9e3f4 100644 --- a/src/game/uo_files/uofiles_enums_creid.h +++ b/src/game/uo_files/uofiles_enums_creid.h @@ -6,6 +6,8 @@ #ifndef _INC_UOFILES_ENUMS_CREID_H #define _INC_UOFILES_ENUMS_CREID_H +#include + enum CREID_TYPE : uint32_t // enum the creature animations. (dont allow any others !) also know as "model number" { CREID_INVALID = 0, diff --git a/src/game/uo_files/uofiles_enums_itemid.h b/src/game/uo_files/uofiles_enums_itemid.h index be638b488..171806e76 100644 --- a/src/game/uo_files/uofiles_enums_itemid.h +++ b/src/game/uo_files/uofiles_enums_itemid.h @@ -6,7 +6,7 @@ #ifndef _INC_UOFILES_ENUMS_ITEMID_H #define _INC_UOFILES_ENUMS_ITEMID_H -#include +#include #define MULTI_QTY 0x2000 // total address space for multis. diff --git a/src/game/uo_files/uofiles_macros.h b/src/game/uo_files/uofiles_macros.h index c3dc19178..ee53a245c 100644 --- a/src/game/uo_files/uofiles_macros.h +++ b/src/game/uo_files/uofiles_macros.h @@ -6,8 +6,6 @@ #ifndef _INC_UOFILES_MACROS_H #define _INC_UOFILES_MACROS_H -#include "uofiles_enums.h" - // Door ID Attribute flags #define DOOR_OPENED 0x00000001 // set is open diff --git a/src/network/CClientIterator.cpp b/src/network/CClientIterator.cpp index 3ca02581c..ee861577b 100644 --- a/src/network/CClientIterator.cpp +++ b/src/network/CClientIterator.cpp @@ -1,3 +1,4 @@ +#include "../game/clients/CClient.h" #include "CNetState.h" #include "CNetworkManager.h" #include "CClientIterator.h" @@ -9,7 +10,7 @@ ClientIterator::ClientIterator(const CNetworkManager* network) m_nextClient = static_cast (m_network->m_clients.GetContainerHead()); } -ClientIterator::~ClientIterator(void) +ClientIterator::~ClientIterator() { m_network = nullptr; m_nextClient = nullptr; diff --git a/src/network/CClientIterator.h b/src/network/CClientIterator.h index 667ad3282..9bfd33a6b 100644 --- a/src/network/CClientIterator.h +++ b/src/network/CClientIterator.h @@ -6,8 +6,7 @@ #ifndef _INC_CCLIENTITERATOR_H #define _INC_CCLIENTITERATOR_H -#include "../game/clients/CClient.h" - +class CClient; class CNetworkManager; class ClientIterator @@ -18,15 +17,13 @@ class ClientIterator public: explicit ClientIterator(const CNetworkManager* network = nullptr); - ~ClientIterator(void); + ~ClientIterator(); -private: - ClientIterator(const ClientIterator& copy); - ClientIterator& operator=(const ClientIterator& other); + ClientIterator(const ClientIterator& copy) = delete; + ClientIterator& operator=(const ClientIterator& other) = delete; -public: CClient* next(bool includeClosing = false); // finds next client }; -#endif // _INC_CCLIENTITERATOR_H \ No newline at end of file +#endif // _INC_CCLIENTITERATOR_H diff --git a/src/network/CNetworkInput.cpp b/src/network/CNetworkInput.cpp index cdf5d2339..23380e34d 100644 --- a/src/network/CNetworkInput.cpp +++ b/src/network/CNetworkInput.cpp @@ -98,7 +98,7 @@ void CNetworkInput::receiveData() // receive data EXC_SET_BLOCK("messages - receive"); int received = state->m_socket.Receive(m_receiveBuffer, NETWORK_BUFFERSIZE, 0); - state->_iInByteCounter += SphereAbs(received); + state->_iInByteCounter += abs(received); if (received <= 0 || received > NETWORK_BUFFERSIZE) { state->markReadClosed(); diff --git a/src/network/CNetworkOutput.h b/src/network/CNetworkOutput.h index 62815e63d..c4cabbfe7 100644 --- a/src/network/CNetworkOutput.h +++ b/src/network/CNetworkOutput.h @@ -8,7 +8,9 @@ #include "../common/common.h" +class CNetState; class CNetworkThread; +class PacketSend; class PacketTransaction; diff --git a/src/network/CPacketManager.cpp b/src/network/CPacketManager.cpp index 14cd0cb07..77a7f2ca3 100644 --- a/src/network/CPacketManager.cpp +++ b/src/network/CPacketManager.cpp @@ -1,9 +1,8 @@ -#include "../common/CLog.h" -#include "../game/CServerConfig.h" +#include "../sphere/threads.h" #include "packet.h" #include "receive.h" -#include "send.h" #include "CPacketManager.h" +#include PacketManager::PacketManager(void) diff --git a/src/network/CSocket.cpp b/src/network/CSocket.cpp index 8a9497cbf..c99c40b05 100644 --- a/src/network/CSocket.cpp +++ b/src/network/CSocket.cpp @@ -5,6 +5,7 @@ #include "../common/sphere_library/sstring.h" #include "../common/CLog.h" + void AddSocketToSet(fd_set& fds, SOCKET socket, int& count) { #ifdef _WIN32 diff --git a/src/network/CSocket.h b/src/network/CSocket.h index 616a0d027..1dc7f9c6e 100644 --- a/src/network/CSocket.h +++ b/src/network/CSocket.h @@ -17,7 +17,6 @@ #include #include #include - #include #include // Compatibility stuff. diff --git a/src/network/PingServer.cpp b/src/network/PingServer.cpp index d84b3aeca..63a4dd4ad 100644 --- a/src/network/PingServer.cpp +++ b/src/network/PingServer.cpp @@ -1,8 +1,8 @@ -#include "../common/common.h" #include "../sphere/ProfileTask.h" #include "PingServer.h" + PingServer g_PingServer; // run the thread in RealTime as we need pings to be responded to ASAP diff --git a/src/network/packet.cpp b/src/network/packet.cpp index cde1e6475..10adbb25a 100644 --- a/src/network/packet.cpp +++ b/src/network/packet.cpp @@ -204,7 +204,7 @@ void Packet::seek(uint pos) void Packet::skip(int count) { // ensure we can't go lower than 0 - if (count < 0 && (uint)SphereAbs(count) > m_position) + if (count < 0 && (uint)abs(count) > m_position) { m_position = 0; return; diff --git a/src/network/receive.cpp b/src/network/receive.cpp index 53f75dc37..f78aef4f0 100644 --- a/src/network/receive.cpp +++ b/src/network/receive.cpp @@ -1,10 +1,12 @@ #include "../common/resource/sections/CDialogDef.h" +#include "../common/CExpression.h" #include "../common/CLog.h" #include "../common/CUOClientVersion.h" +#include "../game/uo_files/uofiles_enums_creid.h" #include "../game/chars/CChar.h" #include "../game/clients/CClient.h" -#include "../game/items/CItem.h" +#include "../game/items/CItemContainer.h" #include "../game/items/CItemMap.h" #include "../game/items/CItemMessage.h" #include "../game/items/CItemMultiCustom.h" diff --git a/src/network/receive.h b/src/network/receive.h index c2a09d87d..4f7c65400 100644 --- a/src/network/receive.h +++ b/src/network/receive.h @@ -6,7 +6,6 @@ #ifndef _INC_RECEIVE_H #define _INC_RECEIVE_H -#include "../common/sphere_library/CSTime.h" #include "../common/CUID.h" #include "../common/sphereproto.h" #include "../game/uo_files/uofiles_enums.h" diff --git a/src/network/send.cpp b/src/network/send.cpp index 019b4199b..d65972369 100644 --- a/src/network/send.cpp +++ b/src/network/send.cpp @@ -1,23 +1,21 @@ -#ifndef _WIN32 - #include -#endif -#include - #include "../common/resource/CResourceLock.h" +#include "../common/CExpression.h" #include "../common/CLog.h" #include "../common/CUOInstall.h" #include "../game/chars/CChar.h" +#include "../game/components/CCItemDamageable.h" +#include "../game/components/CCPropsChar.h" #include "../game/clients/CClient.h" #include "../game/clients/CClientTooltip.h" #include "../game/clients/CParty.h" -#include "../game/items/CItem.h" +#include "../game/items/CItemCorpse.h" #include "../game/items/CItemMap.h" #include "../game/items/CItemMessage.h" #include "../game/items/CItemMultiCustom.h" +#include "../game/items/CItemStone.h" #include "../game/items/CItemVendable.h" -#include "../game/components/CCItemDamageable.h" -#include "../game/components/CCPropsChar.h" +#include "../game/uo_files/uofiles_enums_creid.h" #include "../game/CServer.h" #include "../game/CWorldGameTime.h" #include "CNetworkManager.h" @@ -27,6 +25,12 @@ namespace zlib { #include } +#ifndef _WIN32 +# include +#endif +#include + + /*************************************************************************** * * diff --git a/src/network/send.h b/src/network/send.h index ddb041f44..52f5d41a2 100644 --- a/src/network/send.h +++ b/src/network/send.h @@ -8,9 +8,9 @@ #include "../common/CUID.h" +#include "../common/CLanguageID.h" #include "../common/sphereproto.h" #include "../common/CRect.h" -#include "../game/CRegion.h" #include "../game/game_enums.h" #include "../game/CServerConfig.h" #include "CNetState.h" diff --git a/src/resources/SphereSvr.rc b/src/resources/SphereSvr.rc index 50b758b65..7d99d47b0 100644 --- a/src/resources/SphereSvr.rc +++ b/src/resources/SphereSvr.rc @@ -1,7 +1,7 @@ // Microsoft Visual C++ generated resource script (hand-edited). // #include "win_resource.h" -#define COPYRIGHT_STR "Copyright (C) 1998-2023 SphereServer development team" +#define COPYRIGHT_STR "Copyright (C) 1998-2024 SphereServer development team" #define APSTUDIO_READONLY_SYMBOLS ///////////////////////////////////////////////////////////////////////////// @@ -9,10 +9,21 @@ // Generated from the TEXTINCLUDE 2 resource. // #ifdef _WIN32 - #ifndef WIN32_LEAN_AND_MEAN - #define WIN32_LEAN_AND_MEAN // include just windows.h without the other winapi headers, we'll add them manually when needed - #endif - #include +# ifndef WIN32_LEAN_AND_MEAN +# define WIN32_LEAN_AND_MEAN // include just windows.h without the other winapi headers, we'll add them manually when needed +# endif + +# ifdef _MSC_VER + // Workaround to a possible VS compiler bug: instead of complaining if a macro expands to a "defined" macro, + // it complains if a define macro contains the words "defined" in its name... +# pragma warning(push) +# pragma warning(disable: 5105) +# endif +# include +# ifdef _MSC_VER +# pragma warning(pop) +# endif + #endif ///////////////////////////////////////////////////////////////////////////// diff --git a/src/sphere/ConsoleInterface.h b/src/sphere/ConsoleInterface.h index e6a1312d2..0b96d588f 100644 --- a/src/sphere/ConsoleInterface.h +++ b/src/sphere/ConsoleInterface.h @@ -2,11 +2,11 @@ #define _INC_CONSOLEINTERFACE_H #include "../common/sphere_library/CSString.h" -#include "../common/basic_threading.h" #ifndef _WIN32 #include #endif #include +#include enum ConsoleTextColor // needed by both windows and unix diff --git a/src/sphere/ProfileData.cpp b/src/sphere/ProfileData.cpp index 281cb247e..9789a3334 100644 --- a/src/sphere/ProfileData.cpp +++ b/src/sphere/ProfileData.cpp @@ -1,8 +1,9 @@ -#include -#include "../common/sphere_library/CSString.h" + +#include "../common/sphere_library/CSTime.h" #include "../game/CScriptProfiler.h" #include "ProfileData.h" #include "threads.h" +#include ProfileData::ProfileData() noexcept { diff --git a/src/sphere/UnixTerminal.cpp b/src/sphere/UnixTerminal.cpp index daa884170..d522ae61e 100644 --- a/src/sphere/UnixTerminal.cpp +++ b/src/sphere/UnixTerminal.cpp @@ -2,7 +2,6 @@ #ifndef _WIN32 #include "../common/CException.h" -#include "../game/CServer.h" #include "UnixTerminal.h" #ifndef _USECURSES diff --git a/src/sphere/asyncdb.cpp b/src/sphere/asyncdb.cpp index 0458f4a0a..cff073390 100644 --- a/src/sphere/asyncdb.cpp +++ b/src/sphere/asyncdb.cpp @@ -1,7 +1,6 @@ #include "../common/CScriptObj.h" #include "../common/CScriptTriggerArgs.h" -#include "../game/triggers.h" #include "../game/CServer.h" #include "asyncdb.h" diff --git a/src/sphere/asyncdb.h b/src/sphere/asyncdb.h index e5dbf0e14..aede0ba29 100644 --- a/src/sphere/asyncdb.h +++ b/src/sphere/asyncdb.h @@ -6,8 +6,10 @@ #ifndef _INC_ASYNCDB_H #define _INC_ASYNCDB_H +#include "../common/sphere_library/CSString.h" #include "../common/sphere_library/smutex.h" #include "threads.h" +#include class CDataBaseAsyncHelper : public AbstractSphereThread diff --git a/src/sphere/ntservice.cpp b/src/sphere/ntservice.cpp index e9c1f4461..88857c81c 100644 --- a/src/sphere/ntservice.cpp +++ b/src/sphere/ntservice.cpp @@ -4,6 +4,7 @@ #include #include "../common/CException.h" +#include "../common/CExpression.h" #include "../common/sphereversion.h" #include "../common/CLog.h" #include "../game/CObjBase.h" diff --git a/src/sphere/ntwindow.cpp b/src/sphere/ntwindow.cpp index 166d98243..5b21fbb47 100644 --- a/src/sphere/ntwindow.cpp +++ b/src/sphere/ntwindow.cpp @@ -4,6 +4,7 @@ #include "../common/sphere_library/CSWindow.h" #include "../common/sphere_library/CSString.h" #include "../common/CException.h" +#include "../common/CExpression.h" #include "../common/CTextConsole.h" #include "../common/CLog.h" #include "../common/sphereversion.h" // sphere version diff --git a/src/sphere/threads.cpp b/src/sphere/threads.cpp index c15f53f7c..36ea2275c 100644 --- a/src/sphere/threads.cpp +++ b/src/sphere/threads.cpp @@ -1,9 +1,6 @@ // this thing is somehow required to be able to initialise OLE #define _WIN32_DCOM -#include -#include -#include #include "../common/basic_threading.h" #include "../common/CException.h" #include "../common/CLog.h" @@ -18,6 +15,10 @@ #include #endif +#include +#include +#include + // number of exceptions after which we restart thread and think that the thread have gone in exceptioning loops #define EXCEPTIONS_ALLOWED 10 diff --git a/src/sphere/threads.h b/src/sphere/threads.h index e8b305d94..f4ea58293 100644 --- a/src/sphere/threads.h +++ b/src/sphere/threads.h @@ -7,13 +7,10 @@ #define _INC_THREADS_H #include "../common/common.h" -#include "../common/sphere_library/smutex.h" #include "../common/sphere_library/sresetevents.h" #include "../common/sphere_library/sstringobjs.h" -#include "../common/sphere_library/CSTime.h" #include "../sphere/ProfileData.h" #include -#include #include #ifndef _WIN32 diff --git a/src/tables/classnames.tbl b/src/tables/classnames.tbl index a26551248..c499f313e 100644 --- a/src/tables/classnames.tbl +++ b/src/tables/classnames.tbl @@ -12,6 +12,7 @@ #include "../common/resource/sections/CSkillClassDef.h" #include "../common/sphere_library/CSObjCont.h" #include "../common/sphere_library/CSObjList.h" +#include "../common/CSFileObj.h" #include "../common/CSFileObjContainer.h" #include "../game/CEntity.h" @@ -22,17 +23,25 @@ #include "../game/components/CCSpawn.h" #include "../game/components/CCChampion.h" #include "../game/items/CItemCommCrystal.h" +#include "../game/items/CItemContainer.h" +#include "../game/items/CItemCorpse.h" #include "../game/items/CItemMultiCustom.h" #include "../game/items/CItemMap.h" #include "../game/items/CItemMessage.h" #include "../game/items/CItemShip.h" +#include "../game/items/CItemStone.h" #include "../game/CSectorList.h" +#include "../game/CServer.h" +#include "../game/CServerDef.h" #include "../game/CPathFinder.h" + +#include "../game/CWorld.h" #include "../game/CWorldComm.h" #include "../game/CWorldGameTime.h" #include "../game/CWorldMap.h" #include "../game/CWorldTickingList.h" +#include "../network/CNetworkManager.h" #include "../network/CNetworkInput.h" #include "../network/CNetworkOutput.h" #include "../network/CNetworkThread.h" From a5c6b7eb793e7b529d83bce6ed1a052e95746480 Mon Sep 17 00:00:00 2001 From: cbnolok Date: Sun, 15 Sep 2024 15:27:24 +0200 Subject: [PATCH 40/86] Fixed wrong ASSERT when moving an item to a sector. --- src/game/CSectorTemplate.cpp | 47 +++++++++++++++++++++++++----------- src/game/chars/CCharNPC.cpp | 4 +-- 2 files changed, 35 insertions(+), 16 deletions(-) diff --git a/src/game/CSectorTemplate.cpp b/src/game/CSectorTemplate.cpp index 56fa4da28..79acf97df 100644 --- a/src/game/CSectorTemplate.cpp +++ b/src/game/CSectorTemplate.cpp @@ -1,3 +1,4 @@ +#include "../common/CException.h" #include "../common/CLog.h" #include "../common/CRect.h" #include "../game/CWorld.h" @@ -90,6 +91,7 @@ void CItemsList::OnRemoveObj(CSObjContRec* pObjRec) pItem->OnMoveFrom(); // IT_MULTI, IT_SHIP and IT_COMM_CRYSTAL } + // NOLINTNEXTLINE(clang-analyzer-core.CallAndMessage) (It's intentional that we don't check it everytime) DEBUG_ASSERT(pObjRec->GetParent() == this); CSObjCont::OnRemoveObj(pObjRec); DEBUG_ASSERT(pObjRec->GetParent() == nullptr); @@ -108,23 +110,40 @@ void CItemsList::AddItemToSector( CItem * pItem ) CSObjCont* pParent = pItem->GetParent(); if (pParent != this) { - DEBUG_ASSERT( - (pParent == nullptr) || - (pParent == g_World.GetObjectsNew()) || - (nullptr != dynamic_cast(pParent)) - ); - - CSObjCont::InsertContentTail(pItem); // this also removes the Char from the old sector - - DEBUG_ASSERT(pItem->GetParent() == this); #ifdef _DEBUG - const CSObjCont* pObjNew = g_World.GetObjectsNew(); - auto itNew = std::find(pObjNew->cbegin(), pObjNew->cend(), pItem); - DEBUG_ASSERT(itNew == pObjNew->cend()); + if (!pParent) + throw CSError(LOGL_ERROR, 0, "No parent?"); + + const auto* pNewWorldObjCont = g_World.GetObjectsNew(); + if (pParent == pNewWorldObjCont) + { + // Just created, unplaced yet. + auto itNew = std::find(pNewWorldObjCont->cbegin(), pNewWorldObjCont->cend(), pItem); + DEBUG_ASSERT(itNew != pNewWorldObjCont->cend()); + } + else if (dynamic_cast(pParent)) + { + // I'm moving it here from another sector. + auto itOldParent = std::find(pParent->cbegin(), pParent->cend(), pItem); + DEBUG_ASSERT(itOldParent != pParent->cend()); + } + else if (dynamic_cast(pParent)) + { + // CItemContainer, CChar... + auto itOldParent = std::find(pParent->cbegin(), pParent->cend(), pItem); + DEBUG_ASSERT(itOldParent != pParent->cend()); + } + else + { + if (dynamic_cast(pParent)) + throw CSError(LOGL_ERROR, 0, "Parent is an unknown CObjBase?"); + throw CSError(LOGL_ERROR, 0, "Parent not NEW nor a Sector? Unknown type."); + } - auto itOldParent = std::find(pParent->cbegin(), pParent->cend(), pItem); - DEBUG_ASSERT(itOldParent == pParent->cend()); #endif + + CSObjCont::InsertContentTail(pItem); // this also removes the Char from the old sector + DEBUG_ASSERT(pItem->GetParent() == this); } pItem->RemoveUIDFlags(UID_O_DISCONNECT); diff --git a/src/game/chars/CCharNPC.cpp b/src/game/chars/CCharNPC.cpp index eaf48d8e3..d6cb5a6ac 100644 --- a/src/game/chars/CCharNPC.cpp +++ b/src/game/chars/CCharNPC.cpp @@ -83,7 +83,7 @@ bool CCharNPC::r_LoadVal( CChar * pChar, CScript &s ) pChar->UpdatePropertyFlag(); break; case CNC_ACTPRI: - m_Act_Motivation = (uchar)(s.GetArgVal()); + m_Act_Motivation = s.GetArgUCVal(); break; case CNC_NPC: m_Brain = NPCBRAIN_TYPE(s.GetArgVal()); @@ -93,7 +93,7 @@ bool CCharNPC::r_LoadVal( CChar * pChar, CScript &s ) { pChar->m_ptHome = pChar->GetTopPoint(); } - m_Home_Dist_Wander = (word)(s.GetArgVal()); + m_Home_Dist_Wander = s.GetArgWVal(); break; case CNC_NEED: case CNC_NEEDNAME: From 8889ea62d0209cfd802410dacaa6061c29ba05c8 Mon Sep 17 00:00:00 2001 From: cbnolok Date: Tue, 17 Sep 2024 20:02:12 +0200 Subject: [PATCH 41/86] New fix for followerslots. Fixed BaseID cropping IDs > int16_max. Added CBaseBase::GetKey. --- Changelog.txt | 4 +- src/common/CFloatMath.cpp | 1 - src/game/CBase.h | 12 +++- src/game/CObjBase.h | 4 +- src/game/chars/CChar.cpp | 116 +++++++++++++++++------------- src/game/chars/CChar.h | 6 +- src/game/chars/CCharAct.cpp | 5 +- src/game/chars/CCharBase.cpp | 11 +-- src/game/chars/CCharNPCPet.cpp | 28 ++++---- src/game/chars/CCharUse.cpp | 80 +++++++++++++++------ src/game/clients/CClientEvent.cpp | 4 +- src/game/items/CItem.cpp | 5 ++ src/game/items/CItem.h | 4 +- src/sphere/UnixTerminal.cpp | 2 +- src/sphere/threads.cpp | 10 +-- 15 files changed, 186 insertions(+), 106 deletions(-) diff --git a/Changelog.txt b/Changelog.txt index 05f4a6c19..715ae2881 100644 --- a/Changelog.txt +++ b/Changelog.txt @@ -3891,7 +3891,9 @@ Added: 'H' shortcut for variables to get the value as hexadecimal. RETURN 1: Only reject the connection. RETURN 2: Reject and ban the IP for seconds. -13-09-2024, Nolok +17-09-2024, Nolok - Fixed: When acquiring a new pet follower, CurFollower incremented by 1 regardless of pet's FollowerSlots value (Issue #1251). - Fixed: dynamic FOLLOWERSLOTS property wasn't correctly saved and loaded from a worldsave. +- Added: dynamic FOLLOWERSLOTS property is now copied to the figurine as TAG.FOLLOWERSLOTS when an NPC is shrinked, and it's applied back when unshrinked. - Added: FOLLOWER. to reference char followers. +- Fixed: "mounting"/guiding through the ship pilot exit/dismount bug. diff --git a/src/common/CFloatMath.cpp b/src/common/CFloatMath.cpp index 231afabed..1cfd8afe1 100644 --- a/src/common/CFloatMath.cpp +++ b/src/common/CFloatMath.cpp @@ -2,7 +2,6 @@ #include #include #include -#include "../game/CObjBase.h" #include "../game/CServerConfig.h" #include "../sphere/threads.h" #include "sphere_library/CSRand.h" diff --git a/src/game/CBase.h b/src/game/CBase.h index 52e26582d..3f635a826 100644 --- a/src/game/CBase.h +++ b/src/game/CBase.h @@ -139,10 +139,20 @@ struct CBaseBaseDef : public CResourceLink, public CEntityProps uint64 m_Can; // Base attribute flags. CAN_C_GHOST, etc public: + /** + * @brief Gets definition pointer. + * @param ptcKey The key. + * @return The definition pointer. + */ + CVarDefCont * GetKey( lpctstr ptcKey ) const + { + return m_BaseDefs.GetKey(ptcKey); + } + /** * @brief Gets definition string. * @param ptcKey The key. - * @param fZero true to zero. + * @param fZero Return "0" if empty/undefined. * @return The definition string. */ lpctstr GetDefStr( lpctstr ptcKey, bool fZero = false ) const diff --git a/src/game/CObjBase.h b/src/game/CObjBase.h index b94b37b6b..7a94ef5e1 100644 --- a/src/game/CObjBase.h +++ b/src/game/CObjBase.h @@ -524,14 +524,14 @@ public: virtual bool IsDeleted() const override; // Accessors /** - * @fn virtual word CObjBase::GetBaseID() const = 0; + * @fn virtual dword CObjBase::GetBaseID() const = 0; * * @brief Gets base identifier. * * @return The base identifier. */ - virtual word GetBaseID() const = 0; + virtual dword GetBaseID() const = 0; /** * @fn void CObjBase::SetUID( dword dwVal, bool fItem ); diff --git a/src/game/chars/CChar.cpp b/src/game/chars/CChar.cpp index 43d7917d2..e2b9d8d82 100644 --- a/src/game/chars/CChar.cpp +++ b/src/game/chars/CChar.cpp @@ -260,6 +260,7 @@ CChar::CChar( CREID_TYPE baseID ) : m_sTitle(false), m_Skill{}, m_Stat{} { + ADDTOCALLSTACK("CChar::CChar"); g_Serv.StatInc( SERV_STAT_CHARS ); // Count created CChars. m_pArea = nullptr; @@ -312,7 +313,7 @@ CChar::CChar( CREID_TYPE baseID ) : m_defenseRange = pCharDef->m_defenseRange; _wBloodHue = pCharDef->_wBloodHue; // when damaged , what color is the blood (-1) = no blood - SetName( pCharDef->GetTypeName()); // set the name in case there is a name template. + CChar::SetName( pCharDef->GetTypeName()); // set the name in case there is a name template. Stat_SetVal( STAT_FOOD, Stat_GetMaxAdjusted(STAT_FOOD) ); m_uiFame = 0; @@ -1533,10 +1534,9 @@ CREID_TYPE CChar::GetID() const return pCharDef->GetID(); } -word CChar::GetBaseID() const +dword CChar::GetBaseID() const { - // future: strongly typed enums will remove the need for this cast - return (word)(GetID()); + return GetID(); } CREID_TYPE CChar::GetDispID() const @@ -1908,9 +1908,9 @@ void CChar::InitPlayer( CClient *pClient, const char *pszCharname, bool fFemale, 0x322, 0x323, 0x324, 0x325, 0x326, 0x369, 0x386, 0x387, 0x388, 0x389, 0x38A, 0x59D, 0x6B8, 0x725, 0x853 }; - constexpr uint iMax = ARRAY_COUNT(sm_ElfHairHues); + constexpr uint uiMax = ARRAY_COUNT(sm_ElfHairHues); bool isValid = 0; - for ( uint i = 0; i < iMax; ++i ) + for ( uint i = 0; i < uiMax; ++i ) { if ( sm_ElfHairHues[i] == wHairHue ) { @@ -1930,9 +1930,9 @@ void CChar::InitPlayer( CClient *pClient, const char *pszCharname, bool fFemale, 0x709, 0x70B, 0x70D, 0x70F, 0x711, 0x763, 0x765, 0x768, 0x76B, 0x6F3, 0x6F1, 0x6EF, 0x6E4, 0x6E2, 0x6E0, 0x709, 0x70B, 0x70D }; - constexpr uint iMax = ARRAY_COUNT(sm_GargoyleHornHues); + constexpr uint uiMax = ARRAY_COUNT(sm_GargoyleHornHues); bool isValid = 0; - for ( uint i = 0; i < iMax; ++i ) + for ( uint i = 0; i < uiMax; ++i ) { if ( sm_GargoyleHornHues[i] == wHairHue ) { @@ -1993,23 +1993,23 @@ void CChar::InitPlayer( CClient *pClient, const char *pszCharname, bool fFemale, case RACETYPE_GARGOYLE: { - static constexpr int sm_GargoyleBeardHues[] = + static constexpr ushort sm_GargoyleBeardHues[] = { 0x709, 0x70B, 0x70D, 0x70F, 0x711, 0x763, 0x765, 0x768, 0x76B, 0x6F3, 0x6F1, 0x6EF, 0x6E4, 0x6E2, 0x6E0, 0x709, 0x70B, 0x70D }; - int iMax = ARRAY_COUNT(sm_GargoyleBeardHues); + const uint uiMax = ARRAY_COUNT(sm_GargoyleBeardHues); bool isValid = 0; - for ( int i = 0; i < iMax; ++i ) + for ( uint i = 0; i < uiMax; ++i ) { - if ( sm_GargoyleBeardHues[i] == wHairHue ) + if ( sm_GargoyleBeardHues[i] == wBeardHue ) { isValid = 1; break; } } if ( !isValid ) - wHairHue = (HUE_TYPE)(sm_GargoyleBeardHues[0]); + wBeardHue = (HUE_TYPE)(sm_GargoyleBeardHues[0]); } break; @@ -2423,7 +2423,7 @@ bool CChar::r_WriteVal( lpctstr ptcKey, CSString & sVal, CTextConsole * pSrc, bo } else if ( !strnicmp(ptcKey, "TARGET", 6 ) ) { - ptcKey += 6; + //ptcKey += 6; //Using both m_Act_UID and m_Fight_Targ_UID will take care of both spell and fighting targets. if (m_Act_UID.IsValidUID() || m_Fight_Targ_UID.IsValidUID()) sVal.FormatHex((dword)(m_Fight_Targ_UID)); @@ -3365,45 +3365,62 @@ bool CChar::r_LoadVal( CScript & s ) EXC_SET_BLOCK("Keyword"); lpctstr ptcKey = s.GetKey(); - CHC_TYPE iKeyNum = (CHC_TYPE) FindTableHeadSorted( ptcKey, sm_szLoadKeys, ARRAY_COUNT( sm_szLoadKeys )-1 ); - if ( iKeyNum < 0 ) - { - if (!strnicmp("FOLLOWER", ptcKey, 8)) + if (!strnicmp("FOLLOWER", ptcKey, 8)) + { + // Need to do this before FindTableHeadSorted, because it might match FOLLOWERSLOTS instead! + if (ptcKey[8] == '.') { - if (ptcKey[8] == '.') - { - ptcKey += 9; - // I'm probably loading from a save, or that's a very weird way to add a follower... - // Anyways, i expect the followers to be passed with sequential incremental ids: 0, 1, 2... Not random order. - const uint uiIndex = Exp_GetUVal(ptcKey); - if (uiIndex != m_followers.size()) - return false; + ptcKey += 9; + // I'm probably loading from a save, or that's a very weird way to add a follower... + // Anyways, i expect the followers to be passed with sequential incremental ids: 0, 1, 2... Not random order. - const CUID uidPet(Exp_GetDWVal(ptcKey)); - const CChar* pCharPet = uidPet.CharFind(); - if (!pCharPet) - return false; + const uint uiIndex = Exp_GetUVal(ptcKey); + if (uiIndex != m_followers.size()) + return false; - const bool fExists = - !m_followers.empty() && - m_followers.end() != - std::find_if(m_followers.begin(), m_followers.end(), - [&uidPet](auto const& inp_struct) -> bool { - return inp_struct.uid == uidPet; - }); - if (fExists) - return false; + int64 piVals[2]{}; + const int iValsCount = Str_ParseCmds(s.GetArgStr(), piVals, ARRAY_COUNT(piVals)); + if (iValsCount < 1) + return false; + if (iValsCount < 2) + { + g_Log.EventWarn("Missing FollowerSlots number (old Sphere build?), defaulting to 1.\n"); + piVals[1] = 1; + } - m_followers.emplace_back( - FollowerCharData { - .uid = uidPet, - .followerslots = pCharPet->GetFollowerSlots() - }); + const CUID uidPet(piVals[0]); + const short iFollowerSlots = n64_narrow_n16(piVals[1]); + + // If i'm loading the world, this char might not exist yet! + //const CChar* pCharPet = uidPet.CharFind(); + //if (!pCharPet) + // return false; + + // Already loaded as a follower?! + const bool fExists = + !m_followers.empty() && + m_followers.end() != + std::find_if(m_followers.begin(), m_followers.end(), + [&uidPet](auto const& inp_struct) -> bool { + return inp_struct.uid == uidPet; + }); + if (fExists) + return false; - return true; - } + m_followers.emplace_back( + FollowerCharData { + .uid = uidPet, + .followerslots = iFollowerSlots + //.followerslots = pCharPet->GetFollowerSlots() // If the char doesn't exist yet... + }); + + return true; } + } + CHC_TYPE iKeyNum = (CHC_TYPE) FindTableHeadSorted( ptcKey, sm_szLoadKeys, ARRAY_COUNT( sm_szLoadKeys )-1 ); + if ( iKeyNum < 0 ) + { if ( m_pPlayer ) { if ( m_pPlayer->r_LoadVal( this, s )) @@ -4022,10 +4039,9 @@ void CChar::r_Write( CScript & s ) CObjBase::r_Write(s); for (uint i = 0; auto const& fdata : m_followers) { - dword dUID = (dword)fdata.uid; - char *pszTag = Str_GetTemp(); - snprintf(pszTag, Str_TempLength(), "FOLLOWER.%u", i); - s.WriteKeyHex(pszTag, dUID); + char *pcTag = Str_GetTemp(); + snprintf(pcTag, Str_TempLength(), "FOLLOWER.%u", i); + s.WriteKeyFormat(pcTag, "0%" PRIx32 ",%d", fdata.uid.GetObjUID(), fdata.followerslots); ++ i; } diff --git a/src/game/chars/CChar.h b/src/game/chars/CChar.h index c5a5434d9..20a4bd212 100644 --- a/src/game/chars/CChar.h +++ b/src/game/chars/CChar.h @@ -399,15 +399,15 @@ public: void StatFlag_Mod(uint64 uiStatFlag, bool fMod) noexcept; // Information about us. CREID_TYPE GetID() const; - virtual word GetBaseID() const override; + virtual dword GetBaseID() const override final; CREID_TYPE GetDispID() const; bool SetDispID(CREID_TYPE id); void SetID( CREID_TYPE id ); - virtual lpctstr GetName() const override; + virtual lpctstr GetName() const override final; lpctstr GetNameWithoutIncognito() const; lpctstr GetName( bool fAllowAlt ) const; - virtual bool SetName( lpctstr pName ) override; + virtual bool SetName( lpctstr pName ) override final; height_t GetHeightMount( bool fEyeSubstract = false ) const; height_t GetHeight() const; diff --git a/src/game/chars/CCharAct.cpp b/src/game/chars/CCharAct.cpp index d5475a04c..897a1e55d 100644 --- a/src/game/chars/CCharAct.cpp +++ b/src/game/chars/CCharAct.cpp @@ -3601,7 +3601,8 @@ CItem * CChar::Make_Figurine( const CUID &uidOwner, ITEMID_TYPE id ) if ( IsDisconnected() || m_pPlayer ) return nullptr; - CCharBase* pCharDef = Char_GetDef(); + const CCharBase* pCharDef = Char_GetDef(); + const CVarDefCont* pDynamicVarFollowerSlots = GetDefKey("FOLLOWERSLOTS", false); // turn creature into a figurine. CItem * pItem = CItem::CreateScript( (id == ITEMID_NOTHING) ? pCharDef->m_trackID : id, this ); @@ -3614,6 +3615,8 @@ CItem * CChar::Make_Figurine( const CUID &uidOwner, ITEMID_TYPE id ) pItem->m_itFigurine.m_ID = GetID(); // Base type of creature. (More1 of i_memory) pItem->m_itFigurine.m_UID = GetUID(); pItem->m_uidLink = uidOwner; + if (pDynamicVarFollowerSlots) + pItem->m_TagDefs.SetNum("FOLLOWERSLOTS", pDynamicVarFollowerSlots->GetValNum(), false, false); if ( IsStatFlag(STATF_INSUBSTANTIAL) ) pItem->SetAttr(ATTR_INVIS); diff --git a/src/game/chars/CCharBase.cpp b/src/game/chars/CCharBase.cpp index 10e1ecc39..30ecdb6e2 100644 --- a/src/game/chars/CCharBase.cpp +++ b/src/game/chars/CCharBase.cpp @@ -342,13 +342,16 @@ bool CCharBase::r_LoadVal( CScript & s ) } break; //Set as number only - case CBC_FOLLOWERSLOTS: + case CBC_FOLLOWERSLOTS: case CBC_MAXFOLLOWER: - case CBC_BONDED: - case CBC_TITHING: - SetDefNum(s.GetKey(), s.GetArgVal(), false); + SetDefNum(s.GetKey(), abs(s.GetArgVal()), false); break; + case CBC_BONDED: + case CBC_TITHING: + SetDefNum(s.GetKey(), s.GetArgLLVal(), false); + break; + case CBC_ANIM: m_Anims = s.GetArgVal(); break; diff --git a/src/game/chars/CCharNPCPet.cpp b/src/game/chars/CCharNPCPet.cpp index ae2d7d137..a9ce07c0a 100644 --- a/src/game/chars/CCharNPCPet.cpp +++ b/src/game/chars/CCharNPCPet.cpp @@ -516,7 +516,7 @@ bool CChar::NPC_OnHearPetCmdTarg( int iCmd, CChar *pSrc, CObjBase *pObj, const C if ( IsSetOF(OF_PetSlots) ) { short iFollowerSlots = GetFollowerSlots(); - if ( !pCharTarg->FollowersUpdate(this, (maximum(0, iFollowerSlots)), true) ) + if ( !pCharTarg->FollowersUpdate(this, iFollowerSlots, true) ) { pSrc->SysMessageDefault(DEFMSG_PETSLOTS_TRY_TRANSFER); break; @@ -587,8 +587,8 @@ void CChar::NPC_PetClearOwners() if ( pOwner && IsSetOF(OF_PetSlots) ) { - short iFollowerSlots = GetFollowerSlots(); - pOwner->FollowersUpdate(this, -maximum(0, iFollowerSlots)); + const short iFollowerSlots = GetFollowerSlots(); + pOwner->FollowersUpdate(this, -iFollowerSlots); } } @@ -600,7 +600,7 @@ bool CChar::NPC_PetSetOwner( CChar * pChar ) if ( m_pPlayer || !pChar || (pChar == this) ) return false; - const CChar * pOwner = NPC_PetGetOwner(); + CChar * pOwner = NPC_PetGetOwner(); if ( pOwner == pChar ) return false; @@ -609,8 +609,10 @@ bool CChar::NPC_PetSetOwner( CChar * pChar ) CCSpawn* pSpawn = GetSpawn(); if ( pSpawn ) pSpawn->DelObj( GetUID() ); + Memory_AddObjTypes(pChar, MEMORY_IPET); NPC_Act_Follow(); + if ( NPC_IsVendor() ) { // Clear my cash total. @@ -622,7 +624,7 @@ bool CChar::NPC_PetSetOwner( CChar * pChar ) if ( IsSetOF(OF_PetSlots) ) { const short iFollowerSlots = GetFollowerSlots(); - pChar->FollowersUpdate(this, maximum(0, iFollowerSlots)); + pChar->FollowersUpdate(this, iFollowerSlots); } return true; @@ -646,24 +648,24 @@ bool CChar::NPC_CheckHirelingStatus() CCharBase * pCharDef = Char_GetDef(); int64 iFoodConsumeRate = g_Cfg.m_iRegenRate[STAT_FOOD] / MSECS_PER_SEC; - uint iWage = pCharDef->GetHireDayWage(); - if ( ! iWage || ! iFoodConsumeRate ) + uint uiWage = pCharDef->GetHireDayWage(); + if ( ! uiWage || ! iFoodConsumeRate ) return true; // I am hired for money not for food. - uint iPeriodWage = (uint)IMulDivLL( iWage, iFoodConsumeRate, 24 * 60 * g_Cfg.m_iGameMinuteLength ); - if ( iPeriodWage <= 0 ) - iPeriodWage = 1; + uint uiPeriodWage = (uint)IMulDivLL( uiWage, iFoodConsumeRate, 24 * 60 * g_Cfg.m_iGameMinuteLength ); + if ( uiPeriodWage <= 0 ) + uiPeriodWage = 1; CItemContainer * pBank = GetBank(); - if ( pBank->m_itEqBankBox.m_Check_Amount > iPeriodWage ) + if ( pBank->m_itEqBankBox.m_Check_Amount > uiPeriodWage ) { - pBank->m_itEqBankBox.m_Check_Amount -= iPeriodWage; + pBank->m_itEqBankBox.m_Check_Amount -= uiPeriodWage; } else { tchar* pszMsg = Str_GetTemp(); - snprintf(pszMsg, Str_TempLength(), g_Cfg.GetDefaultMsg( DEFMSG_NPC_PET_WAGE_COST ), iWage); + snprintf(pszMsg, Str_TempLength(), g_Cfg.GetDefaultMsg( DEFMSG_NPC_PET_WAGE_COST ), uiWage); Speak(pszMsg); CChar * pOwner = NPC_PetGetOwner(); diff --git a/src/game/chars/CCharUse.cpp b/src/game/chars/CCharUse.cpp index 6ac60941c..74b87ab5a 100644 --- a/src/game/chars/CCharUse.cpp +++ b/src/game/chars/CCharUse.cpp @@ -1123,6 +1123,30 @@ CChar * CChar::Use_Figurine( CItem * pItem, bool fCheckFollowerSlots ) return nullptr; } + std::optional iFollowerSlots; + const bool fShouldCheckFollowerSlots = (fCheckFollowerSlots && IsSetOF(OF_PetSlots)); + auto _CheckFollowerSlots = [this](short iFollowerSlots) -> bool + { + if ( !FollowersUpdate(this, iFollowerSlots, true) ) + { + SysMessageDefault(DEFMSG_PETSLOTS_TRY_CONTROL); + return false; + } + return true; + }; + + if (fShouldCheckFollowerSlots) + { + const CVarDefCont *pFigurineVarDef = pItem->m_TagDefs.GetKey("FOLLOWERSLOTS"); + if (pFigurineVarDef) + { + // The figurine has a FOLLOWERSLOTS override for the char. Use this. + iFollowerSlots = pFigurineVarDef->GetValNum(); + if (!_CheckFollowerSlots(iFollowerSlots.value())) + return nullptr; + } + } + // Create a new NPC if there's no one linked to this figurine bool fCreatedNewNpc = false; CChar *pPet = pItem->m_itFigurine.m_UID.CharFind(); @@ -1138,7 +1162,7 @@ CChar * CChar::Use_Figurine( CItem * pItem, bool fCheckFollowerSlots ) return nullptr; } } - fCreatedNewNpc = true; + fCreatedNewNpc = true; pPet = CreateNPC(id); ASSERT(pPet); pPet->SetName(pItem->GetName()); @@ -1150,17 +1174,22 @@ CChar * CChar::Use_Figurine( CItem * pItem, bool fCheckFollowerSlots ) } } - if ( fCheckFollowerSlots && IsSetOF(OF_PetSlots) ) - { - const short iFollowerSlots = GetFollowerSlots(); - if ( !FollowersUpdate(pPet, (maximum(0, iFollowerSlots)), true) ) - { - SysMessageDefault(DEFMSG_PETSLOTS_TRY_CONTROL); - if ( fCreatedNewNpc ) - pPet->Delete(); - return nullptr; - } - } + if (fShouldCheckFollowerSlots) + { + ASSERT(pPet); + if (!iFollowerSlots.has_value()) + iFollowerSlots = pPet->GetFollowerSlots(); + + ASSERT(iFollowerSlots.has_value()); + if ( !FollowersUpdate(pPet, iFollowerSlots.value(), true) ) + { + if ( fCreatedNewNpc ) + pPet->Delete(); + return nullptr; + } + + pPet->SetDefNum("FOLLOWERSLOTS", iFollowerSlots.value(), true); + } if ( pPet->IsDisconnected() ) pPet->StatFlag_Clear(STATF_RIDDEN); // pull the creature out of IDLE space @@ -1177,7 +1206,9 @@ CChar * CChar::Use_Figurine( CItem * pItem, bool fCheckFollowerSlots ) short CChar::GetFollowerSlots() const { - return n64_narrow_n16(GetDefNum("FOLLOWERSLOTS", true, 1)); + const int64 val = GetDefNum("FOLLOWERSLOTS", true, 1); + ASSERT(val >= 0); + return n64_narrow_n16(val); } short CChar::GetCurFollowers() const @@ -1221,7 +1252,7 @@ bool CChar::FollowersUpdate(CChar * pCharPet, short iPetFollowerSlots, bool fChe } } - short iMaxFollower = n64_narrow_n16(GetDefNum("MAXFOLLOWER", true)); + const short iMaxFollower = n64_narrow_n16(GetDefNum("MAXFOLLOWER", true)); ASSERT(iMaxFollower >= 0); if (IsSetEF(EF_FollowerList)) { @@ -1237,14 +1268,15 @@ bool CChar::FollowersUpdate(CChar * pCharPet, short iPetFollowerSlots, bool fChe } } - if (!fCharAlreadyFollower && (fIgnoreMax || (GetCurFollowers() + iPetFollowerSlots <= iMaxFollower))) + const short iNewCurFollower = GetCurFollowers() + iPetFollowerSlots; + if (!fCharAlreadyFollower && (fIgnoreMax || (iNewCurFollower <= iMaxFollower))) { if (!fCheckOnly) { m_followers.emplace_back( FollowerCharData { .uid = pCharPet->GetUID(), - .followerslots = pCharPet->GetFollowerSlots() + .followerslots = iPetFollowerSlots }); } } @@ -1252,11 +1284,18 @@ bool CChar::FollowersUpdate(CChar * pCharPet, short iPetFollowerSlots, bool fChe return false; } else if (!fCheckOnly) - { + { + // If iPetFollowerSlots is negative, remove this follower. std::erase_if( m_followers, - [pCharPet](auto const& inp_struct) -> bool { - return inp_struct.uid == pCharPet->GetUID(); + [pCharPet, iPetFollowerSlots](auto const& inp_struct) -> bool { + const bool fIsSame = inp_struct.uid == pCharPet->GetUID(); + if (!fIsSame) + return false; + if (inp_struct.followerslots != iPetFollowerSlots) + g_Log.EventWarn("Removed Follower with UID 0%" PRIx32 " with actual FollowerSlots %d, but expected %d.\n", + inp_struct.uid.GetObjUID(), inp_struct.followerslots, abs(iPetFollowerSlots)); + return true; }); } } @@ -1266,7 +1305,7 @@ bool CChar::FollowersUpdate(CChar * pCharPet, short iPetFollowerSlots, bool fChe if (!fIgnoreMax && (iNewCurFollower > iMaxFollower)) return false; if (!fCheckOnly) - SetDefNum("CURFOLLOWER", maximum(iNewCurFollower, 0)); + SetDefNum("CURFOLLOWER", iNewCurFollower); } if ( !fCheckOnly ) @@ -1280,6 +1319,7 @@ bool CChar::Use_Key( CItem * pKey, CItem * pItemTarg ) { ADDTOCALLSTACK("CChar::Use_Key"); ASSERT(pKey); + // NOLINTNEXTLINE(clang-analyzer-core.CallAndMessage) ASSERT(pKey->IsType(IT_KEY)); if ( !pItemTarg ) { diff --git a/src/game/clients/CClientEvent.cpp b/src/game/clients/CClientEvent.cpp index 3bcef0795..5764f0635 100644 --- a/src/game/clients/CClientEvent.cpp +++ b/src/game/clients/CClientEvent.cpp @@ -1194,8 +1194,8 @@ void CClient::Event_VendorBuy(CChar* pVendor, const VendorItem* items, uint uiIt CCharBase* pPetDef = CCharBase::FindCharBase(CREID_TYPE(pItemPet->m_ttFigurine.m_idChar.GetResIndex())); if (pPetDef) { - short iFollowerSlots = (short)pPetDef->GetDefNum("FOLLOWERSLOTS"); - if (!m_pChar->FollowersUpdate(pVendor, (maximum(0, iFollowerSlots) * items[i].m_vcAmount), true)) + const short uiFollowerSlots = n64_narrow_n16(pItem->GetDefNum("FOLLOWERSLOTS", true)); + if (!m_pChar->FollowersUpdate(pVendor, (uiFollowerSlots * items[i].m_vcAmount), true)) { m_pChar->SysMessageDefault(DEFMSG_PETSLOTS_TRY_CONTROL); return; diff --git a/src/game/items/CItem.cpp b/src/game/items/CItem.cpp index 242e9c2a9..e4696be88 100644 --- a/src/game/items/CItem.cpp +++ b/src/game/items/CItem.cpp @@ -2132,6 +2132,11 @@ ITEMID_TYPE CItem::GetID() const return pItemDef->GetID(); } +dword CItem::GetBaseID() const +{ + return GetID(); +} + bool CItem::SetID( ITEMID_TYPE id ) { ADDTOCALLSTACK("CItem::SetID"); diff --git a/src/game/items/CItem.h b/src/game/items/CItem.h index 4f046c588..1ee537082 100644 --- a/src/game/items/CItem.h +++ b/src/game/items/CItem.h @@ -633,9 +633,7 @@ class CItem : public CObjBase CItemBase * Item_GetDef() const noexcept; ITEMID_TYPE GetID() const; - inline virtual word GetBaseID() const override { - return enum32_narrow_n16_checked(GetID()); - } + virtual dword GetBaseID() const override final; inline ITEMID_TYPE GetDispID() const noexcept { // This is what the item looks like. // May not be the same as the item that defines it's type. diff --git a/src/sphere/UnixTerminal.cpp b/src/sphere/UnixTerminal.cpp index d522ae61e..e3e961b13 100644 --- a/src/sphere/UnixTerminal.cpp +++ b/src/sphere/UnixTerminal.cpp @@ -137,7 +137,7 @@ void UnixTerminal::print(lpctstr message) wrefresh(m_window); #else fputs(message, stdout); - //fflush(stdout); + fflush(stdout); #endif } diff --git a/src/sphere/threads.cpp b/src/sphere/threads.cpp index 36ea2275c..201514c2a 100644 --- a/src/sphere/threads.cpp +++ b/src/sphere/threads.cpp @@ -286,8 +286,9 @@ void ThreadHolder::push(IThread *thread) noexcept } else { - g_Log.Event(LOGM_DEBUG|LOGL_EVENT, "Registered thread '%s' with ThreadHolder ID %d.\n", - thread->getName(), thread->m_threadHolderId); + g_Log.Event(LOGM_DEBUG|LOGL_EVENT|LOGF_CONSOLE_ONLY, + "Registered thread '%s' with ThreadHolder ID %d.\n", + thread->getName(), thread->m_threadHolderId); } } @@ -711,7 +712,8 @@ void AbstractThread::onStart() if (isActive()) // This thread has actually been spawned and the code is executing on a different thread setThreadName(getName()); - g_Log.Event(LOGM_DEBUG|LOGL_EVENT, "Started thread '%s' with ThreadHolder ID %d and system ID %" PRIu64 ".\n", + g_Log.Event(LOGM_DEBUG|LOGL_EVENT|LOGF_CONSOLE_ONLY, + "Started thread '%s' with ThreadHolder ID %d and system ID %" PRIu64 ".\n", getName(), m_threadHolderId, (uint64)m_threadSystemId); } @@ -917,7 +919,7 @@ void AbstractSphereThread::printStackTrace() noexcept //EXC_NOTIFY_DEBUGGER; g_Log.EventDebug("Printing STACK TRACE for debugging purposes.\n"); - g_Log.EventDebug(" _______ thread (id) name _______ | # | _____________ function _____________ |\n"); + g_Log.EventDebug(" _ thread (id) name _ | # | _____________ function _____________ |\n"); for ( ssize_t i = 0; i < (ssize_t)ARRAY_COUNT(m_stackInfo); ++i ) { if( m_stackInfo[i].functionName == nullptr ) From 55f9688159047a87c70a2bc7bbfdd300fb22d129 Mon Sep 17 00:00:00 2001 From: cbnolok Date: Tue, 17 Sep 2024 20:02:47 +0200 Subject: [PATCH 42/86] Changed compiler flags for debug builds, to enable better line-to-line debugging. --- CMakeLists.txt | 28 +++++++++++++++---- README.md | 20 +++++-------- .../include/Linux-Clang_common.inc.cmake | 4 +-- .../include/Linux-GNU_common.inc.cmake | 4 +-- .../include/OSX-AppleClang_common.inc.cmake | 4 +-- .../include/Windows-Clang_common.inc.cmake | 4 +-- .../include/Windows-GNU_common.inc.cmake | 4 +-- 7 files changed, 40 insertions(+), 28 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index cd485cba2..c2b2ab9f9 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,9 +1,9 @@ # Main config # -cmake_minimum_required(VERSION 3.19) +cmake_minimum_required(VERSION 3.24) set(CMAKE_SUPPRESS_REGENERATION TRUE) # Supress the ZERO_CHECK generation -# GUI checkboxes +# -------------------- GUI checkboxes -------------------- option( CMAKE_NO_GIT_REVISION "Do not try to retrieve the current git revision. Useful for building source not git-cloned from Github." @@ -38,7 +38,7 @@ option(USE_MSAN "Enable MemorySanitizer." FALSE) option(USE_LSAN "Enable LeakSanitizer." FALSE) option(USE_UBSAN "Enable Undefined Behavior Sanitizer." FALSE) -# Utility functions +# -------------------- Utility functions -------------------- function(booleanize_str_find VAR) if(${VAR} EQUAL -1) unset(${VAR} PARENT_SCOPE) @@ -47,7 +47,7 @@ function(booleanize_str_find VAR) endif() endfunction() -# -- Start: initializations +# -------------------- Start: initializations -------------------- # Should i load the toolchain passed as argument? if((NOT TOOLCHAIN_LOADED) AND (NOT ${CMAKE_TOOLCHAIN_FILE} STREQUAL "")) @@ -104,7 +104,9 @@ if(NOT TOOLCHAIN_LOADED) include("cmake/DetectDefaultToolchain.cmake") endif() -#-- Stuff that needs to be executed after PROJECT but before ADD_EXECUTABLE + +# -------------------- Stuff that needs to be executed after PROJECT but before ADD_EXECUTABLE + toolchain_after_project() string(FIND "${CMAKE_GENERATOR}" "Makefiles" GEN_IS_MAKEFILE) @@ -120,7 +122,11 @@ endif() if(SINGLE_TARGET) # If you want to manually specify the build type, call cmake with parameter: -DCMAKE_BUILD_TYPE=something + # TODO: add NightlyWithDebInfo ? message(STATUS "Single-target build system (${CMAKE_GENERATOR}) detected: generating multiple projects!") + set_property(CACHE CMAKE_BUILD_TYPE PROPERTY STRINGS + "Debug" "Nightly" "Release" + ) if(NOT ${CMAKE_BUILD_TYPE} STREQUAL "") if( (NOT ${CMAKE_BUILD_TYPE} STREQUAL "Release") @@ -169,6 +175,8 @@ if(SINGLE_TARGET) # ${docs_TEXT} ) set_target_properties(spheresvr_release PROPERTIES OUTPUT_NAME SphereSvrX${ARCH_BITS}_release) + #set_target_properties(spheresvr_release PROPERTIES CXX_EXTENSIONS OFF) + #target_compile_features(spheresvr_release PUBLIC cxx_std_20) endif() if(("${CMAKE_BUILD_TYPE}" STREQUAL "") OR (${CMAKE_BUILD_TYPE} MATCHES "(N|n?)ightly")) set(TARGETS ${TARGETS} spheresvr_nightly) @@ -179,6 +187,8 @@ if(SINGLE_TARGET) # ${docs_TEXT} ) set_target_properties(spheresvr_nightly PROPERTIES OUTPUT_NAME SphereSvrX${ARCH_BITS}_nightly) + #set_target_properties(spheresvr_nightly PROPERTIES CXX_EXTENSIONS OFF) + #target_compile_features(spheresvr_nightly PUBLIC cxx_std_20) endif() if(("${CMAKE_BUILD_TYPE}" STREQUAL "") OR (${CMAKE_BUILD_TYPE} MATCHES "(D|d?)ebug")) set(TARGETS ${TARGETS} spheresvr_debug) @@ -189,6 +199,8 @@ if(SINGLE_TARGET) # ${docs_TEXT} ) set_target_properties(spheresvr_debug PROPERTIES OUTPUT_NAME SphereSvrX${ARCH_BITS}_debug) + #set_target_properties(spheresvr_debug PROPERTIES CXX_EXTENSIONS OFF) + #target_compile_features(spheresvr_debug PUBLIC cxx_std_20) endif() else(SINGLE_TARGET) set(TARGETS ${TARGETS} spheresvr) @@ -196,8 +208,14 @@ else(SINGLE_TARGET) set_target_properties(spheresvr PROPERTIES OUTPUT_NAME_RELEASE SphereSvrX${ARCH_BITS}_release) set_target_properties(spheresvr PROPERTIES OUTPUT_NAME_NIGHTLY SphereSvrX${ARCH_BITS}_nightly) set_target_properties(spheresvr PROPERTIES OUTPUT_NAME_DEBUG SphereSvrX${ARCH_BITS}_debug) + #set_target_properties(spheresvr PROPERTIES CXX_EXTENSIONS OFF) + #target_compile_features(spheresvr PUBLIC cxx_std_20) + endif(SINGLE_TARGET) + +# -------------------- + # Now include external libraries add_subdirectory(lib) diff --git a/README.md b/README.md index 2dc55d47d..67aabfb3a 100644 --- a/README.md +++ b/README.md @@ -8,6 +8,7 @@ Ultima Online game server, developed in C++.
[![Coverity Scan Build Status](https://scan.coverity.com/projects/20225/badge.svg)](https://scan.coverity.com/projects/sphereserver-source-x)     [![GitHub Issues](https://img.shields.io/github/issues/Sphereserver/Source-X.svg)](https://github.com/Sphereserver/Source-X/issues) + | Join the SphereServer Discord channel! | | :---: | | [![Discord Shield](https://discordapp.com/api/guilds/354358315373035542/widget.png?style=shield)](https://discord.gg/ZrMTXrs) | @@ -72,7 +73,6 @@ Most notable changes (right now) are: ### Required libraries (Windows) + `libmariadb.dll` (MariaDB Client v10.*package), found in `lib/bin/*cpu_architecture*/mariadb/libmariadb.dll` -
### Required libraries (Linux) @@ -120,14 +120,16 @@ Before starting: does CMake give you an error? Ensure that you have Git installe When using Makefiles or Ninja, you can specify a build type by setting (also this via GUI or CLI) `CMAKE_BUILD_TYPE="build"`, where build is **Nightly**, **Debug** or **Release**. If the build type was not set, by default the makefiles for all of the three build types are generated. **Debug** build is expected to be slow and it's to be used, you guessed it, for debugging purposes (best coupled with a debugger or with sanitizers enabled, more on them right below), so don't use it for a live shard! -
Other useful CMake flags: -+ You can add other compiler flags with the custom variables `C_FLAGS_EXTRA` and `CXX_FLAGS_EXTRA`. ++ You can add other compiler flags with the custom variables `C_FLAGS_EXTRA`, `CXX_FLAGS_EXTRA`, `CMAKE_EXE_LINKER_FLAGS_EXTRA`. + Enable Sanitizers: `USE_ASAN[=ON]`, `USE_UBSAN`, `USE_LSAN`, etc. + If you are using Address Sanitizer, Undefined Behaviour Sanitizer, Leak Sanitizer on Windows, it might be useful to redirect stderr to stdout to correctly show the output: `SphereSvrX64_nightly > Sphere_ASan_log.txt 2>&1`. + Remember to setup Sanitizers settings by setting the respective shell variables. To ease this, there are some batch/shell scripts doing that for you inside `utilities/`. + `CROSSCOMPILING_ARCH`: set this to TRUE to tell the compiler you are building binary files for a different architecture (not from x86_64 to x86, but for example from x86 to ARM). Example to build makefiles on Linux for a 64 bits Nightly version, inside the "build" directory (run the command inside the project's root folder): + ```bash mkdir build cmake -DCMAKE_TOOLCHAIN_FILE=cmake/toolchains/Linux-GNU-x86_64.cmake -G "Unix Makefiles" -DCMAKE_BUILD_TYPE="Nightly" -B ./build -S ./ @@ -140,7 +142,7 @@ cmake -DCMAKE_TOOLCHAIN_FILE=cmake/toolchains/Linux-GNU-x86_64.cmake -G "Unix Ma Building will require more packages than the ones needed to run Sphere. + Ubuntu and Debian -Install these additional packages: + Install these additional packages: + Build tools (other than the compiler): `sudo apt-get install git cmake`. + MariaDB client: `sudo apt-get install libmariadb-dev` and `libmariadb3` or `mariadb-client` (depends on the OS version) If you are on a 64 bits architecture but you want to compile (or execute) a 32 bits binary, you will need to @@ -156,13 +158,6 @@ Install these additional packages: Just run the `make` command inside the `build` folder. You can pass the -jX argument (`make -jX`, where X is a number) to speed up the compilation and split the work between X threads. -#### Address Sanitizer and Undefined Behaviour Sanitizer - -You can enable Address Sanitizer (ASan) and Undefined Behaviour Sanitizer (UBSan) with the ENABLE_SANITIZERS checkbox via the GUI, or via the CLI flag `-DENABLE_SANITIZERS=true`. -This is easier with GCC and Clang on Linux. -Since ASan redirects the error output to stderr, you can retrieve its output by launching sphere from cmd (Command Prompt) or shell with the following command: -`SphereSvrX64_nightly > Sphere_ASan_log.txt 2>&1`, or simply use the precise flag to redirect the errors to a log file. - ## Coding Notes (add as you wish to standardize the coding for new contributors) + Make sure you can compile and run the program before pushing a commit. @@ -171,7 +166,7 @@ Since ASan redirects the error output to stderr, you can retrieve its output by cannot be replicated from script to keep some backwards compatibility. + Comment your code, add informations about its logic. It's very important since it helps others to understand your work. + Be sure to use Sphere's custom datatypes and the string formatting macros described in src/common/datatypes.h. -+ When casting numeric data types, always prefer C-style casts, like (int), to C++ static_cast<int>(). ++ When casting numeric data types, always prefer C-style casts, like (int), to C++ static_cast<int>(). It's way more concise. + Be wary that in SphereScript unsigned values does not exist, all numbers are considered signed, and that 64 bits integers meant to be printed to or retrieved by scripts should always be signed. + Don't use "long" except if you know why do you actually need it. Always prefer "int" or "llong". @@ -238,4 +233,3 @@ Copyright 2024 SphereServer development team. Licensed under the Apache License, Version 2.0 (the "License"). You may not use any file of this project except in compliance with the License. You may obtain a copy of the License at - diff --git a/cmake/toolchains/include/Linux-Clang_common.inc.cmake b/cmake/toolchains/include/Linux-Clang_common.inc.cmake index c2c6a077c..88695e547 100644 --- a/cmake/toolchains/include/Linux-Clang_common.inc.cmake +++ b/cmake/toolchains/include/Linux-Clang_common.inc.cmake @@ -167,7 +167,7 @@ See comments in the toolchain and: https://github.com/google/sanitizers/wiki/Mem endif() if(TARGET spheresvr_nightly) if(ENABLED_SANITIZER) - target_compile_options(spheresvr_nightly PUBLIC -ggdb3 -O1 ${COMPILE_OPTIONS_EXTRA}) + target_compile_options(spheresvr_nightly PUBLIC -ggdb3 -Og ${COMPILE_OPTIONS_EXTRA}) else() target_compile_options( spheresvr_nightly @@ -176,7 +176,7 @@ See comments in the toolchain and: https://github.com/google/sanitizers/wiki/Mem endif() endif() if(TARGET spheresvr_debug) - target_compile_options(spheresvr_debug PUBLIC -ggdb3 -Og ${COMPILE_OPTIONS_EXTRA}) + target_compile_options(spheresvr_debug PUBLIC -ggdb3 -O0 ${COMPILE_OPTIONS_EXTRA}) endif() #-- Store common linker flags. diff --git a/cmake/toolchains/include/Linux-GNU_common.inc.cmake b/cmake/toolchains/include/Linux-GNU_common.inc.cmake index d5110736d..90c80b83f 100644 --- a/cmake/toolchains/include/Linux-GNU_common.inc.cmake +++ b/cmake/toolchains/include/Linux-GNU_common.inc.cmake @@ -148,13 +148,13 @@ function(toolchain_exe_stuff_common) endif() if(TARGET spheresvr_nightly) if(ENABLED_SANITIZER) - target_compile_options(spheresvr_nightly PUBLIC -ggdb3 -O1 ${COMPILE_OPTIONS_EXTRA}) + target_compile_options(spheresvr_nightly PUBLIC -ggdb3 -Og ${COMPILE_OPTIONS_EXTRA}) else() target_compile_options(spheresvr_nightly PUBLIC -O3 ${COMPILE_OPTIONS_EXTRA}) endif() endif() if(TARGET spheresvr_debug) - target_compile_options(spheresvr_debug PUBLIC -ggdb3 -Og ${COMPILE_OPTIONS_EXTRA}) + target_compile_options(spheresvr_debug PUBLIC -ggdb3 -O0 ${COMPILE_OPTIONS_EXTRA}) endif() #-- Store common linker flags. diff --git a/cmake/toolchains/include/OSX-AppleClang_common.inc.cmake b/cmake/toolchains/include/OSX-AppleClang_common.inc.cmake index 5e4a74ebf..62088924a 100644 --- a/cmake/toolchains/include/OSX-AppleClang_common.inc.cmake +++ b/cmake/toolchains/include/OSX-AppleClang_common.inc.cmake @@ -127,13 +127,13 @@ function(toolchain_exe_stuff_common) endif() if(TARGET spheresvr_nightly) if(ENABLED_SANITIZER) - target_compile_options(spheresvr_nightly PUBLIC -ggdb3 -O1 ${COMPILE_OPTIONS_EXTRA}) + target_compile_options(spheresvr_nightly PUBLIC -ggdb3 -Og ${COMPILE_OPTIONS_EXTRA}) else() target_compile_options(spheresvr_nightly PUBLIC -O3 ${COMPILE_OPTIONS_EXTRA}) endif() endif() if(TARGET spheresvr_debug) - target_compile_options(spheresvr_debug PUBLIC -ggdb3 -Og ${COMPILE_OPTIONS_EXTRA}) + target_compile_options(spheresvr_debug PUBLIC -ggdb3 -O0 ${COMPILE_OPTIONS_EXTRA}) endif() #-- Store common linker flags. diff --git a/cmake/toolchains/include/Windows-Clang_common.inc.cmake b/cmake/toolchains/include/Windows-Clang_common.inc.cmake index ac2815981..a502a5185 100644 --- a/cmake/toolchains/include/Windows-Clang_common.inc.cmake +++ b/cmake/toolchains/include/Windows-Clang_common.inc.cmake @@ -156,7 +156,7 @@ function(toolchain_exe_stuff_common) endif() if(TARGET spheresvr_nightly) if(ENABLED_SANITIZER) - target_compile_options(spheresvr_nightly PUBLIC -ggdb3 -O1 ${COMPILE_OPTIONS_EXTRA}) + target_compile_options(spheresvr_nightly PUBLIC -ggdb3 -Og ${COMPILE_OPTIONS_EXTRA}) else() target_compile_options( spheresvr_nightly @@ -174,7 +174,7 @@ function(toolchain_exe_stuff_common) ]] endif() if(TARGET spheresvr_debug) - target_compile_options(spheresvr_debug PUBLIC -ggdb3 -Og) + target_compile_options(spheresvr_debug PUBLIC -ggdb3 -O0) #[[ IF (NOT ${CLANG_USE_GCC_LINKER}) if (${RUNTIME_STATIC_LINK}) diff --git a/cmake/toolchains/include/Windows-GNU_common.inc.cmake b/cmake/toolchains/include/Windows-GNU_common.inc.cmake index d0ab94af1..efbffb09b 100644 --- a/cmake/toolchains/include/Windows-GNU_common.inc.cmake +++ b/cmake/toolchains/include/Windows-GNU_common.inc.cmake @@ -141,13 +141,13 @@ function(toolchain_exe_stuff_common) endif() if(TARGET spheresvr_nightly) if(ENABLED_SANITIZER) - target_compile_options(spheresvr_nightly PUBLIC -ggdb3 -O1 ${COMPILE_OPTIONS_EXTRA}) + target_compile_options(spheresvr_nightly PUBLIC -ggdb3 -Og ${COMPILE_OPTIONS_EXTRA}) else() target_compile_options(spheresvr_nightly PUBLIC -O3 ${COMPILE_OPTIONS_EXTRA}) endif() endif() if(TARGET spheresvr_debug) - target_compile_options(spheresvr_debug PUBLIC -ggdb3 -Og ${COMPILE_OPTIONS_EXTRA}) + target_compile_options(spheresvr_debug PUBLIC -ggdb3 -O0 ${COMPILE_OPTIONS_EXTRA}) endif() #-- Store common linker flags. From 05a7f00e0cf55f905c3c03c652880a901088288b Mon Sep 17 00:00:00 2001 From: cbnolok Date: Wed, 18 Sep 2024 18:09:26 +0200 Subject: [PATCH 43/86] Fixed Windows MSVC compilation warnings. --- src/game/chars/CChar.cpp | 2 +- src/game/chars/CCharUse.cpp | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/game/chars/CChar.cpp b/src/game/chars/CChar.cpp index e2b9d8d82..5b3811bc3 100644 --- a/src/game/chars/CChar.cpp +++ b/src/game/chars/CChar.cpp @@ -3388,7 +3388,7 @@ bool CChar::r_LoadVal( CScript & s ) piVals[1] = 1; } - const CUID uidPet(piVals[0]); + const CUID uidPet((dword)piVals[0]); const short iFollowerSlots = n64_narrow_n16(piVals[1]); // If i'm loading the world, this char might not exist yet! diff --git a/src/game/chars/CCharUse.cpp b/src/game/chars/CCharUse.cpp index 74b87ab5a..f2af5dc88 100644 --- a/src/game/chars/CCharUse.cpp +++ b/src/game/chars/CCharUse.cpp @@ -1114,7 +1114,7 @@ CChar * CChar::Use_Figurine( CItem * pItem, bool fCheckFollowerSlots ) ADDTOCALLSTACK("CChar::Use_Figurine"); // NOTE: The figurine is NOT destroyed. - if ( !pItem ) + if ( !pItem ) return nullptr; if ( pItem->m_uidLink.IsValidUID() && pItem->m_uidLink.IsChar() && (pItem->m_uidLink != GetUID()) && !IsPriv(PRIV_GM) ) @@ -1141,7 +1141,7 @@ CChar * CChar::Use_Figurine( CItem * pItem, bool fCheckFollowerSlots ) if (pFigurineVarDef) { // The figurine has a FOLLOWERSLOTS override for the char. Use this. - iFollowerSlots = pFigurineVarDef->GetValNum(); + iFollowerSlots = n64_narrow_n16(pFigurineVarDef->GetValNum()); if (!_CheckFollowerSlots(iFollowerSlots.value())) return nullptr; } From 16f3030be6e7457ca830ca07f8214f5dbfa675e3 Mon Sep 17 00:00:00 2001 From: cbnolok Date: Wed, 18 Sep 2024 18:10:47 +0200 Subject: [PATCH 44/86] Fixed Linux x86 compilation, broken after upgrading the minimum CMake required version due to a new policy. --- CMakeLists.txt | 17 ++++------------- cmake/toolchains/Linux-Clang-AArch64.cmake | 6 ++++-- cmake/toolchains/Linux-Clang-x86.cmake | 6 ++++-- cmake/toolchains/Linux-Clang-x86_64.cmake | 6 ++++-- cmake/toolchains/Linux-GNU-AArch64.cmake | 4 +++- cmake/toolchains/Linux-GNU-x86.cmake | 6 ++++-- cmake/toolchains/Linux-GNU-x86_64.cmake | 6 ++++-- cmake/toolchains/OSX-AppleClang-AArch64.cmake | 6 ++++-- cmake/toolchains/OSX-AppleClang-x86_64.cmake | 6 ++++-- cmake/toolchains/Windows-Clang-x86.cmake | 6 ++++-- cmake/toolchains/Windows-Clang-x86_64.cmake | 6 ++++-- cmake/toolchains/Windows-GNU-x86.cmake | 6 ++++-- cmake/toolchains/Windows-GNU-x86_64.cmake | 4 +++- utilities/run_clang-format.sh | 4 ++-- utilities/run_gersemi_cmake.sh | 4 ++-- 15 files changed, 54 insertions(+), 39 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index c2b2ab9f9..121381744 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -15,11 +15,7 @@ option( "Statically link inside the executable the runtime libraries? (MSVC, libc/libcc, libstdc++)." FALSE ) -option( - CMAKE_EXPORT_COMPILE_COMMANDS - "Export compiler commands to compile_commands.json" - TRUE -) +option(CMAKE_EXPORT_COMPILE_COMMANDS "Export compiler commands to compile_commands.json" TRUE) set(predef_LIB_LIBEV_BUILD FALSE) if(NOT WIN32) @@ -104,7 +100,6 @@ if(NOT TOOLCHAIN_LOADED) include("cmake/DetectDefaultToolchain.cmake") endif() - # -------------------- Stuff that needs to be executed after PROJECT but before ADD_EXECUTABLE toolchain_after_project() @@ -124,9 +119,7 @@ if(SINGLE_TARGET) # TODO: add NightlyWithDebInfo ? message(STATUS "Single-target build system (${CMAKE_GENERATOR}) detected: generating multiple projects!") - set_property(CACHE CMAKE_BUILD_TYPE PROPERTY STRINGS - "Debug" "Nightly" "Release" - ) + set_property(CACHE CMAKE_BUILD_TYPE PROPERTY STRINGS "Debug" "Nightly" "Release") if(NOT ${CMAKE_BUILD_TYPE} STREQUAL "") if( (NOT ${CMAKE_BUILD_TYPE} STREQUAL "Release") @@ -176,7 +169,7 @@ if(SINGLE_TARGET) ) set_target_properties(spheresvr_release PROPERTIES OUTPUT_NAME SphereSvrX${ARCH_BITS}_release) #set_target_properties(spheresvr_release PROPERTIES CXX_EXTENSIONS OFF) - #target_compile_features(spheresvr_release PUBLIC cxx_std_20) + #target_compile_features(spheresvr_release PUBLIC cxx_std_20) endif() if(("${CMAKE_BUILD_TYPE}" STREQUAL "") OR (${CMAKE_BUILD_TYPE} MATCHES "(N|n?)ightly")) set(TARGETS ${TARGETS} spheresvr_nightly) @@ -188,7 +181,7 @@ if(SINGLE_TARGET) ) set_target_properties(spheresvr_nightly PROPERTIES OUTPUT_NAME SphereSvrX${ARCH_BITS}_nightly) #set_target_properties(spheresvr_nightly PROPERTIES CXX_EXTENSIONS OFF) - #target_compile_features(spheresvr_nightly PUBLIC cxx_std_20) + #target_compile_features(spheresvr_nightly PUBLIC cxx_std_20) endif() if(("${CMAKE_BUILD_TYPE}" STREQUAL "") OR (${CMAKE_BUILD_TYPE} MATCHES "(D|d?)ebug")) set(TARGETS ${TARGETS} spheresvr_debug) @@ -210,10 +203,8 @@ else(SINGLE_TARGET) set_target_properties(spheresvr PROPERTIES OUTPUT_NAME_DEBUG SphereSvrX${ARCH_BITS}_debug) #set_target_properties(spheresvr PROPERTIES CXX_EXTENSIONS OFF) #target_compile_features(spheresvr PUBLIC cxx_std_20) - endif(SINGLE_TARGET) - # -------------------- # Now include external libraries diff --git a/cmake/toolchains/Linux-Clang-AArch64.cmake b/cmake/toolchains/Linux-Clang-AArch64.cmake index c2cd70ecc..e358ef11e 100644 --- a/cmake/toolchains/Linux-Clang-AArch64.cmake +++ b/cmake/toolchains/Linux-Clang-AArch64.cmake @@ -21,10 +21,12 @@ endfunction() function(toolchain_after_project) message(STATUS "Toolchain: Linux-Clang-AArch64.cmake.") # Do not set CMAKE_SYSTEM_NAME if compiling for the same OS, otherwise CMAKE_CROSSCOMPILING will be set to TRUE - #SET(CMAKE_SYSTEM_NAME "Linux" CACHE INTERNAL "" FORCE) + #unset(CMAKE_SYSTEM_NAME) + #set(CMAKE_SYSTEM_NAME "Linux" CACHE INTERNAL "" FORCE) + unset(CMAKE_SYSTEM_PROCESSOR) set(CMAKE_SYSTEM_PROCESSOR "aarch64" CACHE INTERNAL "" FORCE) set(CMAKE_RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/bin-aarch64" PARENT_SCOPE) - #set(ARCH_BITS 64 CACHE INTERNAL "" FORCE) # provide it + #set(ARCH_BITS 64 CACHE INTERNAL "" FORCE) # automatically gotten from CMAKE_SYSTEM_PROCESSOR if(CROSSCOMPILING_ARCH) # possible cross-compilation foreign arch lib locations diff --git a/cmake/toolchains/Linux-Clang-x86.cmake b/cmake/toolchains/Linux-Clang-x86.cmake index cf3a1c5ed..db1b4757b 100644 --- a/cmake/toolchains/Linux-Clang-x86.cmake +++ b/cmake/toolchains/Linux-Clang-x86.cmake @@ -23,10 +23,12 @@ endfunction() function(toolchain_after_project) message(STATUS "Toolchain: Linux-Clang-x86.cmake.") # Do not set CMAKE_SYSTEM_NAME if compiling for the same OS, otherwise CMAKE_CROSSCOMPILING will be set to TRUE - #SET(CMAKE_SYSTEM_NAME "Linux" CACHE INTERNAL "" FORCE) # target OS + #unset(CMAKE_SYSTEM_NAME) + #set(CMAKE_SYSTEM_NAME "Linux" CACHE INTERNAL "" FORCE) # target OS + unset(CMAKE_SYSTEM_PROCESSOR) set(CMAKE_SYSTEM_PROCESSOR "x86" CACHE INTERNAL "" FORCE) # target arch set(CMAKE_RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/bin-x86" PARENT_SCOPE) - #set(ARCH_BITS 32 CACHE INTERNAL "" FORCE) # provide it + #set(ARCH_BITS 32 CACHE INTERNAL "" FORCE) # automatically gotten from CMAKE_SYSTEM_PROCESSOR if(CROSSCOMPILING_ARCH) # possible cross-compilation foreign arch lib locations diff --git a/cmake/toolchains/Linux-Clang-x86_64.cmake b/cmake/toolchains/Linux-Clang-x86_64.cmake index fdc1fbe84..1cb11614e 100644 --- a/cmake/toolchains/Linux-Clang-x86_64.cmake +++ b/cmake/toolchains/Linux-Clang-x86_64.cmake @@ -23,10 +23,12 @@ endfunction() function(toolchain_after_project) message(STATUS "Toolchain: Linux-Clang-x86_64.cmake.") # Do not set CMAKE_SYSTEM_NAME if compiling for the same OS, otherwise CMAKE_CROSSCOMPILING will be set to TRUE - #SET(CMAKE_SYSTEM_NAME "Linux" CACHE INTERNAL "" FORCE) # target OS + #unset(CMAKE_SYSTEM_NAME) + #set(CMAKE_SYSTEM_NAME "Linux" CACHE INTERNAL "" FORCE) # target OS + unset(CMAKE_SYSTEM_PROCESSOR) set(CMAKE_SYSTEM_PROCESSOR "x86_64" CACHE INTERNAL "" FORCE) # target arch set(CMAKE_RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/bin-x86_64" PARENT_SCOPE) - set(ARCH_BITS 64 CACHE INTERNAL "" FORCE) # provide it + set(ARCH_BITS 64 CACHE INTERNAL "" FORCE) # automatically gotten from CMAKE_SYSTEM_PROCESSOR if(CROSSCOMPILING_ARCH) # possible cross-compilation foreign arch lib locations diff --git a/cmake/toolchains/Linux-GNU-AArch64.cmake b/cmake/toolchains/Linux-GNU-AArch64.cmake index bb908928e..48969ee00 100644 --- a/cmake/toolchains/Linux-GNU-AArch64.cmake +++ b/cmake/toolchains/Linux-GNU-AArch64.cmake @@ -24,7 +24,9 @@ endfunction() function(toolchain_after_project) message(STATUS "Toolchain: Linux-GNU-AArch64.cmake.") # Do not set CMAKE_SYSTEM_NAME if compiling for the same OS, otherwise CMAKE_CROSSCOMPILING will be set to TRUE - #SET(CMAKE_SYSTEM_NAME "Linux" CACHE INTERNAL "" FORCE) + #unset(CMAKE_SYSTEM_NAME) + #set(CMAKE_SYSTEM_NAME "Linux" CACHE INTERNAL "" FORCE) + unset(CMAKE_SYSTEM_PROCESSOR) set(CMAKE_SYSTEM_PROCESSOR "aarch64" CACHE INTERNAL "" FORCE) set(CMAKE_RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/bin-aarch64" CACHE INTERNAL "" FORCE) set(ARCH_BITS 64 CACHE INTERNAL "" FORCE) # provide it diff --git a/cmake/toolchains/Linux-GNU-x86.cmake b/cmake/toolchains/Linux-GNU-x86.cmake index aa2f38f57..614d88e6d 100644 --- a/cmake/toolchains/Linux-GNU-x86.cmake +++ b/cmake/toolchains/Linux-GNU-x86.cmake @@ -27,10 +27,12 @@ endfunction() function(toolchain_after_project) message(STATUS "Toolchain: Linux-GNU-x86.cmake.") # Do not set CMAKE_SYSTEM_NAME if compiling for the same OS, otherwise CMAKE_CROSSCOMPILING will be set to TRUE - #SET(CMAKE_SYSTEM_NAME "Linux" CACHE INTERNAL "" FORCE) + #unset(CMAKE_SYSTEM_NAME) + #set(CMAKE_SYSTEM_NAME "Linux" CACHE INTERNAL "" FORCE) + unset(CMAKE_SYSTEM_PROCESSOR) set(CMAKE_SYSTEM_PROCESSOR "x86" CACHE INTERNAL "" FORCE) set(CMAKE_RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/bin-x86" PARENT_SCOPE) - #set(ARCH_BITS 32 CACHE INTERNAL "" FORCE) # provide it + #set(ARCH_BITS 32 CACHE INTERNAL "" FORCE) # automatically gotten from CMAKE_SYSTEM_PROCESSOR if(CROSSCOMPILING_ARCH) # possible cross-compilation foreign arch lib locations diff --git a/cmake/toolchains/Linux-GNU-x86_64.cmake b/cmake/toolchains/Linux-GNU-x86_64.cmake index 170c9454f..12e844576 100644 --- a/cmake/toolchains/Linux-GNU-x86_64.cmake +++ b/cmake/toolchains/Linux-GNU-x86_64.cmake @@ -27,10 +27,12 @@ endfunction() function(toolchain_after_project) message(STATUS "Toolchain: Linux-GNU-x86_64.cmake.") # Do not set CMAKE_SYSTEM_NAME if compiling for the same OS, otherwise CMAKE_CROSSCOMPILING will be set to TRUE - #SET(CMAKE_SYSTEM_NAME "Linux" CACHE INTERNAL "" FORCE) # target os + #unset(CMAKE_SYSTEM_NAME) + #set(CMAKE_SYSTEM_NAME "Linux" CACHE INTERNAL "" FORCE) # target os + unset(CMAKE_SYSTEM_PROCESSOR) set(CMAKE_SYSTEM_PROCESSOR "x86_64" CACHE INTERNAL "" FORCE) # target arch set(CMAKE_RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/bin-x86_64" PARENT_SCOPE) - #set(ARCH_BITS 64 CACHE INTERNAL "" FORCE) # provide it + #set(ARCH_BITS 64 CACHE INTERNAL "" FORCE) # automatically gotten from CMAKE_SYSTEM_PROCESSOR if(CROSSCOMPILING_ARCH) # possible cross-compilation foreign arch lib locations diff --git a/cmake/toolchains/OSX-AppleClang-AArch64.cmake b/cmake/toolchains/OSX-AppleClang-AArch64.cmake index cd19f8216..45efe18fc 100644 --- a/cmake/toolchains/OSX-AppleClang-AArch64.cmake +++ b/cmake/toolchains/OSX-AppleClang-AArch64.cmake @@ -15,10 +15,12 @@ endfunction() function(toolchain_after_project) message(STATUS "Toolchain: OSX-AppleClang-AArch64.cmake.") # Do not set CMAKE_SYSTEM_NAME if compiling for the same OS, otherwise CMAKE_CROSSCOMPILING will be set to TRUE - #SET(CMAKE_SYSTEM_NAME "Darwin" CACHE INTERNAL "" FORCE) + #unset(CMAKE_SYSTEM_NAME) + #set(CMAKE_SYSTEM_NAME "Darwin" CACHE INTERNAL "" FORCE) + unset(CMAKE_SYSTEM_PROCESSOR) set(CMAKE_SYSTEM_PROCESSOR "aarch64" CACHE INTERNAL "" FORCE) set(CMAKE_RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/bin-aarch64" PARENT_SCOPE) - #set(ARCH_BITS 64 CACHE INTERNAL "" FORCE) # provide it + #set(ARCH_BITS 64 CACHE INTERNAL "" FORCE) # automatically gotten from CMAKE_SYSTEM_PROCESSOR toolchain_after_project_common() diff --git a/cmake/toolchains/OSX-AppleClang-x86_64.cmake b/cmake/toolchains/OSX-AppleClang-x86_64.cmake index a0d352499..7a2755de7 100644 --- a/cmake/toolchains/OSX-AppleClang-x86_64.cmake +++ b/cmake/toolchains/OSX-AppleClang-x86_64.cmake @@ -16,10 +16,12 @@ endfunction() function(toolchain_after_project) message(STATUS "Toolchain: OSX-AppleClang-x86_64.cmake.") # Do not set CMAKE_SYSTEM_NAME if compiling for the same OS, otherwise CMAKE_CROSSCOMPILING will be set to TRUE - #SET(CMAKE_SYSTEM_NAME "Darwin" CACHE INTERNAL "" FORCE) + #unset(CMAKE_SYSTEM_NAME) + #set(CMAKE_SYSTEM_NAME "Darwin" CACHE INTERNAL "" FORCE) + unset(CMAKE_SYSTEM_PROCESSOR) set(CMAKE_SYSTEM_PROCESSOR "x86_64" CACHE INTERNAL "" FORCE) set(CMAKE_RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/bin-x86_64" PARENT_SCOPE) - #set(ARCH_BITS 64 CACHE INTERNAL "" FORCE) # provide it + #set(ARCH_BITS 64 CACHE INTERNAL "" FORCE) # automatically gotten from CMAKE_SYSTEM_PROCESSOR toolchain_after_project_common() diff --git a/cmake/toolchains/Windows-Clang-x86.cmake b/cmake/toolchains/Windows-Clang-x86.cmake index 8d24d467f..614a0a260 100644 --- a/cmake/toolchains/Windows-Clang-x86.cmake +++ b/cmake/toolchains/Windows-Clang-x86.cmake @@ -22,10 +22,12 @@ endfunction() function(toolchain_after_project) message(STATUS "Toolchain: Windows-Clang-x86.cmake.") # Do not set CMAKE_SYSTEM_NAME if compiling for the same OS, otherwise CMAKE_CROSSCOMPILING will be set to TRUE - #SET(CMAKE_SYSTEM_NAME "Windows" CACHE INTERNAL "" FORCE) + #unset(CMAKE_SYSTEM_NAME) + #set(CMAKE_SYSTEM_NAME "Windows" CACHE INTERNAL "" FORCE) + unset(CMAKE_SYSTEM_PROCESSOR) set(CMAKE_SYSTEM_PROCESSOR "x86" CACHE INTERNAL "" FORCE) set(CMAKE_RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/bin-x86" PARENT_SCOPE) - #set(ARCH_BITS 32 CACHE INTERNAL "" FORCE) # provide it + #set(ARCH_BITS 32 CACHE INTERNAL "" FORCE) # automatically gotten from CMAKE_SYSTEM_PROCESSOR toolchain_after_project_common() # To enable RC language, to compile Windows Resource files diff --git a/cmake/toolchains/Windows-Clang-x86_64.cmake b/cmake/toolchains/Windows-Clang-x86_64.cmake index 36392f5dc..14e03c250 100644 --- a/cmake/toolchains/Windows-Clang-x86_64.cmake +++ b/cmake/toolchains/Windows-Clang-x86_64.cmake @@ -22,10 +22,12 @@ endfunction() function(toolchain_after_project) message(STATUS "Toolchain: Windows-Clang-x86_64.cmake.") # Do not set CMAKE_SYSTEM_NAME if compiling for the same OS, otherwise CMAKE_CROSSCOMPILING will be set to TRUE - #SET(CMAKE_SYSTEM_NAME "Windows" CACHE INTERNAL "" FORCE) + #unset(CMAKE_SYSTEM_NAME) + #set(CMAKE_SYSTEM_NAME "Windows" CACHE INTERNAL "" FORCE) + unset(CMAKE_SYSTEM_PROCESSOR) set(CMAKE_SYSTEM_PROCESSOR "x86_64" CACHE INTERNAL "" FORCE) set(CMAKE_RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/bin-x86_64" PARENT_SCOPE) - #set(ARCH_BITS 64 CACHE INTERNAL "" FORCE) # provide it + #set(ARCH_BITS 64 CACHE INTERNAL "" FORCE) # automatically gotten from CMAKE_SYSTEM_PROCESSOR toolchain_after_project_common() # To enable RC language, to compile Windows Resource files diff --git a/cmake/toolchains/Windows-GNU-x86.cmake b/cmake/toolchains/Windows-GNU-x86.cmake index de440beba..1bdf2d378 100644 --- a/cmake/toolchains/Windows-GNU-x86.cmake +++ b/cmake/toolchains/Windows-GNU-x86.cmake @@ -15,10 +15,12 @@ endfunction() function(toolchain_after_project) message(STATUS "Toolchain: Windows-GNU-x86.cmake.") # Do not set CMAKE_SYSTEM_NAME if compiling for the same OS, otherwise CMAKE_CROSSCOMPILING will be set to TRUE - #SET(CMAKE_SYSTEM_NAME "Windows" CACHE INTERNAL "" FORCE) + #unset(CMAKE_SYSTEM_NAME) + #set(CMAKE_SYSTEM_NAME "Windows" CACHE INTERNAL "" FORCE) + unset(CMAKE_SYSTEM_PROCESSOR) set(CMAKE_SYSTEM_PROCESSOR "x86" CACHE INTERNAL "" FORCE) set(CMAKE_RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/bin_x86" PARENT_SCOPE) - #set(ARCH_BITS 32 CACHE INTERNAL "" FORCE) # provide it + #set(ARCH_BITS 32 CACHE INTERNAL "" FORCE) # automatically gotten from CMAKE_SYSTEM_PROCESSOR toolchain_after_project_common() # Also to enable RC language, to compile Windows Resource files diff --git a/cmake/toolchains/Windows-GNU-x86_64.cmake b/cmake/toolchains/Windows-GNU-x86_64.cmake index b85339500..00b1fafc1 100644 --- a/cmake/toolchains/Windows-GNU-x86_64.cmake +++ b/cmake/toolchains/Windows-GNU-x86_64.cmake @@ -15,10 +15,12 @@ endfunction() function(toolchain_after_project) message(STATUS "Toolchain: Windows-GNU-x86_64.cmake.") # Do not set CMAKE_SYSTEM_NAME if compiling for the same OS, otherwise CMAKE_CROSSCOMPILING will be set to TRUE + #unset(CMAKE_SYSTEM_NAME) #SET(CMAKE_SYSTEM_NAME "Windows" CACHE INTERNAL "" FORCE) + unset() set(CMAKE_SYSTEM_PROCESSOR "x86_64" CACHE INTERNAL "" FORCE) set(CMAKE_RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/bin-x86_64" PARENT_SCOPE) - #set(ARCH_BITS 64 CACHE INTERNAL "" FORCE) # provide it + #set(ARCH_BITS 64 CACHE INTERNAL "" FORCE) # automatically gotten from CMAKE_SYSTEM_PROCESSOR toolchain_after_project_common() # To enable RC language, to compile Windows Resource files diff --git a/utilities/run_clang-format.sh b/utilities/run_clang-format.sh index 2755261c4..253483a46 100644 --- a/utilities/run_clang-format.sh +++ b/utilities/run_clang-format.sh @@ -41,8 +41,8 @@ case $action in ;; --changed) # Get modified and staged files (combined) - unstaged_files=$(git diff --name-only) - staged_files=$(git diff --cached --name-only) + unstaged_files=$(git diff --name-only --line-prefix="$project_root_dir/") + staged_files=$(git diff --cached --name-only --line-prefix="$project_root_dir/") files=$( (echo "$unstaged_files" && echo "$staged_files") | sort | uniq | grep -E '\.cpp$|\.h$|\.hpp$') ;; --last-commit) diff --git a/utilities/run_gersemi_cmake.sh b/utilities/run_gersemi_cmake.sh index c115c78f9..1e03acb3b 100644 --- a/utilities/run_gersemi_cmake.sh +++ b/utilities/run_gersemi_cmake.sh @@ -50,8 +50,8 @@ case $action in ;; --changed) # Get modified and staged files (combined) - unstaged_files=$(git diff --name-only) - staged_files=$(git diff --cached --name-only) + unstaged_files=$(git diff --name-only --line-prefix="$project_root_dir/") + staged_files=$(git diff --cached --name-only --line-prefix="$project_root_dir/") files=$( (echo "$unstaged_files" && echo "$staged_files") | sort | uniq | grep -E '\.cmake$|CMakeLists\.txt$') ;; --last-commit) From aafb23444d3237975cca7365b0398b5b9f8659b9 Mon Sep 17 00:00:00 2001 From: cbnolok Date: Wed, 18 Sep 2024 20:19:40 +0200 Subject: [PATCH 45/86] Added precompiled headers. This speeds up dramatically the compilation speed. --- CMakeLists.txt | 4 ++++ lib/CMakeLists.txt | 2 +- src/CMakeSources.cmake | 24 ++++++++++++++++++++++++ src/common/common.h | 6 ++++++ src/common/datatypes.h | 1 - 5 files changed, 35 insertions(+), 2 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 121381744..e54f63669 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -170,6 +170,7 @@ if(SINGLE_TARGET) set_target_properties(spheresvr_release PROPERTIES OUTPUT_NAME SphereSvrX${ARCH_BITS}_release) #set_target_properties(spheresvr_release PROPERTIES CXX_EXTENSIONS OFF) #target_compile_features(spheresvr_release PUBLIC cxx_std_20) + target_precompile_headers(spheresvr_release ${pch_options}) endif() if(("${CMAKE_BUILD_TYPE}" STREQUAL "") OR (${CMAKE_BUILD_TYPE} MATCHES "(N|n?)ightly")) set(TARGETS ${TARGETS} spheresvr_nightly) @@ -182,6 +183,7 @@ if(SINGLE_TARGET) set_target_properties(spheresvr_nightly PROPERTIES OUTPUT_NAME SphereSvrX${ARCH_BITS}_nightly) #set_target_properties(spheresvr_nightly PROPERTIES CXX_EXTENSIONS OFF) #target_compile_features(spheresvr_nightly PUBLIC cxx_std_20) + target_precompile_headers(spheresvr_nightly ${pch_options}) endif() if(("${CMAKE_BUILD_TYPE}" STREQUAL "") OR (${CMAKE_BUILD_TYPE} MATCHES "(D|d?)ebug")) set(TARGETS ${TARGETS} spheresvr_debug) @@ -194,6 +196,7 @@ if(SINGLE_TARGET) set_target_properties(spheresvr_debug PROPERTIES OUTPUT_NAME SphereSvrX${ARCH_BITS}_debug) #set_target_properties(spheresvr_debug PROPERTIES CXX_EXTENSIONS OFF) #target_compile_features(spheresvr_debug PUBLIC cxx_std_20) + target_precompile_headers(spheresvr_debug ${pch_options}) endif() else(SINGLE_TARGET) set(TARGETS ${TARGETS} spheresvr) @@ -203,6 +206,7 @@ else(SINGLE_TARGET) set_target_properties(spheresvr PROPERTIES OUTPUT_NAME_DEBUG SphereSvrX${ARCH_BITS}_debug) #set_target_properties(spheresvr PROPERTIES CXX_EXTENSIONS OFF) #target_compile_features(spheresvr PUBLIC cxx_std_20) + target_precompile_headers(spheresvr ${pch_options}) endif(SINGLE_TARGET) # -------------------- diff --git a/lib/CMakeLists.txt b/lib/CMakeLists.txt index 7aa07d072..f153491b3 100644 --- a/lib/CMakeLists.txt +++ b/lib/CMakeLists.txt @@ -1,5 +1,5 @@ add_subdirectory(bcrypt) -add_subdirectory(cdrc) +#add_subdirectory(cdrc) add_subdirectory(flat_containers) add_subdirectory(mariadb_connector_c) add_subdirectory(object_ptr) diff --git a/src/CMakeSources.cmake b/src/CMakeSources.cmake index 7bf73af39..d5ecf054b 100644 --- a/src/CMakeSources.cmake +++ b/src/CMakeSources.cmake @@ -1,3 +1,27 @@ +# Precompiled header: it's parsed only once and stored in memory as an intermediate form. This speeds up compilation drastically. +# Be wise in chosing those, since every time we change one of them, we'll have to recompile every one on the list. +set(pch_options + PRIVATE src/common/common.h + #PRIVATE src/common/sphere_library/CSRand.h + PRIVATE src/common/sphere_library/CSString.h + PRIVATE src/common/sphere_library/sstring.h + PRIVATE src/common/sphere_library/sstringobjs.h + PRIVATE src/common/CException.h + PRIVATE src/common/CExpression.h + PRIVATE src/common/CLog.h + #PRIVATE src/common/CServerMap.h + PRIVATE src/game/CObjBase.h + #PRIVATE src/game/CSector.h + #PRIVATE src/game/CWorld.h + PRIVATE src/sphere/threads.h + #PRIVATE src/network/send.h + #PRIVATE src/network/receive.h + #PRIVATE src/game/clients/CClient.h + #PRIVATE src/game/chars/CChar.h + #PRIVATE src/game/items/CItem.h + +) + # Main program files: threads, console... set(sphere_SRCS src/sphere/asyncdb.cpp diff --git a/src/common/common.h b/src/common/common.h index 3101aa3ff..582a0c8ed 100644 --- a/src/common/common.h +++ b/src/common/common.h @@ -19,7 +19,13 @@ // C abs function has different in/out types the std:: ones in cmath. It's defined in stdlib.h. #include +#include +#include +#include #include // for smart pointers +#include +#include +#include #include "assertion.h" #include "basic_threading.h" diff --git a/src/common/datatypes.h b/src/common/datatypes.h index ba4bb17b9..c7125776e 100644 --- a/src/common/datatypes.h +++ b/src/common/datatypes.h @@ -30,7 +30,6 @@ #define _INC_DATATYPES_H -#include #include /* -- Macros from we should use when formatting numbers inside strings -- -- (like in printf/sprintf/etc) to achieve best cross-platform/compiler support -- From 441d7248db0b122985e9cb52fa457a09f0ed9858 Mon Sep 17 00:00:00 2001 From: cbnolok Date: Thu, 19 Sep 2024 11:21:27 +0200 Subject: [PATCH 46/86] Fixed followerslots with animal taming. --- .clangd | 5 +++++ src/CMakeSources.cmake | 1 + src/common/common.h | 7 +++++++ src/game/chars/CChar.cpp | 5 ++++- src/game/chars/CCharSkill.cpp | 6 +++--- src/game/chars/CCharUse.cpp | 2 +- src/network/send.cpp | 4 ---- 7 files changed, 21 insertions(+), 9 deletions(-) diff --git a/.clangd b/.clangd index f72b2a4c5..6b5f08c53 100644 --- a/.clangd +++ b/.clangd @@ -10,3 +10,8 @@ CompileFlags: - -I!cmake - -I!lib - -I!utilities + +# If: +# PathMatch: '.*/src/common/common\.h' +# Diagnostics: +# Suppress: ['-Wunused-include-directive'] diff --git a/src/CMakeSources.cmake b/src/CMakeSources.cmake index d5ecf054b..d1b52321f 100644 --- a/src/CMakeSources.cmake +++ b/src/CMakeSources.cmake @@ -15,6 +15,7 @@ set(pch_options #PRIVATE src/game/CWorld.h PRIVATE src/sphere/threads.h #PRIVATE src/network/send.h + #PRIVATE src/network/CSocket.h #PRIVATE src/network/receive.h #PRIVATE src/game/clients/CClient.h #PRIVATE src/game/chars/CChar.h diff --git a/src/common/common.h b/src/common/common.h index 582a0c8ed..65b68040d 100644 --- a/src/common/common.h +++ b/src/common/common.h @@ -1,6 +1,7 @@ /** * @file common.h * @brief Header that should be included by every file. +* When set as a precompiled header, it's automatically included in every file. */ #ifndef _INC_COMMON_H @@ -19,13 +20,19 @@ // C abs function has different in/out types the std:: ones in cmath. It's defined in stdlib.h. #include + #include +//#include #include + #include #include // for smart pointers +#include #include #include +#include #include + #include "assertion.h" #include "basic_threading.h" diff --git a/src/game/chars/CChar.cpp b/src/game/chars/CChar.cpp index 5b3811bc3..5688241b4 100644 --- a/src/game/chars/CChar.cpp +++ b/src/game/chars/CChar.cpp @@ -3488,6 +3488,9 @@ bool CChar::r_LoadVal( CScript & s ) break; case CHC_CURFOLLOWER: + if (!s.HasArgs()) + return false; + if (!IsSetEF(EF_FollowerList)) { SetDefNum(s.GetKey(), s.GetArgSVal(), false); @@ -3536,7 +3539,7 @@ bool CChar::r_LoadVal( CScript & s ) if (!fExists) { const CChar* pCharPet = uid.CharFind(); - ASSERT(pCharPet); + PERSISTANT_ASSERT(pCharPet); m_followers.emplace_back( FollowerCharData{ .uid = uid, diff --git a/src/game/chars/CCharSkill.cpp b/src/game/chars/CCharSkill.cpp index 88b0f4019..5721611b1 100644 --- a/src/game/chars/CCharSkill.cpp +++ b/src/game/chars/CCharSkill.cpp @@ -2280,8 +2280,8 @@ int CChar::Skill_Taming( SKTRIG_TYPE stage ) if (IsSetOF(OF_PetSlots)) { - short iFollowerSlots = GetFollowerSlots(); - if (!FollowersUpdate(pChar, maximum(0, iFollowerSlots), true)) + short iFollowerSlots = pChar->GetFollowerSlots(); + if (!FollowersUpdate(pChar, iFollowerSlots, true)) { SysMessageDefault(DEFMSG_PETSLOTS_TRY_TAMING); return -SKTRIG_QTY; @@ -2296,7 +2296,7 @@ int CChar::Skill_Taming( SKTRIG_TYPE stage ) if ( pChar->Memory_FindObjTypes( this, MEMORY_FIGHT|MEMORY_HARMEDBY|MEMORY_IRRITATEDBY|MEMORY_AGGREIVED )) // I've attacked it before ? iDifficulty += 50; // is it too much? - m_atTaming.m_dwStrokeCount = (word)(g_Rand.GetVal(4) + 2); + m_atTaming.m_dwStrokeCount = (dword)(g_Rand.GetVal(4) + 2); return iDifficulty; // How difficult? 1-1000 } diff --git a/src/game/chars/CCharUse.cpp b/src/game/chars/CCharUse.cpp index f2af5dc88..bc30d853d 100644 --- a/src/game/chars/CCharUse.cpp +++ b/src/game/chars/CCharUse.cpp @@ -1292,7 +1292,7 @@ bool CChar::FollowersUpdate(CChar * pCharPet, short iPetFollowerSlots, bool fChe const bool fIsSame = inp_struct.uid == pCharPet->GetUID(); if (!fIsSame) return false; - if (inp_struct.followerslots != iPetFollowerSlots) + if (inp_struct.followerslots != abs(iPetFollowerSlots)) g_Log.EventWarn("Removed Follower with UID 0%" PRIx32 " with actual FollowerSlots %d, but expected %d.\n", inp_struct.uid.GetObjUID(), inp_struct.followerslots, abs(iPetFollowerSlots)); return true; diff --git a/src/network/send.cpp b/src/network/send.cpp index d65972369..b70bc8527 100644 --- a/src/network/send.cpp +++ b/src/network/send.cpp @@ -24,10 +24,6 @@ namespace zlib { #include } - -#ifndef _WIN32 -# include -#endif #include From 75c7492e4cb6aaf8a2ad2f65846199dbbf23a165 Mon Sep 17 00:00:00 2001 From: cbnolok Date: Thu, 19 Sep 2024 11:24:03 +0200 Subject: [PATCH 47/86] Renamed PERSISTANT_ASSERT to ASSERT_ALWAYS. --- src/common/CScriptObj.cpp | 2 +- src/common/assertion.h | 2 +- src/common/resource/CResourceHolder.cpp | 2 +- src/game/chars/CChar.cpp | 2 +- src/game/chars/CCharSpell.cpp | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/common/CScriptObj.cpp b/src/common/CScriptObj.cpp index 9653393aa..684109e4d 100644 --- a/src/common/CScriptObj.cpp +++ b/src/common/CScriptObj.cpp @@ -1943,7 +1943,7 @@ int CScriptObj::ParseScriptText(tchar * ptcResponse, CTextConsole * pSrc, int iF if (pContext->_iParseScriptText_Reentrant > 32 ) { EXC_SET_BLOCK("recursive brackets limit"); - PERSISTANT_ASSERT(pContext->_iParseScriptText_Reentrant < 32); + ASSERT_ALWAYS(pContext->_iParseScriptText_Reentrant < 32); } ASSERT(pContext->_fParseScriptText_Brackets == true); diff --git a/src/common/assertion.h b/src/common/assertion.h index 07558b259..fd96e715a 100644 --- a/src/common/assertion.h +++ b/src/common/assertion.h @@ -9,7 +9,7 @@ extern void Assert_Fail(const char * pExp, const char *pFile, long long llLine); -#define PERSISTANT_ASSERT(exp) if ( !(exp) ) [[unlikely]] Assert_Fail(#exp, __FILE__, __LINE__) +#define ASSERT_ALWAYS(exp) if ( !(exp) ) [[unlikely]] Assert_Fail(#exp, __FILE__, __LINE__) #if defined(STATIC_ANALYSIS) #include diff --git a/src/common/resource/CResourceHolder.cpp b/src/common/resource/CResourceHolder.cpp index e2c5f355a..621628f1a 100644 --- a/src/common/resource/CResourceHolder.cpp +++ b/src/common/resource/CResourceHolder.cpp @@ -112,7 +112,7 @@ CResourceScript * CResourceHolder::AddResourceFile( lpctstr pszName ) tchar szTitle[_MAX_PATH]; lpctstr ptcTitle = CScript::GetFilesTitle(szName); - PERSISTANT_ASSERT(strlen(ptcTitle) < sizeof(szTitle)); + ASSERT_ALWAYS(strlen(ptcTitle) < sizeof(szTitle)); Str_CopyLimitNull(szTitle, ptcTitle, sizeof(szTitle)); if ( szTitle[0] == '\0' ) diff --git a/src/game/chars/CChar.cpp b/src/game/chars/CChar.cpp index 5688241b4..72ef26483 100644 --- a/src/game/chars/CChar.cpp +++ b/src/game/chars/CChar.cpp @@ -3539,7 +3539,7 @@ bool CChar::r_LoadVal( CScript & s ) if (!fExists) { const CChar* pCharPet = uid.CharFind(); - PERSISTANT_ASSERT(pCharPet); + ASSERT_ALWAYS(pCharPet); m_followers.emplace_back( FollowerCharData{ .uid = uid, diff --git a/src/game/chars/CCharSpell.cpp b/src/game/chars/CCharSpell.cpp index e5ed0e7bc..5bcff3143 100644 --- a/src/game/chars/CCharSpell.cpp +++ b/src/game/chars/CCharSpell.cpp @@ -1391,7 +1391,7 @@ void CChar::Spell_Effect_Add( CItem * pSpell ) StatFlag_Set( STATF_REACTIVE ); int iSkill = -1; const bool fValidSkill = pSpellDef->GetPrimarySkill(&iSkill, nullptr); - PERSISTANT_ASSERT(fValidSkill); + ASSERT_ALWAYS(fValidSkill); pSpell->m_itSpell.m_PolyStr = (int16)pSpellDef->m_vcEffect.GetLinear(pCaster->Skill_GetBase((SKILL_TYPE)iSkill)) / 10; // % of damage reflected. } if (pClient && IsSetOF(OF_Buffs)) From fdad3b73e8d12962dce0fce8f33a4a69a70b3985 Mon Sep 17 00:00:00 2001 From: cbnolok Date: Thu, 19 Sep 2024 15:28:17 +0200 Subject: [PATCH 48/86] Fixed followerslots and summon creature spells. --- src/game/chars/CCharSpell.cpp | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/game/chars/CCharSpell.cpp b/src/game/chars/CCharSpell.cpp index 5bcff3143..f96cbefad 100644 --- a/src/game/chars/CCharSpell.cpp +++ b/src/game/chars/CCharSpell.cpp @@ -350,6 +350,7 @@ CChar * CChar::Spell_Summon_Place( CChar * pChar, CPointMap ptTarg, int64 iDurat } pChar->StatFlag_Set(STATF_CONJURED); // conjured creates have no loot pChar->NPC_LoadScript(false); + ASSERT(FollowersUpdate(pChar, pChar->GetFollowerSlots(), true)); pChar->NPC_PetSetOwner(this); pChar->MoveToChar(ptTarg); pChar->m_ptHome = ptTarg; @@ -359,7 +360,7 @@ CChar * CChar::Spell_Summon_Place( CChar * pChar, CPointMap ptTarg, int64 iDurat pChar->OnSpellEffect(SPELL_Summon, this, Skill_GetAdjusted((SKILL_TYPE)iSkill), nullptr, false, iDuration); pChar->Update(); pChar->UpdateAnimate(ANIM_SUMMON); - pChar->SetTimeout(2000); + pChar->SetTimeoutS(2); pChar->SoundChar(CRESND_GETHIT); m_Act_UID = pChar->GetUID(); // for last target stuff return pChar; @@ -2617,8 +2618,8 @@ CChar * CChar::Spell_Summon_Try(SPELL_TYPE spell, CPointMap ptTarg, CREID_TYPE u if (IsSetOF(OF_PetSlots)) { - short iFollowerSlots = GetFollowerSlots(); - if (!FollowersUpdate(pChar, maximum(0, iFollowerSlots), true)) + short iFollowerSlots = pChar->GetFollowerSlots(); + if (!FollowersUpdate(pChar, iFollowerSlots, true)) { SysMessageDefault(DEFMSG_PETSLOTS_TRY_SUMMON); pChar->Delete(); From 49763ac62cf52888e1cfc1c5aaba60e95fd4cb7c Mon Sep 17 00:00:00 2001 From: cbnolok Date: Sat, 21 Sep 2024 07:37:47 +0200 Subject: [PATCH 49/86] Other FollowerSlots/CurFollower fixes. --- Changelog.txt | 7 +- src/game/chars/CChar.cpp | 127 +++++++++++++++----------- src/game/chars/CCharNPCAct_Vendor.cpp | 7 +- src/game/chars/CCharUse.cpp | 13 +-- 4 files changed, 84 insertions(+), 70 deletions(-) diff --git a/Changelog.txt b/Changelog.txt index 715ae2881..210e47371 100644 --- a/Changelog.txt +++ b/Changelog.txt @@ -3895,5 +3895,10 @@ Added: 'H' shortcut for variables to get the value as hexadecimal. - Fixed: When acquiring a new pet follower, CurFollower incremented by 1 regardless of pet's FollowerSlots value (Issue #1251). - Fixed: dynamic FOLLOWERSLOTS property wasn't correctly saved and loaded from a worldsave. - Added: dynamic FOLLOWERSLOTS property is now copied to the figurine as TAG.FOLLOWERSLOTS when an NPC is shrinked, and it's applied back when unshrinked. -- Added: FOLLOWER. to reference char followers. - Fixed: "mounting"/guiding through the ship pilot exit/dismount bug. + +21-09-2024, Nolok +- Changed: CURFOLLOWER.n now works as a reference for that pet, meaning it can be accessed as an object (like with FINDID). +- Changed: added desired FollowerSlots as a second argument to CURFOLLOWER.ADD. Default value: its FollowerSlots. +- Changed: @FollowerUpdate ARGN1 and ARGN2 are now read-only. Having them RW and actually get them working would have meant many other changes, breaking script compatibility. +- Fixed: CURFOLLOWER.DEL/DELETE/CLEAR not working properly. diff --git a/src/game/chars/CChar.cpp b/src/game/chars/CChar.cpp index 72ef26483..bc12f2842 100644 --- a/src/game/chars/CChar.cpp +++ b/src/game/chars/CChar.cpp @@ -2308,22 +2308,6 @@ bool CChar::r_WriteVal( lpctstr ptcKey, CSString & sVal, CTextConsole * pSrc, bo { do_default: - if (!strnicmp("FOLLOWER", ptcKey, 8)) - { - if (ptcKey[8] == '.') - { - ptcKey += 9; - const uint uiIndex = Exp_GetUVal(ptcKey); - if (uiIndex >= m_followers.size()) - return false; - - CChar* pCharArg = CUID::CharFindFromUID(m_followers[uiIndex].uid); - ASSERT(pCharArg); - if (pCharArg->r_WriteVal(ptcKey, sVal, pSrc, fNoCallParent, fNoCallChildren)) - return true; - } - } - if ( m_pPlayer ) { if ( m_pPlayer->r_WriteVal( this, ptcKey, sVal )) @@ -2377,21 +2361,20 @@ bool CChar::r_WriteVal( lpctstr ptcKey, CSString & sVal, CTextConsole * pSrc, bo sVal.FormatVal(0); ptcKey += 11; - if (*ptcKey == '.' && !m_followers.empty()) - { - ++ptcKey; - int iIndex = std::max((int)0, Exp_GetVal(ptcKey)); - SKIP_SEPARATORS(ptcKey); - if (iIndex < (int)m_followers.size()) - { - if ((!strnicmp(ptcKey, "UID", 3)) || (*ptcKey == '\0')) - { - CUID const& uid = m_followers[iIndex].uid; - sVal.FormatHex(uid.CharFind() ? (dword)uid : 0); - return true; - } - } - } + if (*ptcKey != '.' || m_followers.empty()) + return false; + + const uint uiIndex = Exp_GetUVal(ptcKey); + if (uiIndex >= m_followers.size()) + return false; + + CChar* pCharArg = CUID::CharFindFromUID(m_followers[uiIndex].uid); + if (!pCharArg) + return false; + + if (pCharArg->r_WriteVal(ptcKey, sVal, pSrc, fNoCallParent, fNoCallChildren)) + return true; + return true; } //On these ones, check BaseDef if not found on dynamic @@ -3367,6 +3350,7 @@ bool CChar::r_LoadVal( CScript & s ) if (!strnicmp("FOLLOWER", ptcKey, 8)) { + // This keyword is used only for WORLDSAVES! // Need to do this before FindTableHeadSorted, because it might match FOLLOWERSLOTS instead! if (ptcKey[8] == '.') { @@ -3508,44 +3492,77 @@ bool CChar::r_LoadVal( CScript & s ) ++ptcKey; if (!strnicmp(ptcKey, "CLEAR", 5)) { - if (!m_followers.empty()) - m_followers.clear(); + if (m_followers.empty()) + return true; + + for (auto& follower : m_followers) + { + CChar *pFollower = follower.uid.CharFind(); + if (!pFollower) + continue; + pFollower->NPC_PetClearOwners(); + } + + m_followers.clear(); UpdateStatsFlag(); return true; } - else if (!strnicmp(ptcKey, "DELETE", 6) || !strnicmp(ptcKey, "DEL", 3)) + if (!strnicmp(ptcKey, "DELETE", 6) || !strnicmp(ptcKey, "DEL", 3)) { - if (!m_followers.empty()) + if (m_followers.empty()) + return false; + + const CUID uid(s.GetArgDWVal()); + for (auto it = m_followers.begin(); it != m_followers.end();) { - const CUID uid(s.GetArgDWVal()); - std::erase_if(m_followers, - [&uid](auto const& inp_struct) -> bool - { - return inp_struct.uid == uid; - }); + auto& followerData = *it; + if (followerData.uid != uid) + { + ++it; + continue; + } + + CChar *pChar = uid.CharFind(); + it = m_followers.erase(it); + + if (!pChar) + continue; + pChar->NPC_PetClearOwners(); } return true; } - else if (!strnicmp(ptcKey, "ADD", 3)) + if (!strnicmp(ptcKey, "ADD", 3)) { - const CUID uid(s.GetArgDWVal()); + int64 piCmd[2]; + const int iArgQty = Str_ParseCmds( s.GetArgStr(), piCmd, ARRAY_COUNT(piCmd) ); + if ( iArgQty < 1 ) + return false; + + const CUID uidNewFollower(s.GetArgDWVal()); const bool fExists = !m_followers.empty() && - m_followers.end() != + m_followers.end() != std::find_if(m_followers.begin(), m_followers.end(), - [&uid](auto const& inp_struct) -> bool { - return inp_struct.uid == uid; - }); - if (!fExists) + [&uidNewFollower](auto const& inp_struct) -> bool { + return inp_struct.uid == uidNewFollower; + }); + if (fExists) { - const CChar* pCharPet = uid.CharFind(); - ASSERT_ALWAYS(pCharPet); - m_followers.emplace_back( - FollowerCharData{ - .uid = uid, - .followerslots = pCharPet->GetFollowerSlots() - }); + g_Log.EventError("Char is already a follower of mine.\n"); + return false; } + + const CChar* pCharPet = uidNewFollower.CharFind(); + if (!pCharPet) + return false; + const short uiNewSlots = (iArgQty >= 2) ? piCmd[1] : pCharPet->GetFollowerSlots(); + + m_followers.emplace_back( + FollowerCharData{ + .uid = uidNewFollower, + .followerslots = uiNewSlots + }); + return true; } return false; diff --git a/src/game/chars/CCharNPCAct_Vendor.cpp b/src/game/chars/CCharNPCAct_Vendor.cpp index 6fd99e9ff..b04482eef 100644 --- a/src/game/chars/CCharNPCAct_Vendor.cpp +++ b/src/game/chars/CCharNPCAct_Vendor.cpp @@ -192,7 +192,7 @@ bool CChar::NPC_StablePetRetrieve( CChar * pCharPlayer ) CItem* pItem = static_cast(pObjRec); if (pItem->IsType(IT_FIGURINE)) { - CChar* pPet = pCharPlayer->Use_Figurine(pItem); + CChar* pPet = pCharPlayer->Use_Figurine(pItem, true); if (!pPet) { tchar *pszTemp = Str_GetTemp(); @@ -202,11 +202,6 @@ bool CChar::NPC_StablePetRetrieve( CChar * pCharPlayer ) } pItem->Delete(); - if (IsSetOF(OF_PetSlots)) - { - const short iFollowerSlots = GetFollowerSlots(); - pCharPlayer->FollowersUpdate(pPet, (maximum(0, iFollowerSlots)), false); - } ++iCount; } } diff --git a/src/game/chars/CCharUse.cpp b/src/game/chars/CCharUse.cpp index bc30d853d..8b9599e2f 100644 --- a/src/game/chars/CCharUse.cpp +++ b/src/game/chars/CCharUse.cpp @@ -1236,20 +1236,17 @@ bool CChar::FollowersUpdate(CChar * pCharPet, short iPetFollowerSlots, bool fChe if (!fCheckOnly && IsTrigUsed(TRIGGER_FOLLOWERSUPDATE)) { + // Arguments should be read only. Otherwise we have to call this trigger also if fCheckOnly == true and + // everyone scripts have to be changed to recognize this scenario. + CScriptTriggerArgs Args; Args.m_iN1 = (iPetFollowerSlots >= 0) ? 0 : 1; Args.m_iN2 = abs(iPetFollowerSlots); + //Args.m_iN3 = fCheckOnly; if (OnTrigger(CTRIG_FollowersUpdate, pCharPet, &Args) == TRIGRET_RET_TRUE) return false; - if (Args.m_iN1 == 1) - { - iPetFollowerSlots = - n64_narrow_n16(Args.m_iN2); - } - else - { - iPetFollowerSlots = n64_narrow_n16(Args.m_iN2); - } + //iPetFollowerSlots = n64_narrow_n16(Args.m_iN2) * ((Args.m_iN1 == 1) ? -1 : 1); } const short iMaxFollower = n64_narrow_n16(GetDefNum("MAXFOLLOWER", true)); From 335c9461560babb4ee4c5acd3512abd4e805cd89 Mon Sep 17 00:00:00 2001 From: cbnolok Date: Sat, 21 Sep 2024 07:39:07 +0200 Subject: [PATCH 50/86] Added CMake script to autodetect supported compiler flags, among those of interest. --- CMakeLists.txt | 28 ++- cmake/CompilerFlagsChecker.cmake | 275 +++++++++++++++++++++++++++++ lib/lib_build_flags_common_c.cmake | 10 +- 3 files changed, 304 insertions(+), 9 deletions(-) create mode 100644 cmake/CompilerFlagsChecker.cmake diff --git a/CMakeLists.txt b/CMakeLists.txt index e54f63669..9c7bb54b6 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -3,6 +3,7 @@ cmake_minimum_required(VERSION 3.24) set(CMAKE_SUPPRESS_REGENERATION TRUE) # Supress the ZERO_CHECK generation + # -------------------- GUI checkboxes -------------------- option( CMAKE_NO_GIT_REVISION @@ -43,6 +44,7 @@ function(booleanize_str_find VAR) endif() endfunction() + # -------------------- Start: initializations -------------------- # Should i load the toolchain passed as argument? @@ -100,8 +102,10 @@ if(NOT TOOLCHAIN_LOADED) include("cmake/DetectDefaultToolchain.cmake") endif() + # -------------------- Stuff that needs to be executed after PROJECT but before ADD_EXECUTABLE +message(STATUS) toolchain_after_project() string(FIND "${CMAKE_GENERATOR}" "Makefiles" GEN_IS_MAKEFILE) @@ -122,7 +126,7 @@ if(SINGLE_TARGET) set_property(CACHE CMAKE_BUILD_TYPE PROPERTY STRINGS "Debug" "Nightly" "Release") if(NOT ${CMAKE_BUILD_TYPE} STREQUAL "") if( - (NOT ${CMAKE_BUILD_TYPE} STREQUAL "Release") + ( NOT ${CMAKE_BUILD_TYPE} STREQUAL "Release") AND (NOT ${CMAKE_BUILD_TYPE} STREQUAL "Debug") AND (NOT ${CMAKE_BUILD_TYPE} STREQUAL "Nightly") ) @@ -153,9 +157,11 @@ else(SINGLE_TARGET) set(CMAKE_CONFIGURATION_TYPES "Debug;Release;Nightly" CACHE STRING "" FORCE) endif(SINGLE_TARGET) + # Include the list of all Sphere source files include("src/CMakeSources.cmake") + # Configure output binaries set(TARGETS "" CACHE INTERNAL "List of Sphere targets to build.") if(SINGLE_TARGET) @@ -165,7 +171,7 @@ if(SINGLE_TARGET) spheresvr_release ${is_win32_app_linker} ${SPHERE_SOURCES} - # ${docs_TEXT} + #${docs_TEXT} ) set_target_properties(spheresvr_release PROPERTIES OUTPUT_NAME SphereSvrX${ARCH_BITS}_release) #set_target_properties(spheresvr_release PROPERTIES CXX_EXTENSIONS OFF) @@ -178,7 +184,7 @@ if(SINGLE_TARGET) spheresvr_nightly ${is_win32_app_linker} ${SPHERE_SOURCES} - # ${docs_TEXT} + #${docs_TEXT} ) set_target_properties(spheresvr_nightly PROPERTIES OUTPUT_NAME SphereSvrX${ARCH_BITS}_nightly) #set_target_properties(spheresvr_nightly PROPERTIES CXX_EXTENSIONS OFF) @@ -191,7 +197,7 @@ if(SINGLE_TARGET) spheresvr_debug ${is_win32_app_linker} ${SPHERE_SOURCES} - # ${docs_TEXT} + #${docs_TEXT} ) set_target_properties(spheresvr_debug PROPERTIES OUTPUT_NAME SphereSvrX${ARCH_BITS}_debug) #set_target_properties(spheresvr_debug PROPERTIES CXX_EXTENSIONS OFF) @@ -209,12 +215,26 @@ else(SINGLE_TARGET) target_precompile_headers(spheresvr ${pch_options}) endif(SINGLE_TARGET) + +# -------------------- + +#message(STATUS) +#include("${CMAKE_SOURCE_DIR}/cmake/CompilerFlagsChecker.cmake") + # -------------------- # Now include external libraries + +message(STATUS) +message(STATUS "Configuring external libraries...") add_subdirectory(lib) + +message(STATUS) toolchain_exe_stuff() # stuff to be executed after ADD_EXECUTABLE # Get the Git revision number +message(STATUS) +message(STATUS "Retrieving git data...") include("cmake/GitStatus.cmake") +message(STATUS) diff --git a/cmake/CompilerFlagsChecker.cmake b/cmake/CompilerFlagsChecker.cmake new file mode 100644 index 000000000..0e2e0399e --- /dev/null +++ b/cmake/CompilerFlagsChecker.cmake @@ -0,0 +1,275 @@ +include(CheckCXXCompilerFlag) +message(STATUS "Checking available compiler flags...") + + +if (NOT MSVC) + message(STATUS "-- Compilation options:") + # Compiler option flags. Common to both compilers, but older versions might not support the following. + #check_cxx_compiler_flag("" COMP_HAS_) + + # Compiler option flags. Expected to work on GCC but not Clang, at the moment. + check_cxx_compiler_flag("-fno-expensive-optimizations" COMP_HAS_FNO_EXPENSIVE_OPTIMIZATIONS) + + # Compiler option flags. Expected to work on Clang but not GCC, at the moment. + #check_cxx_compiler_flag("-fforce-emit-vtables" COMP_HAS_F_FORCE_EMIT_VTABLES) + + message(STATUS "-- Compilation options (Address Sanitizer):") + # Compiler option flags. Sanitizers related (ASAN). + #check_cxx_compiler_flag("-fsanitize=safe-stack" COMP_HAS_) # Can't be used with asan! + check_cxx_compiler_flag("-fsanitize-cfi" COMP_HAS_FSAN_CFI) # cfi: control flow integrity + check_cxx_compiler_flag("-fsanitize-address-use-after-scope" COMP_HAS_FSAN_ADDRESS_USE_AFTER_SCOPE) + check_cxx_compiler_flag("-fsanitize=pointer-compare" COMP_HAS_FSAN_PTR_COMP) + check_cxx_compiler_flag("-fsanitize=pointer-subtract" COMP_HAS_FSAN_PTR_SUB) + check_cxx_compiler_flag("-fsanitize-trap=all" COMP_HAS_FSAN_TRAP_ALL) + + message(STATUS "-- Compilation options (Sanitizers-related and safety checks):") + # Compiler option flags. Sanitizers related (other). + # fsanitize=signed-integer-overflow # -fno-strict-overflow (which implies -fwrapv-pointer and -fwrapv) + check_cxx_compiler_flag("-fcf-protection=full" COMP_HAS_FCF_PROTECTION_FULL) + check_cxx_compiler_flag("-fstack-check" COMP_HAS_F_STACK_CHECK) + check_cxx_compiler_flag("-fstack-protector-all" COMP_HAS_F_STACK_PROTECTOR_ALL) + check_cxx_compiler_flag("-fstack-protector-strong" COMP_HAS_F_STACK_PROTECTOR_STRONG) + check_cxx_compiler_flag("-fstack-protector" COMP_HAS_F_STACK_PROTECTOR) + check_cxx_compiler_flag("-fstack-clash-protection" COMP_HAS_F_STACK_CLASH_PROTECTION) + #Flags GCC specific? + check_cxx_compiler_flag("-fvtable-verify=preinit" COMP_HAS_F_VTABLE_VERIFY_PREINIT) + check_cxx_compiler_flag("-fharden-control-flow-redundancy" COMP_HAS_F_HARDEN_CFR) + check_cxx_compiler_flag("-fhardcfr-check-exceptions" COMP_HAS_F_HARDCFR_CHECK_EXCEPTIONS) + #check_cxx_compiler_flag("" COMP_HAS_) + + # Compiler warning flags. + message(STATUS "-- Compilation options (warnings):") + check_cxx_compiler_flag("-Wuseless-cast" COMP_HAS_W_USELESS_CAST) + check_cxx_compiler_flag("-Wnull-dereference" COMP_HAS_W_NULL_DEREFERENCE) + check_cxx_compiler_flag("-Wconversion" COMP_HAS_W_CONVERSION) # Temporarily disabled. Implicit type conversions that might change a value, such as narrowing conversions. + check_cxx_compiler_flag("-Wcast-qual" COMP_HAS_W_CAST_QUAL) # casts that remove a type's const or volatile qualifier. + check_cxx_compiler_flag("-Wzero-as-null-pointer-constant" COMP_HAS_W_ZERO_NULLPTR) + check_cxx_compiler_flag("-Wdisabled-optimization" COMP_HAS_W_DISABLE_OPT) + check_cxx_compiler_flag("-Winvalid-pch" COMP_HAS_W_INVALID_PCH) + check_cxx_compiler_flag("-Wshadow" COMP_HAS_W_SHADOW) + #check_cxx_compiler_flag("" COMP_HAS_) + + # Compiler warning flags. Expected to work con GCC but not Clang, at the moment. + check_cxx_compiler_flag("-Wlto-type-mismatch" COMP_HAS_W_LTO_TYPE_MISMATCH) + check_cxx_compiler_flag("-Wshift-overflow=2" COMP_HAS_W_SHIFT_OVERFLOW) + check_cxx_compiler_flag("-Wduplicated-cond" COMP_HAS_W_DUPLICATED_COND) + check_cxx_compiler_flag("-Wsized-deallocation" COMP_HAS_W_SIZED_DEALLOC) + check_cxx_compiler_flag("-Wvector-operation-performance" COMP_HAS_W_VECTOR_OP_PERF) + check_cxx_compiler_flag("-Wtrampolines" COMP_HAS_W_TRAMPOLINES) # we don't want trampolines for security concerns (it's a technique to implement nested functions). + #check_cxx_compiler_flag("" COMP_HAS_) + + # Compiler warning flags. Expected to work con Clang but not GCC, at the moment. + check_cxx_compiler_flag("-Wweak-vtables" COMP_HAS_W_WEAK_VTABLES) + check_cxx_compiler_flag("-Wmissing-prototypes" COMP_HAS_W_MISSING_PROTOTYPES) + check_cxx_compiler_flag("-Wmissing-variable-declarations" COMP_HAS_W_MISSING_VARIABLE_DECL) + #check_cxx_compiler_flag("" COMP_HAS_) + + # Compiler warning flags. TODO: To be evaluated... + # -Wshadow + # -Wfree-nonheap-object (good but false positive warnings on GCC?) + # -Wcast-align=strict + # -Wcast-user-defined + # -Wdate-time + + # Compiler warning flags. To be disabled. + message(STATUS "-- Compilation options (disable specific warnings):") + check_cxx_compiler_flag("-Wno-format-nonliteral" COMP_HAS_WNO_FORMAT_NONLITERAL) # Since -Wformat=2 is stricter, you would need to disable this warning. + check_cxx_compiler_flag("-Wno-nonnull-compare" COMP_HAS_WNO_NONNULL_COMPARE) + check_cxx_compiler_flag("-Wno-maybe-uninitialized" COMP_HAS_WNO_MAYBE_UNINIT) + check_cxx_compiler_flag("-Wno-switch" COMP_HAS_WNO_SWITCH) + check_cxx_compiler_flag("-Wno-implicit-fallthrough" COMP_HAS_WNO_IMPLICIT_FALLTHROUGH) + check_cxx_compiler_flag("-Wno-parentheses" COMP_HAS_WNO_PARENTHESES) + check_cxx_compiler_flag("-Wno-misleading-indentation" COMP_HAS_WNO_MISLEADING_INDENTATION) + check_cxx_compiler_flag("-Wno-unused-result" COMP_HAS_WNO_UNUSED_RESULT) + check_cxx_compiler_flag("-Wno-nested-anon-types" COMP_HAS_WNO_NESTED_ANON_TYPES) + check_cxx_compiler_flag("-Wno-format-security" COMP_HAS_WNO_FORMAT_SECURITY) # TODO: remove that when we'll have time to fix every printf format issue + check_cxx_compiler_flag("-Wno-deprecated-declarations" COMP_HAS_WNO_DEPRECATED_DECLARATIONS) + #check_cxx_compiler_flag("-Wno-unknown-pragmas" COMP_HAS_) + #check_cxx_compiler_flag("" COMP_HAS_) + +else (NOT MSVC) + # Compiler warning flags (MSVC). + message(STATUS "-- Compilation options (MSVC):") + check_cxx_compiler_flag("/Wd5105" COMP_HAS_DEFINE_MACRO_EXPANSION) # False positive warning, maybe even a MSVC bug. + #check_cxx_compiler_flag("" COMP_HAS_) +endif() + + +# ---- Append options into some lists. + +# ---- GCC/Clang + +if(COMP_HAS_FNO_EXPENSIVE_OPTIMIZATIONS) + list(APPEND checked_compiler_options "-fno-expensive-optimizations") +endif() + +if(COMP_HAS_FSAN_CFI) + list(APPEND checked_compiler_options_asan "-fsanitize-cfi") +endif() +if(COMP_HAS_FSAN_ADDRESS_USE_AFTER_SCOPE) + list(APPEND checked_compiler_options_asan "-fsanitize-address-use-after-scope") +endif() +if(COMP_HAS_FSAN_PTR_COMP) + list(APPEND checked_compiler_options_asan "-fsanitize=pointer-compare" ) +endif() +if(COMP_HAS_FSAN_PTR_SUB) + list(APPEND checked_compiler_options_asan "-fsanitize=pointer-subtract" ) +endif() +if(COMP_HAS_FSAN_TRAP_ALL) + list(APPEND checked_compiler_options_asan "-fsanitize-trap=all" ) +endif() + +if(COMP_HAS_FCF_PROTECTION_FULL) + list(APPEND checked_compiler_options_sanitize_other "-fcf-protection=full") +endif() +if(COMP_HAS_F_STACK_CHECK) + list(APPEND checked_compiler_options_sanitize_other "-fstack-check") +endif() +if(COMP_HAS_F_STACK_PROTECTOR_ALL) + list(APPEND checked_compiler_options_sanitize_other "-fstack-protector-all") +elseif(COMP_HAS_F_STACK_PROTECTOR_STRONG) + list(APPEND checked_compiler_options_sanitize_other "-fstack-protector-strong") +elseif(COMP_HAS_F_STACK_PROTECTOR) + list(APPEND checked_compiler_options_sanitize_other "-fstack-protector") +endif() +if(COMP_HAS_F_STACK_CLASH_PROTECTION) + list(APPEND checked_compiler_options_sanitize_other "-fstack-clash-protection") +endif() +if(COMP_HAS_F_VTABLE_VERIFY_PREINIT) + list(APPEND checked_compiler_options_sanitize_other "-fvtable-verify=preinit") +endif() +if(COMP_HAS_F_HARDEN_CFR) + list(APPEND checked_compiler_options_sanitize_other "-fharden-control-flow-redundancy") +endif() +if(COMP_HAS_F_HARDCFR_CHECK_EXCEPTIONS) + list( + APPEND checked_compiler_options_sanitize_other "-fhardcfr-check-exceptions") +endif() + +if(COMP_HAS_W_USELESS_CAST) + list(APPEND checked_compiler_warnings "-Wuseless-cast") +endif() +if(COMP_HAS_NULL_DEREFERENCE) + list(APPEND checked_compiler_warnings "-Wnull-dereference") +endif() +if(COMP_HAS_W_CONVERSION) + list(APPEND checked_compiler_warnings "-Wconversion") +endif() +if(COMP_HAS_W_CAST_QUAL) + list(APPEND checked_compiler_warnings "-Wcast-qual") +endif() +if(COMP_HAS_W_ZERO_NULLPTR) + list(APPEND checked_compiler_warnings "-Wzero-as-null-pointer-constant") +endif() +if(COMP_HAS_W_DISABLE_OPT) + list(APPEND checked_compiler_warnings "-Wdisabled-optimization") +endif() +if(COMP_HAS_W_INVALID_PCH) + list(APPEND checked_compiler_warnings "-Winvalid-pch") +endif() +if(COMP_HAS_W_SHADOW) + list(APPEND checked_compiler_warnings "-Wshadow") +endif() + +if(COMP_HAS_W_LTO_TYPE_MISMATCH) + list(APPEND checked_compiler_warnings "-Wlto-type-mismatch") +endif() +if(COMP_HAS_W_SHIFT_OVERFLOW) + list(APPEND checked_compiler_warnings "-Wshift-overflow=2") +endif() +if(COMP_HAS_W_DUPLICATED_COND) + list(APPEND checked_compiler_warnings "-Wduplicated-cond") +endif() +if(COMP_HAS_W_SIZED_DEALLOC) + list(APPEND checked_compiler_warnings "-Wsized-deallocation") +endif() +if(COMP_HAS_W_VECTOR_OP_PERF) + list(APPEND checked_compiler_warnings "-Wvector-operation-performance") +endif() +if(COMP_HAS_W_TRAMPOLINES) + list(APPEND checked_compiler_warnings "-Wtrampolines") +endif() +if(COMP_HAS_W_WEAK_VTABLES) + list(APPEND checked_compiler_warnings "-Wweak-vtables") +endif() +if(COMP_HAS_W_MISSING_PROTOTYPES) + list(APPEND checked_compiler_warnings "-Wmissing-prototypes") +endif() +if(COMP_HAS_W_MISSING_VARIABLE_DECL) + list(APPEND checked_compiler_warnings "-Wmissing-variable-declarations") +endif() + +if(COMP_HAS_WNO_FORMAT_NONLITERAL) + list(APPEND checked_compiler_warnings_disabled "-Wno-format-nonliteral") +endif() +if(COMP_HAS_WNO_NONNULL_COMPARE) + list(APPEND checked_compiler_warnings_disabled "-Wno-nonnull-compare") +endif() +if(COMP_HAS_WNO_MAYBE_UNINIT) + list(APPEND checked_compiler_warnings_disabled "-Wno-maybe-uninitialized") +endif() +if(COMP_HAS_WNO_SWITCH) + list(APPEND checked_compiler_warnings_disabled "-Wno-switch") +endif() +if(COMP_HAS_WNO_IMPLICIT_FALLTHROUGH) + list(APPEND checked_compiler_warnings_disabled "-Wno-implicit-fallthrough") +endif() +if(COMP_HAS_WNO_PARENTHESES) + list(APPEND checked_compiler_warnings_disabled "-Wno-parentheses") +endif() +if(COMP_HAS_WNO_MISLEADING_INDENTATION) + list(APPEND checked_compiler_warnings_disabled "-Wno-misleading-indentation") +endif() +if(COMP_HAS_WNO_UNUSED_RESULT) + list(APPEND checked_compiler_warnings_disabled "-Wno-unused-result") +endif() +if(COMP_HAS_WNO_NESTED_ANON_TYPES) + list(APPEND checked_compiler_warnings_disabled "-Wno-nested-anon-types") +endif() +if(COMP_HAS_WNO_FORMAT_SECURITY) + list(APPEND checked_compiler_warnings_disabled "-Wno-format-security") +endif() +if(COMP_HAS_WNO_DEPRECATED_DECLARATIONS) + list(APPEND checked_compiler_warnings_disabled "-Wno-deprecated-declarations") +endif() + +# ---- MSVC + +if(COMP_HAS_DEFINE_MACRO_EXPANSION) + list(APPEND checked_compiler_flags_msvc "/Wd5105") +endif() + +# ---- Double checks + +if( + CMAKE_COMPILER_IS_GNUCC + AND CMAKE_CXX_COMPILER_VERSION VERSION_GREATER 12.1 + AND CMAKE_CXX_COMPILER_VERSION VERSION_LESS 13.0 +) + # False positive warning, disable this flag. + unset(COMPILER_SUPPORTS_NULL_DEREFERENCE CACHE) +endif() + + +# ---- + +#[[ +set(checked_compiler_options) +set(checked_compiler_options_asan) +#set(checked_compiler_options_ubsan) +#set(checked_compiler_options_lsan) +set(checked_compiler_options_sanitize_other) +set(checked_compiler_warnings) +set(checked_compiler_warnings_disabled) +set(checked_compiler_flags_msvc) +]] + +message(STATUS "Adding the following conditional compiler options: ${checked_compiler_options}") +message(STATUS "Adding the following conditional compiler options for ASan: ${checked_compiler_options_asan}") +message(STATUS "Adding the following conditional compiler options for sanitizers: ${checked_compiler_options_sanitize_other}") +message(STATUS "Adding the following conditional compiler warnings: ${checked_compiler_warnings}") +message(STATUS "Adding the following conditional compiler warnings ignore options: ${checked_compiler_warnings_disabled}") + +if(MSVC) + message(STATUS "Adding the following conditional compiler options: ${checked_compiler_flags_msvc}") +endif() diff --git a/lib/lib_build_flags_common_c.cmake b/lib/lib_build_flags_common_c.cmake index 623a30f26..d34668325 100644 --- a/lib/lib_build_flags_common_c.cmake +++ b/lib/lib_build_flags_common_c.cmake @@ -7,14 +7,14 @@ if(MSVC) # gersemi: off set (c_compiler_options_common /O2 /EHsc /GA /Gw /Gy /GF /GR- /GS- - $<$: $,/MT,/MD> $<$:/Zi>> + $<$: $,/MT,/MD> $<$:/Zi>> $<$: $,/MT,/MD> $<$:/Zi>> - $<$: $,/MTd,/MDd> $,/Zi,/ZI>> + $<$: $,/MTd,/MDd> $,/Zi,/ZI>> ) set (c_linker_options_common - $<$: /OPT:REF,ICF /LTCG:ON /NODEFAULTLIB:libcmtd> - $<$: /OPT:REF,ICF /LTCG:ON /NODEFAULTLIB:libcmtd> - $<$: /DEBUG /LTCG:OFF /NODEFAULTLIB:libcmt> + $<$: /OPT:REF,ICF /LTCG:ON /NODEFAULTLIB:libcmtd> + $<$: /OPT:REF,ICF /LTCG:ON /NODEFAULTLIB:libcmtd> + $<$: /DEBUG /LTCG:OFF /NODEFAULTLIB:libcmt> ) # gersemi: on else(MSVC) From 4860a3cace3e43055073faae1da78d5016ce8b0d Mon Sep 17 00:00:00 2001 From: cbnolok Date: Sat, 21 Sep 2024 07:45:42 +0200 Subject: [PATCH 51/86] Fixed typo in parsing the house designer csv files. --- src/game/items/CItemMultiCustom.cpp | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/game/items/CItemMultiCustom.cpp b/src/game/items/CItemMultiCustom.cpp index c80080e5a..b1f087703 100644 --- a/src/game/items/CItemMultiCustom.cpp +++ b/src/game/items/CItemMultiCustom.cpp @@ -666,7 +666,7 @@ void CItemMultiCustom::AddRoof(CClient * pClientSrc, ITEMID_TYPE id, int16 x, in CItemBase * pItemBase = CItemBase::FindItemBase(id); if (pItemBase == nullptr) { - g_Log.EventWarn("Unscripted roof tile 0%x being added to building 0%x by 0%x.\n", + g_Log.EventWarn("Unscripted roof tile 0%x being added to building 0%x by Char with UID 0%x.\n", id, (dword)GetUID(), pCharSrc != nullptr ? (dword)pCharSrc->GetUID() : 0); SendStructureTo(pClientSrc); return; @@ -674,7 +674,7 @@ void CItemMultiCustom::AddRoof(CClient * pClientSrc, ITEMID_TYPE id, int16 x, in if ((pItemBase->GetTFlags() & UFLAG4_ROOF) == 0) { - g_Log.EventWarn("Non-roof tile 0%x being added as a roof to building 0%x by 0%x.\n", + g_Log.EventWarn("Non-roof tile 0%x being added as a roof to building 0%x by Char with UID 0%x.\n", id, (dword)GetUID(), pCharSrc != nullptr ? (dword)pCharSrc->GetUID() : 0); SendStructureTo(pClientSrc); return; @@ -682,7 +682,7 @@ void CItemMultiCustom::AddRoof(CClient * pClientSrc, ITEMID_TYPE id, int16 x, in if (z < -3 || z > 12 || (z % 3 != 0)) { - g_Log.EventWarn("Roof tile 0%x being added at invalid height %d to building 0%x by 0%x.\n", + g_Log.EventWarn("Roof tile 0%x being added at invalid height %d to building 0%x by Char with UID 0%x.\n", id, z, (dword)GetUID(), pCharSrc != nullptr ? (dword)pCharSrc->GetUID() : 0); SendStructureTo(pClientSrc); return; @@ -1979,7 +1979,7 @@ bool CItemMultiCustom::LoadValidItems() continue; auto iconv = Str_ToU(strCurRow.c_str(), 10); - if (iconv.has_value()) + if (!iconv.has_value()) { g_Log.EventWarn("Invalid number in file '%s', row=%d. Skipping.\n", sm_szItemFiles[i][0], curCSV.GetCurrentRow()); continue; @@ -1999,11 +1999,11 @@ bool CItemMultiCustom::LoadValidItems() if (strFeatureMask.empty()) { sm_mapValidItems[itemid] = 0; - DEBUG_WARN(("No FeatureMask in file '%s', row=%d.\n", sm_szItemFiles[i][0], curCSV.GetCurrentRow())); + g_Log.EventWarn("No FeatureMask in file '%s', row=%d.\n", sm_szItemFiles[i][0], curCSV.GetCurrentRow()); continue; } iconv = Str_ToU(strCurRow.c_str(), 10); - if (iconv.has_value()) + if (!iconv.has_value()) { g_Log.EventWarn("Invalid FeatureMask number in file '%s', row=%d. Skipping.\n", sm_szItemFiles[i][0], curCSV.GetCurrentRow()); continue; From 9f6466e8606cc0b7817e4740ff46f1b7978e2170 Mon Sep 17 00:00:00 2001 From: cbnolok Date: Sat, 21 Sep 2024 11:09:34 +0200 Subject: [PATCH 52/86] Fixed compilation warning. --- src/game/chars/CChar.cpp | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/src/game/chars/CChar.cpp b/src/game/chars/CChar.cpp index bc12f2842..cf14716cc 100644 --- a/src/game/chars/CChar.cpp +++ b/src/game/chars/CChar.cpp @@ -3472,9 +3472,6 @@ bool CChar::r_LoadVal( CScript & s ) break; case CHC_CURFOLLOWER: - if (!s.HasArgs()) - return false; - if (!IsSetEF(EF_FollowerList)) { SetDefNum(s.GetKey(), s.GetArgSVal(), false); @@ -3507,6 +3504,10 @@ bool CChar::r_LoadVal( CScript & s ) UpdateStatsFlag(); return true; } + + if (!s.HasArgs()) + return false; + if (!strnicmp(ptcKey, "DELETE", 6) || !strnicmp(ptcKey, "DEL", 3)) { if (m_followers.empty()) @@ -3531,6 +3532,7 @@ bool CChar::r_LoadVal( CScript & s ) } return true; } + if (!strnicmp(ptcKey, "ADD", 3)) { int64 piCmd[2]; @@ -3555,7 +3557,7 @@ bool CChar::r_LoadVal( CScript & s ) const CChar* pCharPet = uidNewFollower.CharFind(); if (!pCharPet) return false; - const short uiNewSlots = (iArgQty >= 2) ? piCmd[1] : pCharPet->GetFollowerSlots(); + const short uiNewSlots = (iArgQty >= 2) ? n64_narrow_n16(piCmd[1]) : pCharPet->GetFollowerSlots(); m_followers.emplace_back( FollowerCharData{ From e4b70e2a8df16cfbebc5dba6c99d619b70af2111 Mon Sep 17 00:00:00 2001 From: cbnolok Date: Sat, 21 Sep 2024 11:37:40 +0200 Subject: [PATCH 53/86] Fixed featuremask reading in CItemMultiCustom. --- src/game/items/CItemMultiCustom.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/game/items/CItemMultiCustom.cpp b/src/game/items/CItemMultiCustom.cpp index b1f087703..22e84d1d2 100644 --- a/src/game/items/CItemMultiCustom.cpp +++ b/src/game/items/CItemMultiCustom.cpp @@ -2002,7 +2002,8 @@ bool CItemMultiCustom::LoadValidItems() g_Log.EventWarn("No FeatureMask in file '%s', row=%d.\n", sm_szItemFiles[i][0], curCSV.GetCurrentRow()); continue; } - iconv = Str_ToU(strCurRow.c_str(), 10); + iconv = Str_ToU(strFeatureMask.c_str(), 10); + if (!iconv.has_value()) { g_Log.EventWarn("Invalid FeatureMask number in file '%s', row=%d. Skipping.\n", sm_szItemFiles[i][0], curCSV.GetCurrentRow()); From 7c83f5f09a2c78d6e5a851e53978cbfac001c297 Mon Sep 17 00:00:00 2001 From: DavideRei <118212274+DavideRei@users.noreply.github.com> Date: Sat, 21 Sep 2024 13:09:36 +0300 Subject: [PATCH 54/86] Fix ship turn for custom ship with custom z components (#1288) --- src/game/components/CCMultiMovable.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/game/components/CCMultiMovable.cpp b/src/game/components/CCMultiMovable.cpp index b35062310..53666a36b 100644 --- a/src/game/components/CCMultiMovable.cpp +++ b/src/game/components/CCMultiMovable.cpp @@ -617,6 +617,7 @@ bool CCMultiMovable::Face(DIR_TYPE dir) pt.m_x = pMultiThis->GetTopPoint().m_x + componentnew.m_dx; pt.m_y = pMultiThis->GetTopPoint().m_y + componentnew.m_dy; + pt.m_z = pMultiThis->GetTopPoint().m_z + componentnew.m_dz; } } } From 304255eb3bd2e7df8137401ba107859f181b7c6b Mon Sep 17 00:00:00 2001 From: Jhobean <51728381+Jhobean@users.noreply.github.com> Date: Wed, 25 Sep 2024 04:15:13 -0400 Subject: [PATCH 55/86] Update sphereCrypt.ini (#1297) --- src/sphereCrypt.ini | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/sphereCrypt.ini b/src/sphereCrypt.ini index ad5e2d934..ad0616d0b 100644 --- a/src/sphereCrypt.ini +++ b/src/sphereCrypt.ini @@ -25,6 +25,8 @@ ENC_LOGIN 4 // Rotation cipher used for the Login Server crypt by every client, [SPHERECRYPT] //Classic Clients +7010400 03907237D 0A84B527F ENC_TFISH // 7.0.104.00 +7010300 03949418D 0A864FE7F ENC_TFISH // 7.0.103.00 70010200 03992EB9D 0A81E227F ENC_TFISH // 7.0.102 70010100 039C411AD 0A803DE7F ENC_TFISH // 7.0.101 70010000 03A3D83BD 0A9F5127F ENC_TFISH // 7.0.100 @@ -227,6 +229,8 @@ ENC_LOGIN 4 // Rotation cipher used for the Login Server crypt by every client, 1232700 0D47BD45C 034081CD6 ENC_LOGIN // 1.23.27 //Enhanced Clients +6790010400 01B07237D 0B94B527F ENC_TFISH // 4.00.104 +6790010300 01B49418D 0B964FE7F ENC_TFISH // 4.00.103 670010200 01B92EB9D 0B91E227F ENC_TFISH // 4.00.102 670010100 01BC411AD 0B903DE7F ENC_TFISH // 4.00.101 670010000 0183D83BD 0B8F5127F ENC_TFISH // 4.00.100 From 575d5391d4b53b11e261934cb82762b5bc7a1c39 Mon Sep 17 00:00:00 2001 From: cbnolok Date: Sat, 21 Sep 2024 13:53:26 +0200 Subject: [PATCH 56/86] Added sanitizers options to CompilerFlagsChecker.cmake --- CMakeLists.txt | 14 +- cmake/CompilerFlagsChecker.cmake | 218 +++++++++++++++++++++++-------- 2 files changed, 164 insertions(+), 68 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 9c7bb54b6..29766560a 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -3,7 +3,6 @@ cmake_minimum_required(VERSION 3.24) set(CMAKE_SUPPRESS_REGENERATION TRUE) # Supress the ZERO_CHECK generation - # -------------------- GUI checkboxes -------------------- option( CMAKE_NO_GIT_REVISION @@ -30,10 +29,11 @@ if(WIN32) option(WIN32_SPAWN_CONSOLE "Spawn an additional console, useful for debugging." FALSE) endif() +option(USE_COMPILER_HARDENING_OPTIONS "Enable compiler (even runtime) safety checks and code hardening." FALSE) option(USE_ASAN "Enable AddressSanitizer." FALSE) -option(USE_MSAN "Enable MemorySanitizer." FALSE) -option(USE_LSAN "Enable LeakSanitizer." FALSE) option(USE_UBSAN "Enable Undefined Behavior Sanitizer." FALSE) +option(USE_LSAN "Enable LeakSanitizer." FALSE) +option(USE_MSAN "Enable MemorySanitizer." FALSE) # -------------------- Utility functions -------------------- function(booleanize_str_find VAR) @@ -44,7 +44,6 @@ function(booleanize_str_find VAR) endif() endfunction() - # -------------------- Start: initializations -------------------- # Should i load the toolchain passed as argument? @@ -102,7 +101,6 @@ if(NOT TOOLCHAIN_LOADED) include("cmake/DetectDefaultToolchain.cmake") endif() - # -------------------- Stuff that needs to be executed after PROJECT but before ADD_EXECUTABLE message(STATUS) @@ -126,7 +124,7 @@ if(SINGLE_TARGET) set_property(CACHE CMAKE_BUILD_TYPE PROPERTY STRINGS "Debug" "Nightly" "Release") if(NOT ${CMAKE_BUILD_TYPE} STREQUAL "") if( - ( NOT ${CMAKE_BUILD_TYPE} STREQUAL "Release") + (NOT ${CMAKE_BUILD_TYPE} STREQUAL "Release") AND (NOT ${CMAKE_BUILD_TYPE} STREQUAL "Debug") AND (NOT ${CMAKE_BUILD_TYPE} STREQUAL "Nightly") ) @@ -157,11 +155,9 @@ else(SINGLE_TARGET) set(CMAKE_CONFIGURATION_TYPES "Debug;Release;Nightly" CACHE STRING "" FORCE) endif(SINGLE_TARGET) - # Include the list of all Sphere source files include("src/CMakeSources.cmake") - # Configure output binaries set(TARGETS "" CACHE INTERNAL "List of Sphere targets to build.") if(SINGLE_TARGET) @@ -215,7 +211,6 @@ else(SINGLE_TARGET) target_precompile_headers(spheresvr ${pch_options}) endif(SINGLE_TARGET) - # -------------------- #message(STATUS) @@ -229,7 +224,6 @@ message(STATUS) message(STATUS "Configuring external libraries...") add_subdirectory(lib) - message(STATUS) toolchain_exe_stuff() # stuff to be executed after ADD_EXECUTABLE diff --git a/cmake/CompilerFlagsChecker.cmake b/cmake/CompilerFlagsChecker.cmake index 0e2e0399e..6826f0cac 100644 --- a/cmake/CompilerFlagsChecker.cmake +++ b/cmake/CompilerFlagsChecker.cmake @@ -1,8 +1,7 @@ include(CheckCXXCompilerFlag) message(STATUS "Checking available compiler flags...") - -if (NOT MSVC) +if(NOT MSVC) message(STATUS "-- Compilation options:") # Compiler option flags. Common to both compilers, but older versions might not support the following. #check_cxx_compiler_flag("" COMP_HAS_) @@ -13,29 +12,79 @@ if (NOT MSVC) # Compiler option flags. Expected to work on Clang but not GCC, at the moment. #check_cxx_compiler_flag("-fforce-emit-vtables" COMP_HAS_F_FORCE_EMIT_VTABLES) - message(STATUS "-- Compilation options (Address Sanitizer):") - # Compiler option flags. Sanitizers related (ASAN). - #check_cxx_compiler_flag("-fsanitize=safe-stack" COMP_HAS_) # Can't be used with asan! - check_cxx_compiler_flag("-fsanitize-cfi" COMP_HAS_FSAN_CFI) # cfi: control flow integrity - check_cxx_compiler_flag("-fsanitize-address-use-after-scope" COMP_HAS_FSAN_ADDRESS_USE_AFTER_SCOPE) - check_cxx_compiler_flag("-fsanitize=pointer-compare" COMP_HAS_FSAN_PTR_COMP) - check_cxx_compiler_flag("-fsanitize=pointer-subtract" COMP_HAS_FSAN_PTR_SUB) - check_cxx_compiler_flag("-fsanitize-trap=all" COMP_HAS_FSAN_TRAP_ALL) - - message(STATUS "-- Compilation options (Sanitizers-related and safety checks):") - # Compiler option flags. Sanitizers related (other). - # fsanitize=signed-integer-overflow # -fno-strict-overflow (which implies -fwrapv-pointer and -fwrapv) - check_cxx_compiler_flag("-fcf-protection=full" COMP_HAS_FCF_PROTECTION_FULL) - check_cxx_compiler_flag("-fstack-check" COMP_HAS_F_STACK_CHECK) - check_cxx_compiler_flag("-fstack-protector-all" COMP_HAS_F_STACK_PROTECTOR_ALL) - check_cxx_compiler_flag("-fstack-protector-strong" COMP_HAS_F_STACK_PROTECTOR_STRONG) - check_cxx_compiler_flag("-fstack-protector" COMP_HAS_F_STACK_PROTECTOR) - check_cxx_compiler_flag("-fstack-clash-protection" COMP_HAS_F_STACK_CLASH_PROTECTION) - #Flags GCC specific? - check_cxx_compiler_flag("-fvtable-verify=preinit" COMP_HAS_F_VTABLE_VERIFY_PREINIT) - check_cxx_compiler_flag("-fharden-control-flow-redundancy" COMP_HAS_F_HARDEN_CFR) - check_cxx_compiler_flag("-fhardcfr-check-exceptions" COMP_HAS_F_HARDCFR_CHECK_EXCEPTIONS) - #check_cxx_compiler_flag("" COMP_HAS_) + if(${USE_ASAN}) + # Compiler option flags. Sanitizers related (ASAN). + message(STATUS "-- Compilation options (Address Sanitizer):") + + check_cxx_compiler_flag("-fsanitize=address" COMP_HAS_ASAN) + if(NOT COMP_HAS_ASAN) + message(FATAL_ERROR "This compiler does not support Address Sanitizer. Disable it.") + endif() + + check_cxx_compiler_flag("-fsanitize-cfi" COMP_HAS_FSAN_CFI) # cfi: control flow integrity + check_cxx_compiler_flag("-fsanitize-address-use-after-scope" COMP_HAS_FSAN_ADDRESS_USE_AFTER_SCOPE) + check_cxx_compiler_flag("-fsanitize=pointer-compare" COMP_HAS_FSAN_PTR_COMP) + check_cxx_compiler_flag("-fsanitize=pointer-subtract" COMP_HAS_FSAN_PTR_SUB) + check_cxx_compiler_flag("-fsanitize-trap=all" COMP_HAS_FSAN_TRAP_ALL) + endif() + + if(${USE_UBSAN}) + # Compiler option flags. Sanitizers related (UBSAN). + message(STATUS "-- Compilation options (Undefined Behavior Sanitizer):") + + check_cxx_compiler_flag("-fsanitize=undefined" COMP_HAS_UBSAN) + if(NOT COMP_HAS_UBSAN) + message(FATAL_ERROR "This compiler does not support Undefined Behavior Sanitizer. Disable it.") + endif() + + check_cxx_compiler_flag("-fsanitize=float-divide-by-zero" COMP_HAS_FSAN_FLOAT_DIVIDE_BY_ZERO) + check_cxx_compiler_flag("-fsanitize=unsigned-integer-overflow" COMP_HAS_FSAN_UNSIGNED_INTEGER_OVERFLOW) #Unlike signed integer overflow, this is not undefined behavior, but it is often unintentional. + #check_cxx_compiler_flag("-fsanitize=implicit-conversion" COMP_HAS_FSAN_IMPLICIT_CONVERSION) + #check_cxx_compiler_flag("-fsanitize=local-bounds" COMP_HAS_FSAN_LOCAL_BOUNDS) + check_cxx_compiler_flag("-fno-sanitize=enum" COMP_HAS_FSAN_NO_ENUM) + endif() + + if(${USE_LSAN}) + # Compiler option flags. Sanitizers related (LSAN). + message(STATUS "-- Compilation options (Leak Sanitizer):") + + check_cxx_compiler_flag("-fsanitize=leak" COMP_HAS_LSAN) + if(NOT COMP_HAS_LSAN) + message(FATAL_ERROR "This compiler does not support Leak Sanitizer. Disable it.") + endif() + endif() + + if(${USE_MSAN}) + # Compiler option flags. Sanitizers related (UBSAN). + + message(STATUS "-- Compilation options (Memory Behavior Sanitizer):") + check_cxx_compiler_flag("-fsanitize=memory" COMP_HAS_MSAN) + if(NOT COMP_HAS_MSAN) + message(FATAL_ERROR "This compiler does not support Memory Sanitizer. Disable it.") + endif() + + check_cxx_compiler_flag("-fsanitize=memory-track-origins" COMP_HAS_F_SANITIZE_MEMORY_TRACK_ORIGINS) + check_cxx_compiler_flag("-fPIE" COMP_HAS_F_PIE) + endif() + + if(USE_COMPILER_HARDENING_OPTIONS) + message(STATUS "-- Compilation options (code hardening):") + # Compiler option flags. Other sanitizers or code hardening. + if(NOT USE_ASAN) + check_cxx_compiler_flag("-fsanitize=safe-stack" COMP_HAS_F_SANITIZE_SAFE_STACK) # Can't be used with asan! + endif() + check_cxx_compiler_flag("-fcf-protection=full" COMP_HAS_FCF_PROTECTION_FULL) + check_cxx_compiler_flag("-fstack-check" COMP_HAS_F_STACK_CHECK) + check_cxx_compiler_flag("-fstack-protector-all" COMP_HAS_F_STACK_PROTECTOR_ALL) + check_cxx_compiler_flag("-fstack-protector-strong" COMP_HAS_F_STACK_PROTECTOR_STRONG) + check_cxx_compiler_flag("-fstack-protector" COMP_HAS_F_STACK_PROTECTOR) + check_cxx_compiler_flag("-fstack-clash-protection" COMP_HAS_F_STACK_CLASH_PROTECTION) + #Flags GCC specific? + check_cxx_compiler_flag("-fvtable-verify=preinit" COMP_HAS_F_VTABLE_VERIFY_PREINIT) + check_cxx_compiler_flag("-fharden-control-flow-redundancy" COMP_HAS_F_HARDEN_CFR) + check_cxx_compiler_flag("-fhardcfr-check-exceptions" COMP_HAS_F_HARDCFR_CHECK_EXCEPTIONS) + #check_cxx_compiler_flag("" COMP_HAS_) + endif() # Compiler warning flags. message(STATUS "-- Compilation options (warnings):") @@ -65,7 +114,6 @@ if (NOT MSVC) #check_cxx_compiler_flag("" COMP_HAS_) # Compiler warning flags. TODO: To be evaluated... - # -Wshadow # -Wfree-nonheap-object (good but false positive warnings on GCC?) # -Wcast-align=strict # -Wcast-user-defined @@ -86,15 +134,13 @@ if (NOT MSVC) check_cxx_compiler_flag("-Wno-deprecated-declarations" COMP_HAS_WNO_DEPRECATED_DECLARATIONS) #check_cxx_compiler_flag("-Wno-unknown-pragmas" COMP_HAS_) #check_cxx_compiler_flag("" COMP_HAS_) - -else (NOT MSVC) +else(NOT MSVC) # Compiler warning flags (MSVC). message(STATUS "-- Compilation options (MSVC):") check_cxx_compiler_flag("/Wd5105" COMP_HAS_DEFINE_MACRO_EXPANSION) # False positive warning, maybe even a MSVC bug. #check_cxx_compiler_flag("" COMP_HAS_) endif() - # ---- Append options into some lists. # ---- GCC/Clang @@ -103,47 +149,85 @@ if(COMP_HAS_FNO_EXPENSIVE_OPTIMIZATIONS) list(APPEND checked_compiler_options "-fno-expensive-optimizations") endif() -if(COMP_HAS_FSAN_CFI) - list(APPEND checked_compiler_options_asan "-fsanitize-cfi") +if(COMP_HAS_ASAN) + list(APPEND checked_compiler_options_asan "-fsanitize=address") + if(COMP_HAS_FSAN_CFI) + list(APPEND checked_compiler_options_asan "-fsanitize-cfi") + endif() + if(COMP_HAS_FSAN_ADDRESS_USE_AFTER_SCOPE) + list(APPEND checked_compiler_options_asan "-fsanitize-address-use-after-scope") + endif() + if(COMP_HAS_FSAN_PTR_COMP) + list(APPEND checked_compiler_options_asan "-fsanitize=pointer-compare") + endif() + if(COMP_HAS_FSAN_PTR_SUB) + list(APPEND checked_compiler_options_asan "-fsanitize=pointer-subtract") + endif() + if(COMP_HAS_FSAN_TRAP_ALL) + list(APPEND checked_compiler_options_asan "-fsanitize-trap=all") + endif() endif() -if(COMP_HAS_FSAN_ADDRESS_USE_AFTER_SCOPE) - list(APPEND checked_compiler_options_asan "-fsanitize-address-use-after-scope") -endif() -if(COMP_HAS_FSAN_PTR_COMP) - list(APPEND checked_compiler_options_asan "-fsanitize=pointer-compare" ) + +if(COMP_HAS_UBSAN) + list(APPEND checked_compiler_options_ubsan "-fsanitize=undefined") + if(COMP_HAS_FSAN_FLOAT_DIVIDE_BY_ZERO) + list(APPEND checked_compiler_options_ubsan "-fsanitize=float-divide-by-zero") + endif() + if(COMP_HAS_FSAN_UNSIGNED_INTEGER_OVERFLOW) + list(APPEND checked_compiler_options_ubsan "-fsanitize=unsigned-integer-overflow") + endif() + if(COMP_HAS_FSAN_IMPLICIT_CONVERSION) + list(APPEND checked_compiler_options_ubsan "-fsanitize=implicit-conversion") + endif() + if(COMP_HAS_FSAN_NO_ENUM) + list(APPEND checked_compiler_options_ubsan "-fno-sanitize=enum") + endif() + if(COMP_HAS_FSAN_LOCAL_BOUNDS) + list(APPEND checked_compiler_options_ubsan "-fsanitize=local-bounds") + endif() endif() -if(COMP_HAS_FSAN_PTR_SUB) - list(APPEND checked_compiler_options_asan "-fsanitize=pointer-subtract" ) + +if(COMP_HAS_LSAN) + list(APPEND checked_compiler_options_lsan "-fsanitize=leak") endif() -if(COMP_HAS_FSAN_TRAP_ALL) - list(APPEND checked_compiler_options_asan "-fsanitize-trap=all" ) + +if(COMP_HAS_MSAN) + list(APPEND checked_compiler_options_msan "-fsanitize=memory") + if(COMP_HAS_F_SANITIZE_MEMORY_TRACK_ORIGINS) + list(APPEND checked_compiler_options_msan "-fsanitize=memory-track-origins") + endif() + if(COMP_HAS_F_PIE) + list(APPEND checked_compiler_options_msan "-fPIE") + endif() endif() +if(COMP_HAS_F_SANITIZE_SAFE_STACK) + list(APPEND checked_compiler_options_sanitize_harden "-fsanitize=safe-stack") +endif() if(COMP_HAS_FCF_PROTECTION_FULL) - list(APPEND checked_compiler_options_sanitize_other "-fcf-protection=full") + list(APPEND checked_compiler_options_sanitize_harden "-fcf-protection=full") endif() if(COMP_HAS_F_STACK_CHECK) - list(APPEND checked_compiler_options_sanitize_other "-fstack-check") + list(APPEND checked_compiler_options_sanitize_harden "-fstack-check") endif() if(COMP_HAS_F_STACK_PROTECTOR_ALL) - list(APPEND checked_compiler_options_sanitize_other "-fstack-protector-all") + list(APPEND checked_compiler_options_sanitize_harden "-fstack-protector-all") elseif(COMP_HAS_F_STACK_PROTECTOR_STRONG) - list(APPEND checked_compiler_options_sanitize_other "-fstack-protector-strong") + list(APPEND checked_compiler_options_sanitize_harden "-fstack-protector-strong") elseif(COMP_HAS_F_STACK_PROTECTOR) - list(APPEND checked_compiler_options_sanitize_other "-fstack-protector") + list(APPEND checked_compiler_options_sanitize_harden "-fstack-protector") endif() if(COMP_HAS_F_STACK_CLASH_PROTECTION) - list(APPEND checked_compiler_options_sanitize_other "-fstack-clash-protection") + list(APPEND checked_compiler_options_sanitize_harden "-fstack-clash-protection") endif() if(COMP_HAS_F_VTABLE_VERIFY_PREINIT) - list(APPEND checked_compiler_options_sanitize_other "-fvtable-verify=preinit") + list(APPEND checked_compiler_options_sanitize_harden "-fvtable-verify=preinit") endif() if(COMP_HAS_F_HARDEN_CFR) - list(APPEND checked_compiler_options_sanitize_other "-fharden-control-flow-redundancy") + list(APPEND checked_compiler_options_sanitize_harden "-fharden-control-flow-redundancy") endif() if(COMP_HAS_F_HARDCFR_CHECK_EXCEPTIONS) - list( - APPEND checked_compiler_options_sanitize_other "-fhardcfr-check-exceptions") + list(APPEND checked_compiler_options_sanitize_harden "-fhardcfr-check-exceptions") endif() if(COMP_HAS_W_USELESS_CAST) @@ -250,7 +334,6 @@ if( unset(COMPILER_SUPPORTS_NULL_DEREFERENCE CACHE) endif() - # ---- #[[ @@ -258,18 +341,37 @@ set(checked_compiler_options) set(checked_compiler_options_asan) #set(checked_compiler_options_ubsan) #set(checked_compiler_options_lsan) -set(checked_compiler_options_sanitize_other) +set(checked_compiler_options_sanitize_harden) set(checked_compiler_warnings) set(checked_compiler_warnings_disabled) set(checked_compiler_flags_msvc) ]] -message(STATUS "Adding the following conditional compiler options: ${checked_compiler_options}") -message(STATUS "Adding the following conditional compiler options for ASan: ${checked_compiler_options_asan}") -message(STATUS "Adding the following conditional compiler options for sanitizers: ${checked_compiler_options_sanitize_other}") -message(STATUS "Adding the following conditional compiler warnings: ${checked_compiler_warnings}") -message(STATUS "Adding the following conditional compiler warnings ignore options: ${checked_compiler_warnings_disabled}") +message(STATUS "Adding the following conditional compiler options: ${checked_compiler_options}.") +if(COMP_HAS_ASAN) + message(STATUS "Adding the following conditional compiler options for ASan: ${checked_compiler_options_asan}.") +endif() +if(COMP_HAS_UBSAN) + message(STATUS "Adding the following conditional compiler options for UBSan: ${checked_compiler_options_ubsan}.") +endif() +if(COMP_HAS_LSAN) + message(STATUS "Adding the following conditional compiler options for LSan: ${checked_compiler_options_lsan}.") +endif() + +if(COMP_HAS_MSAN) + message(STATUS "Adding the following conditional compiler options for MSan: ${checked_compiler_options_msan}.") +endif() + +message( + STATUS + "Adding the following conditional compiler options for hardening: ${checked_compiler_options_sanitize_harden}." +) +message(STATUS "Adding the following conditional compiler warnings: ${checked_compiler_warnings}.") +message( + STATUS + "Adding the following conditional compiler warnings ignore options: ${checked_compiler_warnings_disabled}." +) if(MSVC) - message(STATUS "Adding the following conditional compiler options: ${checked_compiler_flags_msvc}") + message(STATUS "Adding the following conditional compiler options: ${checked_compiler_flags_msvc}.") endif() From 4446409a08fe74e414097de0e68f12c17e690dd5 Mon Sep 17 00:00:00 2001 From: cbnolok Date: Sat, 21 Sep 2024 18:35:21 +0200 Subject: [PATCH 57/86] Reordered stypecast.h, moved some inlined CSString methods to the .cpp file. --- src/common/CException.h | 2 +- src/common/CLog.h | 5 +- src/common/sphere_library/CSString.cpp | 59 ++++++++++++ src/common/sphere_library/CSString.h | 106 +++++----------------- src/common/sphere_library/stypecast.h | 121 +++++++++++++------------ src/sphere/threads.cpp | 7 +- 6 files changed, 155 insertions(+), 145 deletions(-) diff --git a/src/common/CException.h b/src/common/CException.h index 7f2f9a0c8..a767cc666 100644 --- a/src/common/CException.h +++ b/src/common/CException.h @@ -6,7 +6,7 @@ #ifndef _INC_CEXCEPTION_H #define _INC_CEXCEPTION_H -#include "../sphere/threads.h" +//#include "../sphere/threads.h" #include "CLog.h" // ------------------------------------------------------------------- diff --git a/src/common/CLog.h b/src/common/CLog.h index f644e22fe..a362e5ccc 100644 --- a/src/common/CLog.h +++ b/src/common/CLog.h @@ -9,7 +9,10 @@ #include "sphere_library/CSFileText.h" #include "sphere_library/CSTime.h" #include "../sphere/ConsoleInterface.h" -#include + +namespace std { +class exception; // Forward declaration +} // ----------------------------- // CEventLog diff --git a/src/common/sphere_library/CSString.cpp b/src/common/sphere_library/CSString.cpp index 3e96295a9..8ae01f185 100644 --- a/src/common/sphere_library/CSString.cpp +++ b/src/common/sphere_library/CSString.cpp @@ -398,6 +398,65 @@ void CSString::FormatU64Val(uint64 uiVal) // CSString:: String operations +tchar CSString::GetAt(int nIndex) const +{ + ASSERT(nIndex >= 0); + ASSERT(nIndex <= m_iLength); // Allow to get the null char. + return m_pchData[nIndex]; +} + +tchar& CSString::ReferenceAt(int nIndex) +{ + ASSERT(nIndex >= 0); + ASSERT(nIndex < m_iLength); + return m_pchData[nIndex]; +} + +void CSString::MakeUpper() noexcept +{ + _strupr(m_pchData); +} + +void CSString::MakeLower() noexcept +{ + _strlwr(m_pchData); +} + +void CSString::Reverse() noexcept +{ + Str_Reverse(m_pchData); +} + +int CSString::Compare(lpctstr pStr) const noexcept +{ + return strcmp(m_pchData, pStr); +} + +int CSString::CompareNoCase(lpctstr pStr) const noexcept +{ + return strcmpi(m_pchData, pStr); +} + +int CSString::indexOf(tchar c) noexcept +{ + return indexOf(c, 0); +} + +int CSString::indexOf(const CSString& str) noexcept +{ + return indexOf(str, 0); +} + +int CSString::lastIndexOf(tchar c) noexcept +{ + return lastIndexOf(c, 0); +} + +int CSString::lastIndexOf(const CSString& str) noexcept +{ + return lastIndexOf(str, 0); +} + int CSString::indexOf(tchar c, int offset) noexcept { if ((offset < 0) || !IsValid()) diff --git a/src/common/sphere_library/CSString.h b/src/common/sphere_library/CSString.h index d68e70329..ecd7737b4 100644 --- a/src/common/sphere_library/CSString.h +++ b/src/common/sphere_library/CSString.h @@ -11,8 +11,6 @@ #endif // __MINGW32__ #include // needed for va_list -#include "sstring.h" - /** * @brief Custom String implementation. */ @@ -195,7 +193,7 @@ class CSString * @return character in position nIndex. */ [[nodiscard]] - inline tchar GetAt(int nIndex) const; + tchar GetAt(int nIndex) const; /** * @brief Gets the reference to character a specified position (0 based). @@ -203,7 +201,7 @@ class CSString * @return reference to character in position nIndex. */ [[nodiscard]] - inline tchar& ReferenceAt(int nIndex); + tchar& ReferenceAt(int nIndex); /** * @brief Puts a character in a specified position (0 based). @@ -273,17 +271,17 @@ class CSString /** * @brief Changes the capitalization of CSString to upper. */ - inline void MakeUpper() noexcept; + void MakeUpper() noexcept; /** * @brief Changes the capitalization of CSString to lower. */ - inline void MakeLower() noexcept; + void MakeLower() noexcept; /** * @brief Reverses the CSString. */ - inline void Reverse() noexcept; + void Reverse() noexcept; ///@} @@ -492,7 +490,7 @@ class CSString * @return <0 if the first character that not match has lower value in CSString than in pStr. 0 if the contents of both are equal. >0 if the first character that does not match has greater value in CSString than pStr. */ [[nodiscard]] - inline int Compare(lpctstr pStr) const noexcept; + int Compare(lpctstr pStr) const noexcept; /** * @brief Compares the CSString to string pStr (case insensitive) (_strcmpi wrapper). @@ -505,7 +503,7 @@ class CSString * @return <0 if the first character that not match has lower value in CSString than in pStr. 0 if the contents of both are equal. >0 if the first character that does not match has greater value in CSString than pStr. */ [[nodiscard]] - inline int CompareNoCase(lpctstr pStr) const noexcept; + int CompareNoCase(lpctstr pStr) const noexcept; /** * @brief Gets the internal pointer. @@ -523,7 +521,7 @@ class CSString * @return position of the character in CSString if any, -1 otherwise. */ [[nodiscard]] - inline int indexOf(tchar c) noexcept; + int indexOf(tchar c) noexcept; /** * @brief Look for the first occurence of c in CSString from a position. @@ -540,7 +538,7 @@ class CSString * @return position of the substring in CSString if any, -1 otherwise. */ [[nodiscard]] - inline int indexOf(const CSString& str) noexcept; + int indexOf(const CSString& str) noexcept; /** * @brief Look for the first occurence of a substring in CSString from a position. @@ -557,7 +555,7 @@ class CSString * @return position of the character in CSString if any, -1 otherwise. */ [[nodiscard]] - inline int lastIndexOf(tchar c) noexcept; + int lastIndexOf(tchar c) noexcept; /** * @brief Look for the last occurence of c in CSString from a position to the end. @@ -574,7 +572,7 @@ class CSString * @return position of the substring in CSString if any, -1 otherwise. */ [[nodiscard]] - inline int lastIndexOf(const CSString& str) noexcept; + int lastIndexOf(const CSString& str) noexcept; /** * @brief Look for the last occurence of a substring in CSString from a position to the end. @@ -605,7 +603,12 @@ CSString::CSString(CSString&& s) noexcept : *this = std::move(s); // Call the move assignment operator } -CSString CSString::EmptyNew() +CSString::operator lpctstr() const noexcept +{ + return GetBuffer(); +} + +CSString CSString::EmptyNew() // static { return CSString(false); } @@ -625,90 +628,27 @@ int CSString::GetCapacity() const noexcept return m_iMaxLength; } -tchar CSString::operator[](int nIndex) const -{ - return GetAt(nIndex); -} - -tchar& CSString::operator[](int nIndex) -{ - return ReferenceAt(nIndex); -} - -tchar CSString::GetAt(int nIndex) const -{ - ASSERT(nIndex >= 0); - ASSERT(nIndex <= m_iLength); // Allow to get the null char. - return m_pchData[nIndex]; -} - -tchar& CSString::ReferenceAt(int nIndex) -{ - ASSERT(nIndex >= 0); - ASSERT(nIndex < m_iLength); - return m_pchData[nIndex]; -} - -void CSString::MakeUpper() noexcept -{ - _strupr(m_pchData); -} - -void CSString::MakeLower() noexcept -{ - _strlwr(m_pchData); -} - -void CSString::Reverse() noexcept -{ - Str_Reverse(m_pchData); -} - -CSString::operator lpctstr() const noexcept -{ - return GetBuffer(); -} - -int CSString::Compare(lpctstr pStr) const noexcept -{ - return strcmp(m_pchData, pStr); -} - -int CSString::CompareNoCase(lpctstr pStr) const noexcept -{ - return strcmpi(m_pchData, pStr); -} - lpctstr CSString::GetBuffer() const noexcept { - return m_pchData; + return m_pchData; } /* lptstr CSString::GetBuffer() noexcept { - return m_pchData; + return m_pchData; } */ -int CSString::indexOf(tchar c) noexcept -{ - return indexOf(c, 0); -} - -int CSString::indexOf(const CSString& str) noexcept +tchar CSString::operator[](int nIndex) const { - return indexOf(str, 0); + return GetAt(nIndex); } -int CSString::lastIndexOf(tchar c) noexcept +tchar& CSString::operator[](int nIndex) { - return lastIndexOf(c, 0); + return ReferenceAt(nIndex); } -int CSString::lastIndexOf(const CSString& str) noexcept -{ - return lastIndexOf(str, 0); -} #endif // _INC_CSSTRING_H diff --git a/src/common/sphere_library/stypecast.h b/src/common/sphere_library/stypecast.h index d450be93b..ebbade7cb 100644 --- a/src/common/sphere_library/stypecast.h +++ b/src/common/sphere_library/stypecast.h @@ -1,6 +1,7 @@ #ifndef _INC_STYPECAST_H #define _INC_STYPECAST_H +//#include "../CLog.h" #include #include #include @@ -71,54 +72,6 @@ constexpr Tout enum_alias_cast(const Tin a) noexcept } -/* Unsigned (and size_t) to signed, clamping. */ - -[[nodiscard]] constexpr -int8 i8_from_u8_clamping(const uint8 a) noexcept -{ - return (a > (uint8_t)std::numeric_limits::max()) ? std::numeric_limits::max() : (int8_t)a; -} - -[[nodiscard]] constexpr -int16 i16_from_u16_clamping(const uint16 a) noexcept -{ - return (a > (uint16_t)std::numeric_limits::max()) ? std::numeric_limits::max() : (int16_t)a; -} - -[[nodiscard]] constexpr -int32 i32_from_u32_clamping(const uint32 a) noexcept -{ - return (a > (uint32_t)std::numeric_limits::max()) ? std::numeric_limits::max() : (int32_t)a; -} - -[[nodiscard]] constexpr -int64 i64_from_u64_clamping(const uint64 a) noexcept -{ - return (a > (uint64_t)std::numeric_limits::max()) ? std::numeric_limits::max() : (int64_t)a; -} - -[[nodiscard]] constexpr -int32 i32_from_usize_clamping(const size_t a) noexcept -{ - return (a > (size_t)std::numeric_limits::max()) ? std::numeric_limits::max() : (int32_t)a; -} - -[[nodiscard]] constexpr -int64 i64_from_usize_clamping(const size_t a) noexcept -{ - return (a > (size_t)std::numeric_limits::max()) ? std::numeric_limits::max() : (int64_t)a; -} - -[[nodiscard]] constexpr -uint32 u32_from_usize_clamping(const size_t a) noexcept -{ - if constexpr (sizeof(size_t) == 8) - return (a > (size_t)std::numeric_limits::max()) ? std::numeric_limits::max() : (uint32_t)a; - else - return a; -} - - /* Promotion and narrowing of numbers to a same sign greater/smaller data type */ // Explicitly promote to a larger type or narrow to a smaller type, instead of inattentive raw casts. @@ -456,11 +409,59 @@ uint32 usize_narrow_u32_checked(const size_t a) } +/* Unsigned (and size_t) to signed, clamping. */ + +[[nodiscard]] constexpr + int8 i8_from_u8_clamping(const uint8 a) noexcept +{ + return (a > (uint8_t)std::numeric_limits::max()) ? std::numeric_limits::max() : (int8_t)a; +} + +[[nodiscard]] constexpr + int16 i16_from_u16_clamping(const uint16 a) noexcept +{ + return (a > (uint16_t)std::numeric_limits::max()) ? std::numeric_limits::max() : (int16_t)a; +} + +[[nodiscard]] constexpr + int32 i32_from_u32_clamping(const uint32 a) noexcept +{ + return (a > (uint32_t)std::numeric_limits::max()) ? std::numeric_limits::max() : (int32_t)a; +} + +[[nodiscard]] constexpr + int64 i64_from_u64_clamping(const uint64 a) noexcept +{ + return (a > (uint64_t)std::numeric_limits::max()) ? std::numeric_limits::max() : (int64_t)a; +} + +[[nodiscard]] constexpr + int32 i32_from_usize_clamping(const size_t a) noexcept +{ + return (a > (size_t)std::numeric_limits::max()) ? std::numeric_limits::max() : (int32_t)a; +} + +[[nodiscard]] constexpr + int64 i64_from_usize_clamping(const size_t a) noexcept +{ + return (a > (size_t)std::numeric_limits::max()) ? std::numeric_limits::max() : (int64_t)a; +} + +[[nodiscard]] constexpr + uint32 u32_from_usize_clamping(const size_t a) noexcept +{ + if constexpr (sizeof(size_t) == 8) + return (a > (size_t)std::numeric_limits::max()) ? std::numeric_limits::max() : (uint32_t)a; + else + return a; +} + + /* Unsigned (and size_t) to signed, checked for overflows. */ // Convert an 8 bits unsigned value to signed and ASSERT (because you're reasonably sure but not absolutely certain) that it will fit into its signed datatype counterpart (unsigned variables can store greater values than signed ones). [[nodiscard]] inline -int8 i8_from_u8_checked(const uint8 a) // not clamping/capping + int8 i8_from_u8_checked(const uint8 a) // not clamping/capping { ASSERT(a <= (uint8_t)std::numeric_limits::max()); return static_cast(a); @@ -469,7 +470,7 @@ template int8 i8_from_u8_checked(T) = delete; // disable implicit t // Convert a 16 bits unsigned value to signed and ASSERT (because you're reasonably sure but not absolutely certain) that it will fit into its signed datatype counterpart (unsigned variables can store greater values than signed ones). [[nodiscard]] inline -int16 i16_from_u16_checked(const uint16 a) // not clamping/capping + int16 i16_from_u16_checked(const uint16 a) // not clamping/capping { ASSERT(a <= (uint16_t)std::numeric_limits::max()); return static_cast(a); @@ -477,7 +478,7 @@ int16 i16_from_u16_checked(const uint16 a) // not clamping/capping template int16 i16_from_u16_checked(T) = delete; // disable implicit type conversion for the input argument [[nodiscard]] inline -int16 i16_from_u32_checked(const uint32 a) // not clamping/capping + int16 i16_from_u32_checked(const uint32 a) // not clamping/capping { ASSERT(a <= (uint32_t)std::numeric_limits::max()); return static_cast(a); @@ -485,7 +486,7 @@ int16 i16_from_u32_checked(const uint32 a) // not clamping/capping template int16 i16_from_u32_checked(T) = delete; // disable implicit type conversion for the input argument [[nodiscard]] inline -int16 i16_from_u64_checked(const uint64 a) // not clamping/capping + int16 i16_from_u64_checked(const uint64 a) // not clamping/capping { ASSERT(a <= (uint64_t)std::numeric_limits::max()); return static_cast(a); @@ -494,7 +495,7 @@ template int16 i16_from_u64_checked(T) = delete; // disable implici // Convert a 32 bits unsigned value to signed and ASSERT (because you're reasonably sure but not absolutely certain) that it will fit into its signed datatype counterpart (unsigned variables can store greater values than signed ones). [[nodiscard]] inline -int32 i32_from_u32_checked(const uint32 a) // not clamping/capping + int32 i32_from_u32_checked(const uint32 a) // not clamping/capping { ASSERT(a <= (uint32_t)std::numeric_limits::max()); return static_cast(a); @@ -502,7 +503,7 @@ int32 i32_from_u32_checked(const uint32 a) // not clamping/capping template int32 i32_from_u32_checked(T) = delete; // disable implicit type conversion for the input argument [[nodiscard]] inline -int32 i32_from_u64_checked(const uint64 a) // not clamping/capping + int32 i32_from_u64_checked(const uint64 a) // not clamping/capping { ASSERT(a <= (uint64_t)std::numeric_limits::max()); return static_cast(a); @@ -511,7 +512,7 @@ template int32 i32_from_u64_checked(T) = delete; // disable implici // Convert a 64 bits unsigned value to signed and ASSERT (because you're reasonably sure but not absolutely certain) that it will fit into its signed datatype counterpart (unsigned variables can store greater values than signed ones). [[nodiscard]] inline -int64 i64_from_u64_checked(const uint64 a) // not clamping/capping + int64 i64_from_u64_checked(const uint64 a) // not clamping/capping { ASSERT(a <= (uint64_t)std::numeric_limits::max()); return static_cast(a); @@ -521,7 +522,7 @@ template int64 i64_from_u64_checked(T) = delete; // disable implici // size_t conversions [[nodiscard]] inline -int8 i8_from_usize_checked(const size_t a) // not clamping/capping + int8 i8_from_usize_checked(const size_t a) // not clamping/capping { #if SIZE_MAX == UINT64_MAX return n64_narrow_n8_checked(a); @@ -535,7 +536,7 @@ template int8 i8_from_usize_checked(T) = delete; // disable implici [[nodiscard]] inline -int16 i16_from_usize_checked(const size_t a) // not clamping/capping + int16 i16_from_usize_checked(const size_t a) // not clamping/capping { #if SIZE_MAX == UINT64_MAX return n64_narrow_n16_checked(a); @@ -548,7 +549,7 @@ int16 i16_from_usize_checked(const size_t a) // not clamping/capping template int16 i16_from_usize_checked(T) = delete; // disable implicit type conversion for the input argument [[nodiscard]] inline -int32 i32_from_usize_checked(const size_t a) // not clamping/capping + int32 i32_from_usize_checked(const size_t a) // not clamping/capping { #if SIZE_MAX == UINT64_MAX return i32_from_u32_clamping(n64_narrow_n32_checked(a)); @@ -561,7 +562,7 @@ int32 i32_from_usize_checked(const size_t a) // not clamping/capping template int32 i32_from_usize_checked(T) = delete; // disable implicit type conversion for the input argument [[nodiscard]] inline -int64 i64_from_usize_checked(const size_t a) // not clamping/capping + int64 i64_from_usize_checked(const size_t a) // not clamping/capping { #if SIZE_MAX == UINT64_MAX return i64_from_u64_checked(n_alias_cast(a)); @@ -574,4 +575,6 @@ int64 i64_from_usize_checked(const size_t a) // not clamping/capping template int64 i64_from_usize_checked(T) = delete; // disable implicit type conversion for the input argument + + #endif // _INC_STYPECAST_H diff --git a/src/sphere/threads.cpp b/src/sphere/threads.cpp index 201514c2a..5a319fdf9 100644 --- a/src/sphere/threads.cpp +++ b/src/sphere/threads.cpp @@ -114,10 +114,11 @@ void IThread::setThreadName(const char* name) auto athr = static_cast(ThreadHolder::get().current()); ASSERT(athr); +#ifdef _DEBUG g_Log.Event(LOGF_CONSOLE_ONLY|LOGM_DEBUG|LOGL_EVENT, "Setting thread (ThreadHolder ID %d, internal name '%s') system name: '%s'.\n", athr->m_threadHolderId, athr->getName(), name_trimmed); - +#endif athr->overwriteInternalThreadName(name_trimmed); } @@ -278,6 +279,7 @@ void ThreadHolder::push(IThread *thread) noexcept RaiseImmediateAbort(); } +#ifdef _DEBUG if (dynamic_cast(thread)) { // Too early in the init process to use the console... @@ -290,6 +292,7 @@ void ThreadHolder::push(IThread *thread) noexcept "Registered thread '%s' with ThreadHolder ID %d.\n", thread->getName(), thread->m_threadHolderId); } +#endif } /* @@ -712,9 +715,11 @@ void AbstractThread::onStart() if (isActive()) // This thread has actually been spawned and the code is executing on a different thread setThreadName(getName()); +#ifdef _DEBUG g_Log.Event(LOGM_DEBUG|LOGL_EVENT|LOGF_CONSOLE_ONLY, "Started thread '%s' with ThreadHolder ID %d and system ID %" PRIu64 ".\n", getName(), m_threadHolderId, (uint64)m_threadSystemId); +#endif } void AbstractThread::setPriority(IThread::Priority pri) From e3ba11d7ec360555a397afc56a9f591f449bcff0 Mon Sep 17 00:00:00 2001 From: cbnolok Date: Sat, 21 Sep 2024 18:35:30 +0200 Subject: [PATCH 58/86] Updated .clang-format --- .clang-format | 30 +++++++++++++++++++++++------- 1 file changed, 23 insertions(+), 7 deletions(-) diff --git a/.clang-format b/.clang-format index b993d79f0..7e32248d7 100644 --- a/.clang-format +++ b/.clang-format @@ -13,9 +13,14 @@ ColumnLimit: 160 AlignAfterOpenBracket: AlwaysBreak AlignConsecutiveAssignments: true AlignConsecutiveDeclarations: false -#AlignEscapedNewlinesLeft: false -AlignTrailingComments: true - +#AlignConsecutiveTableGenDefinitionColons: +# Enabled: true +# AcrossEmptyLines: true +# AcrossComments: false +AlignEscapedNewlines: Left # LeftWithLastLine # Right +AlignTrailingComments: + Kind: Always + OverEmptyLines: 1 DerivePointerAlignment: false PointerAlignment: Right @@ -48,12 +53,15 @@ BraceWrapping: Cpp11BracedListStyle: false ##-- Line breaks -AlwaysBreakAfterDefinitionReturnType: None +#AllowBreakBeforeNoexceptSpecifier: OnlyWithParen +AlwaysBreakAfterDefinitionReturnType: All AlwaysBreakAfterReturnType: None AlwaysBreakBeforeMultilineStrings: true +BreakAfterAttributes: Always AlwaysBreakTemplateDeclarations: true BreakAfterJavaFieldAnnotations: false BreakBeforeBinaryOperators: None +BreakBeforeConceptDeclarations: Always BreakConstructorInitializers: AfterColon #BreakInheritanceList: AfterColon BreakBeforeTernaryOperators: false @@ -70,6 +78,8 @@ LambdaBodyIndentation: Signature NamespaceIndentation: Inner ##-- Spaces in/between statements/etc +MaxEmptyLinesToKeep: 2 +SeparateDefinitionBlocks: Always SpaceAfterCStyleCast: false SpaceAfterTemplateKeyword: false #SpaceAroundPointerQualifiers: Left @@ -85,19 +95,25 @@ SpacesInContainerLiterals: false SpacesInParentheses: false SpacesInSquareBrackets: false + +##-- Code sections/blocks +#MacroBlockBegin: [regex -> EXC_TRY...] +#MacroBlockEnd: +FixNamespaceComments: true +ShortNamespaceLines: 2 +#StatementMacros: [-> ASSERT?] + ##-- Misc AllowAllParametersOfDeclarationOnNextLine: true AccessModifierOffset: -4 BinPackArguments: false BinPackParameters: false -BreakAfterAttributes: Always -ExperimentalAutoDetectBinPacking: false ConstructorInitializerAllOnOneLineOrOnePerLine: false DisableFormat: false +ExperimentalAutoDetectBinPacking: false InsertNewlineAtEOF: true KeepEmptyLinesAtTheStartOfBlocks: false ReflowComments: false -SeparateDefinitionBlocks: Always #-- Include order #IncludeIsMainRegex: '$?' From 639368611da5776e8b3f6a42064c58bab0801531 Mon Sep 17 00:00:00 2001 From: cbnolok Date: Mon, 23 Sep 2024 18:28:33 +0200 Subject: [PATCH 59/86] Added some static qualifiers, moved some functions from spheresvr.cpp to CServer.cpp --- src/common/CDataBase.cpp | 4 +- src/common/CException.cpp | 14 +- src/common/CExpression.cpp | 6 +- src/common/CFloatMath.cpp | 2 +- src/common/crypto/CBCrypt.cpp | 6 +- src/common/sqlite/SQLite.cpp | 8 +- src/common/sqlite/SQLite.h | 6 +- src/game/CServer.cpp | 297 +++++++++++++++++++++++++++++++++ src/game/CServerDef.cpp | 6 +- src/game/CWorld.cpp | 10 +- src/game/chars/CChar.cpp | 6 +- src/game/spheresvr.cpp | 303 +--------------------------------- src/game/triggers.cpp | 20 +-- src/network/PingServer.cpp | 2 +- src/network/PingServer.h | 5 +- src/sphere/asyncdb.h | 3 + src/sphere/threads.cpp | 1 + 17 files changed, 350 insertions(+), 349 deletions(-) diff --git a/src/common/CDataBase.cpp b/src/common/CDataBase.cpp index 3266a643e..4f56d3a34 100644 --- a/src/common/CDataBase.cpp +++ b/src/common/CDataBase.cpp @@ -2,15 +2,13 @@ #include "../game/CServer.h" #include "../game/CServerTime.h" #include "../sphere/asyncdb.h" -#include "resource/sections/CResourceNamedDef.h" +#include "resource/sections/CResourceNamedDef.h" // Needed because it was only forward declared. #include "CLog.h" #include "CException.h" #include "CExpression.h" #include "CScriptTriggerArgs.h" #include "CDataBase.h" -extern CDataBaseAsyncHelper g_asyncHdb; - CDataBase::CDataBase() { diff --git a/src/common/CException.cpp b/src/common/CException.cpp index a29834e7c..8c92641b1 100644 --- a/src/common/CException.cpp +++ b/src/common/CException.cpp @@ -70,7 +70,7 @@ void SetAbortImmediate(bool on) noexcept { *_GetAbortImmediate() = on; } -bool IsAbortImmediate() noexcept +static bool IsAbortImmediate() noexcept { return *_GetAbortImmediate(); } @@ -225,7 +225,7 @@ void Assert_Fail( lpctstr pExp, lpctstr pFile, long long llLine ) throw CAssert(LOGL_CRIT, pExp, pFile, llLine); } -void _cdecl Sphere_Purecall_Handler() +static void _cdecl Sphere_Purecall_Handler() { // catch this special type of C++ exception as well. Assert_Fail("purecall", "unknown", 1); @@ -273,7 +273,7 @@ void SetExceptionTranslator() } #ifndef _WIN32 -void _cdecl Signal_Hangup(int sig = 0) noexcept // If shutdown is initialized +static void _cdecl Signal_Hangup(int sig = 0) noexcept // If shutdown is initialized { UnreferencedParameter(sig); @@ -292,7 +292,7 @@ void _cdecl Signal_Hangup(int sig = 0) noexcept // If shutdown is initialized g_Serv.SetExitFlag(SIGHUP); } -void _cdecl Signal_Terminate(int sig = 0) noexcept // If shutdown is initialized +static void _cdecl Signal_Terminate(int sig = 0) noexcept // If shutdown is initialized { g_Log.Event(LOGL_FATAL, "Server Unstable: %s signal received\n", strsignal(sig)); @@ -346,7 +346,7 @@ void _cdecl Signal_Terminate(int sig = 0) noexcept // If shutdown is initialized //exit(EXIT_FAILURE); // Having set the exit flag, all threads "should" terminate cleanly. } -void _cdecl Signal_Break(int sig = 0) // signal handler attached when using secure mode +static void _cdecl Signal_Break(int sig = 0) // signal handler attached when using secure mode { // Shouldn't be needed, since gdb consumes the signals itself and this code won't be executed //#ifdef _DEBUG @@ -367,7 +367,7 @@ void _cdecl Signal_Break(int sig = 0) // signal handler attached when using sec } } -void _cdecl Signal_Illegal_Instruction(int sig = 0) +static void _cdecl Signal_Illegal_Instruction(int sig = 0) { #ifdef THREAD_TRACK_CALLSTACK StackDebugInformation::freezeCallStack(true); @@ -394,7 +394,7 @@ void _cdecl Signal_Illegal_Instruction(int sig = 0) throw CSError(LOGL_FATAL, sig, strsignal(sig)); } -void _cdecl Signal_Children(int sig = 0) +static void _cdecl Signal_Children(int sig = 0) { UnreferencedParameter(sig); while (waitpid((pid_t)(-1), nullptr, WNOHANG) > 0) {} diff --git a/src/common/CExpression.cpp b/src/common/CExpression.cpp index 208a57e58..550a177ad 100644 --- a/src/common/CExpression.cpp +++ b/src/common/CExpression.cpp @@ -125,7 +125,7 @@ int StrncpyCharBytesWritten(int iBytesToWrite, size_t uiBufSize, bool fPrintErro return (uiBufSize > 1) ? int(uiBufSize - 1) : 0; // Bytes written, excluding the string terminator. } -llong power(llong base, llong level) +static llong cexpression_power(llong base, llong level) { double rc = pow((double)base, (double)level); return (llong)rc; @@ -1057,7 +1057,7 @@ llong CExpression::GetValMath( llong llVal, lpctstr & pExpr ) llValSecond = GetVal(pExpr); if (llVal < 0) { - llVal = power(llVal, llValSecond); + llVal = cexpression_power(llVal, llValSecond); break; } else if ((llVal == 0) && (llValSecond <= 0)) //The information from https://en.cppreference.com/w/cpp/numeric/math/pow says if both input are 0, it can cause errors too. @@ -1065,7 +1065,7 @@ llong CExpression::GetValMath( llong llVal, lpctstr & pExpr ) g_Log.EventError("Power of zero with zero or negative exponent is undefined.\n"); break; } - llVal = power(llVal, llValSecond); + llVal = cexpression_power(llVal, llValSecond); break; } diff --git a/src/common/CFloatMath.cpp b/src/common/CFloatMath.cpp index 1cfd8afe1..8b0238ce6 100644 --- a/src/common/CFloatMath.cpp +++ b/src/common/CFloatMath.cpp @@ -19,7 +19,7 @@ CSString CFloatMath::FloatMath(lpctstr& Expr) } -short int _iReentrant_Count = 0; +static thread_local short int _iReentrant_Count = 0; realtype CFloatMath::MakeFloatMath( lpctstr & Expr ) { diff --git a/src/common/crypto/CBCrypt.cpp b/src/common/crypto/CBCrypt.cpp index e917d422c..ef39b8cca 100644 --- a/src/common/crypto/CBCrypt.cpp +++ b/src/common/crypto/CBCrypt.cpp @@ -61,7 +61,7 @@ static int timing_safe_strcmp(const char *str1, const char *str2) * nonzero otherwise. * */ -int bcrypt_gensalt(const char* prefix, int factor, char salt[BCRYPT_HASHSIZE]) +static int bcrypt_gensalt(const char* prefix, int factor, char salt[BCRYPT_HASHSIZE]) { #define RANDBYTES (16) //char input[RANDBYTES]; @@ -94,7 +94,7 @@ int bcrypt_gensalt(const char* prefix, int factor, char salt[BCRYPT_HASHSIZE]) * The return value is zero if the password could be hashed and nonzero * otherwise. */ -int bcrypt_hashpw(const char *passwd, const char salt[BCRYPT_HASHSIZE], char hash[BCRYPT_HASHSIZE]) +static int bcrypt_hashpw(const char *passwd, const char salt[BCRYPT_HASHSIZE], char hash[BCRYPT_HASHSIZE]) { char *aux; aux = crypt_rn(passwd, salt, hash, BCRYPT_HASHSIZE); @@ -110,7 +110,7 @@ int bcrypt_hashpw(const char *passwd, const char salt[BCRYPT_HASHSIZE], char has * passwords don't match. * */ -int bcrypt_checkpw(const char *passwd, const char hash[BCRYPT_HASHSIZE]) +static int bcrypt_checkpw(const char *passwd, const char hash[BCRYPT_HASHSIZE]) { int ret; char outhash[BCRYPT_HASHSIZE]; diff --git a/src/common/sqlite/SQLite.cpp b/src/common/sqlite/SQLite.cpp index f2fa7078e..2414c39e5 100644 --- a/src/common/sqlite/SQLite.cpp +++ b/src/common/sqlite/SQLite.cpp @@ -702,10 +702,10 @@ SQLiteTablePtr::SQLiteTablePtr( SQLiteTable * pTable ) m_pTable = pTable; } -SQLiteTablePtr::SQLiteTablePtr( const SQLiteTablePtr & cTablePtr ) +SQLiteTablePtr::SQLiteTablePtr( SQLiteTablePtr & cTablePtr ) { m_pTable=cTablePtr.m_pTable; - ((SQLiteTablePtr *)&cTablePtr)->m_pTable=nullptr; + cTablePtr.m_pTable=nullptr; } SQLiteTablePtr::~SQLiteTablePtr() @@ -714,12 +714,12 @@ SQLiteTablePtr::~SQLiteTablePtr() delete m_pTable; } -void SQLiteTablePtr::operator =( const SQLiteTablePtr & cTablePtr ) +void SQLiteTablePtr::operator =( SQLiteTablePtr & cTablePtr ) { if (m_pTable) delete m_pTable; m_pTable=cTablePtr.m_pTable; - ((SQLiteTablePtr *)&cTablePtr)->m_pTable=nullptr; + cTablePtr.m_pTable=nullptr; } SQLiteTable * SQLiteTablePtr::Detach() diff --git a/src/common/sqlite/SQLite.h b/src/common/sqlite/SQLite.h index e06b1a910..5386bba5f 100644 --- a/src/common/sqlite/SQLite.h +++ b/src/common/sqlite/SQLite.h @@ -181,7 +181,8 @@ class SQLiteTablePtr // If you have a previous table connected to this class, // you do not have to worry, // it will commit suicide before eating the new table. - SQLiteTablePtr( const SQLiteTablePtr & cTablePtr ); + SQLiteTablePtr( SQLiteTablePtr & cTablePtr ); + SQLiteTablePtr( const SQLiteTablePtr & cTablePtr ) = delete; // Destructor... virtual ~SQLiteTablePtr(); @@ -191,7 +192,8 @@ class SQLiteTablePtr // If you have a previous table connected to this class, // you do not have to worry, // it will commit suicide before eating the new table. - void operator =(const SQLiteTablePtr & cTablePtr); + void operator =(SQLiteTablePtr & cTablePtr); + void operator =(const SQLiteTablePtr & cTablePtr) = delete; // Functor operator, will de-reference the m_pTable member. // WARNING: Use with care! Check for non-null m_pTable first! diff --git a/src/game/CServer.cpp b/src/game/CServer.cpp index 354749a43..cbbb47a35 100644 --- a/src/game/CServer.cpp +++ b/src/game/CServer.cpp @@ -35,6 +35,303 @@ #include +//****************************************************** + +static void dword_q_sort(dword *numbers, dword left, dword right) +{ + dword pivot, l_hold, r_hold; + + l_hold = left; + r_hold = right; + pivot = numbers[left]; + while (left < right) + { + while ((numbers[right] >= pivot) && (left < right)) right--; + if (left != right) + { + numbers[left] = numbers[right]; + left++; + } + while ((numbers[left] <= pivot) && (left < right)) left++; + if (left != right) + { + numbers[right] = numbers[left]; + right--; + } + } + numbers[left] = pivot; + pivot = left; + left = l_hold; + right = r_hold; + if (left < pivot) + dword_q_sort(numbers, left, pivot-1); + if (right > pivot) + dword_q_sort(numbers, pivot+1, right); +} + +static void defragSphere(char *path) +{ + ASSERT(path != nullptr); + + constexpr size_t mb10 = 10*1024*1024; + constexpr size_t mb5 = 5*1024*1024; + + CSFileText inf; + CSFile ouf; + char file_buf[1024]; + char path_buf[_MAX_PATH], path_buf_2[_MAX_PATH]; + char *str_ptr = nullptr, *str_ptr_2 = nullptr; + + g_Log.Event(LOGM_INIT, "Defragmentation (UID alteration) of " SPHERE_TITLE " saves.\n" + "Use it on your risk and if you know what you are doing since it can possibly harm your server.\n" + "The process can take up to several hours depending on the CPU you have.\n" + "After finished, you will have your '" SPHERE_FILE "*.scp' files converted and saved as '" SPHERE_FILE "*.scp.new'.\n"); + + // UID_O_INDEX_MASK ? + constexpr dword MAX_UID = 40'000'000U; // limit to 40mln of objects, takes 40mln*4bytes ~= 160mb + + dword dwIdxUID = 0; + dword* puids = (dword*)calloc(MAX_UID, sizeof(dword)); + for ( uint i = 0; i < 3; ++i ) + { + Str_CopyLimitNull(path_buf, path, sizeof(path_buf)); + if ( i == 0 ) strcat(path_buf, SPHERE_FILE "statics" SPHERE_SCRIPT); + else if ( i == 1 ) strcat(path_buf, SPHERE_FILE "world" SPHERE_SCRIPT); + else strcat(path_buf, SPHERE_FILE "chars" SPHERE_SCRIPT); + + g_Log.Event(LOGM_INIT, "Reading current UIDs: %s\n", path_buf); + if ( !inf.Open(path_buf, OF_READ|OF_TEXT|OF_DEFAULTMODE) ) + { + g_Log.Event(LOGM_INIT, "Cannot open file for reading. Skipped!\n"); + continue; + } + size_t uiBytesRead = 0, uiTotalMb = 0; + while ((dwIdxUID < MAX_UID) && !feof(inf._pStream)) + { + fgets(file_buf, sizeof(file_buf), inf._pStream); + uiBytesRead += strlen(file_buf); + if ( uiBytesRead > mb10 ) + { + uiBytesRead -= mb10; + uiTotalMb += 10; + g_Log.Event(LOGM_INIT, "Total read %" PRIuSIZE_T " Mb\n", uiTotalMb); + } + if (( file_buf[0] == 'S' ) && ( strstr(file_buf, "SERIAL=") == file_buf )) + { + str_ptr = file_buf + 7; + str_ptr_2 = str_ptr; + while (*str_ptr_2 && (*str_ptr_2 != '\r') && (*str_ptr_2 != '\n')) + { + ++str_ptr_2; + } + *str_ptr_2 = 0; + + // prepare new uid + *(str_ptr-1) = '0'; + *str_ptr = 'x'; + --str_ptr; + puids[dwIdxUID++] = strtoul(str_ptr, &str_ptr_2, 16); + } + } + inf.Close(); + } + const dword dwTotalUIDs = dwIdxUID; + g_Log.Event(LOGM_INIT, "Totally having %" PRIu32 " unique objects (UIDs), latest: 0%x\n", dwTotalUIDs, puids[dwTotalUIDs-1]); + + g_Log.Event(LOGM_INIT, "Quick-Sorting the UIDs array...\n"); + dword_q_sort(puids, 0, dwTotalUIDs -1); + + for ( uint i = 0; i < 5; ++i ) + { + Str_CopyLimitNull(path_buf, path, sizeof(path_buf)); + if ( !i ) strcat(path_buf, SPHERE_FILE "accu.scp"); + else if ( i == 1 ) strcat(path_buf, SPHERE_FILE "chars" SPHERE_SCRIPT); + else if ( i == 2 ) strcat(path_buf, SPHERE_FILE "data" SPHERE_SCRIPT); + else if ( i == 3 ) strcat(path_buf, SPHERE_FILE "world" SPHERE_SCRIPT); + else if ( i == 4 ) strcat(path_buf, SPHERE_FILE "statics" SPHERE_SCRIPT); + g_Log.Event(LOGM_INIT, "Updating UID-s in %s to %s.new\n", path_buf, path_buf); + if ( !inf.Open(path_buf, OF_READ|OF_TEXT|OF_DEFAULTMODE) ) + { + g_Log.Event(LOGM_INIT, "Cannot open file for reading. Skipped!\n"); + continue; + } + Str_ConcatLimitNull(path_buf, ".new", sizeof(path_buf)); + if ( !ouf.Open(path_buf, OF_WRITE|OF_CREATE|OF_DEFAULTMODE) ) + { + g_Log.Event(LOGM_INIT, "Cannot open file for writing. Skipped!\n"); + continue; + } + + size_t uiBytesRead = 0, uiTotalMb = 0; + while ( inf.ReadString(file_buf, sizeof(file_buf)) ) + { + dwIdxUID = (dword)strlen(file_buf); + if (dwIdxUID > (ARRAY_COUNT(file_buf) - 3)) + dwIdxUID = ARRAY_COUNT(file_buf) - 3; + + file_buf[dwIdxUID] = file_buf[dwIdxUID +1] = file_buf[dwIdxUID +2] = 0; // just to be sure to be in line always + // NOTE: it is much faster than to use memcpy to clear before reading + bool fSpecial = false; + uiBytesRead += dwIdxUID; + if ( uiBytesRead > mb5 ) + { + uiBytesRead -= mb5; + uiTotalMb += 5; + g_Log.Event(LOGM_INIT, "Total processed %" PRIuSIZE_T " Mb\n", uiTotalMb); + } + str_ptr = file_buf; + + // Note 28-Jun-2004 + // mounts seems having ACTARG1 > 0x30000000. The actual UID is ACTARG1-0x30000000. The + // new also should be new+0x30000000. need investigation if this can help making mounts + // not to disappear after the defrag + if (( file_buf[0] == 'A' ) && ( strstr(file_buf, "ACTARG1=0") == file_buf )) // ACTARG1= + str_ptr += 8; + else if (( file_buf[0] == 'C' ) && ( strstr(file_buf, "CONT=0") == file_buf )) // CONT= + str_ptr += 5; + else if (( file_buf[0] == 'C' ) && ( strstr(file_buf, "CHARUID=0") == file_buf )) // CHARUID= + str_ptr += 8; + else if (( file_buf[0] == 'L' ) && ( strstr(file_buf, "LASTCHARUID=0") == file_buf )) // LASTCHARUID= + str_ptr += 12; + else if (( file_buf[0] == 'L' ) && ( strstr(file_buf, "LINK=0") == file_buf )) // LINK= + str_ptr += 5; + else if (( file_buf[0] == 'M' ) && ( strstr(file_buf, "MEMBER=0") == file_buf )) // MEMBER= + { + str_ptr += 7; + fSpecial = true; + } + else if (( file_buf[0] == 'M' ) && ( strstr(file_buf, "MORE1=0") == file_buf )) // MORE1= + str_ptr += 6; + else if (( file_buf[0] == 'M' ) && ( strstr(file_buf, "MORE2=0") == file_buf )) // MORE2= + str_ptr += 6; + else if (( file_buf[0] == 'S' ) && ( strstr(file_buf, "SERIAL=0") == file_buf )) // SERIAL= + str_ptr += 7; + else if ((( file_buf[0] == 'T' ) && ( strstr(file_buf, "TAG.") == file_buf )) || // TAG.= + (( file_buf[0] == 'R' ) && ( strstr(file_buf, "REGION.TAG") == file_buf ))) + { + while ( *str_ptr && ( *str_ptr != '=' )) + ++str_ptr; + ++str_ptr; + } + else if (( i == 2 ) && strchr(file_buf, '=')) // spheredata.scp - plain VARs + { + while ( *str_ptr && ( *str_ptr != '=' )) + ++str_ptr; + ++str_ptr; + } + else + str_ptr = nullptr; + + // UIDs are always hex, so prefixed by 0 + if ( str_ptr && ( *str_ptr != '0' )) + str_ptr = nullptr; + + // here we got potentialy UID-contained variable + // check if it really is only UID-like var containing + if ( str_ptr ) + { + str_ptr_2 = str_ptr; + while ( *str_ptr_2 && + ((( *str_ptr_2 >= '0' ) && ( *str_ptr_2 <= '9' )) || + (( *str_ptr_2 >= 'a' ) && ( *str_ptr_2 <= 'f' ))) ) + ++str_ptr_2; + if ( !fSpecial ) + { + if ( *str_ptr_2 && ( *str_ptr_2 != '\r' ) && ( *str_ptr_2 != '\n' )) // some more text in line + str_ptr = nullptr; + } + } + + // here we definitely know that this is very uid-like + if ( str_ptr ) + { + char c, c1, c2; + c = *str_ptr_2; + + *str_ptr_2 = 0; + // here in p we have the current value of the line. + // check if it is a valid UID + + // prepare converting 0.. to 0x.. + c1 = *(str_ptr-1); + c2 = *str_ptr; + *(str_ptr-1) = '0'; + *str_ptr = 'x'; + --str_ptr; + dwIdxUID = strtoul(str_ptr, &str_ptr_2, 16); + ++str_ptr; + *(str_ptr-1) = c1; + *str_ptr = c2; + // Note 28-Jun-2004 + // The search algourytm is very simple and fast. But maybe integrate some other, at least /2 algorythm + // since has amount/2 tryes at worst chance to get the item and never scans the whole array + // It should improve speed since defragmenting 150Mb saves takes ~2:30 on 2.0Mhz CPU + { + dword dStep = dwTotalUIDs /2; + dword d = dStep; + for (;;) + { + dStep /= 2; + + if ( puids[d] == dwIdxUID) + { + dwIdxUID = d | (puids[d]&0xF0000000); // do not forget attach item and special flags like 04.. + break; + } + else + { + if (puids[d] < dwIdxUID) + d += dStep; + else + d -= dStep; + } + + if ( dStep == 1 ) + { + dwIdxUID = 0xFFFFFFFFL; + break; // did not find the UID + } + } + } + + // Search for this uid in the table + /* for ( d = 0; d < dTotalUIDs; d++ ) + { + if ( !uids[d] ) // end of array + { + uid = 0xFFFFFFFFL; + break; + } + else if ( uids[d] == uid ) + { + uid = d | (uids[d]&0xF0000000); // do not forget attach item and special flags like 04.. + break; + } + }*/ + + // replace UID by the new one since it has been found + *str_ptr_2 = c; + if (dwIdxUID != 0xFFFFFFFFL ) + { + *str_ptr = 0; + ASSERT(strlen(str_ptr_2) < sizeof(path_buf)); + Str_CopyLimitNull(path_buf, str_ptr_2, sizeof(path_buf)); // here we don't need anymore the old values of path_buf, so i can reuse it here + snprintf(path_buf_2, sizeof(path_buf_2), "0%" PRIx32, dwIdxUID); + strcat(file_buf, path_buf_2); + strcat(file_buf, path_buf); + } + } + // output the resulting line + ouf.Write(file_buf, (int)strlen(file_buf)); + } + inf.Close(); + ouf.Close(); + } + + free(puids); + g_Log.Event(LOGM_INIT, "Defragmentation complete.\n"); +} + //////////////////////////////////////////////////////////////////////////////////////// // -CServer diff --git a/src/game/CServerDef.cpp b/src/game/CServerDef.cpp index 232c7a691..a60500067 100644 --- a/src/game/CServerDef.cpp +++ b/src/game/CServerDef.cpp @@ -38,7 +38,7 @@ #else // (Unix) #include #endif - bool m_fPmemory = true; // process memory information is available? + static bool sm_fHasMemoryInfo = true; // process memory information is available? ////////////////////////////////////////////////////////////////////// // -CServerDef @@ -68,7 +68,7 @@ size_t CServerDef::StatGet(SERV_STAT_TYPE i) const if ( i == SERV_STAT_MEM ) // memory information { d = 0; - if ( m_fPmemory ) + if ( sm_fHasMemoryInfo ) { #ifdef _WIN32 if ( !m_hmPsapiDll ) // try to load psapi.dll if not loaded yet @@ -147,7 +147,7 @@ size_t CServerDef::StatGet(SERV_STAT_TYPE i) const if ( !d ) { g_Log.EventError(("Unable to load process information from getrusage() and procfs. Memory information will be not available.\n")); - m_fPmemory = false; + sm_fHasMemoryInfo = false; } #endif } diff --git a/src/game/CWorld.cpp b/src/game/CWorld.cpp index 1d09fa9e3..05134381d 100644 --- a/src/game/CWorld.cpp +++ b/src/game/CWorld.cpp @@ -1,15 +1,15 @@ #include "../common/CException.h" #include "../common/CExpression.h" +#include "../common/CLog.h" #include "../common/sphereversion.h" #include "../network/CClientIterator.h" #include "../network/CNetworkManager.h" #include "../sphere/ProfileTask.h" -#include "../common/CLog.h" #include "chars/CChar.h" #include "clients/CClient.h" #include "clients/CGMPage.h" #include "items/CItemMulti.h" -#include "items/CItemStone.h" +#include "items/CItemStone.h" // Needed to use CItemmStone methods, the unique_ptr was forward declared in the header #include "CServer.h" #include "CScriptProfiler.h" #include "CSector.h" @@ -24,7 +24,7 @@ #include -lpctstr GetReasonForGarbageCode(int iCode = -1) +static lpctstr GetReasonForGarbageCode(int iCode = -1) noexcept { lpctstr pStr; switch ( iCode ) @@ -194,7 +194,7 @@ lpctstr GetReasonForGarbageCode(int iCode = -1) return pStr; } -void ReportGarbageCollection(CObjBase * pObj, int iResultCode) +static void ReportGarbageCollection(CObjBase * pObj, int iResultCode) { ASSERT(pObj != nullptr); @@ -967,7 +967,7 @@ bool CWorld::SaveForce() // Save world state else pCurBlock = save_msgs[5]; - fSave = SaveStage(); + fSave = SaveStage(); if ( !(_iSaveStage & 0x7F) ) { g_Serv.PrintPercent( _iSaveStage, (ssize_t)iSectorsQty + 3 ); diff --git a/src/game/chars/CChar.cpp b/src/game/chars/CChar.cpp index cf14716cc..42802a5b6 100644 --- a/src/game/chars/CChar.cpp +++ b/src/game/chars/CChar.cpp @@ -1591,7 +1591,7 @@ void CChar::SetID( CREID_TYPE id ) CCharBase * pCharDef = CCharBase::FindCharBase(id); if ( pCharDef == nullptr ) { - if ( (id != (CREID_TYPE)-1) && (id != CREID_INVALID) ) + if ( id != CREID_INVALID ) DEBUG_ERR(("Setting invalid char ID 0%x\n", id)); id = (CREID_TYPE)(g_Cfg.ResourceGetIndexType(RES_CHARDEF, "DEFAULTCHAR")); @@ -4995,7 +4995,7 @@ bool CChar::OnTriggerSpeech( bool bIsPet, lpctstr pszText, CChar * pSrc, TALKMOD } // Gaining exp -uint Calc_ExpGet_Exp(uint level) +static uint Calc_ExpGet_Exp(uint level) { if (level <= 1) return 0; @@ -5015,7 +5015,7 @@ uint Calc_ExpGet_Exp(uint level) } // Increasing level -uint Calc_ExpGet_Level(uint exp) +static uint Calc_ExpGet_Level(uint exp) { if (g_Cfg.m_iLevelNextAt < 1) //Must do this check in case ini's LevelNextAt is not set or server will freeze because exp will never decrease in the while. { diff --git a/src/game/spheresvr.cpp b/src/game/spheresvr.cpp index 350d633ae..176ce878d 100644 --- a/src/game/spheresvr.cpp +++ b/src/game/spheresvr.cpp @@ -164,9 +164,8 @@ CSStringList g_AutoComplete; // auto-complete list CScriptProfiler g_profiler; // script profiler CUOMapList g_MapList; // global maps information -MainThread g_Main; -extern PingServer g_PingServer; -extern CDataBaseAsyncHelper g_asyncHdb; +static MainThread g_Main; +static PingServer g_PingServer; @@ -469,304 +468,6 @@ static void Sphere_MainMonitorLoop() } -//****************************************************** - -static void dword_q_sort(dword *numbers, dword left, dword right) -{ - dword pivot, l_hold, r_hold; - - l_hold = left; - r_hold = right; - pivot = numbers[left]; - while (left < right) - { - while ((numbers[right] >= pivot) && (left < right)) right--; - if (left != right) - { - numbers[left] = numbers[right]; - left++; - } - while ((numbers[left] <= pivot) && (left < right)) left++; - if (left != right) - { - numbers[right] = numbers[left]; - right--; - } - } - numbers[left] = pivot; - pivot = left; - left = l_hold; - right = r_hold; - if (left < pivot) - dword_q_sort(numbers, left, pivot-1); - if (right > pivot) - dword_q_sort(numbers, pivot+1, right); -} - -void defragSphere(char *path) -{ - ASSERT(path != nullptr); - - constexpr size_t mb10 = 10*1024*1024; - constexpr size_t mb5 = 5*1024*1024; - - CSFileText inf; - CSFile ouf; - char file_buf[1024]; - char path_buf[_MAX_PATH], path_buf_2[_MAX_PATH]; - char *str_ptr = nullptr, *str_ptr_2 = nullptr; - - g_Log.Event(LOGM_INIT, "Defragmentation (UID alteration) of " SPHERE_TITLE " saves.\n" - "Use it on your risk and if you know what you are doing since it can possibly harm your server.\n" - "The process can take up to several hours depending on the CPU you have.\n" - "After finished, you will have your '" SPHERE_FILE "*.scp' files converted and saved as '" SPHERE_FILE "*.scp.new'.\n"); - - // UID_O_INDEX_MASK ? - constexpr dword MAX_UID = 40'000'000U; // limit to 40mln of objects, takes 40mln*4bytes ~= 160mb - - dword dwIdxUID = 0; - dword* puids = (dword*)calloc(MAX_UID, sizeof(dword)); - for ( uint i = 0; i < 3; ++i ) - { - Str_CopyLimitNull(path_buf, path, sizeof(path_buf)); - if ( i == 0 ) strcat(path_buf, SPHERE_FILE "statics" SPHERE_SCRIPT); - else if ( i == 1 ) strcat(path_buf, SPHERE_FILE "world" SPHERE_SCRIPT); - else strcat(path_buf, SPHERE_FILE "chars" SPHERE_SCRIPT); - - g_Log.Event(LOGM_INIT, "Reading current UIDs: %s\n", path_buf); - if ( !inf.Open(path_buf, OF_READ|OF_TEXT|OF_DEFAULTMODE) ) - { - g_Log.Event(LOGM_INIT, "Cannot open file for reading. Skipped!\n"); - continue; - } - size_t uiBytesRead = 0, uiTotalMb = 0; - while ((dwIdxUID < MAX_UID) && !feof(inf._pStream)) - { - fgets(file_buf, sizeof(file_buf), inf._pStream); - uiBytesRead += strlen(file_buf); - if ( uiBytesRead > mb10 ) - { - uiBytesRead -= mb10; - uiTotalMb += 10; - g_Log.Event(LOGM_INIT, "Total read %" PRIuSIZE_T " Mb\n", uiTotalMb); - } - if (( file_buf[0] == 'S' ) && ( strstr(file_buf, "SERIAL=") == file_buf )) - { - str_ptr = file_buf + 7; - str_ptr_2 = str_ptr; - while (*str_ptr_2 && (*str_ptr_2 != '\r') && (*str_ptr_2 != '\n')) - { - ++str_ptr_2; - } - *str_ptr_2 = 0; - - // prepare new uid - *(str_ptr-1) = '0'; - *str_ptr = 'x'; - --str_ptr; - puids[dwIdxUID++] = strtoul(str_ptr, &str_ptr_2, 16); - } - } - inf.Close(); - } - const dword dwTotalUIDs = dwIdxUID; - g_Log.Event(LOGM_INIT, "Totally having %" PRIu32 " unique objects (UIDs), latest: 0%x\n", dwTotalUIDs, puids[dwTotalUIDs-1]); - - g_Log.Event(LOGM_INIT, "Quick-Sorting the UIDs array...\n"); - dword_q_sort(puids, 0, dwTotalUIDs -1); - - for ( uint i = 0; i < 5; ++i ) - { - Str_CopyLimitNull(path_buf, path, sizeof(path_buf)); - if ( !i ) strcat(path_buf, SPHERE_FILE "accu.scp"); - else if ( i == 1 ) strcat(path_buf, SPHERE_FILE "chars" SPHERE_SCRIPT); - else if ( i == 2 ) strcat(path_buf, SPHERE_FILE "data" SPHERE_SCRIPT); - else if ( i == 3 ) strcat(path_buf, SPHERE_FILE "world" SPHERE_SCRIPT); - else if ( i == 4 ) strcat(path_buf, SPHERE_FILE "statics" SPHERE_SCRIPT); - g_Log.Event(LOGM_INIT, "Updating UID-s in %s to %s.new\n", path_buf, path_buf); - if ( !inf.Open(path_buf, OF_READ|OF_TEXT|OF_DEFAULTMODE) ) - { - g_Log.Event(LOGM_INIT, "Cannot open file for reading. Skipped!\n"); - continue; - } - Str_ConcatLimitNull(path_buf, ".new", sizeof(path_buf)); - if ( !ouf.Open(path_buf, OF_WRITE|OF_CREATE|OF_DEFAULTMODE) ) - { - g_Log.Event(LOGM_INIT, "Cannot open file for writing. Skipped!\n"); - continue; - } - - size_t uiBytesRead = 0, uiTotalMb = 0; - while ( inf.ReadString(file_buf, sizeof(file_buf)) ) - { - dwIdxUID = (dword)strlen(file_buf); - if (dwIdxUID > (ARRAY_COUNT(file_buf) - 3)) - dwIdxUID = ARRAY_COUNT(file_buf) - 3; - - file_buf[dwIdxUID] = file_buf[dwIdxUID +1] = file_buf[dwIdxUID +2] = 0; // just to be sure to be in line always - // NOTE: it is much faster than to use memcpy to clear before reading - bool fSpecial = false; - uiBytesRead += dwIdxUID; - if ( uiBytesRead > mb5 ) - { - uiBytesRead -= mb5; - uiTotalMb += 5; - g_Log.Event(LOGM_INIT, "Total processed %" PRIuSIZE_T " Mb\n", uiTotalMb); - } - str_ptr = file_buf; - - // Note 28-Jun-2004 - // mounts seems having ACTARG1 > 0x30000000. The actual UID is ACTARG1-0x30000000. The - // new also should be new+0x30000000. need investigation if this can help making mounts - // not to disappear after the defrag - if (( file_buf[0] == 'A' ) && ( strstr(file_buf, "ACTARG1=0") == file_buf )) // ACTARG1= - str_ptr += 8; - else if (( file_buf[0] == 'C' ) && ( strstr(file_buf, "CONT=0") == file_buf )) // CONT= - str_ptr += 5; - else if (( file_buf[0] == 'C' ) && ( strstr(file_buf, "CHARUID=0") == file_buf )) // CHARUID= - str_ptr += 8; - else if (( file_buf[0] == 'L' ) && ( strstr(file_buf, "LASTCHARUID=0") == file_buf )) // LASTCHARUID= - str_ptr += 12; - else if (( file_buf[0] == 'L' ) && ( strstr(file_buf, "LINK=0") == file_buf )) // LINK= - str_ptr += 5; - else if (( file_buf[0] == 'M' ) && ( strstr(file_buf, "MEMBER=0") == file_buf )) // MEMBER= - { - str_ptr += 7; - fSpecial = true; - } - else if (( file_buf[0] == 'M' ) && ( strstr(file_buf, "MORE1=0") == file_buf )) // MORE1= - str_ptr += 6; - else if (( file_buf[0] == 'M' ) && ( strstr(file_buf, "MORE2=0") == file_buf )) // MORE2= - str_ptr += 6; - else if (( file_buf[0] == 'S' ) && ( strstr(file_buf, "SERIAL=0") == file_buf )) // SERIAL= - str_ptr += 7; - else if ((( file_buf[0] == 'T' ) && ( strstr(file_buf, "TAG.") == file_buf )) || // TAG.= - (( file_buf[0] == 'R' ) && ( strstr(file_buf, "REGION.TAG") == file_buf ))) - { - while ( *str_ptr && ( *str_ptr != '=' )) - ++str_ptr; - ++str_ptr; - } - else if (( i == 2 ) && strchr(file_buf, '=')) // spheredata.scp - plain VARs - { - while ( *str_ptr && ( *str_ptr != '=' )) - ++str_ptr; - ++str_ptr; - } - else - str_ptr = nullptr; - - // UIDs are always hex, so prefixed by 0 - if ( str_ptr && ( *str_ptr != '0' )) - str_ptr = nullptr; - - // here we got potentialy UID-contained variable - // check if it really is only UID-like var containing - if ( str_ptr ) - { - str_ptr_2 = str_ptr; - while ( *str_ptr_2 && - ((( *str_ptr_2 >= '0' ) && ( *str_ptr_2 <= '9' )) || - (( *str_ptr_2 >= 'a' ) && ( *str_ptr_2 <= 'f' ))) ) - ++str_ptr_2; - if ( !fSpecial ) - { - if ( *str_ptr_2 && ( *str_ptr_2 != '\r' ) && ( *str_ptr_2 != '\n' )) // some more text in line - str_ptr = nullptr; - } - } - - // here we definitely know that this is very uid-like - if ( str_ptr ) - { - char c, c1, c2; - c = *str_ptr_2; - - *str_ptr_2 = 0; - // here in p we have the current value of the line. - // check if it is a valid UID - - // prepare converting 0.. to 0x.. - c1 = *(str_ptr-1); - c2 = *str_ptr; - *(str_ptr-1) = '0'; - *str_ptr = 'x'; - --str_ptr; - dwIdxUID = strtoul(str_ptr, &str_ptr_2, 16); - ++str_ptr; - *(str_ptr-1) = c1; - *str_ptr = c2; - // Note 28-Jun-2004 - // The search algourytm is very simple and fast. But maybe integrate some other, at least /2 algorythm - // since has amount/2 tryes at worst chance to get the item and never scans the whole array - // It should improve speed since defragmenting 150Mb saves takes ~2:30 on 2.0Mhz CPU - { - dword dStep = dwTotalUIDs /2; - dword d = dStep; - for (;;) - { - dStep /= 2; - - if ( puids[d] == dwIdxUID) - { - dwIdxUID = d | (puids[d]&0xF0000000); // do not forget attach item and special flags like 04.. - break; - } - else - { - if (puids[d] < dwIdxUID) - d += dStep; - else - d -= dStep; - } - - if ( dStep == 1 ) - { - dwIdxUID = 0xFFFFFFFFL; - break; // did not find the UID - } - } - } - - // Search for this uid in the table -/* for ( d = 0; d < dTotalUIDs; d++ ) - { - if ( !uids[d] ) // end of array - { - uid = 0xFFFFFFFFL; - break; - } - else if ( uids[d] == uid ) - { - uid = d | (uids[d]&0xF0000000); // do not forget attach item and special flags like 04.. - break; - } - }*/ - - // replace UID by the new one since it has been found - *str_ptr_2 = c; - if (dwIdxUID != 0xFFFFFFFFL ) - { - *str_ptr = 0; - ASSERT(strlen(str_ptr_2) < sizeof(path_buf)); - Str_CopyLimitNull(path_buf, str_ptr_2, sizeof(path_buf)); // here we don't need anymore the old values of path_buf, so i can reuse it here - snprintf(path_buf_2, sizeof(path_buf_2), "0%" PRIx32, dwIdxUID); - strcat(file_buf, path_buf_2); - strcat(file_buf, path_buf); - } - } - // output the resulting line - ouf.Write(file_buf, (int)strlen(file_buf)); - } - inf.Close(); - ouf.Close(); - } - - free(puids); - g_Log.Event(LOGM_INIT, "Defragmentation complete.\n"); -} - - void atexit_handler() { ThreadHolder::get().markThreadsClosing(); diff --git a/src/game/triggers.cpp b/src/game/triggers.cpp index ffa50a500..8dd92fbcf 100644 --- a/src/game/triggers.cpp +++ b/src/game/triggers.cpp @@ -21,7 +21,7 @@ struct TRIGGER_T_ID //{ // int m_used; //}; -std::vector g_triggers_id; +static std::vector sm_vTriggersId; bool IsTrigUsed(E_TRIGGERS id) @@ -29,7 +29,7 @@ bool IsTrigUsed(E_TRIGGERS id) if ( g_Serv.IsLoading() == true) return false; - return (( (uint)id < g_triggers_id.size() ) && g_triggers_id[id].m_used ); + return (( (uint)id < sm_vTriggersId.size() ) && sm_vTriggersId[id].m_used ); } bool IsTrigUsed(const char *name) @@ -47,12 +47,12 @@ bool IsTrigUsed(const char *name) void TriglistInit() { TRIGGER_T_ID trig{}; - g_triggers_id.clear(); + sm_vTriggersId.clear(); #define ADD(_a_) \ snprintf(trig.m_name, TRIGGER_NAME_MAX_LEN, "@%s", #_a_); \ trig.m_used = 0; \ - g_triggers_id.push_back(trig); + sm_vTriggersId.push_back(trig); #include "../tables/triggers.tbl" #undef ADD @@ -60,7 +60,7 @@ void TriglistInit() void TriglistClear() { - for ( auto it = g_triggers_id.begin(), end = g_triggers_id.end(); it != end; ++it ) + for ( auto it = sm_vTriggersId.begin(), end = sm_vTriggersId.end(); it != end; ++it ) { it->m_used = 0; } @@ -68,13 +68,13 @@ void TriglistClear() void TriglistAdd(E_TRIGGERS id) { - if (g_triggers_id.size() ) - ++ g_triggers_id[id].m_used; + if (sm_vTriggersId.size() ) + ++ sm_vTriggersId[id].m_used; } void TriglistAdd(const char *name) { - for ( auto it = g_triggers_id.begin(), end = g_triggers_id.end(); it != end; ++it ) + for ( auto it = sm_vTriggersId.begin(), end = sm_vTriggersId.end(); it != end; ++it ) { if ( !strcmpi(it->m_name, name) ) { @@ -87,7 +87,7 @@ void TriglistAdd(const char *name) void Triglist(int &total, int &used) { total = used = 0; - for ( auto it = g_triggers_id.cbegin(), end = g_triggers_id.cend(); it != end; ++it ) + for ( auto it = sm_vTriggersId.cbegin(), end = sm_vTriggersId.cend(); it != end; ++it ) { ++total; if ( it->m_used ) @@ -97,7 +97,7 @@ void Triglist(int &total, int &used) void TriglistPrint() { - for ( auto it = g_triggers_id.cbegin(), end = g_triggers_id.cend(); it != end; ++it ) + for ( auto it = sm_vTriggersId.cbegin(), end = sm_vTriggersId.cend(); it != end; ++it ) { if (it->m_used) { diff --git a/src/network/PingServer.cpp b/src/network/PingServer.cpp index 63a4dd4ad..0c2c3ec50 100644 --- a/src/network/PingServer.cpp +++ b/src/network/PingServer.cpp @@ -3,7 +3,7 @@ #include "PingServer.h" -PingServer g_PingServer; +static PingServer s_PingServer; // run the thread in RealTime as we need pings to be responded to ASAP PingServer::PingServer() : AbstractSphereThread("PingServer", IThread::RealTime) diff --git a/src/network/PingServer.h b/src/network/PingServer.h index 9be1d819a..6e28717ac 100644 --- a/src/network/PingServer.h +++ b/src/network/PingServer.h @@ -23,9 +23,8 @@ class PingServer : public AbstractSphereThread PingServer(void); virtual ~PingServer(void); -private: - PingServer(const PingServer& copy); - PingServer& operator=(const PingServer& other); + PingServer(const PingServer& copy) = delete; + PingServer& operator=(const PingServer& other) = delete; public: virtual void onStart() override; diff --git a/src/sphere/asyncdb.h b/src/sphere/asyncdb.h index aede0ba29..2bc3018c0 100644 --- a/src/sphere/asyncdb.h +++ b/src/sphere/asyncdb.h @@ -39,4 +39,7 @@ class CDataBaseAsyncHelper : public AbstractSphereThread void addQuery(bool isQuery, lpctstr sFunction, lpctstr sQuery); }; +extern CDataBaseAsyncHelper g_asyncHdb; + + #endif // _INC_ASYNCDB_H diff --git a/src/sphere/threads.cpp b/src/sphere/threads.cpp index 5a319fdf9..d68907d97 100644 --- a/src/sphere/threads.cpp +++ b/src/sphere/threads.cpp @@ -803,6 +803,7 @@ char *AbstractSphereThread::allocateBuffer() noexcept return buffer; } +static TemporaryStringThreadSafeStateHolder::TemporaryStringStorage * getThreadRawStringBuffer() { From 250cae76f0b5775065b97470e237b3da303e2a86 Mon Sep 17 00:00:00 2001 From: cbnolok Date: Mon, 23 Sep 2024 19:32:18 +0200 Subject: [PATCH 60/86] Moved all the compiler/linker flags selection for GCC/Clang in CompilerFlagsChecker.cmake. --- .clangd | 3 + CMakeLists.txt | 32 +++- cmake/CompilerFlagsChecker.cmake | 179 +++++++++++++----- .../include/Linux-Clang_common.inc.cmake | 158 ++-------------- .../include/Linux-GNU_common.inc.cmake | 148 ++------------- .../include/OSX-AppleClang_common.inc.cmake | 122 ++---------- .../include/Windows-Clang_common.inc.cmake | 121 +----------- .../include/Windows-GNU_common.inc.cmake | 130 +------------ src/common/CExpression.cpp | 28 +-- src/common/resource/sections/CDialogDef.cpp | 26 +-- src/game/chars/CCharUse.cpp | 4 +- src/game/components/CCSpawn.cpp | 20 +- 12 files changed, 265 insertions(+), 706 deletions(-) diff --git a/.clangd b/.clangd index 6b5f08c53..243a3c7f2 100644 --- a/.clangd +++ b/.clangd @@ -1,5 +1,6 @@ CompileFlags: Add: + # Exclude the following folders from the source code analysis. - -I!.codelite - -I!.ctagsd - -I!.git @@ -15,3 +16,5 @@ CompileFlags: # PathMatch: '.*/src/common/common\.h' # Diagnostics: # Suppress: ['-Wunused-include-directive'] + +# TODO: disable clazy-non-pod-global-static diff --git a/CMakeLists.txt b/CMakeLists.txt index 29766560a..295f32bd4 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -35,7 +35,13 @@ option(USE_UBSAN "Enable Undefined Behavior Sanitizer." FALSE) option(USE_LSAN "Enable LeakSanitizer." FALSE) option(USE_MSAN "Enable MemorySanitizer." FALSE) +set(ENABLED_SANITIZER FALSE) +if(USE_ASAN OR USE_MSAN OR USE_LSAN OR USE_MSAN) + set(ENABLED_SANITIZER TRUE) +endif() + # -------------------- Utility functions -------------------- + function(booleanize_str_find VAR) if(${VAR} EQUAL -1) unset(${VAR} PARENT_SCOPE) @@ -75,7 +81,8 @@ set(CMAKE_CXX_EXTENSIONS OFF) set(CMAKE_SHARED_LIBRARY_LINK_C_FLAGS "") set(CMAKE_SHARED_LIBRARY_LINK_CXX_FLAGS "") -# CMake also sets other predefined flags, which we don't want... +# CMake also sets other predefined flags, which we don't want? +#[[ set(CMAKE_C_FLAGS "") set(CMAKE_C_FLAGS_DEBUG "") set(CMAKE_C_FLAGS_NIGHTLY "") @@ -90,6 +97,7 @@ set(CMAKE_EXE_LINKER_FLAGS "") set(CMAKE_EXE_LINKER_FLAGS_DEBUG "") set(CMAKE_EXE_LINKER_FLAGS_NIGHTLY "") set(CMAKE_EXE_LINKER_FLAGS_RELEASE "") +]] set(is_win32_app_linker) if(WIN32 AND NOT ${WIN32_SPAWN_CONSOLE}) @@ -213,8 +221,26 @@ endif(SINGLE_TARGET) # -------------------- -#message(STATUS) -#include("${CMAKE_SOURCE_DIR}/cmake/CompilerFlagsChecker.cmake") +message(STATUS) +include("${CMAKE_SOURCE_DIR}/cmake/CompilerFlagsChecker.cmake") + +# -------------------- + +if(USE_ASAN) + set(PREPROCESSOR_DEFS_EXTRA ${PREPROCESSOR_DEFS_EXTRA} ADDRESS_SANITIZER) +endif() +if(USE_UBSAN) + set(PREPROCESSOR_DEFS_EXTRA ${PREPROCESSOR_DEFS_EXTRA} UNDEFINED_BEHAVIOR_SANITIZER) +endif() +if(USE_LSAN) + set(PREPROCESSOR_DEFS_EXTRA ${PREPROCESSOR_DEFS_EXTRA} LEAK_SANITIZER) +endif() +if(USE_MSAN) + set(PREPROCESSOR_DEFS_EXTRA ${PREPROCESSOR_DEFS_EXTRA} MEMORY_SANITIZER) +endif() +if(ENABLED_SANITIZER) + set(PREPROCESSOR_DEFS_EXTRA ${PREPROCESSOR_DEFS_EXTRA} _SANITIZERS) +endif() # -------------------- diff --git a/cmake/CompilerFlagsChecker.cmake b/cmake/CompilerFlagsChecker.cmake index 6826f0cac..039af7d1e 100644 --- a/cmake/CompilerFlagsChecker.cmake +++ b/cmake/CompilerFlagsChecker.cmake @@ -3,6 +3,19 @@ message(STATUS "Checking available compiler flags...") if(NOT MSVC) message(STATUS "-- Compilation options:") + + # Compiler option flags. + list( + APPEND + compiler_options_base + -pthread + -fexceptions + -fnon-call-exceptions + -pipe + -ffast-math + ) + list(APPEND compiler_options_warning_base -Werror;-Wall;-Wextra;-Wpedantic) + # Compiler option flags. Common to both compilers, but older versions might not support the following. #check_cxx_compiler_flag("" COMP_HAS_) @@ -10,13 +23,17 @@ if(NOT MSVC) check_cxx_compiler_flag("-fno-expensive-optimizations" COMP_HAS_FNO_EXPENSIVE_OPTIMIZATIONS) # Compiler option flags. Expected to work on Clang but not GCC, at the moment. - #check_cxx_compiler_flag("-fforce-emit-vtables" COMP_HAS_F_FORCE_EMIT_VTABLES) + # check_cxx_compiler_flag("-fforce-emit-vtables" COMP_HAS_F_FORCE_EMIT_VTABLES) + # -fwhole-program-vtables + # -fstrict-vtable-pointers if(${USE_ASAN}) # Compiler option flags. Sanitizers related (ASAN). message(STATUS "-- Compilation options (Address Sanitizer):") + set(CMAKE_REQUIRED_LIBRARIES -fsanitize=address) # link against sanitizer lib, being required by the following compilation test check_cxx_compiler_flag("-fsanitize=address" COMP_HAS_ASAN) + unset(CMAKE_REQUIRED_LIBRARIES) if(NOT COMP_HAS_ASAN) message(FATAL_ERROR "This compiler does not support Address Sanitizer. Disable it.") endif() @@ -32,7 +49,9 @@ if(NOT MSVC) # Compiler option flags. Sanitizers related (UBSAN). message(STATUS "-- Compilation options (Undefined Behavior Sanitizer):") + set(CMAKE_REQUIRED_LIBRARIES -fsanitize=undefined) # link against sanitizer lib, being required by the following compilation test check_cxx_compiler_flag("-fsanitize=undefined" COMP_HAS_UBSAN) + unset(CMAKE_REQUIRED_LIBRARIES) if(NOT COMP_HAS_UBSAN) message(FATAL_ERROR "This compiler does not support Undefined Behavior Sanitizer. Disable it.") endif() @@ -48,7 +67,9 @@ if(NOT MSVC) # Compiler option flags. Sanitizers related (LSAN). message(STATUS "-- Compilation options (Leak Sanitizer):") + set(CMAKE_REQUIRED_LIBRARIES -fsanitize=leak) # link against sanitizer lib, being required by the following compilation test check_cxx_compiler_flag("-fsanitize=leak" COMP_HAS_LSAN) + unset(CMAKE_REQUIRED_LIBRARIES) if(NOT COMP_HAS_LSAN) message(FATAL_ERROR "This compiler does not support Leak Sanitizer. Disable it.") endif() @@ -56,13 +77,30 @@ if(NOT MSVC) if(${USE_MSAN}) # Compiler option flags. Sanitizers related (UBSAN). - message(STATUS "-- Compilation options (Memory Behavior Sanitizer):") + + set(CMAKE_REQUIRED_LIBRARIES -fsanitize=memory) # link against sanitizer lib, being required by the following compilation test check_cxx_compiler_flag("-fsanitize=memory" COMP_HAS_MSAN) + unset(CMAKE_REQUIRED_LIBRARIES) if(NOT COMP_HAS_MSAN) message(FATAL_ERROR "This compiler does not support Memory Sanitizer. Disable it.") endif() + # MemorySanitizer: it doesn't work out of the box. It needs to be linked to an MSAN-instrumented build of libc++ and libc++abi. + # This means: one should build them from LLVM source... + # https://github.com/google/sanitizers/wiki/MemorySanitizerLibcxxHowTo + #IF (${USE_MSAN}) + # SET (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -stdlib=libc++") + #ENDIF() + # Use "-stdlib=libstdc++" to link against GCC c/c++ libs (this is done by default) + # To use LLVM libc++ use "-stdlib=libc++", but you need to install it separately + + message( + WARNING + "You have enabled MSAN. Make sure you do know what you are doing. It doesn't work out of the box. \ +See comments in the toolchain and: https://github.com/google/sanitizers/wiki/MemorySanitizerLibcxxHowTo" + ) + check_cxx_compiler_flag("-fsanitize=memory-track-origins" COMP_HAS_F_SANITIZE_MEMORY_TRACK_ORIGINS) check_cxx_compiler_flag("-fPIE" COMP_HAS_F_PIE) endif() @@ -88,10 +126,10 @@ if(NOT MSVC) # Compiler warning flags. message(STATUS "-- Compilation options (warnings):") - check_cxx_compiler_flag("-Wuseless-cast" COMP_HAS_W_USELESS_CAST) + #check_cxx_compiler_flag("-Wuseless-cast" COMP_HAS_W_USELESS_CAST) check_cxx_compiler_flag("-Wnull-dereference" COMP_HAS_W_NULL_DEREFERENCE) - check_cxx_compiler_flag("-Wconversion" COMP_HAS_W_CONVERSION) # Temporarily disabled. Implicit type conversions that might change a value, such as narrowing conversions. - check_cxx_compiler_flag("-Wcast-qual" COMP_HAS_W_CAST_QUAL) # casts that remove a type's const or volatile qualifier. + #check_cxx_compiler_flag("-Wconversion" COMP_HAS_W_CONVERSION) # Temporarily disabled. Implicit type conversions that might change a value, such as narrowing conversions. + #check_cxx_compiler_flag("-Wcast-qual" COMP_HAS_W_CAST_QUAL) # casts that remove a type's const or volatile qualifier. check_cxx_compiler_flag("-Wzero-as-null-pointer-constant" COMP_HAS_W_ZERO_NULLPTR) check_cxx_compiler_flag("-Wdisabled-optimization" COMP_HAS_W_DISABLE_OPT) check_cxx_compiler_flag("-Winvalid-pch" COMP_HAS_W_INVALID_PCH) @@ -121,18 +159,19 @@ if(NOT MSVC) # Compiler warning flags. To be disabled. message(STATUS "-- Compilation options (disable specific warnings):") - check_cxx_compiler_flag("-Wno-format-nonliteral" COMP_HAS_WNO_FORMAT_NONLITERAL) # Since -Wformat=2 is stricter, you would need to disable this warning. - check_cxx_compiler_flag("-Wno-nonnull-compare" COMP_HAS_WNO_NONNULL_COMPARE) - check_cxx_compiler_flag("-Wno-maybe-uninitialized" COMP_HAS_WNO_MAYBE_UNINIT) - check_cxx_compiler_flag("-Wno-switch" COMP_HAS_WNO_SWITCH) - check_cxx_compiler_flag("-Wno-implicit-fallthrough" COMP_HAS_WNO_IMPLICIT_FALLTHROUGH) - check_cxx_compiler_flag("-Wno-parentheses" COMP_HAS_WNO_PARENTHESES) - check_cxx_compiler_flag("-Wno-misleading-indentation" COMP_HAS_WNO_MISLEADING_INDENTATION) - check_cxx_compiler_flag("-Wno-unused-result" COMP_HAS_WNO_UNUSED_RESULT) - check_cxx_compiler_flag("-Wno-nested-anon-types" COMP_HAS_WNO_NESTED_ANON_TYPES) - check_cxx_compiler_flag("-Wno-format-security" COMP_HAS_WNO_FORMAT_SECURITY) # TODO: remove that when we'll have time to fix every printf format issue - check_cxx_compiler_flag("-Wno-deprecated-declarations" COMP_HAS_WNO_DEPRECATED_DECLARATIONS) - #check_cxx_compiler_flag("-Wno-unknown-pragmas" COMP_HAS_) + check_cxx_compiler_flag("-Wunused-function" COMP_HAS_WNO_UNUSED_FUNCTION) + check_cxx_compiler_flag("-Wformat-nonliteral" COMP_HAS_WNO_FORMAT_NONLITERAL) # Since -Wformat=2 is stricter, you would need to disable this warning. + check_cxx_compiler_flag("-Wnonnull-compare" COMP_HAS_WNO_NONNULL_COMPARE) + check_cxx_compiler_flag("-Wmaybe-uninitialized" COMP_HAS_WNO_MAYBE_UNINIT) + check_cxx_compiler_flag("-Wswitch" COMP_HAS_WNO_SWITCH) + check_cxx_compiler_flag("-Wimplicit-fallthrough" COMP_HAS_WNO_IMPLICIT_FALLTHROUGH) + check_cxx_compiler_flag("-Wparentheses" COMP_HAS_WNO_PARENTHESES) + check_cxx_compiler_flag("-Wmisleading-indentation" COMP_HAS_WNO_MISLEADING_INDENTATION) + check_cxx_compiler_flag("-Wunused-result" COMP_HAS_WNO_UNUSED_RESULT) + check_cxx_compiler_flag("-Wnested-anon-types" COMP_HAS_WNO_NESTED_ANON_TYPES) + check_cxx_compiler_flag("-Wformat-security" COMP_HAS_WNO_FORMAT_SECURITY) # TODO: remove that when we'll have time to fix every printf format issue + check_cxx_compiler_flag("-Wdeprecated-declarations" COMP_HAS_WNO_DEPRECATED_DECLARATIONS) + #check_cxx_compiler_flag("-Wunknown-pragmas" COMP_HAS_) #check_cxx_compiler_flag("" COMP_HAS_) else(NOT MSVC) # Compiler warning flags (MSVC). @@ -151,6 +190,10 @@ endif() if(COMP_HAS_ASAN) list(APPEND checked_compiler_options_asan "-fsanitize=address") + list(APPEND checked_linker_options_all "-fsanitize=address") + if(RUNTIME_STATIC_LINK) + list(APPEND checked_linker_options_all "-static-libasan") + endif() if(COMP_HAS_FSAN_CFI) list(APPEND checked_compiler_options_asan "-fsanitize-cfi") endif() @@ -170,6 +213,10 @@ endif() if(COMP_HAS_UBSAN) list(APPEND checked_compiler_options_ubsan "-fsanitize=undefined") + list(APPEND checked_linker_options_all "-fsanitize=undefined") + if(RUNTIME_STATIC_LINK) + list(APPEND checked_linker_options_all "-static-libubsan") + endif() if(COMP_HAS_FSAN_FLOAT_DIVIDE_BY_ZERO) list(APPEND checked_compiler_options_ubsan "-fsanitize=float-divide-by-zero") endif() @@ -189,15 +236,24 @@ endif() if(COMP_HAS_LSAN) list(APPEND checked_compiler_options_lsan "-fsanitize=leak") + list(APPEND checked_linker_options_all "-fsanitize=leak") + if(RUNTIME_STATIC_LINK) + list(APPEND checked_linker_options_all "-static-liblsan") + endif() endif() if(COMP_HAS_MSAN) list(APPEND checked_compiler_options_msan "-fsanitize=memory") + list(APPEND checked_linker_options_all "-fsanitize=memory") + if(RUNTIME_STATIC_LINK) + list(APPEND checked_linker_options_all "-static-libmsan") + endif() if(COMP_HAS_F_SANITIZE_MEMORY_TRACK_ORIGINS) list(APPEND checked_compiler_options_msan "-fsanitize=memory-track-origins") endif() if(COMP_HAS_F_PIE) list(APPEND checked_compiler_options_msan "-fPIE") + list(APPEND checked_linker_options_all "-pie") endif() endif() @@ -283,6 +339,9 @@ if(COMP_HAS_W_MISSING_VARIABLE_DECL) list(APPEND checked_compiler_warnings "-Wmissing-variable-declarations") endif() +if(COMP_HAS_WNO_UNUSED_FUNCTION) + list(APPEND checked_compiler_warnings_disabled "-Wno-unused-function") +endif() if(COMP_HAS_WNO_FORMAT_NONLITERAL) list(APPEND checked_compiler_warnings_disabled "-Wno-format-nonliteral") endif() @@ -320,7 +379,7 @@ endif() # ---- MSVC if(COMP_HAS_DEFINE_MACRO_EXPANSION) - list(APPEND checked_compiler_flags_msvc "/Wd5105") + list(APPEND checked_compiler_options_msvc "/Wd5105") endif() # ---- Double checks @@ -344,34 +403,68 @@ set(checked_compiler_options_asan) set(checked_compiler_options_sanitize_harden) set(checked_compiler_warnings) set(checked_compiler_warnings_disabled) -set(checked_compiler_flags_msvc) +set(checked_compiler_options_msvc) ]] -message(STATUS "Adding the following conditional compiler options: ${checked_compiler_options}.") -if(COMP_HAS_ASAN) - message(STATUS "Adding the following conditional compiler options for ASan: ${checked_compiler_options_asan}.") -endif() -if(COMP_HAS_UBSAN) - message(STATUS "Adding the following conditional compiler options for UBSan: ${checked_compiler_options_ubsan}.") -endif() -if(COMP_HAS_LSAN) - message(STATUS "Adding the following conditional compiler options for LSan: ${checked_compiler_options_lsan}.") -endif() +## ---- + +list( + APPEND + list_gnu_explicit_compiler_options_all + ${compiler_options_base} + ${compiler_options_warning_base} + ${checked_compiler_options} + ${checked_compiler_options_asan} + ${checked_compiler_options_ubsan} + ${checked_compiler_options_lsan} + ${checked_compiler_options_msan} + ${checked_compiler_options_sanitize_harden} + ${checked_compiler_warnings} + ${checked_compiler_warnings_disabled} + ${checked_compiler_options_msvc} +) -if(COMP_HAS_MSAN) - message(STATUS "Adding the following conditional compiler options for MSan: ${checked_compiler_options_msan}.") -endif() +list(APPEND list_gnu_explicit_linker_options_all ${checked_linker_options_all};-pthread;-dynamic;-Wl,--fatal-warnings) -message( - STATUS - "Adding the following conditional compiler options for hardening: ${checked_compiler_options_sanitize_harden}." -) -message(STATUS "Adding the following conditional compiler warnings: ${checked_compiler_warnings}.") -message( - STATUS - "Adding the following conditional compiler warnings ignore options: ${checked_compiler_warnings_disabled}." -) +#string(JOIN " " string_checked_compiler_options_all ${list_checked_compiler_options_all}) +#set(string_checked_compiler_options_all CACHE STRING "Additional compiler flags, dynamically added." FORCE) +set(list_gnu_explicit_compiler_options_all CACHE STRING "Additional compiler flags, dynamically added." FORCE) +set(list_gnu_explicit_linker_options_all CACHE STRING "Additional linker flags, dynamically added." FORCE) + +## ---- + +if(NOT MSVC) + message(STATUS "Adding the following base compiler options: ${compiler_options_base}") + message(STATUS "Adding the following base compiler warning options: ${compiler_options_warning_base}") + + message(STATUS "Adding the following conditional compiler options: ${checked_compiler_options}.") + if(COMP_HAS_ASAN) + message(STATUS "Adding the following conditional compiler options for ASan: ${checked_compiler_options_asan}.") + endif() + if(COMP_HAS_UBSAN) + message( + STATUS + "Adding the following conditional compiler options for UBSan: ${checked_compiler_options_ubsan}." + ) + endif() + if(COMP_HAS_LSAN) + message(STATUS "Adding the following conditional compiler options for LSan: ${checked_compiler_options_lsan}.") + endif() + + if(COMP_HAS_MSAN) + message(STATUS "Adding the following conditional compiler options for MSan: ${checked_compiler_options_msan}.") + endif() -if(MSVC) - message(STATUS "Adding the following conditional compiler options: ${checked_compiler_flags_msvc}.") + message( + STATUS + "Adding the following conditional compiler options for hardening: ${checked_compiler_options_sanitize_harden}." + ) + message(STATUS "Adding the following conditional compiler warnings: ${checked_compiler_warnings}.") + message( + STATUS + "Adding the following conditional compiler warnings ignore options: ${checked_compiler_warnings_disabled}." + ) + message(STATUS "Adding the following linker options: ${list_gnu_explicit_linker_options_all}.") +elseif(MSVC) + message(STATUS "Adding the following conditional compiler options: ${checked_compiler_options_msvc}.") endif() diff --git a/cmake/toolchains/include/Linux-Clang_common.inc.cmake b/cmake/toolchains/include/Linux-Clang_common.inc.cmake index 88695e547..b7493dc50 100644 --- a/cmake/toolchains/include/Linux-Clang_common.inc.cmake +++ b/cmake/toolchains/include/Linux-Clang_common.inc.cmake @@ -9,186 +9,54 @@ function(toolchain_exe_stuff_common) message(STATUS "Locating libraries to be linked to...") - set(LIBS_LINK_LIST mariadb dl) - foreach(LIB_NAME ${LIBS_LINK_LIST}) - find_library(LIB_${LIB_NAME}_WITH_PATH ${LIB_NAME} PATH ${lib_search_paths}) - message(STATUS "Library ${LIB_NAME}: ${LIB_${LIB_NAME}_WITH_PATH}") + set(libs_link_list mariadb dl) + foreach(lib_name ${libs_link_list}) + find_library(lib_${lib_name}_with_path ${lib_name} PATH ${lib_search_paths}) + message(STATUS "Library ${lib_name}: ${lib_${lib_name}_with_path}") endforeach() #-- Validate sanitizers options and store them between the common compiler flags. - set(ENABLED_SANITIZER false) # From https://clang.llvm.org/docs/ClangCommandLineReference.html # -static-libsan Statically link the sanitizer runtime (Not supported for ASan, TSan or UBSan on darwin) #string(REPLACE ";" " " CXX_FLAGS_EXTRA "${CXX_FLAGS_EXTRA}") - if(${USE_ASAN}) - set(CXX_FLAGS_EXTRA - ${CXX_FLAGS_EXTRA} - # -fsanitize=safe-stack # Can't be used with asan! - -fsanitize=address - -fno-sanitize-recover=address - #-fsanitize-cfi # cfi: control flow integrity - -fsanitize-address-use-after-scope - -fsanitize=pointer-compare - -fsanitize=pointer-subtract - # Flags for additional instrumentation not strictly needing asan to be enabled - -fcf-protection=full - -fstack-check - -fstack-protector-all - -fstack-clash-protection - # Not supported by Clang, but supported by GCC - #-fvtable-verify=preinit -fharden-control-flow-redundancy -fhardcfr-check-exceptions - # Other - #-fsanitize-trap=all - ) - set(CMAKE_EXE_LINKER_FLAGS_EXTRA ${CMAKE_EXE_LINKER_FLAGS_EXTRA} -fsanitize=address) - set(PREPROCESSOR_DEFS_EXTRA ${PREPROCESSOR_DEFS_EXTRA} ADDRESS_SANITIZER) - set(ENABLED_SANITIZER true) - endif() - if(${USE_MSAN}) - message( - WARNING - "You have enabled MSAN. Make sure you do know what you are doing. It doesn't work out of the box. \ -See comments in the toolchain and: https://github.com/google/sanitizers/wiki/MemorySanitizerLibcxxHowTo" - ) - set(CXX_FLAGS_EXTRA ${CXX_FLAGS_EXTRA} -fsanitize=memory -fsanitize-memory-track-origins -fPIE) - set(CMAKE_EXE_LINKER_FLAGS_EXTRA ${CMAKE_EXE_LINKER_FLAGS_EXTRA} -fsanitize=memory) - set(PREPROCESSOR_DEFS_EXTRA ${PREPROCESSOR_DEFS_EXTRA} MEMORY_SANITIZER) - set(ENABLED_SANITIZER true) - endif() - if(${USE_LSAN}) - set(CXX_FLAGS_EXTRA ${CXX_FLAGS_EXTRA} -fsanitize=leak) - set(CMAKE_EXE_LINKER_FLAGS_EXTRA ${CMAKE_EXE_LINKER_FLAGS_EXTRA} -fsanitize=leak>) - set(PREPROCESSOR_DEFS_EXTRA ${PREPROCESSOR_DEFS_EXTRA} LEAK_SANITIZER) - set(ENABLED_SANITIZER true) - endif() - if(${USE_UBSAN}) - set(UBSAN_FLAGS - -fsanitize=undefined,float-divide-by-zero,local-bounds - -fno-sanitize=enum - # Supported? - -fsanitize=unsigned-integer-overflow #Unlike signed integer overflow, this is not undefined behavior, but it is often unintentional. - -fsanitize=implicit-conversion - ) - set(CXX_FLAGS_EXTRA ${CXX_FLAGS_EXTRA} ${UBSAN_FLAGS} -fsanitize=return,vptr) - set(CMAKE_EXE_LINKER_FLAGS_EXTRA ${CMAKE_EXE_LINKER_FLAGS_EXTRA} -fsanitize=undefined) - set(PREPROCESSOR_DEFS_EXTRA ${PREPROCESSOR_DEFS_EXTRA} UNDEFINED_BEHAVIOR_SANITIZER) - set(ENABLED_SANITIZER true) - endif() - - if(${ENABLED_SANITIZER}) - set(PREPROCESSOR_DEFS_EXTRA ${PREPROCESSOR_DEFS_EXTRA} _SANITIZERS) - set(CMAKE_EXE_LINKER_FLAGS_EXTRA - ${CMAKE_EXE_LINKER_FLAGS_EXTRA} - $<$:-static-libsan> - ) - endif() - - #-- Store compiler flags common to all builds. - - set(cxx_local_opts_warnings - -Werror - -Wall - -Wextra - -Wpedantic - - -Wmissing-include-dirs # Warns when an include directory provided with -I does not exist. - -Wformat=2 - #-Wcast-qual # Warns about casts that remove a type's const or volatile qualifier. - #-Wconversion # Temporarily disabled. Warns about implicit type conversions that might change a value, such as narrowing conversions. - -Wdisabled-optimization - #-Winvalid-pch - -Wzero-as-null-pointer-constant - -Wnull-dereference - - # Clang-only - -Wweak-vtables - #-Wmissing-prototypes - #-Wmissing-variable-declarations - - # Unsupported by Clang, but supported by GCC: - #-fno-expensive-optimizations - #-Wtrampolines # Warns when trampolines (a technique to implement nested functions) are generated (don't want this for security reasons). - #-Wvector-operation-performance - #-Wsized-deallocation - #-Wduplicated-cond - #-Wshift-overflow=2 - #-Wno-maybe-uninitialized - #-Wno-nonnull-compare - - # Disable errors: - -Wno-format-nonliteral # Since -Wformat=2 is stricter, you would need to disable this warning. - -Wno-switch - -Wno-implicit-fallthrough - -Wno-parentheses - -Wno-misleading-indentation - -Wno-unused-result - -Wno-format-security # TODO: disable that when we'll have time to fix every printf format issue - -Wno-nested-anon-types - ) - set(cxx_local_opts - -std=c++20 - -pthread - -fexceptions - -fnon-call-exceptions - -pipe - -ffast-math - # clang -specific: - # -fforce-emit-vtables - ) - set(cxx_compiler_options_common ${cxx_local_opts_warnings} ${cxx_local_opts} ${CXX_FLAGS_EXTRA}) + set(cxx_compiler_options_common ${list_gnu_explicit_compiler_options_all} ${CXX_FLAGS_EXTRA}) #separate_arguments(cxx_compiler_options_common) - # GCC flags not supported by clang: - - # MemorySanitizer: it doesn't work out of the box. It needs to be linked to an MSAN-instrumented build of libc++ and libc++abi. - # This means: one should build them from LLVM source... - # https://github.com/google/sanitizers/wiki/MemorySanitizerLibcxxHowTo - #IF (${USE_MSAN}) - # SET (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -stdlib=libc++") - #ENDIF() - # Use "-stdlib=libstdc++" to link against GCC c/c++ libs (this is done by default) - # To use LLVM libc++ use "-stdlib=libc++", but you need to install it separately - #-- Apply compiler flags, only the ones specific per build type. # -fno-omit-frame-pointer disables a good optimization which may corrupt the debugger stack trace. - set(COMPILE_OPTIONS_EXTRA) + set(local_compile_options_extra) if(ENABLED_SANITIZER OR TARGET spheresvr_debug) - set(COMPILE_OPTIONS_EXTRA -fno-omit-frame-pointer -fno-inline) + set(local_compile_options_extra -fno-omit-frame-pointer -fno-inline) endif() if(TARGET spheresvr_release) target_compile_options( spheresvr_release - PUBLIC -O3 -flto=full -fvirtual-function-elimination ${COMPILE_OPTIONS_EXTRA} + PUBLIC -O3 -flto=full -fvirtual-function-elimination ${local_compile_options_extra} ) endif() if(TARGET spheresvr_nightly) if(ENABLED_SANITIZER) - target_compile_options(spheresvr_nightly PUBLIC -ggdb3 -Og ${COMPILE_OPTIONS_EXTRA}) + target_compile_options(spheresvr_nightly PUBLIC -ggdb3 -Og ${local_compile_options_extra}) else() target_compile_options( spheresvr_nightly - PUBLIC -O3 -flto=full -fvirtual-function-elimination ${COMPILE_OPTIONS_EXTRA} + PUBLIC -O3 -flto=full -fvirtual-function-elimination ${local_compile_options_extra} ) endif() endif() if(TARGET spheresvr_debug) - target_compile_options(spheresvr_debug PUBLIC -ggdb3 -O0 ${COMPILE_OPTIONS_EXTRA}) + target_compile_options(spheresvr_debug PUBLIC -ggdb3 -O0 ${local_compile_options_extra}) endif() #-- Store common linker flags. - if(${USE_MSAN}) - set(CMAKE_EXE_LINKER_FLAGS_EXTRA ${CMAKE_EXE_LINKER_FLAGS_EXTRA} -pie) - endif() set(cxx_linker_options_common + ${list_gnu_explicit_linker_options_all} ${CMAKE_EXE_LINKER_FLAGS_EXTRA} - -pthread - -dynamic - -Wl,--fatal-warnings $<$: -static-libstdc++ -static-libgcc> # no way to safely statically link against libc @@ -222,7 +90,7 @@ See comments in the toolchain and: https://github.com/google/sanitizers/wiki/Mem target_compile_options(${tgt} PRIVATE ${cxx_compiler_options_common}) target_compile_definitions(${tgt} PRIVATE ${cxx_compiler_definitions_common}) target_link_options(${tgt} PRIVATE ${cxx_linker_options_common}) - target_link_libraries(${tgt} PRIVATE ${LIB_mariadb_WITH_PATH} ${LIB_dl_WITH_PATH}) + target_link_libraries(${tgt} PRIVATE ${lib_mariadb_with_path} ${lib_dl_with_path}) endforeach() #-- Set different output folders for each build type diff --git a/cmake/toolchains/include/Linux-GNU_common.inc.cmake b/cmake/toolchains/include/Linux-GNU_common.inc.cmake index 90c80b83f..ce705b3a6 100644 --- a/cmake/toolchains/include/Linux-GNU_common.inc.cmake +++ b/cmake/toolchains/include/Linux-GNU_common.inc.cmake @@ -9,164 +9,42 @@ function(toolchain_exe_stuff_common) message(STATUS "Locating libraries to be linked to...") - set(LIBS_LINK_LIST mariadb dl) - foreach(LIB_NAME ${LIBS_LINK_LIST}) - find_library(LIB_${LIB_NAME}_WITH_PATH ${LIB_NAME} PATH ${lib_search_paths}) - message(STATUS "Library ${LIB_NAME}: ${LIB_${LIB_NAME}_WITH_PATH}") + set(libs_link_list mariadb dl) + foreach(lib_name ${libs_link_list}) + find_library(lib_${lib_name}_with_path ${lib_name} PATH ${lib_search_paths}) + message(STATUS "Library ${lib_name}: ${lib_${lib_name}_with_path}") endforeach() - #-- Validate sanitizers options and store them between the common compiler flags. - - set(ENABLED_SANITIZER false) - - if(${USE_ASAN}) - set(CXX_FLAGS_EXTRA - ${CXX_FLAGS_EXTRA} - -fsanitize=address - -fno-sanitize-recover=address - #-fsanitize-cfi # cfi: control flow integrity, not supported by GCC - -fsanitize-address-use-after-scope - -fsanitize=pointer-compare - -fsanitize=pointer-subtract - # Flags for additional instrumentation not strictly needing asan to be enabled - #-fvtable-verify=preinit # This causes a GCC internal error! Tested with 13.2.0 - -fstack-check - -fstack-protector-all - -fcf-protection=full - # GCC 14? - #-fharden-control-flow-redundancy - #-fhardcfr-check-exceptions - # Other - #-fsanitize-trap=all - ) - set(CMAKE_EXE_LINKER_FLAGS_EXTRA - ${CMAKE_EXE_LINKER_FLAGS_EXTRA} - -fsanitize=address - $<$:-static-libasan> - ) - set(PREPROCESSOR_DEFS_EXTRA ${PREPROCESSOR_DEFS_EXTRA} ADDRESS_SANITIZER) - set(ENABLED_SANITIZER true) - endif() - if(${USE_MSAN}) - message(FATAL_ERROR "Linux GCC doesn't yet support MSAN") - set(USE_MSAN false) - #SET (CXX_FLAGS_EXTRA ${CXX_FLAGS_EXTRA} -fsanitize=memory -fsanitize-memory-track-origins=2 -fPIE) - #set (CMAKE_EXE_LINKER_FLAGS_EXTRA ${CMAKE_EXE_LINKER_FLAGS_EXTRA} -fsanitize=memory )#$<$:-static-libmsan>) - #SET (PREPROCESSOR_DEFS_EXTRA ${PREPROCESSOR_DEFS_EXTRA} MEMORY_SANITIZER) - #SET (ENABLED_SANITIZER true) - endif() - if(${USE_LSAN}) - set(CXX_FLAGS_EXTRA ${CXX_FLAGS_EXTRA} -fsanitize=leak) - set(CMAKE_EXE_LINKER_FLAGS_EXTRA - ${CMAKE_EXE_LINKER_FLAGS_EXTRA} - -fsanitize=leak - $<$:-static-liblsan> - ) - set(PREPROCESSOR_DEFS_EXTRA ${PREPROCESSOR_DEFS_EXTRA} LEAK_SANITIZER) - set(ENABLED_SANITIZER true) - endif() - if(${USE_UBSAN}) - set(UBSAN_FLAGS - -fsanitize=undefined,float-divide-by-zero - -fno-sanitize=enum - # Unsupported (yet?) by GCC 13 - #-fsanitize=unsigned-integer-overflow #Unlike signed integer overflow, this is not undefined behavior, but it is often unintentional. - #-fsanitize=implicit-conversion, local-bounds - ) - set(CXX_FLAGS_EXTRA ${CXX_FLAGS_EXTRA} ${UBSAN_FLAGS} -fsanitize=return,vptr) - set(CMAKE_EXE_LINKER_FLAGS_EXTRA - ${CMAKE_EXE_LINKER_FLAGS_EXTRA} - -fsanitize=undefined - $<$:-static-libubsan> - ) - set(PREPROCESSOR_DEFS_EXTRA ${PREPROCESSOR_DEFS_EXTRA} UNDEFINED_BEHAVIOR_SANITIZER) - set(ENABLED_SANITIZER true) - endif() - - if(${ENABLED_SANITIZER}) - set(PREPROCESSOR_DEFS_EXTRA ${PREPROCESSOR_DEFS_EXTRA} _SANITIZERS) - endif() - #-- Store compiler flags common to all builds. - set(cxx_local_opts_warnings - -Werror - -Wall - -Wextra - -Wpedantic - - -Wmissing-include-dirs # Warns when an include directory provided with -I does not exist. - -Wformat=2 - #-Wcast-qual # Warns about casts that remove a type's const or volatile qualifier. - #-Wconversion # Temporarily disabled. Warns about implicit type conversions that might change a value, such as narrowing conversions. - -Wdisabled-optimization - #-Winvalid-pch - -Wzero-as-null-pointer-constant - #-Wnull-dereference # Don't: on GCC 12 causes some false positives... - -Wduplicated-cond - - # Supported by Clang, but unsupported by GCC: - #-Wweak-vtables - - # Unsupported by Clang, but supported by GCC: - -Wtrampolines # Warns when trampolines (a technique to implement nested functions) are generated (don't want this for security reasons). - -Wvector-operation-performance - -Wsized-deallocation - -Wduplicated-cond - -Wshift-overflow=2 - - # Disable errors: - -Wno-format-nonliteral # Since -Wformat=2 is stricter, you would need to disable this warning. - -Wno-nonnull-compare # GCC only - -Wno-switch - -Wno-implicit-fallthrough - -Wno-parentheses - -Wno-misleading-indentation - -Wno-unused-result - -Wno-format-security # TODO: disable that when we'll have time to fix every printf format issue - -Wno-nested-anon-types - ) - set(cxx_local_opts - -std=c++20 - -pthread - -fexceptions - -fnon-call-exceptions - -pipe - -ffast-math - ) - set(cxx_compiler_options_common ${cxx_local_opts_warnings} ${cxx_local_opts} ${CXX_FLAGS_EXTRA}) + set(cxx_compiler_options_common ${list_gnu_explicit_compiler_options_all} ${CXX_FLAGS_EXTRA}) #-- Apply compiler flags, only the ones specific per build type. # -fno-omit-frame-pointer disables a good optimization which may corrupt the debugger stack trace. - set(COMPILE_OPTIONS_EXTRA) + set(local_compile_options_extra) if(ENABLED_SANITIZER OR TARGET spheresvr_debug) - set(COMPILE_OPTIONS_EXTRA -fno-omit-frame-pointer -fno-inline) + set(local_compile_options_extra -fno-omit-frame-pointer -fno-inline) endif() if(TARGET spheresvr_release) - target_compile_options(spheresvr_release PUBLIC -s -O3 ${COMPILE_OPTIONS_EXTRA}) + target_compile_options(spheresvr_release PUBLIC -s -O3 ${local_compile_options_extra}) endif() if(TARGET spheresvr_nightly) if(ENABLED_SANITIZER) - target_compile_options(spheresvr_nightly PUBLIC -ggdb3 -Og ${COMPILE_OPTIONS_EXTRA}) + target_compile_options(spheresvr_nightly PUBLIC -ggdb3 -Og ${local_compile_options_extra}) else() - target_compile_options(spheresvr_nightly PUBLIC -O3 ${COMPILE_OPTIONS_EXTRA}) + target_compile_options(spheresvr_nightly PUBLIC -O3 ${local_compile_options_extra}) endif() endif() if(TARGET spheresvr_debug) - target_compile_options(spheresvr_debug PUBLIC -ggdb3 -O0 ${COMPILE_OPTIONS_EXTRA}) + target_compile_options(spheresvr_debug PUBLIC -ggdb3 -O0 ${local_compile_options_extra}) endif() #-- Store common linker flags. - if(${USE_MSAN}) - set(CMAKE_EXE_LINKER_FLAGS_EXTRA ${CMAKE_EXE_LINKER_FLAGS_EXTRA} -pie) - endif() set(cxx_linker_options_common + ${list_gnu_explicit_linker_options_all} ${CMAKE_EXE_LINKER_FLAGS_EXTRA} - -pthread - -dynamic - -Wl,--fatal-warnings $<$: -static-libstdc++ -static-libgcc # no way to safely statically link against libc @@ -202,7 +80,7 @@ function(toolchain_exe_stuff_common) target_compile_options(${tgt} PRIVATE ${cxx_compiler_options_common}) target_compile_definitions(${tgt} PRIVATE ${cxx_compiler_definitions_common}) target_link_options(${tgt} PRIVATE ${cxx_linker_options_common}) - target_link_libraries(${tgt} PRIVATE ${LIB_mariadb_WITH_PATH} ${LIB_dl_WITH_PATH}) + target_link_libraries(${tgt} PRIVATE ${lib_mariadb_with_path} ${lib_dl_with_path}) endforeach() #-- Set different output folders for each build type diff --git a/cmake/toolchains/include/OSX-AppleClang_common.inc.cmake b/cmake/toolchains/include/OSX-AppleClang_common.inc.cmake index 62088924a..fb877cffe 100644 --- a/cmake/toolchains/include/OSX-AppleClang_common.inc.cmake +++ b/cmake/toolchains/include/OSX-AppleClang_common.inc.cmake @@ -9,143 +9,49 @@ function(toolchain_exe_stuff_common) message(STATUS "Locating libraries to be linked to...") - set(LIBS_LINK_LIST mariadb dl) - foreach(LIB_NAME ${LIBS_LINK_LIST}) + set(libs_link_list mariadb dl) + foreach(lib_name ${libs_link_list}) find_library( - LIB_${LIB_NAME}_WITH_PATH - ${LIB_NAME} + lib_${lib_name}_with_path + ${lib_name} HINT "/usr/local/opt/mariadb-connector-c/lib/mariadb" "/opt/homebrew/var/mariadb-connector-c/lib/mariadb" "/opt/homebrew/lib/mariadb" ) - message(STATUS "Library ${LIB_NAME}: ${LIB_${LIB_NAME}_WITH_PATH}") + message(STATUS "Library ${lib_name}: ${lib_${lib_name}_with_path}") endforeach() - #-- Validate sanitizers options and store them between the common compiler flags. - - set(ENABLED_SANITIZER false) - # From https://clang.llvm.org/docs/ClangCommandLineReference.html - # -static-libsan Statically link the sanitizer runtime (Not supported for ASan, TSan or UBSan on darwin) - - if(${USE_ASAN}) - set(CXX_FLAGS_EXTRA - ${CXX_FLAGS_EXTRA} # -fsanitize=safe-stack # Can't be used with asan! - -fsanitize=address - -fno-sanitize-recover=address #-fsanitize-cfi # cfi: control flow integrity - -fsanitize-address-use-after-scope - -fsanitize=pointer-compare - -fsanitize=pointer-subtract - # Flags for additional instrumentation not strictly needing asan to be enabled - -fcf-protection=full - -fstack-check - -fstack-protector-all - -fstack-clash-protection - # Not supported by Clang, but supported by GCC - #-fvtable-verify=preinit -fharden-control-flow-redundancy -fhardcfr-check-exceptions - # Other - #-fsanitize-trap=all - ) - set(CMAKE_EXE_LINKER_FLAGS_EXTRA ${CMAKE_EXE_LINKER_FLAGS_EXTRA} -fsanitize=address) - set(PREPROCESSOR_DEFS_EXTRA ${PREPROCESSOR_DEFS_EXTRA} ADDRESS_SANITIZER) - set(ENABLED_SANITIZER true) - endif() - if(${USE_MSAN}) - set(CXX_FLAGS_EXTRA ${CXX_FLAGS_EXTRA} -fsanitize=memory -fsanitize-memory-track-origins=2 -fPIE) - set(CMAKE_EXE_LINKER_FLAGS_EXTRA ${CMAKE_EXE_LINKER_FLAGS_EXTRA} -fsanitize=memory) - set(PREPROCESSOR_DEFS_EXTRA ${PREPROCESSOR_DEFS_EXTRA} MEMORY_SANITIZER) - set(ENABLED_SANITIZER true) - endif() - if(${USE_LSAN}) - set(CXX_FLAGS_EXTRA ${CXX_FLAGS_EXTRA} -fsanitize=leak) - set(CMAKE_EXE_LINKER_FLAGS_EXTRA ${CMAKE_EXE_LINKER_FLAGS_EXTRA} -fsanitize=leak) - set(PREPROCESSOR_DEFS_EXTRA ${PREPROCESSOR_DEFS_EXTRA} LEAK_SANITIZER) - set(ENABLED_SANITIZER true) - endif() - if(${USE_UBSAN}) - set(UBSAN_FLAGS - -fsanitize=undefined,float-divide-by-zero,local-bounds - -fno-sanitize=enum - # Supported? - -fsanitize=unsigned-integer-overflow #Unlike signed integer overflow, this is not undefined behavior, but it is often unintentional. - -fsanitize=implicit-conversion - ) - set(CXX_FLAGS_EXTRA ${CXX_FLAGS_EXTRA} ${UBSAN_FLAGS} -fsanitize=return,vptr) - set(CMAKE_EXE_LINKER_FLAGS_EXTRA ${CMAKE_EXE_LINKER_FLAGS_EXTRA} -fsanitize=undefined) - set(PREPROCESSOR_DEFS_EXTRA ${PREPROCESSOR_DEFS_EXTRA} UNDEFINED_BEHAVIOR_SANITIZER) - set(ENABLED_SANITIZER true) - endif() - - if(${ENABLED_SANITIZER}) - set(PREPROCESSOR_DEFS_EXTRA ${PREPROCESSOR_DEFS_EXTRA} _SANITIZERS) - set(CMAKE_EXE_LINKER_FLAGS_EXTRA - ${CMAKE_EXE_LINKER_FLAGS_EXTRA} - $<$:-static-libsan> - ) - endif() - #-- Store compiler flags common to all builds. - set(cxx_local_opts_warnings - -Werror - -Wall - -Wextra - -Wno-unknown-pragmas - -Wno-switch - -Wno-implicit-fallthrough - -Wno-parentheses - -Wno-misleading-indentation - -Wno-conversion-null - -Wno-unused-result - -Wno-format-security # TODO: disable that when we'll have time to fix every printf format issue - # clang-specific: - -Wno-deprecated-declarations # spams so much warnings for the use of sprintf - ) - set(cxx_local_opts - -std=c++20 - -pthread - -fexceptions - -fnon-call-exceptions - -pipe - -ffast-math - ) - set(cxx_compiler_options_common ${cxx_local_opts_warnings} ${cxx_local_opts} ${CXX_FLAGS_EXTRA}) - - # GCC flags not supported by clang: - # Warnings: "-Wno-nonnull-compare -Wno-maybe-uninitialized" - # Other: "-fno-expensive-optimizations" + set(cxx_compiler_options_common ${list_gnu_explicit_compiler_options_all} ${cxx_local_opts} ${CXX_FLAGS_EXTRA}) #-- Apply compiler flags, only the ones specific per build type. # -fno-omit-frame-pointer disables a good optimization which may corrupt the debugger stack trace. - set(COMPILE_OPTIONS_EXTRA) + set(local_compile_options_extra) if(ENABLED_SANITIZER OR TARGET spheresvr_debug) - set(COMPILE_OPTIONS_EXTRA -fno-omit-frame-pointer -fno-inline) + set(local_compile_options_extra -fno-omit-frame-pointer -fno-inline) endif() if(TARGET spheresvr_release) - target_compile_options(spheresvr_release PUBLIC -O3 ${COMPILE_OPTIONS_EXTRA}) + target_compile_options(spheresvr_release PUBLIC -O3 ${local_compile_options_extra}) endif() if(TARGET spheresvr_nightly) if(ENABLED_SANITIZER) - target_compile_options(spheresvr_nightly PUBLIC -ggdb3 -Og ${COMPILE_OPTIONS_EXTRA}) + target_compile_options(spheresvr_nightly PUBLIC -ggdb3 -Og ${local_compile_options_extra}) else() - target_compile_options(spheresvr_nightly PUBLIC -O3 ${COMPILE_OPTIONS_EXTRA}) + target_compile_options(spheresvr_nightly PUBLIC -O3 ${local_compile_options_extra}) endif() endif() if(TARGET spheresvr_debug) - target_compile_options(spheresvr_debug PUBLIC -ggdb3 -O0 ${COMPILE_OPTIONS_EXTRA}) + target_compile_options(spheresvr_debug PUBLIC -ggdb3 -O0 ${local_compile_options_extra}) endif() #-- Store common linker flags. - if(${USE_MSAN}) - set(CMAKE_EXE_LINKER_FLAGS_EXTRA ${CMAKE_EXE_LINKER_FLAGS_EXTRA} -pie) - endif() set(cxx_linker_options_common + ${list_gnu_explicit_linker_options_all} ${CMAKE_EXE_LINKER_FLAGS_EXTRA} - -pthread - -dynamic - -Wl,-fatal_warnings $<$: -static-libstdc++ -static-libgcc> # no way to statically link against libc @@ -188,7 +94,7 @@ function(toolchain_exe_stuff_common) target_compile_options(${tgt} PRIVATE ${cxx_compiler_options_common}) target_compile_definitions(${tgt} PRIVATE ${cxx_compiler_definitions_common}) target_link_options(${tgt} PRIVATE ${cxx_linker_options_common}) - target_link_libraries(${tgt} PRIVATE ${LIB_mariadb_WITH_PATH} ${LIB_dl_WITH_PATH}) + target_link_libraries(${tgt} PRIVATE ${lib_mariadb_with_path} ${lib_dl_with_path}) endforeach() #-- Set different output folders for each build type diff --git a/cmake/toolchains/include/Windows-Clang_common.inc.cmake b/cmake/toolchains/include/Windows-Clang_common.inc.cmake index a502a5185..7e7f9f30c 100644 --- a/cmake/toolchains/include/Windows-Clang_common.inc.cmake +++ b/cmake/toolchains/include/Windows-Clang_common.inc.cmake @@ -24,125 +24,26 @@ function(toolchain_exe_stuff_common) endif() endif() - #-- Validate sanitizers options and store them between the common compiler flags. - - set(ENABLED_SANITIZER false) - # From https://clang.llvm.org/docs/ClangCommandLineReference.html - # -static-libsan Statically link the sanitizer runtime (Not supported for ASan, TSan or UBSan on darwin) - - if(${USE_ASAN}) - set(CXX_FLAGS_EXTRA - ${CXX_FLAGS_EXTRA} # -fsanitize=safe-stack # Can't be used with asan! - -fsanitize=address - -fno-sanitize-recover=address #-fsanitize-cfi # cfi: control flow integrity - -fsanitize-address-use-after-scope - -fsanitize=pointer-compare - -fsanitize=pointer-subtract - # Flags for additional instrumentation not strictly needing asan to be enabled - -fcf-protection=full - -fstack-check - -fstack-protector-all - -fstack-clash-protection - # Not supported by Clang, but supported by GCC - #-fvtable-verify=preinit -fharden-control-flow-redundancy -fhardcfr-check-exceptions - # Other - #-fsanitize-trap=all - ) - if(${CLANG_USE_GCC_LINKER}) - set(CMAKE_EXE_LINKER_FLAGS_EXTRA ${CMAKE_EXE_LINKER_FLAGS_EXTRA} -fsanitize=address) - endif() - set(PREPROCESSOR_DEFS_EXTRA ${PREPROCESSOR_DEFS_EXTRA} ADDRESS_SANITIZER) - set(ENABLED_SANITIZER true) - endif() - if(${USE_MSAN}) - message(FATAL_ERROR "Windows Clang doesn't yet support MSAN") - set(USE_MSAN false) - #SET (CXX_FLAGS_EXTRA ${CXX_FLAGS_EXTRA} -fsanitize=memory -fsanitize-memory-track-origins=2 -fPIE) - #IF (${CLANG_USE_GCC_LINKER}) - #set (CMAKE_EXE_LINKER_FLAGS_EXTRA ${CMAKE_EXE_LINKER_FLAGS_EXTRA} -fsanitize=memory) - #ENDIF - #SET (PREPROCESSOR_DEFS_EXTRA ${PREPROCESSOR_DEFS_EXTRA} MEMORY_SANITIZER) - #SET (ENABLED_SANITIZER true) - endif() - if(${USE_LSAN}) - message(FATAL_ERROR "Windows Clang doesn't yet support LSAN") - set(USE_LSAN false) - #SET (CXX_FLAGS_EXTRA ${CXX_FLAGS_EXTRA} -fsanitize=leak) - #IF (${CLANG_USE_GCC_LINKER}) - #set (CMAKE_EXE_LINKER_FLAGS_EXTRA ${CMAKE_EXE_LINKER_FLAGS_EXTRA} -fsanitize=leak) - #ENDIF - #SET (PREPROCESSOR_DEFS_EXTRA ${PREPROCESSOR_DEFS_EXTRA} LEAK_SANITIZER) - #SET (ENABLED_SANITIZER true) - endif() - if(${USE_UBSAN}) - set(UBSAN_FLAGS - -fsanitize=undefined,float-divide-by-zero,local-bounds - -fno-sanitize=enum - # Supported? - -fsanitize=unsigned-integer-overflow #Unlike signed integer overflow, this is not undefined behavior, but it is often unintentional. - -fsanitize=implicit-conversion - ) - set(CXX_FLAGS_EXTRA ${CXX_FLAGS_EXTRA} ${UBSAN_FLAGS} -fsanitize=return) - #IF (${CLANG_USE_GCC_LINKER}) - #set (CMAKE_EXE_LINKER_FLAGS_EXTRA ${CMAKE_EXE_LINKER_FLAGS_EXTRA} -fsanitize=undefined) - #ENDIF - set(PREPROCESSOR_DEFS_EXTRA ${PREPROCESSOR_DEFS_EXTRA} UNDEFINED_BEHAVIOR_SANITIZER) - set(ENABLED_SANITIZER true) - endif() - - if(${ENABLED_SANITIZER}) - set(PREPROCESSOR_DEFS_EXTRA ${PREPROCESSOR_DEFS_EXTRA} _SANITIZERS) - if(${RUNTIME_STATIC_LINK}) - set(CMAKE_EXE_LINKER_FLAGS_EXTRA ${CMAKE_EXE_LINKER_FLAGS_EXTRA} -static-libsan) - else() - set(CMAKE_EXE_LINKER_FLAGS_EXTRA ${CMAKE_EXE_LINKER_FLAGS_EXTRA} -shared-libsan) - endif() - endif() - #-- Store compiler flags common to all builds. - set(cxx_local_opts_warnings - -Werror - -Wall - -Wextra - -Wno-unknown-pragmas - -Wno-switch - -Wno-implicit-fallthrough - -Wno-parentheses - -Wno-misleading-indentation - -Wno-conversion-null - -Wno-unused-result - -Wno-format-security # TODO: disable that when we'll have time to fix every printf format issue - # clang -specific: - # -fforce-emit-vtables - ) set(cxx_local_opts - -std=c++20 - -fexceptions - -fnon-call-exceptions - -pipe - -ffast-math -mno-ms-bitfields # -mno-ms-bitfields is needed to fix structure packing; # -pthread unused here? we only need to specify that to the linker? - -Wno-format-security # TODO: disable that when we'll have time to fix every printf format issue - # clang-specific: - # - # Flags supported by GCC but not by Clang: -fno-expensive-optimizations, -Wno-error=maybe-uninitialized ) - set(cxx_compiler_options_common ${cxx_local_opts_warnings} ${cxx_local_opts} ${CXX_FLAGS_EXTRA}) + set(cxx_compiler_options_common ${list_gnu_explicit_compiler_options_all} ${cxx_local_opts} ${CXX_FLAGS_EXTRA}) #-- Apply compiler flags, only the ones specific per build type. # -fno-omit-frame-pointer disables a good optimization which may corrupt the debugger stack trace. - set(COMPILE_OPTIONS_EXTRA) + set(local_compile_options_extra) if(ENABLED_SANITIZER OR TARGET spheresvr_debug) - set(COMPILE_OPTIONS_EXTRA -fno-omit-frame-pointer -fno-inline) + set(local_compile_options_extra -fno-omit-frame-pointer -fno-inline) endif() if(TARGET spheresvr_release) target_compile_options( spheresvr_release - PUBLIC -O3 -flto=full -fvirtual-function-elimination ${COMPILE_OPTIONS_EXTRA} + PUBLIC -O3 -flto=full -fvirtual-function-elimination ${local_compile_options_extra} ) #[[ IF (NOT ${CLANG_USE_GCC_LINKER}) @@ -156,11 +57,11 @@ function(toolchain_exe_stuff_common) endif() if(TARGET spheresvr_nightly) if(ENABLED_SANITIZER) - target_compile_options(spheresvr_nightly PUBLIC -ggdb3 -Og ${COMPILE_OPTIONS_EXTRA}) + target_compile_options(spheresvr_nightly PUBLIC -ggdb3 -Og ${local_compile_options_extra}) else() target_compile_options( spheresvr_nightly - PUBLIC -O3 -flto=full -fvirtual-function-elimination ${COMPILE_OPTIONS_EXTRA} + PUBLIC -O3 -flto=full -fvirtual-function-elimination ${local_compile_options_extra} ) endif() #[[ @@ -188,17 +89,13 @@ function(toolchain_exe_stuff_common) #-- Store common linker flags. - if(${USE_MSAN}) - set(CMAKE_EXE_LINKER_FLAGS_EXTRA ${CMAKE_EXE_LINKER_FLAGS_EXTRA} -pie) - endif() - set(cxx_linker_options_common ${CMAKE_EXE_LINKER_FLAGS_EXTRA}) if(${CLANG_USE_GCC_LINKER}) - set(cxx_linker_options_common ${cxx_linker_options_common} -pthread -dynamic -Wl,--fatal-warnings) + set(cxx_linker_options_common ${list_gnu_explicit_linker_options_all}) if(${RUNTIME_STATIC_LINK}) set(cxx_linker_options_common ${cxx_linker_options_common} -static-libstdc++ -static-libgcc) # no way to statically link against libc? maybe we can on windows? endif() - #[[ +#[[ else () if (${RUNTIME_STATIC_LINK}) set (cxx_linker_options_common ${cxx_linker_options_common} /MTd ) @@ -282,7 +179,7 @@ function(toolchain_exe_stuff_common) endif () endif() endif () -]] + ]] endif() set(libs_to_link_against ${libs_to_link_against} ws2_32 ${libs_prefix}mariadb) diff --git a/cmake/toolchains/include/Windows-GNU_common.inc.cmake b/cmake/toolchains/include/Windows-GNU_common.inc.cmake index efbffb09b..58f2866df 100644 --- a/cmake/toolchains/include/Windows-GNU_common.inc.cmake +++ b/cmake/toolchains/include/Windows-GNU_common.inc.cmake @@ -16,150 +16,38 @@ function(toolchain_exe_stuff_common) ## add_link_options ("LINKER:SHELL:-mwindows") #ENDIF () - #-- Validate sanitizers options and store them between the common compiler flags. - - set(ENABLED_SANITIZER false) - if(${USE_ASAN}) - message(FATAL_ERROR "MinGW-GCC doesn't yet support ASAN") - set(USE_ASAN false) - #[[ - SET (CXX_FLAGS_EXTRA ${CXX_FLAGS_EXTRA} - -fsanitize=address -fno-sanitize-recover=address #-fsanitize-cfi # cfi: control flow integrity, not currently supported by GCC (even on Linux) - -fsanitize-address-use-after-scope -fsanitize=pointer-compare -fsanitize=pointer-subtract - # Flags for additional instrumentation not strictly needing asan to be enabled - #-fvtable-verify=preinit # This causes a GCC internal error! Tested with 13.2.0 - -fstack-check -fstack-protector-all - -fcf-protection=full - # GCC 14? - #-fharden-control-flow-redundancy -fhardcfr-check-exceptions - # Other - #-fsanitize-trap=all - ) - ]] - #set (CMAKE_EXE_LINKER_FLAGS_EXTRA ${CMAKE_EXE_LINKER_FLAGS_EXTRA} -fsanitize=address $<$:-static-libasan>) - #SET (PREPROCESSOR_DEFS_EXTRA ${PREPROCESSOR_DEFS_EXTRA} ADDRESS_SANITIZER) - #SET (ENABLED_SANITIZER true) - endif() - if(${USE_MSAN}) - message(FATAL_ERROR "MinGW-GCC doesn't yet support MSAN") - set(USE_MSAN false) - #SET (CXX_FLAGS_EXTRA ${CXX_FLAGS_EXTRA} -fsanitize=memory -fsanitize-memory-track-origins=2 -fPIE) - #set (CMAKE_EXE_LINKER_FLAGS_EXTRA ${CMAKE_EXE_LINKER_FLAGS_EXTRA} -fsanitize=memory )#$<$:-static-libmsan>) - #SET (PREPROCESSOR_DEFS_EXTRA ${PREPROCESSOR_DEFS_EXTRA} MEMORY_SANITIZER) - #SET (ENABLED_SANITIZER true) - endif() - if(${USE_LSAN}) - message(FATAL_ERROR "MinGW-GCC doesn't yet support LSAN") - set(USE_LSAN false) - #SET (CXX_FLAGS_EXTRA ${CXX_FLAGS_EXTRA} -fsanitize=leak) - #set (CMAKE_EXE_LINKER_FLAGS_EXTRA ${CMAKE_EXE_LINKER_FLAGS_EXTRA} -fsanitize=leak #$<$:-static-liblsan>) - #SET (PREPROCESSOR_DEFS_EXTRA ${PREPROCESSOR_DEFS_EXTRA} LEAK_SANITIZER) - #SET (ENABLED_SANITIZER true) - endif() - if(${USE_UBSAN}) - message(FATAL_ERROR "MinGW-GCC doesn't yet support UBSAN") - set(USE_UBSAN false) - #[[ - SET (UBSAN_FLAGS - -fsanitize=undefined,float-divide-by-zero - -fno-sanitize=enum - # Unsupported (yet?) by GCC 13 - #-fsanitize=unsigned-integer-overflow #Unlike signed integer overflow, this is not undefined behavior, but it is often unintentional. - #-fsanitize=implicit-conversion, local-bounds - ) - ]] - #SET (CXX_FLAGS_EXTRA ${CXX_FLAGS_EXTRA} ${UBSAN_FLAGS} -fsanitize=return,vptr) - #set (CMAKE_EXE_LINKER_FLAGS_EXTRA ${CMAKE_EXE_LINKER_FLAGS_EXTRA} -fsanitize=undefined #$<$:-static-libubsan>) - #SET (PREPROCESSOR_DEFS_EXTRA ${PREPROCESSOR_DEFS_EXTRA} UNDEFINED_BEHAVIOR_SANITIZER) - #SET (ENABLED_SANITIZER true) - endif() - - #IF (${ENABLED_SANITIZER}) - # SET (PREPROCESSOR_DEFS_EXTRA ${PREPROCESSOR_DEFS_EXTRA} _SANITIZERS) - #ENDIF () - - #-- Store compiler flags common to all builds. - - set(cxx_local_opts_warnings - -Werror - -Wall - -Wextra - -Wpedantic - - -Wmissing-include-dirs # Warns when an include directory provided with -I does not exist. - -Wformat=2 - #-Wcast-qual # Warns about casts that remove a type's const or volatile qualifier. - #-Wconversion # Temporarily disabled. Warns about implicit type conversions that might change a value, such as narrowing conversions. - -Wdisabled-optimization - #-Winvalid-pch - -Wzero-as-null-pointer-constant - #-Wnull-dereference # Don't: on GCC 12 causes some false positives... - -Wduplicated-cond - - # Supported by Clang, but unsupported by GCC: - #-Wweak-vtables - - # Unsupported by Clang, but supported by GCC: - -Wtrampolines # Warns when trampolines (a technique to implement nested functions) are generated (don't want this for security reasons). - -Wvector-operation-performance - -Wsized-deallocation - -Wduplicated-cond - -Wshift-overflow=2 - - # Disable errors: - -Wno-format-nonliteral # Since -Wformat=2 is stricter, you would need to disable this warning. - -Wno-nonnull-compare # GCC only - -Wno-switch - -Wno-implicit-fallthrough - -Wno-parentheses - -Wno-misleading-indentation - -Wno-unused-result - -Wno-format-security # TODO: disable that when we'll have time to fix every printf format issue - -Wno-nested-anon-types - ) set(cxx_local_opts - -std=c++20 - -pthread - -fexceptions - -fnon-call-exceptions - -mno-ms-bitfields # it's needed to fix structure packing - -pipe - -ffast-math + -mno-ms-bitfields # it's needed to fix structure packing ) - set(cxx_compiler_options_common ${cxx_local_opts_warnings} ${cxx_local_opts} ${CXX_FLAGS_EXTRA}) + set(cxx_compiler_options_common ${list_gnu_explicit_compiler_options_all} ${cxx_local_opts} ${CXX_FLAGS_EXTRA}) #-- Apply compiler flags, only the ones specific per build type. # -fno-omit-frame-pointer disables a good optimization which may corrupt the debugger stack trace. - set(COMPILE_OPTIONS_EXTRA) + set(local_compile_options_extra) if(ENABLED_SANITIZER OR TARGET spheresvr_debug) - set(COMPILE_OPTIONS_EXTRA -fno-omit-frame-pointer -fno-inline) + set(local_compile_options_extra -fno-omit-frame-pointer -fno-inline) endif() if(TARGET spheresvr_release) - target_compile_options(spheresvr_release PUBLIC -s -O3 ${COMPILE_OPTIONS_EXTRA}) + target_compile_options(spheresvr_release PUBLIC -s -O3 ${local_compile_options_extra}) endif() if(TARGET spheresvr_nightly) if(ENABLED_SANITIZER) - target_compile_options(spheresvr_nightly PUBLIC -ggdb3 -Og ${COMPILE_OPTIONS_EXTRA}) + target_compile_options(spheresvr_nightly PUBLIC -ggdb3 -Og ${local_compile_options_extra}) else() - target_compile_options(spheresvr_nightly PUBLIC -O3 ${COMPILE_OPTIONS_EXTRA}) + target_compile_options(spheresvr_nightly PUBLIC -O3 ${local_compile_options_extra}) endif() endif() if(TARGET spheresvr_debug) - target_compile_options(spheresvr_debug PUBLIC -ggdb3 -O0 ${COMPILE_OPTIONS_EXTRA}) + target_compile_options(spheresvr_debug PUBLIC -ggdb3 -O0 ${local_compile_options_extra}) endif() #-- Store common linker flags. - if(${USE_MSAN}) - set(CMAKE_EXE_LINKER_FLAGS_EXTRA ${CMAKE_EXE_LINKER_FLAGS_EXTRA} -pie) - endif() set(cxx_linker_options_common + ${list_gnu_explicit_linker_options_all} ${CMAKE_EXE_LINKER_FLAGS_EXTRA} - -pthread - -dynamic - -Wl,--fatal-warnings $<$: -static-libstdc++ -static-libgcc> # no way to statically link against libc? maybe we can on windows? diff --git a/src/common/CExpression.cpp b/src/common/CExpression.cpp index 550a177ad..8a530cb15 100644 --- a/src/common/CExpression.cpp +++ b/src/common/CExpression.cpp @@ -1230,18 +1230,18 @@ int CExpression::GetConditionalSubexpressions(lptstr& pExpr, SubexprData(&psSube } // Helper lambda functions for the next section. - auto findLastClosingBracket = [](lptstr pExpr) -> lptstr + auto findLastClosingBracket = [](lptstr pExpr_) -> lptstr { // Returns a pointer to the last closing bracket in the string. // If the last character in the string (ignoring comments) is not ')', it means that, if we find a closing bracket, // it's past other characters, so there's other valid text after the ')'. // Eg: IF (1+2) > 10. The ')' is not at the end of the line, because there's the remaining part of the script. - ASSERT(*pExpr != '\0'); + ASSERT(*pExpr_ != '\0'); lptstr pExprFinder; - const size_t uiExprLength = strlen(pExpr); - const lptstr pComment = Str_FindSubstring(pExpr, "//", uiExprLength, 2); + const size_t uiExprLength = strlen(pExpr_); + const lptstr pComment = Str_FindSubstring(pExpr_, "//", uiExprLength, 2); if (nullptr == pComment) { - pExprFinder = pExpr + uiExprLength - 1; + pExprFinder = pExpr_ + uiExprLength - 1; // Now pExprFinder is at the end of the string } else { @@ -1256,28 +1256,28 @@ int CExpression::GetConditionalSubexpressions(lptstr& pExpr, SubexprData(&psSube --pExprFinder; else break; - } while (pExprFinder > pExpr); + } while (pExprFinder > pExpr_); return (*pExprFinder == ')') ? pExprFinder : nullptr; }; - auto skipBracketedSubexpression = [](lptstr pExpr) -> lptstr + auto skipBracketedSubexpression = [](lptstr pExpr_) -> lptstr { - ASSERT(*pExpr == '('); - tchar ch; + ASSERT(*pExpr_ == '('); + tchar ch_; uint uiOpenedCurlyBrackets = 1; while (uiOpenedCurlyBrackets != 0) // i'm interested only to the outermost range, not eventual sub-sub-sub-blah ranges { - ch = *(++pExpr); - if (ch == '(') + ch_ = *(++pExpr_); + if (ch_ == '(') ++uiOpenedCurlyBrackets; - else if (ch == ')') + else if (ch_ == ')') --uiOpenedCurlyBrackets; - else if (ch == '\0') + else if (ch_ == '\0') return nullptr; // Error } if (uiOpenedCurlyBrackets != 0) return nullptr; // Error - return pExpr; + return pExpr_; }; diff --git a/src/common/resource/sections/CDialogDef.cpp b/src/common/resource/sections/CDialogDef.cpp index f59e75719..ae31f1abb 100644 --- a/src/common/resource/sections/CDialogDef.cpp +++ b/src/common/resource/sections/CDialogDef.cpp @@ -144,25 +144,25 @@ bool CDialogDef::r_Verb( CScript & s, CTextConsole * pSrc ) // some command on t lptstr ptcArgs = s.GetArgStr(); //g_Log.EventDebug("Dialog index %d, KEY %s ARG %s.\n", index, ptcKey, ptcArgs); - const auto _SkipAll = [](lptstr& ptcArgs) noexcept -> void + const auto _SkipAll = [](lptstr& ptcArgs_) noexcept -> void { - SKIP_SEPARATORS(ptcArgs); - GETNONWHITESPACE(ptcArgs); + SKIP_SEPARATORS(ptcArgs_); + GETNONWHITESPACE(ptcArgs_); }; - const auto _CalcRelative = [](lptstr& ptcArgs, int &iCoordBase) -> int + const auto _CalcRelative = [](lptstr& ptcArgs_, int &iCoordBase_) -> int { int c; - if ( *ptcArgs == '-' && IsSpace(ptcArgs[1])) - c = iCoordBase, ++ptcArgs; - else if ( *ptcArgs == '+' ) - c = iCoordBase + Exp_GetSingle( ++ptcArgs ); - else if ( *ptcArgs == '-' ) - c = iCoordBase - Exp_GetSingle( ++ptcArgs ); - else if ( *ptcArgs == '*' ) - iCoordBase = c = iCoordBase + Exp_GetSingle( ++ptcArgs ); + if ( *ptcArgs_ == '-' && IsSpace(ptcArgs_[1])) + c = iCoordBase_, ++ptcArgs_; + else if ( *ptcArgs_ == '+' ) + c = iCoordBase_ + Exp_GetSingle( ++ptcArgs_ ); + else if ( *ptcArgs_ == '-' ) + c = iCoordBase_ - Exp_GetSingle( ++ptcArgs_ ); + else if ( *ptcArgs_ == '*' ) + iCoordBase_ = c = iCoordBase_ + Exp_GetSingle( ++ptcArgs_ ); else - c = Exp_GetSingle( ptcArgs ); + c = Exp_GetSingle( ptcArgs_ ); return c; }; diff --git a/src/game/chars/CCharUse.cpp b/src/game/chars/CCharUse.cpp index 8b9599e2f..56023d9f1 100644 --- a/src/game/chars/CCharUse.cpp +++ b/src/game/chars/CCharUse.cpp @@ -1125,9 +1125,9 @@ CChar * CChar::Use_Figurine( CItem * pItem, bool fCheckFollowerSlots ) std::optional iFollowerSlots; const bool fShouldCheckFollowerSlots = (fCheckFollowerSlots && IsSetOF(OF_PetSlots)); - auto _CheckFollowerSlots = [this](short iFollowerSlots) -> bool + auto _CheckFollowerSlots = [this](short iFollowerSlots_) -> bool { - if ( !FollowersUpdate(this, iFollowerSlots, true) ) + if ( !FollowersUpdate(this, iFollowerSlots_, true) ) { SysMessageDefault(DEFMSG_PETSLOTS_TRY_CONTROL); return false; diff --git a/src/game/components/CCSpawn.cpp b/src/game/components/CCSpawn.cpp index 7abcfe81a..746397e29 100644 --- a/src/game/components/CCSpawn.cpp +++ b/src/game/components/CCSpawn.cpp @@ -158,12 +158,12 @@ const CResourceDef* CCSpawn::_FixDef() if (pItem->IsType(IT_SPAWN_CHAR)) { - auto _TryChar = [this](CREID_TYPE idChar) -> const CResourceDef* + auto _TryChar = [this](CREID_TYPE idChar_) -> const CResourceDef* { - const CResourceDef* pResDef = CCharBase::FindCharBase(idChar); - if (pResDef) - _idSpawn = CResourceIDBase(RES_CHARDEF, idChar); - return pResDef; + const CResourceDef* pResDef_ = CCharBase::FindCharBase(idChar_); + if (pResDef_) + _idSpawn = CResourceIDBase(RES_CHARDEF, idChar_); + return pResDef_; }; CREID_TYPE idChar = (CREID_TYPE)iIndex; @@ -204,12 +204,12 @@ const CResourceDef* CCSpawn::_FixDef() } else if (pItem->IsType(IT_SPAWN_ITEM)) { - auto _TryItem = [this](ITEMID_TYPE idItem) -> const CResourceDef* + auto _TryItem = [this](ITEMID_TYPE idItem_) -> const CResourceDef* { - const CResourceDef* pResDef = CItemBase::FindItemBase(idItem); - if (pResDef) - _idSpawn = CResourceIDBase(RES_ITEMDEF, idItem); - return pResDef; + const CResourceDef* pResDef_ = CItemBase::FindItemBase(idItem_); + if (pResDef_) + _idSpawn = CResourceIDBase(RES_ITEMDEF, idItem_); + return pResDef_; }; ITEMID_TYPE idItem = (ITEMID_TYPE)iIndex; From 05b889d83c7bfc89954f7052da7096fc006011d6 Mon Sep 17 00:00:00 2001 From: cbnolok Date: Thu, 3 Oct 2024 13:19:48 +0200 Subject: [PATCH 61/86] Fixes and additions for FOLLOWERSLOTS, fix for LIST. - Fixed: LIST.ADD ignoring quoted arguments (Issue #1247). - Fixed: FOOD and MAXFOOD not being stored in the worldsave file (Issue #1289). - Added: CURFOLLOWER.CHARCOUNT, to return the raw number of characters you own/that are following you. Plain CURFOLLOWER returns the current total FOLLOWERSLOTS you own. - Changed: removed CURFOLLOWER.DEL and CURFOLLOWER.DELETE in favor of the more specific: CURFOLLOWER.DELUID: The same as .DEL/DELETE, just removed the pet via its UID. CURFOLLOWER.DELINDEX: Removes the pet via its id in the (cur)follower list for that owner. - Added: spells with SPELLFLAG_SUMMON now accept LOCAL.FollowerSlotsOverride in the triggers @Success and @SpellSuccess. Default value (do not override): -1. --- Changelog.txt | 9 ++ src/common/ListDefContMap.cpp | 37 ++++---- src/common/common.h | 7 +- src/game/chars/CChar.cpp | 46 +++++++++- src/game/chars/CChar.h | 2 +- src/game/chars/CCharSpell.cpp | 166 +++++++++++++++++++--------------- 6 files changed, 170 insertions(+), 97 deletions(-) diff --git a/Changelog.txt b/Changelog.txt index 210e47371..eb900a6b8 100644 --- a/Changelog.txt +++ b/Changelog.txt @@ -3902,3 +3902,12 @@ Added: 'H' shortcut for variables to get the value as hexadecimal. - Changed: added desired FollowerSlots as a second argument to CURFOLLOWER.ADD. Default value: its FollowerSlots. - Changed: @FollowerUpdate ARGN1 and ARGN2 are now read-only. Having them RW and actually get them working would have meant many other changes, breaking script compatibility. - Fixed: CURFOLLOWER.DEL/DELETE/CLEAR not working properly. + +03-10-2024, Nolok +- Fixed: LIST.ADD ignoring quoted arguments (Issue #1247). +- Fixed: FOOD and MAXFOOD not being stored in the worldsave file (Issue #1289). +- Added: CURFOLLOWER.CHARCOUNT, to return the raw number of characters you own/that are following you. Plain CURFOLLOWER returns the current total FOLLOWERSLOTS you own. +- Changed: removed CURFOLLOWER.DEL and CURFOLLOWER.DELETE in favor of the more specific: + CURFOLLOWER.DELUID: The same as .DEL/DELETE, just removed the pet via its UID. + CURFOLLOWER.DELINDEX: Removes the pet via its id in the (cur)follower list for that owner. +- Added: spells with SPELLFLAG_SUMMON now accept LOCAL.FollowerSlotsOverride in the triggers @Success and @SpellSuccess. Default value (do not override): -1. diff --git a/src/common/ListDefContMap.cpp b/src/common/ListDefContMap.cpp index 8d0d7c68b..d66757261 100644 --- a/src/common/ListDefContMap.cpp +++ b/src/common/ListDefContMap.cpp @@ -2,7 +2,6 @@ #include "../common/sphere_library/sstringobjs.h" #include "../common/CLog.h" #include "../sphere/threads.h" -#include "../game/CServerConfig.h" #include "CExpression.h" #include "CScript.h" #include "CTextConsole.h" @@ -269,7 +268,7 @@ bool CListDefCont::AddElementStr(lpctstr ptcKey) if ( (m_listElements.size() + 1) >= INTPTR_MAX ) // overflow? is it even useful? return false; - REMOVE_QUOTES( ptcKey ); + REMOVE_QUOTES( ptcKey ); m_listElements.emplace_back( new CListDefContStr(m_Key.GetBuffer(), ptcKey) ); @@ -774,14 +773,14 @@ bool CListDefMap::r_LoadVal( lpctstr ptcKey, CScript & s ) Str_Parse(ppCmds[0], &(ppCmds[1]), "." ); CListDefCont* pListBase = GetKey(ppCmds[0]); - lpctstr ptcArg = s.GetArgRaw(); + lpctstr ptcArg = s.GetArgRaw(); // LIST. if ( ppCmds[1] && *(ppCmds[1]) ) { Str_Parse(ppCmds[1], &(ppCmds[2]), "." ); - if ( !IsSimpleNumberString(ppCmds[1]) ) + if ( !IsStrNumeric(ppCmds[1]) ) { // LIST.. // Am i calling a valid operation? @@ -806,7 +805,7 @@ bool CListDefMap::r_LoadVal( lpctstr ptcKey, CScript & s ) m_Container.insert(pListBase); } - if ( IsSimpleNumberString(ptcArg) ) + if ( IsStrNumeric(ptcArg) ) return pListBase->AddElementNum(Exp_Get64Val(ptcArg)); else return pListBase->AddElementStr(ptcArg); @@ -830,22 +829,22 @@ bool CListDefMap::r_LoadVal( lpctstr ptcKey, CScript & s ) m_Container.insert(pListBase); } - tchar* ppCmd[2]; - ppCmd[0] = const_cast(ptcArg); - while ( Str_Parse( ppCmd[0], &(ppCmd[1]), "," )) + tchar* ppArgs[2]; + ppArgs[0] = const_cast(ptcArg); + while ( Str_Parse( ppArgs[0], &(ppArgs[1]), "," )) { - if ( IsSimpleNumberString(ppCmd[0]) ) - pListBase->AddElementNum(Exp_Get64Val(ppCmd[0])); + if ( IsStrNumeric(ppArgs[0]) ) + pListBase->AddElementNum(Exp_Get64Val(ppArgs[0])); else - pListBase->AddElementStr(ppCmd[0]); - ppCmd[0] = ppCmd[1]; + pListBase->AddElementStr(ppArgs[0]); + ppArgs[0] = ppArgs[1]; } //insert last element - if ( IsSimpleNumberString(ppCmd[0]) ) - return pListBase->AddElementNum(Exp_Get64Val(ppCmd[0])); + if ( IsStrNumeric(ppArgs[0]) ) + return pListBase->AddElementNum(Exp_Get64Val(ppArgs[0])); else - return pListBase->AddElementStr(ppCmd[0]); + return pListBase->AddElementStr(ppArgs[0]); } else if ( !strnicmp(ppCmds[1], "sort", 4) ) { @@ -889,7 +888,7 @@ bool CListDefMap::r_LoadVal( lpctstr ptcKey, CScript & s ) else if ( !strnicmp(ppCmds[2], "insert", 6) && ptcArg && *ptcArg ) { // Inserts at the nth index of LIST.xxx - const bool fIsNum = ( IsSimpleNumberString(ptcArg) ); + const bool fIsNum = ( IsStrNumeric(ptcArg) ); if ( nIndex >= pListBase->GetCount() ) { @@ -918,7 +917,7 @@ bool CListDefMap::r_LoadVal( lpctstr ptcKey, CScript & s ) if ( !pListElem ) return false; - if ( IsSimpleNumberString(ptcArg) ) + if ( IsStrNumeric(ptcArg) ) return pListBase->SetNumAt(nIndex, Exp_Get64Val(ptcArg)); else return pListBase->SetStrAt(nIndex, ptcArg); @@ -933,7 +932,7 @@ bool CListDefMap::r_LoadVal( lpctstr ptcKey, CScript & s ) pListBase = new CListDefCont(ppCmds[0]); m_Container.insert(pListBase); - if ( IsSimpleNumberString(ptcArg) ) + if ( IsStrNumeric(ptcArg) ) return pListBase->AddElementNum(Exp_Get64Val(ptcArg)); else return pListBase->AddElementStr(ptcArg); @@ -953,7 +952,7 @@ bool CListDefMap::r_LoadVal( lpctstr ptcKey, CScript & s ) m_Container.insert(pListBase); } - if ( IsSimpleNumberString(ptcArg) ) + if ( IsStrNumeric(ptcArg) ) return pListBase->AddElementNum(Exp_Get64Val(ptcArg)); else return pListBase->AddElementStr(ptcArg); diff --git a/src/common/common.h b/src/common/common.h index 65b68040d..5e75cc24a 100644 --- a/src/common/common.h +++ b/src/common/common.h @@ -131,8 +131,9 @@ constexpr T sign(const T n) noexcept /* Compiler/c++ language helpers */ // Ensure that a constexpr value or a generic expression is evaluated at compile time. +// Constexpr values are constants and cannot be mutated in the code. template -consteval T ensure_comptime(T&& val_) noexcept { +consteval T as_consteval(T&& val_) noexcept { return val_; } @@ -172,6 +173,10 @@ constexpr void UnreferencedParameter(T const&) noexcept { // Function specifier, like noexcept. Use this to make us know that the function code was checked and we know it can throw an exception. #define CANTHROW noexcept(false) +// To be used only as an helper marker, since there are functions with similar names intended to have different signatures and/or not be virtual. +// This means that we do NOT have forgotten to add the "virtual" qualifier, simply this method isn't virtual. +#define NONVIRTUAL + // Cpp attributes #define FALLTHROUGH [[fallthrough]] #define NODISCARD [[nodiscard]] diff --git a/src/game/chars/CChar.cpp b/src/game/chars/CChar.cpp index 42802a5b6..37058219e 100644 --- a/src/game/chars/CChar.cpp +++ b/src/game/chars/CChar.cpp @@ -2355,12 +2355,24 @@ bool CChar::r_WriteVal( lpctstr ptcKey, CSString & sVal, CTextConsole * pSrc, bo if (strlen(ptcKey) == 11) { + // This returns the total current follower slots. sVal.FormatSVal(GetCurFollowers()); return true; } sVal.FormatVal(0); ptcKey += 11; + if (*ptcKey != '.') + return false; + ptcKey += 1; + + if (!strnicmp(ptcKey, "CHARCOUNT", 9)) + { + sVal.FormatSTVal(m_followers.size()); + return true; + } + + // Access objects by ID. if (*ptcKey != '.' || m_followers.empty()) return false; @@ -3508,7 +3520,7 @@ bool CChar::r_LoadVal( CScript & s ) if (!s.HasArgs()) return false; - if (!strnicmp(ptcKey, "DELETE", 6) || !strnicmp(ptcKey, "DEL", 3)) + if (!strnicmp(ptcKey, "DELUID", 6)) { if (m_followers.empty()) return false; @@ -3533,6 +3545,28 @@ bool CChar::r_LoadVal( CScript & s ) return true; } + if (!strnicmp(ptcKey, "DELINDEX", 6)) + { + if (m_followers.empty()) + return false; + + const uint uiIndex = s.GetArgUVal(); + if (uiIndex >= m_followers.size()) + return false; + + CChar *pChar = m_followers[uiIndex].uid.CharFind(); + m_followers.erase(m_followers.begin() + uiIndex); + + if (!pChar) + { + g_Log.EventWarn("Follower with index %u is an invalid char! (Owner: 0%" PRIx32 ".)\n", uiIndex, GetUID().GetObjUID()); + return true; + } + + pChar->NPC_PetClearOwners(); + return true; + } + if (!strnicmp(ptcKey, "ADD", 3)) { int64 piCmd[2]; @@ -4163,10 +4197,14 @@ void CChar::r_Write( CScript & s ) s.WriteKeyVal("OFAME", GetFame() ); int iVal; - if ((iVal = Stat_GetMod(STAT_FOOD)) != 0) - s.WriteKeyVal("MODFOOD", iVal); + //if ((iVal = Stat_GetMod(STAT_FOOD)) != 0) + // s.WriteKeyVal("MODFOOD", iVal); if ((iVal = Stat_GetBase(STAT_FOOD)) != Char_GetDef()->m_MaxFood) s.WriteKeyVal("OFOOD", iVal); + if ((iVal = Stat_GetMaxMod(STAT_FOOD)) != 0) + s.WriteKeyVal("MODMAXFOOD", iVal); + if ((iVal = Stat_GetMax(STAT_FOOD)) != 0) + s.WriteKeyVal("MAXFOOD", iVal); s.WriteKeyVal("FOOD", Stat_GetVal(STAT_FOOD)); static constexpr lpctstr _ptcKeyModStat[STAT_BASE_QTY] = @@ -4182,7 +4220,7 @@ void CChar::r_Write( CScript & s ) "ODEX" }; - for (int j = 0; j < STAT_BASE_QTY; ++j) + for (int j = 0; j < STAT_BASE_QTY; ++j) { // this is VERY important, saving the MOD first if ((iVal = Stat_GetMod((STAT_TYPE)j)) != 0) diff --git a/src/game/chars/CChar.h b/src/game/chars/CChar.h index 20a4bd212..67580ceab 100644 --- a/src/game/chars/CChar.h +++ b/src/game/chars/CChar.h @@ -1019,7 +1019,7 @@ public: void StatFlag_Mod(uint64 uiStatFlag, bool fMod) noexcept; bool Spell_CastDone(); virtual bool OnSpellEffect( SPELL_TYPE spell, CChar * pCharSrc, int iSkillLevel, CItem * pSourceItem, bool fReflecting = false, int64 iDuration = 0) override; bool Spell_CanCast( SPELL_TYPE &spellRef, bool fTest, CObjBase * pSrc, bool fFailMsg, bool fCheckAntiMagic = true ); - CChar* Spell_Summon_Try(SPELL_TYPE spell, CPointMap ptTarg, CREID_TYPE uiCreature); + CChar* Spell_Summon_Try(SPELL_TYPE spell, CPointMap ptTarg, CREID_TYPE uiCreature, std::optional iFollowerSlotsOverride); int64 GetSpellDuration( SPELL_TYPE spell, int iSkillLevel, CChar * pCharSrc = nullptr ); // in tenths of second // Memories about objects in the world. ------------------- diff --git a/src/game/chars/CCharSpell.cpp b/src/game/chars/CCharSpell.cpp index f96cbefad..8e7d62f1f 100644 --- a/src/game/chars/CCharSpell.cpp +++ b/src/game/chars/CCharSpell.cpp @@ -2498,7 +2498,7 @@ bool CChar::Spell_CanCast( SPELL_TYPE &spellRef, bool fTest, CObjBase * pSrc, bo return true; } -CChar * CChar::Spell_Summon_Try(SPELL_TYPE spell, CPointMap ptTarg, CREID_TYPE uiCreature) +CChar * CChar::Spell_Summon_Try(SPELL_TYPE spell, CPointMap ptTarg, CREID_TYPE uiCreature, std::optional iFollowerSlotsOverride) { ADDTOCALLSTACK("CChar::Spell_CanSummon"); //Create the NPC and check if we can actually place it in the world, but do not place it yet. @@ -2618,7 +2618,7 @@ CChar * CChar::Spell_Summon_Try(SPELL_TYPE spell, CPointMap ptTarg, CREID_TYPE u if (IsSetOF(OF_PetSlots)) { - short iFollowerSlots = pChar->GetFollowerSlots(); + short iFollowerSlots = iFollowerSlotsOverride.has_value() ? iFollowerSlotsOverride.value() : pChar->GetFollowerSlots(); if (!FollowersUpdate(pChar, iFollowerSlots, true)) { SysMessageDefault(DEFMSG_PETSLOTS_TRY_SUMMON); @@ -2841,22 +2841,11 @@ bool CChar::Spell_CastDone() CObjBase * pObjSrc = m_Act_Prv_UID.ObjFind(); CChar* pSummon = nullptr; - ITEMID_TYPE iT1 = ITEMID_NOTHING; - ITEMID_TYPE iT2 = ITEMID_NOTHING; - CREID_TYPE iC1 = CREID_INVALID; - HUE_TYPE iColor = HUE_DEFAULT; - - uint fieldWidth = 0; - uint fieldGauge = 0; - uint areaRadius = 0; - SPELL_TYPE spell = m_atMagery.m_iSpell; const CSpellDef * pSpellDef = g_Cfg.GetSpellDef(spell); if (pSpellDef == nullptr) return false; - const bool fIsSpellField = pSpellDef->IsSpellType(SPELLFLAG_FIELD); - int iSkill, iDifficulty; if (!pSpellDef->GetPrimarySkill(&iSkill, &iDifficulty)) return false; @@ -2881,28 +2870,52 @@ bool CChar::Spell_CastDone() if ( (iSkill == SKILL_MYSTICISM) && (g_Cfg.m_iRacialFlags & RACIALF_GARG_MYSTICINSIGHT) && (iSkillLevel < 300) && IsGargoyle() ) iSkillLevel = 300; // Racial trait (Mystic Insight). Gargoyles always have a minimum of 30.0 Mysticism. - CScriptTriggerArgs Args(spell, iSkillLevel, pObjSrc); - Args.m_VarsLocal.SetNum("fieldWidth", 0); - Args.m_VarsLocal.SetNum("fieldGauge", 0); - Args.m_VarsLocal.SetNum("areaRadius", 0); - Args.m_VarsLocal.SetNum("duration", GetSpellDuration(spell, iSkillLevel, this), true); // tenths of second + const bool fIsSpellArea = pSpellDef->IsSpellType(SPELLFLAG_AREA); + const bool fIsSpellField = pSpellDef->IsSpellType(SPELLFLAG_FIELD); + const bool fIsSpellSummon = pSpellDef->IsSpellType(SPELLFLAG_SUMMON); + + HUE_TYPE uiColor = HUE_DEFAULT; + ITEMID_TYPE uiCreatedItemID_1 = ITEMID_NOTHING; + ITEMID_TYPE uiCreatedItemID_2 = ITEMID_NOTHING; + CREID_TYPE uiSummonedCreatureID = CREID_INVALID; + short iFollowerSlotsOverride = -1; + + uint uiFieldWidth = 0; + uint uiFieldGauge = 0; + uint uiAreaRadius = 0; + + CScriptTriggerArgs Args(spell, iSkillLevel, pObjSrc); + Args.m_VarsLocal.SetNum("Duration", GetSpellDuration(spell, iSkillLevel, this), true); // tenths of second + + if (fIsSpellArea) + { + Args.m_VarsLocal.SetNum("AreaRadius", 0); + } if (fIsSpellField) { + Args.m_VarsLocal.SetNum("FieldWidth", 0); + Args.m_VarsLocal.SetNum("FieldGauge", 0); + switch (spell) // Only setting ids and locals for field spells { - case SPELL_Wall_of_Stone: iT1 = ITEMID_STONE_WALL; iT2 = ITEMID_STONE_WALL; break; - case SPELL_Fire_Field: iT1 = ITEMID_FX_FIRE_F_EW; iT2 = ITEMID_FX_FIRE_F_NS; break; - case SPELL_Poison_Field: iT1 = ITEMID_FX_POISON_F_EW; iT2 = ITEMID_FX_POISON_F_NS; break; - case SPELL_Paralyze_Field: iT1 = ITEMID_FX_PARA_F_EW; iT2 = ITEMID_FX_PARA_F_NS; break; - case SPELL_Energy_Field: iT1 = ITEMID_FX_ENERGY_F_EW; iT2 = ITEMID_FX_ENERGY_F_NS; break; + case SPELL_Wall_of_Stone: uiCreatedItemID_1 = ITEMID_STONE_WALL; uiCreatedItemID_2 = ITEMID_STONE_WALL; break; + case SPELL_Fire_Field: uiCreatedItemID_1 = ITEMID_FX_FIRE_F_EW; uiCreatedItemID_2 = ITEMID_FX_FIRE_F_NS; break; + case SPELL_Poison_Field: uiCreatedItemID_1 = ITEMID_FX_POISON_F_EW; uiCreatedItemID_2 = ITEMID_FX_POISON_F_NS; break; + case SPELL_Paralyze_Field: uiCreatedItemID_1 = ITEMID_FX_PARA_F_EW; uiCreatedItemID_2 = ITEMID_FX_PARA_F_NS; break; + case SPELL_Energy_Field: uiCreatedItemID_1 = ITEMID_FX_ENERGY_F_EW; uiCreatedItemID_2 = ITEMID_FX_ENERGY_F_NS; break; default: break; } - Args.m_VarsLocal.SetNum("CreateObject1", iT1, false); - Args.m_VarsLocal.SetNum("CreateObject2", iT2, false); + Args.m_VarsLocal.SetNum("CreateObject1", uiCreatedItemID_1, false); + Args.m_VarsLocal.SetNum("CreateObject2", uiCreatedItemID_2, false); } + if (fIsSpellSummon) + { + Args.m_VarsLocal.SetNum("FollowerSlotsOverride", iFollowerSlotsOverride); + } + if (IsTrigUsed(TRIGGER_SPELLSUCCESS)) { if (OnTrigger(CTRIG_SpellSuccess, this, &Args) == TRIGRET_RET_TRUE) @@ -2925,58 +2938,67 @@ bool CChar::Spell_CastDone() //Setting new IDs as another variables to pass as different arguments to the field function. it1test = (ITEMID_TYPE)(ResGetIndex((dword)Args.m_VarsLocal.GetKeyNum("CreateObject1"))); it2test = (ITEMID_TYPE)(ResGetIndex((dword)Args.m_VarsLocal.GetKeyNum("CreateObject2"))); - fieldWidth = (uint)Args.m_VarsLocal.GetKeyNum("fieldWidth"); - fieldGauge = (uint)Args.m_VarsLocal.GetKeyNum("fieldGauge"); + uiFieldWidth = (uint)Args.m_VarsLocal.GetKeyNum("FieldWidth"); + uiFieldGauge = (uint)Args.m_VarsLocal.GetKeyNum("FieldGauge"); } - iC1 = (CREID_TYPE)(Args.m_VarsLocal.GetKeyNum("CreateObject1") & 0xFFFF); - areaRadius = (uint)Args.m_VarsLocal.GetKeyNum("areaRadius"); - int iDuration = (int)(Args.m_VarsLocal.GetKeyNum("duration")); - iDuration = maximum(0, iDuration); - iColor = (HUE_TYPE)(Args.m_VarsLocal.GetKeyNum("EffectColor")); + uiSummonedCreatureID = (CREID_TYPE)(Args.m_VarsLocal.GetKeyNum("CreateObject1") & 0xFFFF); + uiAreaRadius = (uint)Args.m_VarsLocal.GetKeyNum("AreaRadius"); + int iDuration = (int)(std::max((int64)0, Args.m_VarsLocal.GetKeyNum("Duration"))); + uiColor = (HUE_TYPE)(Args.m_VarsLocal.GetKeyNum("EffectColor")); - if (pSpellDef->IsSpellType(SPELLFLAG_SUMMON)) + if (fIsSpellSummon) { + iFollowerSlotsOverride = n64_narrow_n16(Args.m_VarsLocal.GetKeyNum("FollowerSlotsOverride")); + if (!pSpellDef->IsSpellType(SPELLFLAG_TARG_OBJ | SPELLFLAG_TARG_XYZ)) m_Act_p = GetTopPoint(); - pSummon = Spell_Summon_Try(spell, m_Act_p, iC1); + std::optional iMaybeOverride; + if (iFollowerSlotsOverride != -1) + iMaybeOverride = iFollowerSlotsOverride; + pSummon = Spell_Summon_Try(spell, m_Act_p, uiSummonedCreatureID, iMaybeOverride); if (!pSummon) { return false; } } + // Consume the reagents/mana/scroll/charge if (!Spell_CanCast(spell, false, pObjSrc, true)) + { + if (pSummon) + pSummon->Delete(true); return false; + } if (pSpellDef->IsSpellType(SPELLFLAG_SCRIPTED)) { - if (pSpellDef->IsSpellType(SPELLFLAG_SUMMON)) + if (fIsSpellSummon) { Spell_Summon_Place(pSummon, m_Act_p, iDuration); } else if (fIsSpellField) { - if (iT1 && iT2) + if (uiCreatedItemID_1 && uiCreatedItemID_2) { - if (!fieldWidth) - fieldWidth = 3; - if (!fieldGauge) - fieldGauge = 1; + if (!uiFieldWidth) + uiFieldWidth = 3; + if (!uiFieldGauge) + uiFieldGauge = 1; - Spell_Field(m_Act_p, iT1, iT2, fieldWidth, fieldGauge, iSkillLevel, this, it1test, it2test, iDuration, iColor); + Spell_Field(m_Act_p, uiCreatedItemID_1, uiCreatedItemID_2, uiFieldWidth, uiFieldGauge, iSkillLevel, this, it1test, it2test, iDuration, uiColor); } } - else if (pSpellDef->IsSpellType(SPELLFLAG_AREA)) + else if (fIsSpellArea) { - if (!areaRadius) - areaRadius = 4; + if (!uiAreaRadius) + uiAreaRadius = 4; if (!pSpellDef->IsSpellType(SPELLFLAG_TARG_OBJ | SPELLFLAG_TARG_XYZ)) - Spell_Area(GetTopPoint(), areaRadius, iSkillLevel, iDuration); + Spell_Area(GetTopPoint(), uiAreaRadius, iSkillLevel, iDuration); else - Spell_Area(m_Act_p, areaRadius, iSkillLevel, iDuration); + Spell_Area(m_Act_p, uiAreaRadius, iSkillLevel, iDuration); } else if (pSpellDef->IsSpellType(SPELLFLAG_POLY)) return false; @@ -2988,45 +3010,45 @@ bool CChar::Spell_CastDone() } else if (fIsSpellField) { - if (!fieldWidth) - fieldWidth = 3; - if (!fieldGauge) - fieldGauge = 1; + if (!uiFieldWidth) + uiFieldWidth = 3; + if (!uiFieldGauge) + uiFieldGauge = 1; - Spell_Field(m_Act_p, iT1, iT2, fieldWidth, fieldGauge, iSkillLevel, this, it1test, it2test, iDuration, iColor); + Spell_Field(m_Act_p, uiCreatedItemID_1, uiCreatedItemID_2, uiFieldWidth, uiFieldGauge, iSkillLevel, this, it1test, it2test, iDuration, uiColor); } - else if (pSpellDef->IsSpellType(SPELLFLAG_AREA)) + else if (fIsSpellArea) { - if (!areaRadius) + if (!uiAreaRadius) { switch (spell) { - case SPELL_Arch_Cure: areaRadius = 2; break; - case SPELL_Arch_Prot: areaRadius = 3; break; - case SPELL_Mass_Curse: areaRadius = 2; break; - case SPELL_Reveal: areaRadius = 1 + (iSkillLevel / 200); break; - case SPELL_Chain_Lightning: areaRadius = 2; break; - case SPELL_Mass_Dispel: areaRadius = 8; break; - case SPELL_Meteor_Swarm: areaRadius = 2; break; - case SPELL_Earthquake: areaRadius = 1 + (iSkillLevel / 150); break; - case SPELL_Poison_Strike: areaRadius = 2; break; - case SPELL_Wither: areaRadius = 4; break; - default: areaRadius = 4; break; + case SPELL_Arch_Cure: uiAreaRadius = 2; break; + case SPELL_Arch_Prot: uiAreaRadius = 3; break; + case SPELL_Mass_Curse: uiAreaRadius = 2; break; + case SPELL_Reveal: uiAreaRadius = 1 + (iSkillLevel / 200); break; + case SPELL_Chain_Lightning: uiAreaRadius = 2; break; + case SPELL_Mass_Dispel: uiAreaRadius = 8; break; + case SPELL_Meteor_Swarm: uiAreaRadius = 2; break; + case SPELL_Earthquake: uiAreaRadius = 1 + (iSkillLevel / 150); break; + case SPELL_Poison_Strike: uiAreaRadius = 2; break; + case SPELL_Wither: uiAreaRadius = 4; break; + default: uiAreaRadius = 4; break; } } if (!pSpellDef->IsSpellType(SPELLFLAG_TARG_OBJ | SPELLFLAG_TARG_XYZ)) - Spell_Area(GetTopPoint(), areaRadius, iSkillLevel, iDuration); + Spell_Area(GetTopPoint(), uiAreaRadius, iSkillLevel, iDuration); else - Spell_Area(m_Act_p, areaRadius, iSkillLevel, iDuration); + Spell_Area(m_Act_p, uiAreaRadius, iSkillLevel, iDuration); } - else if (pSpellDef->IsSpellType(SPELLFLAG_SUMMON)) + else if (fIsSpellSummon) { Spell_Summon_Place(pSummon, m_Act_p, iDuration); } else { - iT1 = it1test; // Set iT1 to it1test here because spell_field() needed both values to be passed. + uiCreatedItemID_1 = it1test; // Set iT1 to it1test here because spell_field() needed both values to be passed. switch (spell) { @@ -3035,7 +3057,7 @@ bool CChar::Spell_CastDone() case SPELL_Create_Food: { const CResourceID ridFoodDefault = g_Cfg.ResourceGetIDType(RES_ITEMDEF, "DEFFOOD"); - const ITEMID_TYPE idFood = ((iT1 > ITEMID_NOTHING) ? iT1 : (ITEMID_TYPE)(ridFoodDefault.GetResIndex())); + const ITEMID_TYPE idFood = ((uiCreatedItemID_1 > ITEMID_NOTHING) ? uiCreatedItemID_1 : (ITEMID_TYPE)(ridFoodDefault.GetResIndex())); CItem *pItem = CItem::CreateScript(idFood, this); ASSERT(pItem); if (pSpellDef->IsSpellType(SPELLFLAG_TARG_OBJ|SPELLFLAG_TARG_XYZ)) @@ -3112,12 +3134,12 @@ bool CChar::Spell_CastDone() case SPELL_Flame_Strike: { // Display spell. - if (!iT1) - iT1 = ITEMID_FX_FLAMESTRIKE; + if (!uiCreatedItemID_1) + uiCreatedItemID_1 = ITEMID_FX_FLAMESTRIKE; if (pObj == nullptr) { - EffectLocation(EFFECT_XYZ, iT1, nullptr, &m_Act_p, 20, 30); + EffectLocation(EFFECT_XYZ, uiCreatedItemID_1, nullptr, &m_Act_p, 20, 30); } else { From b75a9c949e2d77d27de1aa38387d029ff6240946 Mon Sep 17 00:00:00 2001 From: cbnolok Date: Thu, 3 Oct 2024 13:24:33 +0200 Subject: [PATCH 62/86] Refactoring and small additions to CompilerFlagsChecker.cmake. --- CMakeLists.txt | 15 +- cmake/CompilerFlagsChecker.cmake | 434 ++++++++++-------- cmake/toolchains/Windows-GNU-x86_64.cmake | 2 +- cmake/toolchains/Windows-MSVC.cmake | 7 +- .../include/Linux-Clang_common.inc.cmake | 4 +- .../include/Linux-GNU_common.inc.cmake | 4 +- .../include/OSX-AppleClang_common.inc.cmake | 4 +- .../include/Windows-Clang_common.inc.cmake | 4 +- .../include/Windows-GNU_common.inc.cmake | 4 +- lib/lib_build_flags_common_c.cmake | 9 +- src/common/sphere_library/CSString.h | 2 + 11 files changed, 268 insertions(+), 221 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 295f32bd4..9554694a9 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -4,6 +4,10 @@ cmake_minimum_required(VERSION 3.24) set(CMAKE_SUPPRESS_REGENERATION TRUE) # Supress the ZERO_CHECK generation # -------------------- GUI checkboxes -------------------- +if(NOT MSVC) + set (CMAKE_BUILD_TYPE "Nightly" CACHE STRING "Which build type to build? Expected values: Debug, Nightly or Release.") +endif() + option( CMAKE_NO_GIT_REVISION "Do not try to retrieve the current git revision. Useful for building source not git-cloned from Github." @@ -35,7 +39,7 @@ option(USE_UBSAN "Enable Undefined Behavior Sanitizer." FALSE) option(USE_LSAN "Enable LeakSanitizer." FALSE) option(USE_MSAN "Enable MemorySanitizer." FALSE) -set(ENABLED_SANITIZER FALSE) +set(ENABLED_SANITIZER CACHE INTERNAL BOOL FALSE) if(USE_ASAN OR USE_MSAN OR USE_LSAN OR USE_MSAN) set(ENABLED_SANITIZER TRUE) endif() @@ -81,7 +85,7 @@ set(CMAKE_CXX_EXTENSIONS OFF) set(CMAKE_SHARED_LIBRARY_LINK_C_FLAGS "") set(CMAKE_SHARED_LIBRARY_LINK_CXX_FLAGS "") -# CMake also sets other predefined flags, which we don't want? +# In some cases, CMake also sets other predefined flags, which we don't want. #[[ set(CMAKE_C_FLAGS "") set(CMAKE_C_FLAGS_DEBUG "") @@ -98,6 +102,10 @@ set(CMAKE_EXE_LINKER_FLAGS_DEBUG "") set(CMAKE_EXE_LINKER_FLAGS_NIGHTLY "") set(CMAKE_EXE_LINKER_FLAGS_RELEASE "") ]] +# Example: using MSVC, /RTC1 is globally added (all projects) to DEBUG builds. It's mostly fine, except in some cases where we don't want it... +# We might want to delete only /RTC* flags, instead of erasing all of them altogether. +#STRING (REGEX REPLACE "/RTC(su|[1su])" "" CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG}") +#STRING (REGEX REPLACE "/RTC(su|[1su])" "" CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG}") set(is_win32_app_linker) if(WIN32 AND NOT ${WIN32_SPAWN_CONSOLE}) @@ -136,7 +144,7 @@ if(SINGLE_TARGET) AND (NOT ${CMAKE_BUILD_TYPE} STREQUAL "Debug") AND (NOT ${CMAKE_BUILD_TYPE} STREQUAL "Nightly") ) - message(WARNING "Invalid parameter -DCMAKE_BUILD_TYPE, defaulting to Nightly.") + message(WARNING "Invalid parameter CMAKE_BUILD_TYPE (${CMAKE_BUILD_TYPE}), defaulting to Nightly.") # -> needed only for MAKEFILE-STYLE generators, which can't switch between different configs set(CMAKE_BUILD_TYPE "Nightly" CACHE STRING "" FORCE) else() @@ -250,7 +258,6 @@ message(STATUS) message(STATUS "Configuring external libraries...") add_subdirectory(lib) -message(STATUS) toolchain_exe_stuff() # stuff to be executed after ADD_EXECUTABLE # Get the Git revision number diff --git a/cmake/CompilerFlagsChecker.cmake b/cmake/CompilerFlagsChecker.cmake index 039af7d1e..2cd570296 100644 --- a/cmake/CompilerFlagsChecker.cmake +++ b/cmake/CompilerFlagsChecker.cmake @@ -14,7 +14,7 @@ if(NOT MSVC) -pipe -ffast-math ) - list(APPEND compiler_options_warning_base -Werror;-Wall;-Wextra;-Wpedantic) + list(APPEND base_compiler_options_warning -Werror;-Wall;-Wextra;-Wpedantic) # Compiler option flags. Common to both compilers, but older versions might not support the following. #check_cxx_compiler_flag("" COMP_HAS_) @@ -105,6 +105,15 @@ See comments in the toolchain and: https://github.com/google/sanitizers/wiki/Mem check_cxx_compiler_flag("-fPIE" COMP_HAS_F_PIE) endif() + if(ENABLED_SANITIZER) + if(RUNTIME_STATIC_LINK) + check_cxx_compiler_flag("-fstatic-libasan" COMP_HAS_F_STATIC_LIBASAN) + if(NOT COMP_HAS_F_STATIC_LIBASAN) + message(FATAL_ERROR "This compiler doesn't support statically linking libasan. Turn off RUNTIME_STATIC_LINK?") + endif() + endif() + endif() + if(USE_COMPILER_HARDENING_OPTIONS) message(STATUS "-- Compilation options (code hardening):") # Compiler option flags. Other sanitizers or code hardening. @@ -171,215 +180,232 @@ See comments in the toolchain and: https://github.com/google/sanitizers/wiki/Mem check_cxx_compiler_flag("-Wnested-anon-types" COMP_HAS_WNO_NESTED_ANON_TYPES) check_cxx_compiler_flag("-Wformat-security" COMP_HAS_WNO_FORMAT_SECURITY) # TODO: remove that when we'll have time to fix every printf format issue check_cxx_compiler_flag("-Wdeprecated-declarations" COMP_HAS_WNO_DEPRECATED_DECLARATIONS) + check_cxx_compiler_flag("-Wlanguage-extension-token" COMP_HAS_WNO_LANGUAGE_EXTENSION_TOKEN) #check_cxx_compiler_flag("-Wunknown-pragmas" COMP_HAS_) #check_cxx_compiler_flag("" COMP_HAS_) -else(NOT MSVC) + +elseif(MSVC) # Compiler warning flags (MSVC). message(STATUS "-- Compilation options (MSVC):") - check_cxx_compiler_flag("/Wd5105" COMP_HAS_DEFINE_MACRO_EXPANSION) # False positive warning, maybe even a MSVC bug. + check_cxx_compiler_flag("/W5105" COMP_HAS_W_DEFINE_MACRO_EXPANSION) # False positive warning, maybe even a MSVC bug. #check_cxx_compiler_flag("" COMP_HAS_) + endif() # ---- Append options into some lists. # ---- GCC/Clang -if(COMP_HAS_FNO_EXPENSIVE_OPTIMIZATIONS) - list(APPEND checked_compiler_options "-fno-expensive-optimizations") -endif() +if(NOT MSVC) + if(COMP_HAS_FNO_EXPENSIVE_OPTIMIZATIONS) + list(APPEND checked_compiler_options "-fno-expensive-optimizations") + endif() -if(COMP_HAS_ASAN) - list(APPEND checked_compiler_options_asan "-fsanitize=address") - list(APPEND checked_linker_options_all "-fsanitize=address") - if(RUNTIME_STATIC_LINK) - list(APPEND checked_linker_options_all "-static-libasan") + if(COMP_HAS_ASAN) + list(APPEND checked_compiler_options_asan "-fsanitize=address") + list(APPEND checked_linker_options_all "-fsanitize=address") + if(COMP_HAS_F_STATIC_LIBASAN) + list(APPEND checked_linker_options_all "-static-libasan") + endif() + if(COMP_HAS_FSAN_CFI) + list(APPEND checked_compiler_options_asan "-fsanitize-cfi") + endif() + if(COMP_HAS_FSAN_ADDRESS_USE_AFTER_SCOPE) + list(APPEND checked_compiler_options_asan "-fsanitize-address-use-after-scope") + endif() + if(COMP_HAS_FSAN_PTR_COMP) + list(APPEND checked_compiler_options_asan "-fsanitize=pointer-compare") + endif() + if(COMP_HAS_FSAN_PTR_SUB) + list(APPEND checked_compiler_options_asan "-fsanitize=pointer-subtract") + endif() + if(COMP_HAS_FSAN_TRAP_ALL) + list(APPEND checked_compiler_options_asan "-fsanitize-trap=all") + endif() endif() - if(COMP_HAS_FSAN_CFI) - list(APPEND checked_compiler_options_asan "-fsanitize-cfi") + + if(COMP_HAS_UBSAN) + list(APPEND checked_compiler_options_ubsan "-fsanitize=undefined") + list(APPEND checked_linker_options_all "-fsanitize=undefined") + if(RUNTIME_STATIC_LINK) + list(APPEND checked_linker_options_all "-static-libubsan") + endif() + if(COMP_HAS_FSAN_FLOAT_DIVIDE_BY_ZERO) + list(APPEND checked_compiler_options_ubsan "-fsanitize=float-divide-by-zero") + endif() + if(COMP_HAS_FSAN_UNSIGNED_INTEGER_OVERFLOW) + list(APPEND checked_compiler_options_ubsan "-fsanitize=unsigned-integer-overflow") + endif() + if(COMP_HAS_FSAN_IMPLICIT_CONVERSION) + list(APPEND checked_compiler_options_ubsan "-fsanitize=implicit-conversion") + endif() + if(COMP_HAS_FSAN_NO_ENUM) + list(APPEND checked_compiler_options_ubsan "-fno-sanitize=enum") + endif() + if(COMP_HAS_FSAN_LOCAL_BOUNDS) + list(APPEND checked_compiler_options_ubsan "-fsanitize=local-bounds") + endif() endif() - if(COMP_HAS_FSAN_ADDRESS_USE_AFTER_SCOPE) - list(APPEND checked_compiler_options_asan "-fsanitize-address-use-after-scope") + + if(COMP_HAS_LSAN) + list(APPEND checked_compiler_options_lsan "-fsanitize=leak") + list(APPEND checked_linker_options_all "-fsanitize=leak") + if(RUNTIME_STATIC_LINK) + list(APPEND checked_linker_options_all "-static-liblsan") + endif() endif() - if(COMP_HAS_FSAN_PTR_COMP) - list(APPEND checked_compiler_options_asan "-fsanitize=pointer-compare") + + if(COMP_HAS_MSAN) + list(APPEND checked_compiler_options_msan "-fsanitize=memory") + list(APPEND checked_linker_options_all "-fsanitize=memory") + if(RUNTIME_STATIC_LINK) + list(APPEND checked_linker_options_all "-static-libmsan") + endif() + if(COMP_HAS_F_SANITIZE_MEMORY_TRACK_ORIGINS) + list(APPEND checked_compiler_options_msan "-fsanitize=memory-track-origins") + endif() + if(COMP_HAS_F_PIE) + list(APPEND checked_compiler_options_msan "-fPIE") + list(APPEND checked_linker_options_all "-pie") + endif() endif() - if(COMP_HAS_FSAN_PTR_SUB) - list(APPEND checked_compiler_options_asan "-fsanitize=pointer-subtract") + + if(COMP_HAS_F_SANITIZE_SAFE_STACK) + list(APPEND checked_compiler_options_sanitize_harden "-fsanitize=safe-stack") endif() - if(COMP_HAS_FSAN_TRAP_ALL) - list(APPEND checked_compiler_options_asan "-fsanitize-trap=all") + if(COMP_HAS_FCF_PROTECTION_FULL) + list(APPEND checked_compiler_options_sanitize_harden "-fcf-protection=full") endif() -endif() - -if(COMP_HAS_UBSAN) - list(APPEND checked_compiler_options_ubsan "-fsanitize=undefined") - list(APPEND checked_linker_options_all "-fsanitize=undefined") - if(RUNTIME_STATIC_LINK) - list(APPEND checked_linker_options_all "-static-libubsan") + if(COMP_HAS_F_STACK_CHECK) + list(APPEND checked_compiler_options_sanitize_harden "-fstack-check") endif() - if(COMP_HAS_FSAN_FLOAT_DIVIDE_BY_ZERO) - list(APPEND checked_compiler_options_ubsan "-fsanitize=float-divide-by-zero") + if(COMP_HAS_F_STACK_PROTECTOR_ALL) + list(APPEND checked_compiler_options_sanitize_harden "-fstack-protector-all") + elseif(COMP_HAS_F_STACK_PROTECTOR_STRONG) + list(APPEND checked_compiler_options_sanitize_harden "-fstack-protector-strong") + elseif(COMP_HAS_F_STACK_PROTECTOR) + list(APPEND checked_compiler_options_sanitize_harden "-fstack-protector") endif() - if(COMP_HAS_FSAN_UNSIGNED_INTEGER_OVERFLOW) - list(APPEND checked_compiler_options_ubsan "-fsanitize=unsigned-integer-overflow") + if(COMP_HAS_F_STACK_CLASH_PROTECTION) + list(APPEND checked_compiler_options_sanitize_harden "-fstack-clash-protection") endif() - if(COMP_HAS_FSAN_IMPLICIT_CONVERSION) - list(APPEND checked_compiler_options_ubsan "-fsanitize=implicit-conversion") + if(COMP_HAS_F_VTABLE_VERIFY_PREINIT) + list(APPEND checked_compiler_options_sanitize_harden "-fvtable-verify=preinit") endif() - if(COMP_HAS_FSAN_NO_ENUM) - list(APPEND checked_compiler_options_ubsan "-fno-sanitize=enum") + if(COMP_HAS_F_HARDEN_CFR) + list(APPEND checked_compiler_options_sanitize_harden "-fharden-control-flow-redundancy") endif() - if(COMP_HAS_FSAN_LOCAL_BOUNDS) - list(APPEND checked_compiler_options_ubsan "-fsanitize=local-bounds") + if(COMP_HAS_F_HARDCFR_CHECK_EXCEPTIONS) + list(APPEND checked_compiler_options_sanitize_harden "-fhardcfr-check-exceptions") endif() -endif() -if(COMP_HAS_LSAN) - list(APPEND checked_compiler_options_lsan "-fsanitize=leak") - list(APPEND checked_linker_options_all "-fsanitize=leak") - if(RUNTIME_STATIC_LINK) - list(APPEND checked_linker_options_all "-static-liblsan") + if(COMP_HAS_W_USELESS_CAST) + list(APPEND checked_compiler_warnings "-Wuseless-cast") endif() -endif() - -if(COMP_HAS_MSAN) - list(APPEND checked_compiler_options_msan "-fsanitize=memory") - list(APPEND checked_linker_options_all "-fsanitize=memory") - if(RUNTIME_STATIC_LINK) - list(APPEND checked_linker_options_all "-static-libmsan") + if(COMP_HAS_NULL_DEREFERENCE) + list(APPEND checked_compiler_warnings "-Wnull-dereference") endif() - if(COMP_HAS_F_SANITIZE_MEMORY_TRACK_ORIGINS) - list(APPEND checked_compiler_options_msan "-fsanitize=memory-track-origins") + if(COMP_HAS_W_CONVERSION) + list(APPEND checked_compiler_warnings "-Wconversion") endif() - if(COMP_HAS_F_PIE) - list(APPEND checked_compiler_options_msan "-fPIE") - list(APPEND checked_linker_options_all "-pie") + if(COMP_HAS_W_CAST_QUAL) + list(APPEND checked_compiler_warnings "-Wcast-qual") + endif() + if(COMP_HAS_W_ZERO_NULLPTR) + list(APPEND checked_compiler_warnings "-Wzero-as-null-pointer-constant") + endif() + if(COMP_HAS_W_DISABLE_OPT) + list(APPEND checked_compiler_warnings "-Wdisabled-optimization") + endif() + if(COMP_HAS_W_INVALID_PCH) + list(APPEND checked_compiler_warnings "-Winvalid-pch") + endif() + if(COMP_HAS_W_SHADOW) + list(APPEND checked_compiler_warnings "-Wshadow") endif() -endif() -if(COMP_HAS_F_SANITIZE_SAFE_STACK) - list(APPEND checked_compiler_options_sanitize_harden "-fsanitize=safe-stack") -endif() -if(COMP_HAS_FCF_PROTECTION_FULL) - list(APPEND checked_compiler_options_sanitize_harden "-fcf-protection=full") -endif() -if(COMP_HAS_F_STACK_CHECK) - list(APPEND checked_compiler_options_sanitize_harden "-fstack-check") -endif() -if(COMP_HAS_F_STACK_PROTECTOR_ALL) - list(APPEND checked_compiler_options_sanitize_harden "-fstack-protector-all") -elseif(COMP_HAS_F_STACK_PROTECTOR_STRONG) - list(APPEND checked_compiler_options_sanitize_harden "-fstack-protector-strong") -elseif(COMP_HAS_F_STACK_PROTECTOR) - list(APPEND checked_compiler_options_sanitize_harden "-fstack-protector") -endif() -if(COMP_HAS_F_STACK_CLASH_PROTECTION) - list(APPEND checked_compiler_options_sanitize_harden "-fstack-clash-protection") -endif() -if(COMP_HAS_F_VTABLE_VERIFY_PREINIT) - list(APPEND checked_compiler_options_sanitize_harden "-fvtable-verify=preinit") -endif() -if(COMP_HAS_F_HARDEN_CFR) - list(APPEND checked_compiler_options_sanitize_harden "-fharden-control-flow-redundancy") -endif() -if(COMP_HAS_F_HARDCFR_CHECK_EXCEPTIONS) - list(APPEND checked_compiler_options_sanitize_harden "-fhardcfr-check-exceptions") -endif() + if(COMP_HAS_W_LTO_TYPE_MISMATCH) + list(APPEND checked_compiler_warnings "-Wlto-type-mismatch") + endif() + if(COMP_HAS_W_SHIFT_OVERFLOW) + list(APPEND checked_compiler_warnings "-Wshift-overflow=2") + endif() + if(COMP_HAS_W_DUPLICATED_COND) + list(APPEND checked_compiler_warnings "-Wduplicated-cond") + endif() + if(COMP_HAS_W_SIZED_DEALLOC) + list(APPEND checked_compiler_warnings "-Wsized-deallocation") + endif() + if(COMP_HAS_W_VECTOR_OP_PERF) + list(APPEND checked_compiler_warnings "-Wvector-operation-performance") + endif() + if(COMP_HAS_W_TRAMPOLINES) + list(APPEND checked_compiler_warnings "-Wtrampolines") + endif() + if(COMP_HAS_W_WEAK_VTABLES) + list(APPEND checked_compiler_warnings "-Wweak-vtables") + endif() + if(COMP_HAS_W_MISSING_PROTOTYPES) + list(APPEND checked_compiler_warnings "-Wmissing-prototypes") + endif() + if(COMP_HAS_W_MISSING_VARIABLE_DECL) + list(APPEND checked_compiler_warnings "-Wmissing-variable-declarations") + endif() -if(COMP_HAS_W_USELESS_CAST) - list(APPEND checked_compiler_warnings "-Wuseless-cast") -endif() -if(COMP_HAS_NULL_DEREFERENCE) - list(APPEND checked_compiler_warnings "-Wnull-dereference") -endif() -if(COMP_HAS_W_CONVERSION) - list(APPEND checked_compiler_warnings "-Wconversion") -endif() -if(COMP_HAS_W_CAST_QUAL) - list(APPEND checked_compiler_warnings "-Wcast-qual") -endif() -if(COMP_HAS_W_ZERO_NULLPTR) - list(APPEND checked_compiler_warnings "-Wzero-as-null-pointer-constant") -endif() -if(COMP_HAS_W_DISABLE_OPT) - list(APPEND checked_compiler_warnings "-Wdisabled-optimization") -endif() -if(COMP_HAS_W_INVALID_PCH) - list(APPEND checked_compiler_warnings "-Winvalid-pch") -endif() -if(COMP_HAS_W_SHADOW) - list(APPEND checked_compiler_warnings "-Wshadow") + if(COMP_HAS_WNO_UNUSED_FUNCTION) + list(APPEND checked_compiler_warnings_disabled "-Wno-unused-function") + endif() + if(COMP_HAS_WNO_FORMAT_NONLITERAL) + list(APPEND checked_compiler_warnings_disabled "-Wno-format-nonliteral") + endif() + if(COMP_HAS_WNO_NONNULL_COMPARE) + list(APPEND checked_compiler_warnings_disabled "-Wno-nonnull-compare") + endif() + if(COMP_HAS_WNO_MAYBE_UNINIT) + list(APPEND checked_compiler_warnings_disabled "-Wno-maybe-uninitialized") + endif() + if(COMP_HAS_WNO_SWITCH) + list(APPEND checked_compiler_warnings_disabled "-Wno-switch") + endif() + if(COMP_HAS_WNO_IMPLICIT_FALLTHROUGH) + list(APPEND checked_compiler_warnings_disabled "-Wno-implicit-fallthrough") + endif() + if(COMP_HAS_WNO_PARENTHESES) + list(APPEND checked_compiler_warnings_disabled "-Wno-parentheses") + endif() + if(COMP_HAS_WNO_MISLEADING_INDENTATION) + list(APPEND checked_compiler_warnings_disabled "-Wno-misleading-indentation") + endif() + if(COMP_HAS_WNO_UNUSED_RESULT) + list(APPEND checked_compiler_warnings_disabled "-Wno-unused-result") + endif() + if(COMP_HAS_WNO_NESTED_ANON_TYPES) + list(APPEND checked_compiler_warnings_disabled "-Wno-nested-anon-types") + endif() + if(COMP_HAS_WNO_FORMAT_SECURITY) + list(APPEND checked_compiler_warnings_disabled "-Wno-format-security") + endif() + if(COMP_HAS_WNO_DEPRECATED_DECLARATIONS) + list(APPEND checked_compiler_warnings_disabled "-Wno-deprecated-declarations") + endif() + if(COMP_HAS_WNO_LANGUAGE_EXTENSION_TOKEN) + list(APPEND checked_compiler_warnings_disabled "-Wno-language-extension-token") + endif() endif() -if(COMP_HAS_W_LTO_TYPE_MISMATCH) - list(APPEND checked_compiler_warnings "-Wlto-type-mismatch") -endif() -if(COMP_HAS_W_SHIFT_OVERFLOW) - list(APPEND checked_compiler_warnings "-Wshift-overflow=2") -endif() -if(COMP_HAS_W_DUPLICATED_COND) - list(APPEND checked_compiler_warnings "-Wduplicated-cond") -endif() -if(COMP_HAS_W_SIZED_DEALLOC) - list(APPEND checked_compiler_warnings "-Wsized-deallocation") -endif() -if(COMP_HAS_W_VECTOR_OP_PERF) - list(APPEND checked_compiler_warnings "-Wvector-operation-performance") -endif() -if(COMP_HAS_W_TRAMPOLINES) - list(APPEND checked_compiler_warnings "-Wtrampolines") -endif() -if(COMP_HAS_W_WEAK_VTABLES) - list(APPEND checked_compiler_warnings "-Wweak-vtables") -endif() -if(COMP_HAS_W_MISSING_PROTOTYPES) - list(APPEND checked_compiler_warnings "-Wmissing-prototypes") -endif() -if(COMP_HAS_W_MISSING_VARIABLE_DECL) - list(APPEND checked_compiler_warnings "-Wmissing-variable-declarations") -endif() +# ---- MSVC -if(COMP_HAS_WNO_UNUSED_FUNCTION) - list(APPEND checked_compiler_warnings_disabled "-Wno-unused-function") -endif() -if(COMP_HAS_WNO_FORMAT_NONLITERAL) - list(APPEND checked_compiler_warnings_disabled "-Wno-format-nonliteral") -endif() -if(COMP_HAS_WNO_NONNULL_COMPARE) - list(APPEND checked_compiler_warnings_disabled "-Wno-nonnull-compare") -endif() -if(COMP_HAS_WNO_MAYBE_UNINIT) - list(APPEND checked_compiler_warnings_disabled "-Wno-maybe-uninitialized") -endif() -if(COMP_HAS_WNO_SWITCH) - list(APPEND checked_compiler_warnings_disabled "-Wno-switch") -endif() -if(COMP_HAS_WNO_IMPLICIT_FALLTHROUGH) - list(APPEND checked_compiler_warnings_disabled "-Wno-implicit-fallthrough") -endif() -if(COMP_HAS_WNO_PARENTHESES) - list(APPEND checked_compiler_warnings_disabled "-Wno-parentheses") -endif() -if(COMP_HAS_WNO_MISLEADING_INDENTATION) - list(APPEND checked_compiler_warnings_disabled "-Wno-misleading-indentation") -endif() -if(COMP_HAS_WNO_UNUSED_RESULT) - list(APPEND checked_compiler_warnings_disabled "-Wno-unused-result") -endif() -if(COMP_HAS_WNO_NESTED_ANON_TYPES) - list(APPEND checked_compiler_warnings_disabled "-Wno-nested-anon-types") -endif() -if(COMP_HAS_WNO_FORMAT_SECURITY) - list(APPEND checked_compiler_warnings_disabled "-Wno-format-security") -endif() -if(COMP_HAS_WNO_DEPRECATED_DECLARATIONS) - list(APPEND checked_compiler_warnings_disabled "-Wno-deprecated-declarations") -endif() +if(MSVC) + #list( + # APPEND + # base_compiler_options_msvc + # "/wd5105" + #) -# ---- MSVC + if(COMP_HAS_W_DEFINE_MACRO_EXPANSION) + list(APPEND checked_compiler_options_msvc "/wd5105") + endif() -if(COMP_HAS_DEFINE_MACRO_EXPANSION) - list(APPEND checked_compiler_options_msvc "/Wd5105") endif() # ---- Double checks @@ -408,34 +434,35 @@ set(checked_compiler_options_msvc) ## ---- -list( - APPEND - list_gnu_explicit_compiler_options_all - ${compiler_options_base} - ${compiler_options_warning_base} - ${checked_compiler_options} - ${checked_compiler_options_asan} - ${checked_compiler_options_ubsan} - ${checked_compiler_options_lsan} - ${checked_compiler_options_msan} - ${checked_compiler_options_sanitize_harden} - ${checked_compiler_warnings} - ${checked_compiler_warnings_disabled} - ${checked_compiler_options_msvc} -) +# Now sum up, report and encapsulate all the options. -list(APPEND list_gnu_explicit_linker_options_all ${checked_linker_options_all};-pthread;-dynamic;-Wl,--fatal-warnings) +if(NOT MSVC) + list( + APPEND + list_explicit_compiler_options_all + ${compiler_options_base} + ${base_compiler_options_warning} + ${checked_compiler_options} + ${checked_compiler_options_asan} + ${checked_compiler_options_ubsan} + ${checked_compiler_options_lsan} + ${checked_compiler_options_msan} + ${checked_compiler_options_sanitize_harden} + ${checked_compiler_warnings} + ${checked_compiler_warnings_disabled} + ) -#string(JOIN " " string_checked_compiler_options_all ${list_checked_compiler_options_all}) -#set(string_checked_compiler_options_all CACHE STRING "Additional compiler flags, dynamically added." FORCE) -set(list_gnu_explicit_compiler_options_all CACHE STRING "Additional compiler flags, dynamically added." FORCE) -set(list_gnu_explicit_linker_options_all CACHE STRING "Additional linker flags, dynamically added." FORCE) + list(APPEND list_explicit_linker_options_all ${checked_linker_options_all};-pthread;-dynamic;-Wl,--fatal-warnings) -## ---- + #string(JOIN " " string_checked_compiler_options_all ${list_checked_compiler_options_all}) + #set(string_checked_compiler_options_all CACHE INTERNAL STRING) + set(list_explicit_compiler_options_all CACHE INTERNAL STRING) + set(list_explicit_linker_options_all CACHE INTERNAL STRING) + + # -- -if(NOT MSVC) message(STATUS "Adding the following base compiler options: ${compiler_options_base}") - message(STATUS "Adding the following base compiler warning options: ${compiler_options_warning_base}") + message(STATUS "Adding the following base compiler warning options: ${base_compiler_options_warning}") message(STATUS "Adding the following conditional compiler options: ${checked_compiler_options}.") if(COMP_HAS_ASAN) @@ -464,7 +491,16 @@ if(NOT MSVC) STATUS "Adding the following conditional compiler warnings ignore options: ${checked_compiler_warnings_disabled}." ) - message(STATUS "Adding the following linker options: ${list_gnu_explicit_linker_options_all}.") + message(STATUS "Adding the following linker options: ${list_explicit_linker_options_all}.") + elseif(MSVC) - message(STATUS "Adding the following conditional compiler options: ${checked_compiler_options_msvc}.") + list( + APPEND + list_explicit_compiler_options_all + ${base_compiler_options_msvc} + ${checked_compiler_options_msvc} + ) + + message(STATUS "Adding the following conditional compiler options: ${list_explicit_compiler_options_all}.") + endif() diff --git a/cmake/toolchains/Windows-GNU-x86_64.cmake b/cmake/toolchains/Windows-GNU-x86_64.cmake index 00b1fafc1..ec6ac7494 100644 --- a/cmake/toolchains/Windows-GNU-x86_64.cmake +++ b/cmake/toolchains/Windows-GNU-x86_64.cmake @@ -17,7 +17,7 @@ function(toolchain_after_project) # Do not set CMAKE_SYSTEM_NAME if compiling for the same OS, otherwise CMAKE_CROSSCOMPILING will be set to TRUE #unset(CMAKE_SYSTEM_NAME) #SET(CMAKE_SYSTEM_NAME "Windows" CACHE INTERNAL "" FORCE) - unset() + unset(CMAKE_SYSTEM_PROCESSOR) set(CMAKE_SYSTEM_PROCESSOR "x86_64" CACHE INTERNAL "" FORCE) set(CMAKE_RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/bin-x86_64" PARENT_SCOPE) #set(ARCH_BITS 64 CACHE INTERNAL "" FORCE) # automatically gotten from CMAKE_SYSTEM_PROCESSOR diff --git a/cmake/toolchains/Windows-MSVC.cmake b/cmake/toolchains/Windows-MSVC.cmake index 3088faee3..3994a6e7f 100644 --- a/cmake/toolchains/Windows-MSVC.cmake +++ b/cmake/toolchains/Windows-MSVC.cmake @@ -42,7 +42,7 @@ function(toolchain_exe_stuff) endif() #-- Validate sanitizers options and store them between the common compiler flags. - + # TODO: move sanitizers checks to CompilerFlagsChecker.cmake. set(ENABLED_SANITIZER false) if(${USE_ASAN}) if(${MSVC_TOOLSET_VERSION} LESS_EQUAL 141) # VS 2017 @@ -74,6 +74,7 @@ function(toolchain_exe_stuff) set(cxx_compiler_flags_common ${CXX_FLAGS_EXTRA} + ${list_explicit_compiler_options_all} /W4 /MP /GR @@ -126,10 +127,10 @@ function(toolchain_exe_stuff) # gersemi: off target_link_options(spheresvr PRIVATE - /WX # treat all warnings as errors + /WX # treat all warnings as errors $<$: ${EXE_LINKER_EXTRA} /NODEFAULTLIB:libcmtd /OPT:REF,ICF /LTCG /INCREMENTAL:NO> $<$: ${EXE_LINKER_EXTRA} /NODEFAULTLIB:libcmtd /OPT:REF,ICF /LTCG /INCREMENTAL:NO> - $<$: ${EXE_LINKER_EXTRA} /NODEFAULTLIB:libcmt /SAFESEH:NO /DEBUG /LTCG:OFF + $<$: ${EXE_LINKER_EXTRA} /NODEFAULTLIB:libcmt /SAFESEH:NO /DEBUG /LTCG:OFF $,/INCREMENTAL:NO /EDITANDCONTINUE:NO,/INCREMENTAL /EDITANDCONTINUE> > ) # gersemi: on diff --git a/cmake/toolchains/include/Linux-Clang_common.inc.cmake b/cmake/toolchains/include/Linux-Clang_common.inc.cmake index b7493dc50..a7304c79c 100644 --- a/cmake/toolchains/include/Linux-Clang_common.inc.cmake +++ b/cmake/toolchains/include/Linux-Clang_common.inc.cmake @@ -22,7 +22,7 @@ function(toolchain_exe_stuff_common) #string(REPLACE ";" " " CXX_FLAGS_EXTRA "${CXX_FLAGS_EXTRA}") - set(cxx_compiler_options_common ${list_gnu_explicit_compiler_options_all} ${CXX_FLAGS_EXTRA}) + set(cxx_compiler_options_common ${list_explicit_compiler_options_all} ${CXX_FLAGS_EXTRA}) #separate_arguments(cxx_compiler_options_common) #-- Apply compiler flags, only the ones specific per build type. @@ -55,7 +55,7 @@ function(toolchain_exe_stuff_common) #-- Store common linker flags. set(cxx_linker_options_common - ${list_gnu_explicit_linker_options_all} + ${list_explicit_linker_options_all} ${CMAKE_EXE_LINKER_FLAGS_EXTRA} $<$: -static-libstdc++ diff --git a/cmake/toolchains/include/Linux-GNU_common.inc.cmake b/cmake/toolchains/include/Linux-GNU_common.inc.cmake index ce705b3a6..19e8c3a71 100644 --- a/cmake/toolchains/include/Linux-GNU_common.inc.cmake +++ b/cmake/toolchains/include/Linux-GNU_common.inc.cmake @@ -17,7 +17,7 @@ function(toolchain_exe_stuff_common) #-- Store compiler flags common to all builds. - set(cxx_compiler_options_common ${list_gnu_explicit_compiler_options_all} ${CXX_FLAGS_EXTRA}) + set(cxx_compiler_options_common ${list_explicit_compiler_options_all} ${CXX_FLAGS_EXTRA}) #-- Apply compiler flags, only the ones specific per build type. @@ -43,7 +43,7 @@ function(toolchain_exe_stuff_common) #-- Store common linker flags. set(cxx_linker_options_common - ${list_gnu_explicit_linker_options_all} + ${list_explicit_linker_options_all} ${CMAKE_EXE_LINKER_FLAGS_EXTRA} $<$: -static-libstdc++ diff --git a/cmake/toolchains/include/OSX-AppleClang_common.inc.cmake b/cmake/toolchains/include/OSX-AppleClang_common.inc.cmake index fb877cffe..699b50881 100644 --- a/cmake/toolchains/include/OSX-AppleClang_common.inc.cmake +++ b/cmake/toolchains/include/OSX-AppleClang_common.inc.cmake @@ -24,7 +24,7 @@ function(toolchain_exe_stuff_common) #-- Store compiler flags common to all builds. - set(cxx_compiler_options_common ${list_gnu_explicit_compiler_options_all} ${cxx_local_opts} ${CXX_FLAGS_EXTRA}) + set(cxx_compiler_options_common ${list_explicit_compiler_options_all} ${cxx_local_opts} ${CXX_FLAGS_EXTRA}) #-- Apply compiler flags, only the ones specific per build type. @@ -50,7 +50,7 @@ function(toolchain_exe_stuff_common) #-- Store common linker flags. set(cxx_linker_options_common - ${list_gnu_explicit_linker_options_all} + ${list_explicit_linker_options_all} ${CMAKE_EXE_LINKER_FLAGS_EXTRA} $<$: -static-libstdc++ diff --git a/cmake/toolchains/include/Windows-Clang_common.inc.cmake b/cmake/toolchains/include/Windows-Clang_common.inc.cmake index 7e7f9f30c..a01a37d09 100644 --- a/cmake/toolchains/include/Windows-Clang_common.inc.cmake +++ b/cmake/toolchains/include/Windows-Clang_common.inc.cmake @@ -31,7 +31,7 @@ function(toolchain_exe_stuff_common) # -mno-ms-bitfields is needed to fix structure packing; # -pthread unused here? we only need to specify that to the linker? ) - set(cxx_compiler_options_common ${list_gnu_explicit_compiler_options_all} ${cxx_local_opts} ${CXX_FLAGS_EXTRA}) + set(cxx_compiler_options_common ${list_explicit_compiler_options_all} ${cxx_local_opts} ${CXX_FLAGS_EXTRA}) #-- Apply compiler flags, only the ones specific per build type. @@ -91,7 +91,7 @@ function(toolchain_exe_stuff_common) set(cxx_linker_options_common ${CMAKE_EXE_LINKER_FLAGS_EXTRA}) if(${CLANG_USE_GCC_LINKER}) - set(cxx_linker_options_common ${list_gnu_explicit_linker_options_all}) + set(cxx_linker_options_common ${list_explicit_linker_options_all}) if(${RUNTIME_STATIC_LINK}) set(cxx_linker_options_common ${cxx_linker_options_common} -static-libstdc++ -static-libgcc) # no way to statically link against libc? maybe we can on windows? endif() diff --git a/cmake/toolchains/include/Windows-GNU_common.inc.cmake b/cmake/toolchains/include/Windows-GNU_common.inc.cmake index 58f2866df..0dfdb2968 100644 --- a/cmake/toolchains/include/Windows-GNU_common.inc.cmake +++ b/cmake/toolchains/include/Windows-GNU_common.inc.cmake @@ -20,7 +20,7 @@ function(toolchain_exe_stuff_common) -mno-ms-bitfields # it's needed to fix structure packing ) - set(cxx_compiler_options_common ${list_gnu_explicit_compiler_options_all} ${cxx_local_opts} ${CXX_FLAGS_EXTRA}) + set(cxx_compiler_options_common ${list_explicit_compiler_options_all} ${cxx_local_opts} ${CXX_FLAGS_EXTRA}) #-- Apply compiler flags, only the ones specific per build type. @@ -46,7 +46,7 @@ function(toolchain_exe_stuff_common) #-- Store common linker flags. set(cxx_linker_options_common - ${list_gnu_explicit_linker_options_all} + ${list_explicit_linker_options_all} ${CMAKE_EXE_LINKER_FLAGS_EXTRA} $<$: -static-libstdc++ diff --git a/lib/lib_build_flags_common_c.cmake b/lib/lib_build_flags_common_c.cmake index d34668325..2d3cc4734 100644 --- a/lib/lib_build_flags_common_c.cmake +++ b/lib/lib_build_flags_common_c.cmake @@ -6,9 +6,9 @@ endif() if(MSVC) # gersemi: off set (c_compiler_options_common - /O2 /EHsc /GA /Gw /Gy /GF /GR- /GS- - $<$: $,/MT,/MD> $<$:/Zi>> - $<$: $,/MT,/MD> $<$:/Zi>> + /EHsc /GA /Gw /Gy /GF /GR- /GS- + $<$: $,/MT,/MD> $,/O1 /Zi,/O2>> + $<$: $,/MT,/MD> $,/O1 /Zi,/O2>> $<$: $,/MTd,/MDd> $,/Zi,/ZI>> ) set (c_linker_options_common @@ -17,7 +17,8 @@ if(MSVC) $<$: /DEBUG /LTCG:OFF /NODEFAULTLIB:libcmt> ) # gersemi: on -else(MSVC) + +elseif(NOT MSVC) set(c_compiler_options_common -pipe -fexceptions diff --git a/src/common/sphere_library/CSString.h b/src/common/sphere_library/CSString.h index ecd7737b4..5537b4015 100644 --- a/src/common/sphere_library/CSString.h +++ b/src/common/sphere_library/CSString.h @@ -6,11 +6,13 @@ #ifndef _INC_CSSTRING_H #define _INC_CSSTRING_H +#include "../common.h" #ifdef __MINGW32__ #include #endif // __MINGW32__ #include // needed for va_list + /** * @brief Custom String implementation. */ From d69dda599ad4c71aab7bcfbc8c65b873ed007149 Mon Sep 17 00:00:00 2001 From: cbnolok Date: Thu, 3 Oct 2024 13:27:02 +0200 Subject: [PATCH 63/86] stypecast.h: split checked casts, one variant using ASSERT, another just printing a warning message. --- src/CMakeSources.cmake | 3 +- src/common/sphere_library/stypecast.cpp | 11 + src/common/sphere_library/stypecast.h | 472 ++++++++++++++++-------- src/game/items/CItemMultiCustom.cpp | 2 +- 4 files changed, 325 insertions(+), 163 deletions(-) create mode 100644 src/common/sphere_library/stypecast.cpp diff --git a/src/CMakeSources.cmake b/src/CMakeSources.cmake index d1b52321f..fbecf9e6b 100644 --- a/src/CMakeSources.cmake +++ b/src/CMakeSources.cmake @@ -8,7 +8,7 @@ set(pch_options PRIVATE src/common/sphere_library/sstringobjs.h PRIVATE src/common/CException.h PRIVATE src/common/CExpression.h - PRIVATE src/common/CLog.h + #PRIVATE src/common/CLog.h #PRIVATE src/common/CServerMap.h PRIVATE src/game/CObjBase.h #PRIVATE src/game/CSector.h @@ -297,6 +297,7 @@ set(spherelibrary_SRCS src/common/sphere_library/sstring.h src/common/sphere_library/sstringobjs.cpp src/common/sphere_library/sstringobjs.h + src/common/sphere_library/stypecast.cpp src/common/sphere_library/stypecast.h ) source_group(common\\sphere_library FILES ${spherelibrary_SRCS}) diff --git a/src/common/sphere_library/stypecast.cpp b/src/common/sphere_library/stypecast.cpp new file mode 100644 index 000000000..f0e0c3de4 --- /dev/null +++ b/src/common/sphere_library/stypecast.cpp @@ -0,0 +1,11 @@ +#include "../CLog.h" +#include "stypecast.h" + +namespace detail_stypecast { + +void LogEventWarnWrapper(const char* warn_str) +{ + g_Log.EventWarn(warn_str); +} + +} diff --git a/src/common/sphere_library/stypecast.h b/src/common/sphere_library/stypecast.h index ebbade7cb..d367c41f1 100644 --- a/src/common/sphere_library/stypecast.h +++ b/src/common/sphere_library/stypecast.h @@ -1,11 +1,20 @@ #ifndef _INC_STYPECAST_H #define _INC_STYPECAST_H -//#include "../CLog.h" #include #include #include +namespace detail_stypecast +{ +void LogEventWarnWrapper(const char* warn_str); +} + +// Helper macros +//#define n64_narrow_n32_assert(source_val) (n64_narrow_n32_checked(source_val, true)) +//#define n64_narrow_n32_warn(source_val) (n64_narrow_n32_checked(source_val, false)) + + // Helper template to work on enum types. // Primary template for non-enum types, T will simply be itself @@ -30,19 +39,19 @@ using underlying_or_self_t = typename underlying_or_self::type; // Use this as a double check, to be sure at compile time that the two variables have the same size and sign. template [[nodiscard]] -constexpr Tout n_alias_cast(const Tin a) noexcept +constexpr Tout n_alias_cast(const Tin source_val) noexcept { static_assert(std::is_arithmetic_v, "Input variable is not an arithmetictype."); static_assert(std::is_arithmetic_v, "Output variable is not an arithmetic type."); static_assert(sizeof(Tin) == sizeof(Tout), "Input and output types do not have the same size."); static_assert(!(std::is_signed_v && std::is_unsigned_v), "Casting signed to unsigned."); static_assert(!(std::is_signed_v && std::is_unsigned_v ), "Casting unsigned to signed."); - return static_cast(a); + return static_cast(source_val); } template [[nodiscard]] -constexpr Tout enum_alias_cast(const Tin a) noexcept +constexpr Tout enum_alias_cast(const Tin source_val) noexcept { static_assert(std::is_enum_v || std::is_enum_v, "Nor input nor output variables are an enum."); static_assert(std::is_arithmetic_v || std::is_enum_v, "Input variable is not a numeric type."); @@ -68,7 +77,7 @@ constexpr Tout enum_alias_cast(const Tin a) noexcept "Casting unsigned to signed."); */ - return static_cast(a); + return static_cast(source_val); } @@ -84,7 +93,7 @@ constexpr Tout enum_alias_cast(const Tin a) noexcept // Promote to the corresponding 32 bits numeric type a smaller numeric variable. template [[nodiscard]] -constexpr auto n_promote_n32(const T a) noexcept +constexpr auto n_promote_n32(const T source_val) noexcept { static_assert(std::is_arithmetic_v, "Input variable has not a arithmetic type."); static_assert(std::is_integral_v || (std::is_floating_point_v && std::is_signed_v), "Unsigned floating point numbers are unsupported by the language standard"); @@ -92,25 +101,25 @@ constexpr auto n_promote_n32(const T a) noexcept if constexpr (std::is_signed_v) { if constexpr (std::is_floating_point_v) - return static_cast(a); - return static_cast(a); + return static_cast(source_val); + return static_cast(source_val); } else - return static_cast(a); + return static_cast(source_val); } template [[nodiscard]] -constexpr auto enum_promote_n32(const T a) noexcept +constexpr auto enum_promote_n32(const T source_val) noexcept { static_assert(std::is_enum_v, "Input variable is not an enum type."); - return n_promote_n32(static_cast>(a)); + return n_promote_n32(static_cast>(source_val)); } // Promote to the corresponding 64 bits numeric type a smaller numeric variable. template [[nodiscard]] -constexpr auto n_promote_n64(const T a) noexcept +constexpr auto n_promote_n64(const T source_val) noexcept { static_assert(std::is_arithmetic_v, "Input variable has not a arithmetic type."); static_assert(std::is_integral_v || (std::is_floating_point_v && std::is_signed_v), "Unsigned floating point numbers are unsupported by the language standard"); @@ -118,25 +127,25 @@ constexpr auto n_promote_n64(const T a) noexcept if constexpr (std::is_signed_v) { if constexpr (std::is_floating_point_v) - return static_cast(a); - return static_cast(a); + return static_cast(source_val); + return static_cast(source_val); } else - return static_cast(a); + return static_cast(source_val); } template [[nodiscard]] -constexpr auto enum_promote_n64(const T a) noexcept +constexpr auto enum_promote_n64(const T source_val) noexcept { static_assert(std::is_enum_v, "Input variable is not an enum type."); - return n_promote_n64(static_cast>(a)); + return n_promote_n64(static_cast>(source_val)); } // Narrow a 64 bits number to a 32 bits number, discarding any upper exceeding bytes. template [[nodiscard]] -constexpr auto n64_narrow_n32(const T a) noexcept +constexpr auto n64_narrow_n32(const T source_val) noexcept { static_assert(std::is_arithmetic_v, "Input variable has not a arithmetic type."); static_assert(std::is_integral_v || (std::is_floating_point_v && std::is_signed_v), "Unsigned floating point numbers are unsupported by the language standard"); @@ -147,40 +156,55 @@ constexpr auto n64_narrow_n32(const T a) noexcept if constexpr (std::is_signed_v) { if constexpr (std::is_floating_point_v) - return static_cast(a & umask); - return static_cast(a & umask); + return static_cast(source_val & umask); + return static_cast(source_val & umask); } else - return static_cast(a & umask); + return static_cast(source_val & umask); } -// Narrow a 64 bits number to a 32 bits number and ASSERT (because you're reasonably sure but not absolutely certain) that it won't overflow. +// Narrow a 64 bits number to a 32 bits number. +// ASSERT (because you're reasonably sure but not absolutely certain) that it won't overflow, otherwise +// otherwise just print an error if it overflows (wise to do this if the values depends from user input/scripts). template [[nodiscard]] inline -auto n64_narrow_n32_checked(const T a) + auto n64_narrow_n32_checked(const T source_val, bool should_assert) { - if constexpr (std::is_signed_v) { - ASSERT(a <= std::numeric_limits::max()); + if (should_assert) + { + if constexpr (std::is_signed_v) { + ASSERT(source_val <= std::numeric_limits::max()); + } + else { + ASSERT(source_val <= std::numeric_limits::max()); + } } - else { - ASSERT(a <= std::numeric_limits::max()); + else + { + if constexpr (std::is_signed_v) { + if (source_val > std::numeric_limits::max()) + detail_stypecast::LogEventWarnWrapper("[Internal] Narrowing conversion from 64 to 32 bits signed integer will overflow.\n"); + } + else { + if (source_val > std::numeric_limits::max()) + detail_stypecast::LogEventWarnWrapper("[Internal] Narrowing conversion from 64 to 32 bits unsigned integer will overflow.\n"); + } } - return n64_narrow_n32(a); + return n64_narrow_n32(source_val); } template [[nodiscard]] -constexpr auto enum64_narrow_n32_checked(const T a) noexcept +constexpr auto enum64_narrow_n32_checked(const T source_val, bool should_assert) noexcept { static_assert(std::is_enum_v, "Input variable is not an enum type."); - return n64_narrow_n32_checked(static_cast>(a)); + return n64_narrow_n32_checked(static_cast>(source_val, should_assert)); } - // Narrow a 64 bits number to a 16 bits number, discarding any upper exceeding bytes. template [[nodiscard]] -constexpr auto n64_narrow_n16(const T a) noexcept +constexpr auto n64_narrow_n16(const T source_val) noexcept { static_assert(std::is_arithmetic_v, "Input variable has not a arithmetic type."); static_assert(std::is_integral_v || (std::is_floating_point_v && std::is_signed_v), "Unsigned floating point numbers are unsupported by the language standard"); @@ -191,39 +215,56 @@ constexpr auto n64_narrow_n16(const T a) noexcept if constexpr (std::is_signed_v) { if constexpr (std::is_floating_point_v) - return static_cast(a & umask); - return static_cast(a & umask); + return static_cast(source_val & umask); + return static_cast(source_val & umask); } else - return static_cast(a & umask); + return static_cast(source_val & umask); } -// Narrow a 64 bits number to a 16 bits number and ASSERT (because you're reasonably sure but not absolutely certain) that it won't overflow. +// Narrow a 64 bits number to a 16 bits number. +// ASSERT (because you're reasonably sure but not absolutely certain) that it won't overflow, otherwise +// otherwise just print an error if it overflows (wise to do this if the values depends from user input/scripts). template [[nodiscard]] inline -auto n64_narrow_n16_checked(const T a) + auto n64_narrow_n16_checked(const T source_val, bool should_assert) { - if constexpr (std::is_signed_v) { - ASSERT(a <= std::numeric_limits::max()); + if (should_assert) + { + if constexpr (std::is_signed_v) { + ASSERT(source_val <= std::numeric_limits::max()); + } + else { + ASSERT(source_val <= std::numeric_limits::max()); + } } - else { - ASSERT(a <= std::numeric_limits::max()); + else + { + if constexpr (std::is_signed_v) { + if (source_val > std::numeric_limits::max()) + detail_stypecast::LogEventWarnWrapper("[Internal] Narrowing conversion from 64 to 16 bits signed integer will overflow.\n"); + } + else { + if (source_val > std::numeric_limits::max()) + detail_stypecast::LogEventWarnWrapper("[Internal] Narrowing conversion from 64 to 16 bits unsigned integer will overflow.\n"); + } } - return n64_narrow_n16(a); + return n64_narrow_n16(source_val); } + template [[nodiscard]] -constexpr auto enum64_narrow_n16_checked(const T a) noexcept +constexpr auto enum64_narrow_n16_checked(const T source_val, bool should_assert) noexcept { static_assert(std::is_enum_v, "Input variable is not an enum type."); - return n64_narrow_n16_checked(static_cast>(a)); + return n64_narrow_n16_checked(static_cast>(source_val, should_assert)); } -// Narrow a 64 bits number to a 8 bits number, discarding any upper exceeding bytes. +// Narrow a 64 bits number to a 8 a number, discarding any upper exceeding bytes. template [[nodiscard]] -constexpr auto n64_narrow_n8(const T a) noexcept +constexpr auto n64_narrow_n8(const T source_val) noexcept { static_assert(std::is_arithmetic_v, "Input variable has not a arithmetic type"); static_assert(std::is_floating_point_v == false, "Corresponding 8-bit floating point type does not exist?"); @@ -233,37 +274,53 @@ constexpr auto n64_narrow_n8(const T a) noexcept // Since the narrowing can be implementation specific, here we decide that we take only the lower 8 bytes and discard the upper ones. constexpr uint64 umask = 0x0000'0000'0000'00FF; if constexpr (std::is_signed_v) - return static_cast(a & umask); + return static_cast(source_val & umask); else - return static_cast(a & umask); + return static_cast(source_val & umask); } -// Narrow a 64 bits number to a 8 bits number and ASSERT (because you're reasonably sure but not absolutely certain) that it won't overflow. +// Narrow a 64 bits number to a 8 bits number. +// ASSERT (because you're reasonably sure but not absolutely certain) that it won't overflow, otherwise +// otherwise just print an error if it overflows (wise to do this if the values depends from user input/scripts). template [[nodiscard]] inline -auto n64_narrow_n8_checked(const T a) + auto n64_narrow_n8_checked(const T source_val, bool should_assert) { - if constexpr (std::is_signed_v) { - ASSERT(a <= std::numeric_limits::max()); + if (should_assert) + { + if constexpr (std::is_signed_v) { + ASSERT(source_val <= std::numeric_limits::max()); + } + else { + ASSERT(source_val <= std::numeric_limits::max()); + } } - else { - ASSERT(a <= std::numeric_limits::max()); + else + { + if constexpr (std::is_signed_v) { + if (source_val > std::numeric_limits::max()) + detail_stypecast::LogEventWarnWrapper("[Internal] Narrowing conversion from 64 to 8 bits signed integer will overflow.\n"); + } + else { + if (source_val > std::numeric_limits::max()) + detail_stypecast::LogEventWarnWrapper("[Internal] Narrowing conversion from 64 to 8 bits unsigned integer will overflow.\n"); + } } - return n64_narrow_n8(a); + return n64_narrow_n8(source_val); } template [[nodiscard]] -constexpr auto enum64_narrow_n8_checked(const T a) noexcept +constexpr auto enum64_narrow_n8_checked(const T source_val, bool should_assert) noexcept { static_assert(std::is_enum_v, "Input variable is not an enum type."); - return n64_narrow_n8_checked(static_cast>(a)); + return n64_narrow_n8_checked(static_cast>(source_val, should_assert)); } // Narrow a 32 bits number to a 16 bits number, discarding any upper exceeding bytes. template [[nodiscard]] -constexpr auto n32_narrow_n16(const T a) noexcept +constexpr auto n32_narrow_n16(const T source_val) noexcept { static_assert(std::is_arithmetic_v, "Input variable has not a arithmetic type."); static_assert(std::is_integral_v || (std::is_floating_point_v && std::is_signed_v), "Unsigned floating point numbers are unsupported by the language standard"); @@ -274,39 +331,55 @@ constexpr auto n32_narrow_n16(const T a) noexcept if constexpr (std::is_signed_v) { if constexpr (std::is_floating_point_v) - return static_cast(a & umask); - return static_cast(a & umask); + return static_cast(source_val & umask); + return static_cast(source_val & umask); } else - return static_cast(a & umask); + return static_cast(source_val & umask); } -// Narrow a 32 bits number to a 16 bits number and ASSERT (because you're reasonably sure but not absolutely certain) that it won't overflow. +// Narrow a 32 bits number to a 16 bits number. +// ASSERT (because you're reasonably sure but not absolutely certain) that it won't overflow, otherwise +// otherwise just print an error if it overflows (wise to do this if the values depends from user input/scripts). template [[nodiscard]] inline -auto n32_narrow_n16_checked(const T a) + auto n32_narrow_n16_checked(const T source_val, bool should_assert) { - if constexpr (std::is_signed_v) { - ASSERT(a <= std::numeric_limits::max()); + if (should_assert) + { + if constexpr (std::is_signed_v) { + ASSERT(source_val <= std::numeric_limits::max()); + } + else { + ASSERT(source_val <= std::numeric_limits::max()); + } } - else { - ASSERT(a <= std::numeric_limits::max()); + else + { + if constexpr (std::is_signed_v) { + if (source_val > std::numeric_limits::max()) + detail_stypecast::LogEventWarnWrapper("[Internal] Narrowing conversion from 32 to 16 bits signed integer will overflow.\n"); + } + else { + if (source_val > std::numeric_limits::max()) + detail_stypecast::LogEventWarnWrapper("[Internal] Narrowing conversion from 32 to 16 bits unsigned integer will overflow.\n"); + } } - return n32_narrow_n16(a); + return n32_narrow_n16(source_val); } template [[nodiscard]] -constexpr auto enum32_narrow_n16_checked(const T a) noexcept +constexpr auto enum32_narrow_n16_checked(const T source_val, bool should_assert) noexcept { static_assert(std::is_enum_v, "Input variable is not an enum type."); - return n32_narrow_n16_checked(static_cast>(a)); + return n32_narrow_n16_checked(static_cast>(source_val, should_assert)); } // Narrow a 32 bits number to a 8 bits number, discarding any upper exceeding bytes. template [[nodiscard]] -constexpr auto n32_narrow_n8(const T a) noexcept +constexpr auto n32_narrow_n8(const T source_val) noexcept { static_assert(std::is_arithmetic_v, "Input variable has not a arithmetic type."); static_assert(sizeof(T) == 4, "Input variable is not a 32 bit number."); @@ -314,37 +387,53 @@ constexpr auto n32_narrow_n8(const T a) noexcept // Since the narrowing can be implementation specific, here we decide that we take only the lower 16 bytes and discard the upper ones. constexpr uint32 umask = 0x0000'00FF; if constexpr (std::is_signed_v) - return static_cast (a & umask); + return static_cast (source_val & umask); else - return static_cast(a & umask); + return static_cast(source_val & umask); } -// Narrow a 32 bits number to an 8 bits number and ASSERT (because you're reasonably sure but not absolutely certain) that it won't overflow. +// Narrow a 32 bits number to a 16 bits number. +// ASSERT (because you're reasonably sure but not absolutely certain) that it won't overflow, otherwise +// otherwise just print an error if it overflows (wise to do this if the values depends from user input/scripts). template [[nodiscard]] inline -auto n32_narrow_n8_checked(const T a) + auto n32_narrow_n8_checked(const T source_val, bool should_assert) { - if constexpr (std::is_signed_v) { - ASSERT(a <= std::numeric_limits::max()); + if (should_assert) + { + if constexpr (std::is_signed_v) { + ASSERT(source_val <= std::numeric_limits::max()); + } + else { + ASSERT(source_val <= std::numeric_limits::max()); + } } - else { - ASSERT(a <= std::numeric_limits::max()); + else + { + if constexpr (std::is_signed_v) { + if (source_val > std::numeric_limits::max()) + detail_stypecast::LogEventWarnWrapper("[Internal] Narrowing conversion from 32 to 8 bits signed integer will overflow.\n"); + } + else { + if (source_val > std::numeric_limits::max()) + detail_stypecast::LogEventWarnWrapper("[Internal] Narrowing conversion from 32 to 8 bits unsigned integer will overflow.\n"); + } } - return n32_narrow_n8(a); + return n32_narrow_n8(source_val); } template [[nodiscard]] -constexpr auto enum32_narrow_n8_checked(const T a) noexcept +constexpr auto enum32_narrow_n8_checked(const T source_val, bool should_assert) noexcept { static_assert(std::is_enum_v, "Input variable is not an enum type."); - return n32_narrow_n8_checked(static_cast>(a)); + return n32_narrow_n8_checked(static_cast>(source_val, should_assert)); } // Narrow a 16 bits number to an 8 bits number, discarding any upper exceeding bytes. template [[nodiscard]] -constexpr auto n16_narrow_n8(const T a) noexcept +constexpr auto n16_narrow_n8(const T source_val) noexcept { static_assert(std::is_arithmetic_v, "Input variable has not a arithmetic type."); static_assert(std::is_integral_v, "Only integral types are supported by this function."); @@ -353,46 +442,62 @@ constexpr auto n16_narrow_n8(const T a) noexcept // Since the narrowing can be implementation specific, here we decide that we take only the lower 16 bytes and discard the upper ones. constexpr uint16 umask = 0x00FF; if constexpr (std::is_signed_v) - return static_cast(a & umask); + return static_cast(source_val & umask); else - return static_cast(a & umask); + return static_cast(source_val & umask); } -// Narrow a 16 bits number to an 8 bits number and ASSERT (because you're reasonably sure but not absolutely certain) that it won't overflow. +// Narrow a 32 bits number to a 16 bits number. +// ASSERT (because you're reasonably sure but not absolutely certain) that it won't overflow, otherwise +// otherwise just print an error if it overflows (wise to do this if the values depends from user input/scripts). template [[nodiscard]] inline -auto n16_narrow_n8_checked(const T a) + auto n16_narrow_n8_checked(const T source_val, bool should_assert) { - if constexpr (std::is_signed_v) { - ASSERT(a <= std::numeric_limits::max()); + if (should_assert) + { + if constexpr (std::is_signed_v) { + ASSERT(source_val <= std::numeric_limits::max()); + } + else { + ASSERT(source_val <= std::numeric_limits::max()); + } } - else { - ASSERT(a <= std::numeric_limits::max()); + else + { + if constexpr (std::is_signed_v) { + if (source_val > std::numeric_limits::max()) + detail_stypecast::LogEventWarnWrapper("[Internal] Narrowing conversion from 16 to 8 bits signed integer will overflow.\n"); + } + else { + if (source_val > std::numeric_limits::max()) + detail_stypecast::LogEventWarnWrapper("[Internal] Narrowing conversion from 16 to 8 bits unsigned integer will overflow.\n"); + } } - return n16_narrow_n8(a); + return n16_narrow_n8(source_val); } template [[nodiscard]] -constexpr auto enum16_narrow_n8_checked(const T a) noexcept +constexpr auto enum16_narrow_n8_checked(const T source_val, bool should_assert) noexcept { static_assert(std::is_enum_v, "Input variable is not an enum type."); - return n16_narrow_n8_checked(static_cast>(a)); + return n16_narrow_n8_checked(static_cast>(source_val, should_assert)); } // If size_t is bigger than a 32 bits number, narrow it to a 32 bits number discarding any upper exceeding bytes, otherwise plain return the same value.. [[nodiscard]] -constexpr uint32 usize_narrow_u32(const size_t a) noexcept +constexpr uint32 usize_narrow_u32(const size_t source_val) noexcept { // This doesn't work because n64_narrow_n32 static_asserts will be evaluated and fail on 32 bits compilation. /* if constexpr (sizeof(size_t) == 8) - return n64_narrow_n32(a); + return n64_narrow_n32(source_val); else return a; */ #if SIZE_MAX == UINT64_MAX - return n64_narrow_n32(a); + return n64_narrow_n32(source_val); #elif SIZE_MAX == UINT32_MAX return a; #else @@ -402,177 +507,222 @@ constexpr uint32 usize_narrow_u32(const size_t a) noexcept // If size_t is bigger than a 32 bits number, narrow it to a 32 bits number and ASSERT (because you're reasonably sure but not absolutely certain) that it won't overflow. If size_t has 32 bits size, plain return the same value. [[nodiscard]] inline -uint32 usize_narrow_u32_checked(const size_t a) +uint32 usize_narrow_u32_checked(const size_t source_val, bool should_assert) { - ASSERT(a <= std::numeric_limits::max()); - return usize_narrow_u32(a); + if (should_assert) + ASSERT(source_val <= std::numeric_limits::max()); + else if (source_val > std::numeric_limits::max()) + detail_stypecast::LogEventWarnWrapper("[Internal] Narrowing conversion from size_t to 32 bits unsigned integer will overflow.\n"); + + return usize_narrow_u32(source_val); } /* Unsigned (and size_t) to signed, clamping. */ [[nodiscard]] constexpr - int8 i8_from_u8_clamping(const uint8 a) noexcept + int8 i8_from_u8_clamping(const uint8 source_val) noexcept { - return (a > (uint8_t)std::numeric_limits::max()) ? std::numeric_limits::max() : (int8_t)a; + return (source_val > (uint8_t)std::numeric_limits::max()) ? std::numeric_limits::max() : (int8_t)source_val; } [[nodiscard]] constexpr - int16 i16_from_u16_clamping(const uint16 a) noexcept + int16 i16_from_u16_clamping(const uint16 source_val) noexcept { - return (a > (uint16_t)std::numeric_limits::max()) ? std::numeric_limits::max() : (int16_t)a; + return (source_val > (uint16_t)std::numeric_limits::max()) ? std::numeric_limits::max() : (int16_t)source_val; } [[nodiscard]] constexpr - int32 i32_from_u32_clamping(const uint32 a) noexcept + int32 i32_from_u32_clamping(const uint32 source_val) noexcept { - return (a > (uint32_t)std::numeric_limits::max()) ? std::numeric_limits::max() : (int32_t)a; + return (source_val > (uint32_t)std::numeric_limits::max()) ? std::numeric_limits::max() : (int32_t)source_val; } [[nodiscard]] constexpr - int64 i64_from_u64_clamping(const uint64 a) noexcept + int64 i64_from_u64_clamping(const uint64 source_val) noexcept { - return (a > (uint64_t)std::numeric_limits::max()) ? std::numeric_limits::max() : (int64_t)a; + return (source_val > (uint64_t)std::numeric_limits::max()) ? std::numeric_limits::max() : (int64_t)source_val; } [[nodiscard]] constexpr - int32 i32_from_usize_clamping(const size_t a) noexcept + int32 i32_from_usize_clamping(const size_t source_val) noexcept { - return (a > (size_t)std::numeric_limits::max()) ? std::numeric_limits::max() : (int32_t)a; + return (source_val > (size_t)std::numeric_limits::max()) ? std::numeric_limits::max() : (int32_t)source_val; } [[nodiscard]] constexpr - int64 i64_from_usize_clamping(const size_t a) noexcept + int64 i64_from_usize_clamping(const size_t source_val) noexcept { - return (a > (size_t)std::numeric_limits::max()) ? std::numeric_limits::max() : (int64_t)a; + return (source_val > (size_t)std::numeric_limits::max()) ? std::numeric_limits::max() : (int64_t)source_val; } [[nodiscard]] constexpr - uint32 u32_from_usize_clamping(const size_t a) noexcept + uint32 u32_from_usize_clamping(const size_t source_val) noexcept { if constexpr (sizeof(size_t) == 8) - return (a > (size_t)std::numeric_limits::max()) ? std::numeric_limits::max() : (uint32_t)a; + return (source_val > (size_t)std::numeric_limits::max()) ? std::numeric_limits::max() : (uint32_t)source_val; else - return a; + return source_val; } /* Unsigned (and size_t) to signed, checked for overflows. */ -// Convert an 8 bits unsigned value to signed and ASSERT (because you're reasonably sure but not absolutely certain) that it will fit into its signed datatype counterpart (unsigned variables can store greater values than signed ones). [[nodiscard]] inline - int8 i8_from_u8_checked(const uint8 a) // not clamping/capping + int8 i8_from_u8_checked(const uint8 source_val, bool should_assert) // not clamping/capping +{ + const bool would_overflow = (source_val > (uint8)std::numeric_limits::max()); + if (should_assert) + ASSERT(!would_overflow); + else if (would_overflow) + detail_stypecast::LogEventWarnWrapper("[Internal] Narrowing conversion from 8 bits unsigned integer to 8 bits signed integer will overflow.\n"); + return static_cast(source_val); +} +template int8 i8_from_u8_checked(T, bool) = delete; // disable implicit type conversion for the inpuT source_valrgument + +[[nodiscard]] inline + int16 i8_from_u16_checked(const uint16 source_val, bool should_assert) // not clamping/capping { - ASSERT(a <= (uint8_t)std::numeric_limits::max()); - return static_cast(a); + const bool would_overflow = (source_val > (uint16)std::numeric_limits::max()); + if (should_assert) + ASSERT(!would_overflow); + else if (would_overflow) + detail_stypecast::LogEventWarnWrapper("[Internal] Narrowing conversion from 16 bits unsigned integer to 8 bits signed integer will overflow.\n"); + + return static_cast(source_val); } -template int8 i8_from_u8_checked(T) = delete; // disable implicit type conversion for the input argument +template int16 i8_from_u16_checked(T, bool) = delete; // disable implicit type conversion for the inpuT source_valrgument -// Convert a 16 bits unsigned value to signed and ASSERT (because you're reasonably sure but not absolutely certain) that it will fit into its signed datatype counterpart (unsigned variables can store greater values than signed ones). [[nodiscard]] inline - int16 i16_from_u16_checked(const uint16 a) // not clamping/capping + int16 i16_from_u16_checked(const uint16 source_val, bool should_assert) // not clamping/capping { - ASSERT(a <= (uint16_t)std::numeric_limits::max()); - return static_cast(a); + const bool would_overflow = (source_val > (uint16)std::numeric_limits::max()); + if (should_assert) + ASSERT(!would_overflow); + else if (would_overflow) + detail_stypecast::LogEventWarnWrapper("[Internal] Narrowing conversion from 16 bits unsigned integer to 16 bits signed integer will overflow.\n"); + + return static_cast(source_val); } -template int16 i16_from_u16_checked(T) = delete; // disable implicit type conversion for the input argument +template int16 i16_from_u16_checked(T, bool) = delete; // disable implicit type conversion for the inpuT source_valrgument [[nodiscard]] inline - int16 i16_from_u32_checked(const uint32 a) // not clamping/capping + int16 i16_from_u32_checked(const uint32 source_val, bool should_assert) // not clamping/capping { - ASSERT(a <= (uint32_t)std::numeric_limits::max()); - return static_cast(a); + const bool would_overflow = (source_val > (uint32)std::numeric_limits::max()); + if (should_assert) + ASSERT(!would_overflow); + else if (would_overflow) + detail_stypecast::LogEventWarnWrapper("[Internal] Narrowing conversion from 32 bits unsigned integer to 16 bits signed integer will overflow.\n"); + + return static_cast(source_val); } -template int16 i16_from_u32_checked(T) = delete; // disable implicit type conversion for the input argument +template int16 i16_from_u32_checked(T, bool) = delete; // disable implicit type conversion for the inpuT source_valrgument [[nodiscard]] inline - int16 i16_from_u64_checked(const uint64 a) // not clamping/capping + int16 i16_from_u64_checked(const uint64 source_val, bool should_assert) // not clamping/capping { - ASSERT(a <= (uint64_t)std::numeric_limits::max()); - return static_cast(a); + const bool would_overflow = (source_val > (uint64)std::numeric_limits::max()); + if (should_assert) + ASSERT(!would_overflow); + else if (would_overflow) + detail_stypecast::LogEventWarnWrapper("[Internal] Narrowing conversion from 64 bits unsigned integer to 16 bits signed integer will overflow.\n"); + return static_cast(source_val); } -template int16 i16_from_u64_checked(T) = delete; // disable implicit type conversion for the input argument +template int16 i16_from_u64_checked(T, bool) = delete; // disable implicit type conversion for the inpuT source_valrgument // Convert a 32 bits unsigned value to signed and ASSERT (because you're reasonably sure but not absolutely certain) that it will fit into its signed datatype counterpart (unsigned variables can store greater values than signed ones). [[nodiscard]] inline - int32 i32_from_u32_checked(const uint32 a) // not clamping/capping + int32 i32_from_u32_checked(const uint32 source_val, bool should_assert) // not clamping/capping { - ASSERT(a <= (uint32_t)std::numeric_limits::max()); - return static_cast(a); + const bool would_overflow = (source_val > (uint32)std::numeric_limits::max()); + if (should_assert) + ASSERT(!would_overflow); + else if (would_overflow) + detail_stypecast::LogEventWarnWrapper("[Internal] Narrowing conversion from 32 bits unsigned integer to 32 bits signed integer will overflow.\n"); + return static_cast(source_val); } -template int32 i32_from_u32_checked(T) = delete; // disable implicit type conversion for the input argument +template int32 i32_from_u32_checked(T, bool) = delete; // disable implicit type conversion for the inpuT source_valrgument [[nodiscard]] inline - int32 i32_from_u64_checked(const uint64 a) // not clamping/capping + int32 i32_from_u64_checked(const uint64 source_val, bool should_assert) // not clamping/capping { - ASSERT(a <= (uint64_t)std::numeric_limits::max()); - return static_cast(a); + const bool would_overflow = (source_val > (uint64)std::numeric_limits::max()); + if (should_assert) + ASSERT(!would_overflow); + else if (would_overflow) + detail_stypecast::LogEventWarnWrapper("[Internal] Narrowing conversion from 64 bits unsigned integer to 32 bits signed integer will overflow.\n"); + return static_cast(source_val); } -template int32 i32_from_u64_checked(T) = delete; // disable implicit type conversion for the input argument +template int32 i32_from_u64_checked(T, bool) = delete; // disable implicit type conversion for the inpuT source_valrgument // Convert a 64 bits unsigned value to signed and ASSERT (because you're reasonably sure but not absolutely certain) that it will fit into its signed datatype counterpart (unsigned variables can store greater values than signed ones). [[nodiscard]] inline - int64 i64_from_u64_checked(const uint64 a) // not clamping/capping + int64 i64_from_u64_checked(const uint64 source_val, bool should_assert) // not clamping/capping { - ASSERT(a <= (uint64_t)std::numeric_limits::max()); - return static_cast(a); + const bool would_overflow = (source_val > (uint64)std::numeric_limits::max()); + if (should_assert) + ASSERT(!would_overflow); + else if (would_overflow) + detail_stypecast::LogEventWarnWrapper("[Internal] Narrowing conversion from 64 bits unsigned integer to 64 bits signed integer will overflow.\n"); + return static_cast(source_val); } -template int64 i64_from_u64_checked(T) = delete; // disable implicit type conversion for the input argument +template int64 i64_from_u64_checked(T, bool) = delete; // disable implicit type conversion for the inpuT source_valrgument // size_t conversions [[nodiscard]] inline - int8 i8_from_usize_checked(const size_t a) // not clamping/capping + int8 i8_from_usize_checked(const size_t source_val, bool should_assert) // not clamping/capping { #if SIZE_MAX == UINT64_MAX - return n64_narrow_n8_checked(a); + return n64_narrow_n8_checked(source_val, should_assert); #elif SIZE_MAX == UINT32_MAX - return n32_narrow_n8_checked(a); + return n32_narrow_n8_checked(source_val); #else # error "size_t is neither 8 nor 4 bytes?" #endif } -template int8 i8_from_usize_checked(T) = delete; // disable implicit type conversion for the input argument +template int8 i8_from_usize_checked(T, bool) = delete; // disable implicit type conversion for the inpuT source_valrgument [[nodiscard]] inline - int16 i16_from_usize_checked(const size_t a) // not clamping/capping + int16 i16_from_usize_checked(const size_t source_val, bool should_assert) // not clamping/capping { #if SIZE_MAX == UINT64_MAX - return n64_narrow_n16_checked(a); + return n64_narrow_n16_checked(source_val, should_assert); #elif SIZE_MAX == UINT32_MAX - return n32_narrow_n16_checked(a); + return n32_narrow_n16_checked(source_val); #else # error "size_t is neither 8 nor 4 bytes?" #endif } -template int16 i16_from_usize_checked(T) = delete; // disable implicit type conversion for the input argument +template int16 i16_from_usize_checked(T, bool) = delete; // disable implicit type conversion for the inpuT source_valrgument [[nodiscard]] inline - int32 i32_from_usize_checked(const size_t a) // not clamping/capping + int32 i32_from_usize_checked(const size_t source_val, bool should_assert) // not clamping/capping { #if SIZE_MAX == UINT64_MAX - return i32_from_u32_clamping(n64_narrow_n32_checked(a)); + return i32_from_u32_clamping(n64_narrow_n32_checked(source_val, should_assert)); #elif SIZE_MAX == UINT32_MAX - return i32_from_u32_checked(n_alias_cast(a)); + return i32_from_u32_checked(n_alias_cast(source_val)); #else # error "size_t is neither 8 nor 4 bytes?" #endif } -template int32 i32_from_usize_checked(T) = delete; // disable implicit type conversion for the input argument +template int32 i32_from_usize_checked(T, bool) = delete; // disable implicit type conversion for the inpuT source_valrgument [[nodiscard]] inline - int64 i64_from_usize_checked(const size_t a) // not clamping/capping + int64 i64_from_usize_checked(const size_t source_val, bool should_assert) // not clamping/capping { #if SIZE_MAX == UINT64_MAX - return i64_from_u64_checked(n_alias_cast(a)); + return i64_from_u64_checked(n_alias_cast(source_val), should_assert); #elif SIZE_MAX == UINT32_MAX - return static_cast(a); // For sure it will fit + return static_cast(source_val); // For sure it will fit #else # error "size_t is neither 8 nor 4 bytes?" #endif } -template int64 i64_from_usize_checked(T) = delete; // disable implicit type conversion for the input argument +template int64 i64_from_usize_checked(T, bool) = delete; // disable implicit type conversion for the inpuT source_valrgument diff --git a/src/game/items/CItemMultiCustom.cpp b/src/game/items/CItemMultiCustom.cpp index 22e84d1d2..3cf453ec2 100644 --- a/src/game/items/CItemMultiCustom.cpp +++ b/src/game/items/CItemMultiCustom.cpp @@ -1894,7 +1894,7 @@ uint8 CItemMultiCustom::GetPlane(const CMultiComponent * pComponent) int8 CItemMultiCustom::GetPlaneZ(uint8 plane) { - return n32_narrow_n8_checked(7 + ((plane - 1) * 20)); + return n32_narrow_n8_checked(7 + ((plane - 1) * 20), true); } bool CItemMultiCustom::IsValidItem(ITEMID_TYPE id, CClient * pClientSrc, bool fMulti) From c3f890d9386478ec24a5f257e973a5cfa552f06a Mon Sep 17 00:00:00 2001 From: cbnolok Date: Thu, 3 Oct 2024 13:28:55 +0200 Subject: [PATCH 64/86] Fixed: on Windows, the console window closed itself after a failed server start attempt. --- src/sphere/ntwindow.cpp | 14 ++++++----- src/sphere/threads.cpp | 52 ++++++++++++++++++++++++++++++----------- src/sphere/threads.h | 26 +++++++++++++-------- 3 files changed, 62 insertions(+), 30 deletions(-) diff --git a/src/sphere/ntwindow.cpp b/src/sphere/ntwindow.cpp index 5b21fbb47..c9f8a049d 100644 --- a/src/sphere/ntwindow.cpp +++ b/src/sphere/ntwindow.cpp @@ -24,7 +24,7 @@ #define IDT_ONTICK 1 -CNTApp theApp; +static CNTApp theApp; //************************************ // -CAboutDlg @@ -166,6 +166,8 @@ BOOL CNTWindow::CStatusDlg::DefDialogProc( UINT message, WPARAM wParam, LPARAM l CNTWindow::CNTWindow() : AbstractSphereThread("T_ConsoleWindow", IThread::Highest), _NTWInitParams{}, m_zCommands {{}} { + _fKeepAliveAtShutdown = true; + m_iLogTextLen = 0; m_fLogScrollLock = false; m_dwColorNew = RGB( 0xaf,0xaf,0xaf ); @@ -274,14 +276,14 @@ void CNTWindow::List_AddSingle(COLORREF color, LPCTSTR ptcText) if ( iNewLen > iMaxTextLen ) { - const int iCut = iNewLen - iMaxTextLen; + const int iCut = iNewLen - iMaxTextLen; m_wndLog.SetSel( 0, iCut ); // These SetRedraw FALSE/TRUE calls will make the log panel scroll much faster when spamming text, but // it will generate some drawing artifact //m_wndLog.SetRedraw(FALSE); - m_wndLog.ReplaceSel( "" ); + m_wndLog.ReplaceSel( "" ); } else if (NTWindow_CanScroll()) theApp.m_wndMain.m_wndLog.ScrollLine(); @@ -318,7 +320,7 @@ void CNTWindow::List_AddGroup(std::deque>&& msgs) { iTotalTextLen += co->GetTextString().GetLength(); } - + const int iNewLen = m_iLogTextLen + iTotalTextLen; if (iNewLen > iMaxTextLen) @@ -1025,7 +1027,7 @@ bool CNTWindow::NTWindow_OnTick( int iWaitmSec ) iWaitmSec = 0; } } - + // Give the windows message loops a tick. for (;;) @@ -1157,7 +1159,7 @@ bool CNTWindow::NTWindow_OnTick( int iWaitmSec ) } else if ( !*pszCurSel ) // or there is still no selection { - curmatch = firstmatch; + curmatch = firstmatch; } else // need to find for the next record { diff --git a/src/sphere/threads.cpp b/src/sphere/threads.cpp index d68907d97..77dba0d3b 100644 --- a/src/sphere/threads.cpp +++ b/src/sphere/threads.cpp @@ -62,6 +62,7 @@ IThread::IThread() noexcept : IThread::~IThread() noexcept = default; #ifdef _WIN32 +/* #pragma pack(push, 8) typedef struct tagTHREADNAME_INFO { @@ -71,9 +72,12 @@ typedef struct tagTHREADNAME_INFO DWORD dwFlags; } THREADNAME_INFO; #pragma pack(pop) +*/ +#ifdef MSVC_COMPILER static constexpr DWORD MS_VC_EXCEPTION = 0x406D1388; #endif +#endif void IThread::setThreadName(const char* name) { @@ -85,7 +89,7 @@ void IThread::setThreadName(const char* name) Str_CopyLimitNull(name_trimmed, name, m_nameMaxLength); #if defined(_WIN32) - #if defined(_MSC_VER) // TODO: support thread naming when compiling with compilers other than Microsoft's + #if defined(MSVC_COMPILER) // TODO: support thread naming when compiling with compilers other than Microsoft's // Windows uses THREADNAME_INFO structure to set thread name THREADNAME_INFO info; info.dwType = 0x1000; @@ -155,18 +159,17 @@ IThread* ThreadHolder::current() noexcept RETRY_SHARED_LOCK_FOR_TASK(m_mutex, lock, retval, ([this, &lock]() -> IThread* { - if (m_closingThreads) - [[unlikely]] - { - //STDERR_LOG("Closing?\n"); - return nullptr; - } - const threadid_t tid = IThread::getCurrentThreadSystemId(); if (m_spherethreadpairs_systemid_ptr.empty()) [[unlikely]] { + if (m_closingThreads) [[unlikely]] + { + //STDERR_LOG("Closing?\n"); + return nullptr; + } + auto thread = static_cast(DummySphereThread::getInstance()); if (!thread) [[unlikely]] @@ -190,6 +193,7 @@ IThread* ThreadHolder::current() noexcept break; } } + if (!found) [[unlikely]] { @@ -211,6 +215,22 @@ IThread* ThreadHolder::current() noexcept return nullptr; } + if (m_closingThreads) [[unlikely]] + { + auto spherethread = dynamic_cast(thread); + if (!spherethread) + { + // Should never happen. + RaiseImmediateAbort(); + } + + if (!spherethread->_fKeepAliveAtShutdown) + { + //STDERR_LOG("Closing?\n"); + return nullptr; + } + } + // Uncomment it only for testing purposes, since this method is called very often and we don't need the additional overhead //DEBUG_ASSERT( thread->isSameThread(thread->getId()) ); @@ -349,6 +369,9 @@ void ThreadHolder::markThreadsClosing() CANTHROW for (auto& thread_data : m_threads) { auto sphere_thread = static_cast(thread_data.m_ptr); + if (sphere_thread->_fKeepAliveAtShutdown) + continue; + sphere_thread->_fIsClosing = true; thread_data.m_closed = true; } @@ -399,7 +422,8 @@ IThread * ThreadHolder::getThreadAt(size_t at) noexcept */ int AbstractThread::m_threadsAvailable = 0; -AbstractThread::AbstractThread(const char *name, IThread::Priority priority) +AbstractThread::AbstractThread(const char *name, IThread::Priority priority) : + _fKeepAliveAtShutdown(false), _fIsClosing(false) { if( AbstractThread::m_threadsAvailable == 0 ) { @@ -414,7 +438,7 @@ AbstractThread::AbstractThread(const char *name, IThread::Priority priority) } m_threadSystemId = 0; Str_CopyLimitNull(m_name, name, sizeof(m_name)); - m_handle = 0; + m_handle = SPHERE_THREADT_NULL; m_hangCheck = 0; _thread_selfTerminateAfterThisTick = true; m_terminateRequested = true; @@ -493,7 +517,7 @@ void AbstractThread::terminate(bool ended) // Common things ThreadHolder::get().remove(this); m_threadSystemId = 0; - m_handle = 0; + m_handle = SPHERE_THREADT_NULL; // let everyone know we have been terminated m_terminateEvent.set(); @@ -626,7 +650,7 @@ SPHERE_THREADENTRY_RETNTYPE AbstractThread::runner(void *callerThread) bool AbstractThread::isActive() const { - return (m_handle != 0); + return (m_handle != SPHERE_THREADT_NULL); } void AbstractThread::waitForClose() @@ -756,14 +780,14 @@ void AbstractThread::setPriority(IThread::Priority pri) bool AbstractThread::shouldExit() noexcept { - return m_terminateRequested || _thread_selfTerminateAfterThisTick; + return closing() || m_terminateRequested || _thread_selfTerminateAfterThisTick; } /* * AbstractSphereThread */ AbstractSphereThread::AbstractSphereThread(const char *name, Priority priority) - : AbstractThread(name, priority), _fIsClosing(false) + : AbstractThread(name, priority) { #ifdef THREAD_TRACK_CALLSTACK m_stackPos = -1; diff --git a/src/sphere/threads.h b/src/sphere/threads.h index f4ea58293..3534efbd6 100644 --- a/src/sphere/threads.h +++ b/src/sphere/threads.h @@ -31,6 +31,7 @@ typedef DWORD threadid_t; #define SPHERE_THREADENTRY_RETNTYPE unsigned #define SPHERE_THREADENTRY_CALLTYPE __stdcall + #define SPHERE_THREADT_NULL nullptr #else typedef pthread_t spherethread_t; #ifdef __APPLE__ @@ -41,6 +42,7 @@ #define SPHERE_THREADENTRY_RETNTYPE void * #define SPHERE_THREADENTRY_CALLTYPE + #define SPHERE_THREADT_NULL 0 #endif class IThread; @@ -207,18 +209,21 @@ class AbstractThread : public IThread friend class ThreadHolder; protected: - bool _thread_selfTerminateAfterThisTick; + bool _fKeepAliveAtShutdown; + volatile std::atomic_bool _thread_selfTerminateAfterThisTick; + volatile std::atomic_bool _fIsClosing; private: - char m_name[30]; + volatile std::atomic_bool m_terminateRequested; + + char m_name[30]; static int m_threadsAvailable; - spherethread_t m_handle; + + spherethread_t m_handle; uint m_hangCheck; Priority m_priority; uint m_tickPeriod; AutoResetEvent m_sleepEvent; - - volatile std::atomic_bool m_terminateRequested; ManualResetEvent m_terminateEvent; public: @@ -246,13 +251,18 @@ class AbstractThread : public IThread void overwriteInternalThreadName(const char* name) noexcept; bool isCurrentThread() const noexcept; + bool closing() noexcept + { + return _fIsClosing; + } + protected: virtual void tick() = 0; // NOTE: this should not be too long-lasted function, so no world loading, etc here!!! virtual void onStart(); virtual bool shouldExit() noexcept override; -private: + private: void run(); static SPHERE_THREADENTRY_RETNTYPE SPHERE_THREADENTRY_CALLTYPE runner(void *callerThread); }; @@ -263,7 +273,6 @@ class AbstractSphereThread : public AbstractThread { friend class ThreadHolder; - bool _fIsClosing; #ifdef THREAD_TRACK_CALLSTACK struct STACK_INFO_REC { @@ -291,9 +300,6 @@ class AbstractSphereThread : public AbstractThread void getStringBuffer(TemporaryString &string) noexcept; void exceptionCaught(); - bool closing() noexcept { - return _fIsClosing; - } #ifdef THREAD_TRACK_CALLSTACK inline void freezeCallStack(bool freeze) noexcept From 28586ef1d206b74c3c1f3062b67fe66202a3cd7e Mon Sep 17 00:00:00 2001 From: cbnolok Date: Thu, 3 Oct 2024 13:31:36 +0200 Subject: [PATCH 65/86] Fixed MinGW compilation with both Clang and MSVC runtime libs. Added different macros, instead of using _MSC_VER. This one is added even when Clang with MSVC runtime, so it's not viable to check if we're compiling with MSVC. --- lib/bcrypt/bcrypt/wrapper.c | 11 +++++-- lib/libev/wrapper_ev.c | 15 +++++++--- src/common/CException.cpp | 10 ++++--- src/common/CScript.cpp | 7 ++++- src/common/CScript.h | 15 ++++++---- src/common/ListDefContMap.h | 6 ++-- src/common/common.h | 22 ++++++++++++-- src/common/crashdump/crashdump.cpp | 14 ++++----- src/common/datatypes.h | 3 +- src/common/os_windows.h | 20 +++++++------ src/common/sphere_library/CSTime.cpp | 18 +++++------ src/common/sphere_library/sptr.h | 11 +++++-- src/common/sphere_library/sstring.cpp | 14 ++++----- src/game/CServerConfig.cpp | 8 +++-- src/game/CServerDef.cpp | 12 ++++---- src/game/CWorldSearch.h | 4 +-- src/game/CWorldTicker.h | 4 +-- src/game/spheresvr.cpp | 2 +- src/game/uo_files/CUOHuesRec.h | 4 +-- src/game/uo_files/CUOIndexRec.h | 4 +-- src/game/uo_files/CUOItemTypeRec.h | 4 +-- src/game/uo_files/CUOMapBlock.h | 4 +-- src/game/uo_files/CUOMapMeter.h | 4 +-- src/game/uo_files/CUOMultiItemRec.h | 4 +-- src/game/uo_files/CUOStaticItemRec.h | 4 +-- src/game/uo_files/CUOTerrainTypeRec.h | 4 +-- src/game/uo_files/CUOVersionBlock.h | 4 +-- src/network/CNetworkOutput.cpp | 2 +- src/network/net_datatypes.h | 4 +-- src/network/packet.cpp | 6 ++-- src/resources/SphereSvr.rc | 8 ++--- src/resources/resource.h | 43 --------------------------- src/sphere/ntservice.cpp | 2 +- src/sphere/ntservice.h | 6 ++-- src/sphere/ntwindow.h | 8 ++--- 35 files changed, 160 insertions(+), 151 deletions(-) delete mode 100644 src/resources/resource.h diff --git a/lib/bcrypt/bcrypt/wrapper.c b/lib/bcrypt/bcrypt/wrapper.c index 197475b8c..6a3503f5b 100644 --- a/lib/bcrypt/bcrypt/wrapper.c +++ b/lib/bcrypt/bcrypt/wrapper.c @@ -49,8 +49,15 @@ extern struct crypt_data _ufc_foobar; char* mystrdup(const char* s) { - char* p = malloc(strlen(s)+1); - if (p) strcpy(p, s); + const size_t len = strlen(s); + char* p = malloc(len) + 1; + if (p) + { + //strcpy(p, s); + strncpy(p, s, len); + p[len] = '\0'; + } + return p; } diff --git a/lib/libev/wrapper_ev.c b/lib/libev/wrapper_ev.c index c9a7cfae2..391df69e3 100644 --- a/lib/libev/wrapper_ev.c +++ b/lib/libev/wrapper_ev.c @@ -2,15 +2,22 @@ #define _LIBEV +// Clang with MSVC backend on Windows defines _MSC_VER! (But also __clang__) +#ifndef MSVC_COMPILER +# if defined(_MSC_VER) && !defined(__clang__) +# define MSVC_COMPILER 1 +# endif +#endif + // libev produces many warnings which isn't really appropriate for us to // address since it is 3rd party code that could be overwritten at any time // with a new version -#ifdef _MSC_VER +#ifdef MSVC_COMPILER #pragma warning(push) #pragma warning(disable:4013 4068 4100 4101 4127 4133 4189 4244 4245 4456 4457 4706 4996) #else - //#define _POSIX_C_SOURCE - #define _POSIX_SOURCE 1 + //#define _POSIX_C_SOURCE 1 + //#define _POSIX_SOURCE #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wcomment" @@ -44,7 +51,7 @@ //config.h for ev.c is generated by cmake #include "libev/ev.c" -#ifdef _MSC_VER +#ifdef MSVC_COMPILER #pragma warning(pop) #else #pragma GCC diagnostic pop diff --git a/src/common/CException.cpp b/src/common/CException.cpp index 8c92641b1..683ae0239 100644 --- a/src/common/CException.cpp +++ b/src/common/CException.cpp @@ -45,7 +45,7 @@ void NotifyDebugger() { #ifdef _WIN32 - #ifdef _MSC_VER + #ifdef MSVC_COMPILER __debugbreak(); #else SetAbortImmediate(false); @@ -70,10 +70,12 @@ void SetAbortImmediate(bool on) noexcept { *_GetAbortImmediate() = on; } +#ifndef _WIN32 static bool IsAbortImmediate() noexcept { return *_GetAbortImmediate(); } +#endif void RaiseRecoverableAbort() { @@ -234,7 +236,7 @@ static void _cdecl Sphere_Purecall_Handler() void SetPurecallHandler() { // We don't want sphere to immediately exit if something calls a pure virtual method. -#ifdef _MSC_VER +#ifdef MSVC_RUNTIME _set_purecall_handler(Sphere_Purecall_Handler); #else // GCC handler for pure calls is __cxxabiv1::__cxa_pure_virtual. @@ -247,7 +249,7 @@ void SetPurecallHandler() #include "crashdump/crashdump.h" -void _cdecl Sphere_Exception_Windows( unsigned int id, struct _EXCEPTION_POINTERS* pData ) +static void _cdecl Sphere_Exception_Windows( unsigned int id, struct _EXCEPTION_POINTERS* pData ) { #ifndef _NO_CRASHDUMP if ( CrashDump::IsEnabled() ) @@ -267,7 +269,7 @@ void _cdecl Sphere_Exception_Windows( unsigned int id, struct _EXCEPTION_POINTER void SetExceptionTranslator() { -#if defined(_MSC_VER) && !defined(_DEBUG) +#ifdef MSVC_COMPILER _set_se_translator( Sphere_Exception_Windows ); #endif } diff --git a/src/common/CScript.cpp b/src/common/CScript.cpp index 681b00ff9..645ad19a0 100644 --- a/src/common/CScript.cpp +++ b/src/common/CScript.cpp @@ -9,11 +9,16 @@ #include "common.h" +/* + * TODO: + * make CScriptKey m_pszKey and m_pszVal private. + * make setter and getters methods that will automatically update the buffer lengths, held in a separate value. +*/ + /////////////////////////////////////////////////////////////// // -CScriptKey - bool CScriptKey::IsKey( lpctstr pszName ) const { ASSERT(m_pszKey); diff --git a/src/common/CScript.h b/src/common/CScript.h index 855f87fe5..605f6156d 100644 --- a/src/common/CScript.h +++ b/src/common/CScript.h @@ -31,11 +31,13 @@ class CScriptKey // Args passed with the key. bool HasArgs() const; - tchar * GetArgRaw() const; // Not need to parse at all. - tchar * GetArgStr( bool * fQuoted ); // this could be a quoted string ? - inline tchar * GetArgStr() { - return GetArgStr(nullptr); - } + + // Not need to parse at all. + tchar * GetArgRaw() const; + + // this could be a quoted string ? + tchar * GetArgStr(bool * fQuoted = nullptr); + char GetArgCVal(); uchar GetArgUCVal(); @@ -62,7 +64,8 @@ class CScriptKey dword GetArgFlag( dword dwStart, dword dwMask ); int64 GetArgLLFlag( uint64 iStart, uint64 iMask ); -public: +// This class is meant only to be inherited. +protected: CScriptKey(); CScriptKey( tchar * ptcKey, tchar * ptcArg ); ~CScriptKey() = default; diff --git a/src/common/ListDefContMap.h b/src/common/ListDefContMap.h index db86bc11e..9df957509 100644 --- a/src/common/ListDefContMap.h +++ b/src/common/ListDefContMap.h @@ -214,9 +214,9 @@ class CListDefMap void ClearKeys(lpctstr mask = nullptr); void DeleteKey( lpctstr key ); - bool r_LoadVal( lpctstr ptcKey, CScript & s ); - bool r_Write( CTextConsole *pSrc, lpctstr pszString, CSString& strVal ); - void r_WriteSave( CScript& s ); + bool r_LoadVal( lpctstr ptcKey, CScript & s ) NONVIRTUAL; + bool r_Write( CTextConsole *pSrc, lpctstr pszString, CSString& strVal ) NONVIRTUAL; + void r_WriteSave( CScript& s ) NONVIRTUAL; }; #endif // _INC_LISTDEFCONTMAP_H diff --git a/src/common/common.h b/src/common/common.h index 5e75cc24a..fdf5a2f9e 100644 --- a/src/common/common.h +++ b/src/common/common.h @@ -49,6 +49,21 @@ /* Coding helpers */ +// On Windows, Clang with MSVC runtime defines _MSC_VER! (But also __clang__). +#if !defined(_MSC_VER) || defined(__clang__) +# define NON_MSVC_COMPILER 1 +#endif + +#if defined(_MSC_VER) && !defined(__clang__) +# define MSVC_COMPILER 1 +#endif + +// On Windows, Clang can use MinGW or MSVC backend. +#ifdef _MSC_VER +# define MSVC_RUNTIME +#endif + + // Strings #define STRINGIFY_IMPL_(x) #x #define STRINGIFY(x) STRINGIFY_IMPL_(x) @@ -197,10 +212,11 @@ constexpr void UnreferencedParameter(T const&) noexcept { // b = 1-based index of arguments // (note: add 1 to index for non-static class methods because 'this' argument // is inserted in position 1) -#ifdef _MSC_VER +#ifdef MSVC_COMPILER #define __printfargs(a,b) #else - #ifdef _WIN32 + #ifdef __MINGW32__ + // Clang doesn't have a way to switch from gnu or ms style printf arguments. It just depends on the runtime used. #define __printfargs(a,b) __attribute__ ((format(gnu_printf, a, b))) #else #define __printfargs(a,b) __attribute__ ((format(printf, a, b))) @@ -210,7 +226,7 @@ constexpr void UnreferencedParameter(T const&) noexcept { /* Sanitizers utilities */ -#if defined(_MSC_VER) +#if defined(MSVC_COMPILER) #if defined(__SANITIZE_ADDRESS__) || defined(ADDRESS_SANITIZER) #define NO_SANITIZE_ADDRESS __declspec(no_sanitize_address) diff --git a/src/common/crashdump/crashdump.cpp b/src/common/crashdump/crashdump.cpp index 469a3c8dd..5f78264f2 100644 --- a/src/common/crashdump/crashdump.cpp +++ b/src/common/crashdump/crashdump.cpp @@ -45,32 +45,32 @@ void CrashDump::Disable() } } -void CrashDump::StartCrashDump( DWORD processID, DWORD threadID, struct _EXCEPTION_POINTERS* pExceptionData ) +void CrashDump::StartCrashDump( DWORD processID, DWORD threadID, struct _EXCEPTION_POINTERS* pExceptionData ) { HANDLE process = nullptr, dumpFile = nullptr; - + if (!processID || !threadID || !pExceptionData) return; process = GetCurrentProcess(); if (process == nullptr) return; - + char buf[128]; SYSTEMTIME st; GetSystemTime(&st); snprintf(buf, sizeof(buf), "sphereCrash_%02i%02i-%02i%02i%02i%04i.dmp", st.wMonth, st.wDay, st.wHour, st.wMinute, st.wSecond, st.wMilliseconds); - dumpFile = CreateFile(buf, GENERIC_WRITE, FILE_SHARE_WRITE, 0, CREATE_ALWAYS, 0, 0); + dumpFile = CreateFile(buf, GENERIC_WRITE, FILE_SHARE_WRITE, nullptr, CREATE_ALWAYS, 0, nullptr); if (dumpFile == INVALID_HANDLE_VALUE) return; - + MINIDUMP_EXCEPTION_INFORMATION eInfo; eInfo.ThreadId = threadID; eInfo.ExceptionPointers = pExceptionData; eInfo.ClientPointers = true; - + m_tDumpFunction(process, processID, dumpFile, MiniDumpWithDataSegs, &eInfo, nullptr, nullptr); - + CloseHandle(dumpFile); return; } diff --git a/src/common/datatypes.h b/src/common/datatypes.h index c7125776e..16531cc31 100644 --- a/src/common/datatypes.h +++ b/src/common/datatypes.h @@ -104,7 +104,7 @@ typedef uint64_t uint64; #else // _WIN32 - #ifdef _MSC_VER // already defined on MinGW + #ifdef _MSC_VER // already defined on MinGW #include typedef SSIZE_T ssize_t; #endif // _MSC_VER @@ -115,6 +115,7 @@ typedef uint64_t uint64; #define PRIxSIZE_T "zx" #define PRIdSSIZE_T "zd" #else + // If using MSVC runtime and not GNU/MinGW. #define PRIuSIZE_T "Iu" #define PRIxSIZE_T "Ix" #define PRIdSSIZE_T "Id" diff --git a/src/common/os_windows.h b/src/common/os_windows.h index 9d8b08f31..5a0d456e1 100644 --- a/src/common/os_windows.h +++ b/src/common/os_windows.h @@ -48,16 +48,18 @@ #define NOTEXTMETRIC #define NOWH -# ifdef _MSC_VER +#if defined(_MSC_VER) && !defined(__clang__) // Workaround to a possible VS compiler bug: instead of complaining if a macro expands to a "defined" macro, // it complains if a define macro contains the words "defined" in its name... -# pragma warning(push) -# pragma warning(disable: 5105) -# endif -# include -# ifdef _MSC_VER -# pragma warning(pop) -# endif +# pragma warning(push) +# pragma warning(disable: 5105) +#endif + +#include + +#if defined(_MSC_VER) && !defined(__clang__) +# pragma warning(pop) +#endif /* file handling definitions */ @@ -76,7 +78,7 @@ #define STRICT // strict conversion of handles and pointers. #endif -#ifndef _MSC_VER // No Microsoft compiler +#ifdef __MINGW32__ // No Microsoft compiler #define _cdecl __cdecl // Not defined for mingw. diff --git a/src/common/sphere_library/CSTime.cpp b/src/common/sphere_library/CSTime.cpp index bc1ee97d4..45d3ac118 100644 --- a/src/common/sphere_library/CSTime.cpp +++ b/src/common/sphere_library/CSTime.cpp @@ -26,7 +26,7 @@ // We don't have GetSupportedTickCount on Windows versions previous to Vista/Windows Server 2008. We need to check for overflows // (which occurs every 49.7 days of continuous running of the server, if measured with GetTickCount, every 7 years // with GetSupportedTickCount) manually every time we compare two values. -# if _MSC_VER +# if MSVC_COMPILER # pragma warning(push) # pragma warning(disable: 28159) # endif @@ -35,7 +35,7 @@ # else static inline llong GetSupportedTickCount() noexcept { return (llong)GetTickCount64(); } # endif -# if _MSC_VER +# if MSVC_COMPILER # pragma warning(pop) # endif #endif @@ -173,7 +173,7 @@ static std::tm safe_localtime(const time_t t) noexcept #if defined(__unix__) || defined(__APPLE__) || defined(_POSIX_VERSION) localtime_r(&t, &atm); -#elif defined(_MSC_VER) +#elif defined(MSVC_RUNTIME) || defined(__MINGW32__) localtime_s(&atm, &t); #elif defined(__STDC_LIB_EXT1__) localtime_s(&t, &atm); @@ -221,7 +221,7 @@ static std::tm safe_gmtime(const time_t t) noexcept #if defined(__unix__) || defined(__APPLE__) || defined(_POSIX_VERSION) gmtime_r(&t, &atm); -#elif defined(_MSC_VER) +#elif defined(MSVC_RUNTIME) || defined(__MINGW32__) gmtime_s(&atm, &t); #elif defined(__STDC_LIB_EXT1__) gmtime_s(&t, &atm); @@ -256,7 +256,7 @@ std::tm CSTime::GetLocalTmPlain() const noexcept #define maxTimeBufferSize 128 #endif -#if defined(_WIN32) && defined (_MSC_VER) +#if defined(_WIN32) && defined (MSVC_COMPILER) static void __cdecl invalidParameterHandler(const wchar_t* expression, const wchar_t* function, const wchar_t* file, uint line, uintptr_t pReserved) { // bad format has been specified @@ -276,12 +276,12 @@ static void FormatDateTime(tchar * pszTemp, lpctstr pszFormat, const struct tm * ASSERT(ptmTemp != nullptr); #ifdef _WIN32 -#ifdef _MSC_VER +#ifdef MSVC_COMPILER // on windows we need to set the invalid parameter handler, or else the program will terminate when a bad format is encountered _invalid_parameter_handler newHandler, oldHandler; newHandler = static_cast<_invalid_parameter_handler>(invalidParameterHandler); oldHandler = _set_invalid_parameter_handler(newHandler); -#endif // _MSC_VER +#endif // MSVC_COMPILER try { #endif // _WIN32 @@ -298,10 +298,10 @@ static void FormatDateTime(tchar * pszTemp, lpctstr pszFormat, const struct tm * pszTemp[0] = '\0'; } -#ifdef _MSC_VER +#ifdef MSVC_COMPILER // restore previous parameter handler _set_invalid_parameter_handler(oldHandler); -#endif // _MSC_VER +#endif // MSVC_COMPILER #endif // _WIN32 } diff --git a/src/common/sphere_library/sptr.h b/src/common/sphere_library/sptr.h index 66bc169bc..ee34faaa6 100644 --- a/src/common/sphere_library/sptr.h +++ b/src/common/sphere_library/sptr.h @@ -1,14 +1,21 @@ #ifndef _INC_SPTR_H #define _INC_SPTR_H -#ifndef _MSC_VER +// On Windows, Clang with MSVC runtime defines _MSC_VER! (But also __clang__). +#ifndef NON_MSVC_COMPILER +# if !defined(_MSC_VER) || !defined(__clang__) +# define NON_MSVC_COMPILER 1 +# endif +#endif + +#if NON_MSVC_COMPILER # pragma GCC diagnostic push # pragma GCC diagnostic ignored "-Wzero-as-null-pointer-constant" #endif #include -#ifndef _MSC_VER +#if NON_MSVC_COMPILER # pragma GCC diagnostic pop #endif diff --git a/src/common/sphere_library/sstring.cpp b/src/common/sphere_library/sstring.cpp index 6311a1930..1c9953f30 100644 --- a/src/common/sphere_library/sstring.cpp +++ b/src/common/sphere_library/sstring.cpp @@ -4,7 +4,7 @@ #include "../CExpression.h" -#if defined(_MSC_VER) +#ifdef MSVC_COMPILER #include #pragma warning( push ) #pragma warning ( disable : ALL_CODE_ANALYSIS_WARNINGS ) @@ -22,7 +22,7 @@ #include -#ifdef _MSC_VER +#ifdef MSVC_COMPILER #pragma warning( pop ) #else #pragma GCC diagnostic pop @@ -482,7 +482,7 @@ size_t strlen_mb(const char* ptr) size_t Str_LengthUTF8(const char* strInUTF8MB) noexcept { size_t len; // number of characters in the string -#ifdef _MSC_VER +#ifdef MSVC_RUNTIME mbstowcs_s(&len, nullptr, 0, strInUTF8MB, 0); // includes null terminator len -= 1; #else @@ -1261,7 +1261,7 @@ MATCH_TYPE Str_Match(lpctstr pPattern, lpctstr pText) noexcept return MATCH_VALID; } -#ifdef _MSC_VER +#ifdef MSVC_COMPILER // /GL + /LTCG flags inline in linking phase this function, but probably in a wrong way, so that // something gets corrupted on the memory and an exception is generated later #pragma auto_inline(off) @@ -1409,7 +1409,7 @@ bool Str_Parse(tchar * pLine, tchar ** ppArg, lpctstr pszSep) noexcept return true; } -#ifdef _MSC_VER +#ifdef MSVC_COMPILER #pragma auto_inline(on) #endif @@ -1761,7 +1761,7 @@ size_t UTF8MBSTR::ConvertStringToUTF8(lpctstr strIn, char*& strOutUTF8MB) noexce strOutUTF8MB = new char[len + 1](); #if defined(_WIN32) && defined(UNICODE) -#ifdef _MSC_VER +#ifdef MSVC_RUNTIME size_t aux = 0; wcstombs_s(&aux, strOutUTF8MB, len + 1, strIn, len); #else @@ -1783,7 +1783,7 @@ size_t UTF8MBSTR::ConvertUTF8ToString(const char* strInUTF8MB, lptstr& strOut) n #if defined(_WIN32) && defined(UNICODE) // tchar is wchar_t -#ifdef _MSC_VER +#ifdef MSVC_RUNTIME size_t aux = 0; mbstowcs_s(&aux, strInUTF8MB, len + 1, strInUTF8MB, len); #else diff --git a/src/game/CServerConfig.cpp b/src/game/CServerConfig.cpp index b5a56b9e5..b30cdb9f1 100644 --- a/src/game/CServerConfig.cpp +++ b/src/game/CServerConfig.cpp @@ -741,7 +741,7 @@ enum RC_TYPE // TODO: use offsetof by cstddef. Though, it requires the class/struct to be a POD type, so we need to encapsulate the values in a separate struct. // This hack does happen because this class hasn't virtual methods? Or simply because the compiler is so smart and protects us from ourselves? -#ifdef __GNUC__ +#if NON_MSVC_COMPILER #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wzero-as-null-pointer-constant" #endif @@ -1030,7 +1030,7 @@ const CAssocReg CServerConfig::sm_szLoadKeys[RC_QTY + 1] { nullptr, { ELEM_VOID, 0, }} }; -#ifdef __GNUC__ +#if defined(__GNUC__) || defined(__clang__) #pragma GCC diagnostic pop #endif @@ -3052,7 +3052,9 @@ bool CServerConfig::LoadResourceSection( CScript * pScript ) } rid = CResourceID( (dword)pVarNum->GetValNum(), 0 ); - restype = rid.GetResType(); + + // This value won't be read, since we return anyways once in this branch. + //restype = rid.GetResType(); CResourceDef * pRes = nullptr; size_t index = m_ResHash.FindKey( rid ); diff --git a/src/game/CServerDef.cpp b/src/game/CServerDef.cpp index a60500067..063600ca4 100644 --- a/src/game/CServerDef.cpp +++ b/src/game/CServerDef.cpp @@ -32,9 +32,9 @@ // PSAPI external definitions typedef intptr_t (WINAPI *pfnGetProcessMemoryInfo)(HANDLE, PPROCESS_MEMORY_COUNTERS, DWORD); - HMODULE m_hmPsapiDll = nullptr; - pfnGetProcessMemoryInfo m_GetProcessMemoryInfo = nullptr; - PROCESS_MEMORY_COUNTERS pcnt; + static HMODULE m_hmPsapiDll = nullptr; + static pfnGetProcessMemoryInfo m_GetProcessMemoryInfo = nullptr; + static PROCESS_MEMORY_COUNTERS pcnt; #else // (Unix) #include #endif @@ -77,17 +77,17 @@ size_t CServerDef::StatGet(SERV_STAT_TYPE i) const m_hmPsapiDll = LoadLibrary(TEXT("psapi.dll")); if (m_hmPsapiDll == nullptr) { - m_fPmemory = false; + sm_fHasMemoryInfo = false; g_Log.EventError(("Unable to load process information PSAPI.DLL library. Memory information will be not available.\n")); } else { -#ifndef _MSC_VER +#ifdef NON_MSVC_COMPILER #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wcast-function-type" #endif m_GetProcessMemoryInfo = reinterpret_cast(::GetProcAddress(m_hmPsapiDll,"GetProcessMemoryInfo")); -#ifndef _MSC_VER +#if NON_MSVC_COMPILER #pragma GCC diagnostic pop #endif } diff --git a/src/game/CWorldSearch.h b/src/game/CWorldSearch.h index 7a598c83b..c8da39010 100644 --- a/src/game/CWorldSearch.h +++ b/src/game/CWorldSearch.h @@ -5,7 +5,7 @@ #include "../common/CRect.h" /* -#ifdef _MSC_VER +#ifdef MSVC_COMPILER # pragma warning(push) # pragma warning(disable : 4244) # pragma warning(disable : 4267) @@ -14,7 +14,7 @@ #include -#ifdef _MSC_VER +#ifdef MSVC_COMPILER # pragma warning(pop) #endif */ diff --git a/src/game/CWorldTicker.h b/src/game/CWorldTicker.h index 31d84a808..22729e3b2 100644 --- a/src/game/CWorldTicker.h +++ b/src/game/CWorldTicker.h @@ -39,14 +39,14 @@ /* End of phmap.h inclusion */ /* Include btree.h */ -#ifdef __GNUC__ +#if NON_MSVC_COMPILER #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wzero-as-null-pointer-constant" #endif #include -#ifdef __GNUC__ +#if NON_MSVC_COMPILER #pragma GCC diagnostic pop #endif /* End of btree.h inclusion */ diff --git a/src/game/spheresvr.cpp b/src/game/spheresvr.cpp index 176ce878d..5b989a4de 100644 --- a/src/game/spheresvr.cpp +++ b/src/game/spheresvr.cpp @@ -72,7 +72,7 @@ GlobalInitializer::GlobalInitializer() //--- Exception handling // Set exception catcher? -#if defined(_WIN32) && defined(_MSC_VER) && !defined(_NIGHTLYBUILD) +#if defined(MSVC_COMPILER) && !defined(_NIGHTLYBUILD) // We don't need an exception translator for the Debug build, since that build would, generally, be used with a debugger. // We don't want that for Release build either because, in order to call _set_se_translator, we should set the /EHa // compiler flag, which slows down code a bit. diff --git a/src/game/uo_files/CUOHuesRec.h b/src/game/uo_files/CUOHuesRec.h index 711fa565c..904cf4558 100644 --- a/src/game/uo_files/CUOHuesRec.h +++ b/src/game/uo_files/CUOHuesRec.h @@ -9,7 +9,7 @@ #include "../../common/common.h" // All these structures must be byte packed. -#if defined(_WIN32) && defined(_MSC_VER) +#ifdef MSVC_COMPILER // Microsoft dependant pragma #pragma pack(1) #define PACK_NEEDED @@ -31,7 +31,7 @@ struct CUOHuesRec // Turn off structure packing. -#if defined(_WIN32) && defined(_MSC_VER) +#ifdef MSVC_COMPILER #pragma pack() #else #undef PACK_NEEDED diff --git a/src/game/uo_files/CUOIndexRec.h b/src/game/uo_files/CUOIndexRec.h index 2ce39725b..8cd663ae9 100644 --- a/src/game/uo_files/CUOIndexRec.h +++ b/src/game/uo_files/CUOIndexRec.h @@ -10,7 +10,7 @@ // All these structures must be byte packed. -#if defined(_WIN32) && defined(_MSC_VER) +#ifdef MSVC_COMPILER // Microsoft dependant pragma #pragma pack(1) #define PACK_NEEDED @@ -53,7 +53,7 @@ struct CUOIndexRec // Turn off structure packing. -#if defined(_WIN32) && defined(_MSC_VER) +#ifdef MSVC_COMPILER #pragma pack() #else #undef PACK_NEEDED diff --git a/src/game/uo_files/CUOItemTypeRec.h b/src/game/uo_files/CUOItemTypeRec.h index 21d4febae..f8c843560 100644 --- a/src/game/uo_files/CUOItemTypeRec.h +++ b/src/game/uo_files/CUOItemTypeRec.h @@ -9,7 +9,7 @@ #include "../../common/common.h" // All these structures must be byte packed. -#if defined(_WIN32) && defined(_MSC_VER) +#ifdef MSVC_COMPILER // Microsoft dependant pragma #pragma pack(1) #define PACK_NEEDED @@ -56,7 +56,7 @@ struct CUOItemTypeRec_HS // Turn off structure packing. -#if defined(_WIN32) && defined(_MSC_VER) +#ifdef MSVC_COMPILER #pragma pack() #else #undef PACK_NEEDED diff --git a/src/game/uo_files/CUOMapBlock.h b/src/game/uo_files/CUOMapBlock.h index 9bc9e9075..6774473b1 100644 --- a/src/game/uo_files/CUOMapBlock.h +++ b/src/game/uo_files/CUOMapBlock.h @@ -10,7 +10,7 @@ #include "uofiles_macros.h" // All these structures must be byte packed. -#if defined(_WIN32) && defined(_MSC_VER) +#ifdef MSVC_COMPILER // Microsoft dependant pragma #pragma pack(1) #define PACK_NEEDED @@ -32,7 +32,7 @@ struct CUOMapBlock // Turn off structure packing. -#if defined(_WIN32) && defined(_MSC_VER) +#ifdef MSVC_COMPILER #pragma pack() #else #undef PACK_NEEDED diff --git a/src/game/uo_files/CUOMapMeter.h b/src/game/uo_files/CUOMapMeter.h index 94350d817..46d664ec5 100644 --- a/src/game/uo_files/CUOMapMeter.h +++ b/src/game/uo_files/CUOMapMeter.h @@ -9,7 +9,7 @@ #include "../../common/common.h" // All these structures must be byte packed. -#if defined(_WIN32) && defined(_MSC_VER) +#ifdef MSVC_COMPILER // Microsoft dependant pragma #pragma pack(1) #define PACK_NEEDED @@ -32,7 +32,7 @@ struct CUOMapMeter // Turn off structure packing. -#if defined(_WIN32) && defined(_MSC_VER) +#ifdef MSVC_COMPILER #pragma pack() #else #undef PACK_NEEDED diff --git a/src/game/uo_files/CUOMultiItemRec.h b/src/game/uo_files/CUOMultiItemRec.h index 421da7c98..da45d75be 100644 --- a/src/game/uo_files/CUOMultiItemRec.h +++ b/src/game/uo_files/CUOMultiItemRec.h @@ -10,7 +10,7 @@ #include "uofiles_enums_itemid.h" // All these structures must be byte packed. -#if defined(_WIN32) && defined(_MSC_VER) +#ifdef MSVC_COMPILER // Microsoft dependant pragma #pragma pack(1) #define PACK_NEEDED @@ -50,7 +50,7 @@ struct CUOMultiItemRec_HS // (Multi.mul, High Seas+) // Turn off structure packing. -#if defined(_WIN32) && defined(_MSC_VER) +#ifdef MSVC_COMPILER #pragma pack() #else #undef PACK_NEEDED diff --git a/src/game/uo_files/CUOStaticItemRec.h b/src/game/uo_files/CUOStaticItemRec.h index 69776f73f..86925e1ee 100644 --- a/src/game/uo_files/CUOStaticItemRec.h +++ b/src/game/uo_files/CUOStaticItemRec.h @@ -10,7 +10,7 @@ #include "uofiles_enums_itemid.h" // All these structures must be byte packed. -#if defined(_WIN32) && defined(_MSC_VER) +#ifdef MSVC_COMPILER // Microsoft dependant pragma #pragma pack(1) #define PACK_NEEDED @@ -39,7 +39,7 @@ struct CUOStaticItemRec // Turn off structure packing. -#if defined(_WIN32) && defined(_MSC_VER) +#ifdef MSVC_COMPILER #pragma pack() #else #undef PACK_NEEDED diff --git a/src/game/uo_files/CUOTerrainTypeRec.h b/src/game/uo_files/CUOTerrainTypeRec.h index 8e3413bad..e97b19354 100644 --- a/src/game/uo_files/CUOTerrainTypeRec.h +++ b/src/game/uo_files/CUOTerrainTypeRec.h @@ -9,7 +9,7 @@ #include "../../common/common.h" // All these structures must be byte packed. -#if defined(_WIN32) && defined(_MSC_VER) +#ifdef MSVC_COMPILER // Microsoft dependant pragma #pragma pack(1) #define PACK_NEEDED @@ -51,7 +51,7 @@ struct CUOTerrainTypeRec_HS // Turn off structure packing. -#if defined(_WIN32) && defined(_MSC_VER) +#ifdef MSVC_COMPILER #pragma pack() #else #undef PACK_NEEDED diff --git a/src/game/uo_files/CUOVersionBlock.h b/src/game/uo_files/CUOVersionBlock.h index 09b2ac2e6..e50e75e4e 100644 --- a/src/game/uo_files/CUOVersionBlock.h +++ b/src/game/uo_files/CUOVersionBlock.h @@ -13,7 +13,7 @@ // All these structures must be byte packed. -#if defined(_WIN32) && defined(_MSC_VER) +#ifdef MSVC_COMPILER // Microsoft dependant pragma #pragma pack(1) #define PACK_NEEDED @@ -59,7 +59,7 @@ struct CUOVersionBlock // Turn off structure packing. -#if defined(_WIN32) && defined(_MSC_VER) +#ifdef MSVC_COMPILER #pragma pack() #else #undef PACK_NEEDED diff --git a/src/network/CNetworkOutput.cpp b/src/network/CNetworkOutput.cpp index 3abf84731..17c8fb1c5 100644 --- a/src/network/CNetworkOutput.cpp +++ b/src/network/CNetworkOutput.cpp @@ -16,7 +16,7 @@ * void SendCompleted_Winsock Winsock event handler for when async operation completes * ***************************************************************************/ -void CALLBACK SendCompleted_Winsock(DWORD dwError, DWORD cbTransferred, LPWSAOVERLAPPED lpOverlapped, DWORD dwFlags) +static void CALLBACK SendCompleted_Winsock(DWORD dwError, DWORD cbTransferred, LPWSAOVERLAPPED lpOverlapped, DWORD dwFlags) { UnreferencedParameter(dwFlags); ADDTOCALLSTACK("SendCompleted_Winsock"); diff --git a/src/network/net_datatypes.h b/src/network/net_datatypes.h index e6633453c..04a5cd44b 100644 --- a/src/network/net_datatypes.h +++ b/src/network/net_datatypes.h @@ -18,7 +18,7 @@ // All these structures must be byte packed. -#if defined(_WIN32) && defined(_MSC_VER) +#if defined(MSVC_COMPILER) // Microsoft dependant pragma #pragma pack(1) #define PACK_NEEDED @@ -81,7 +81,7 @@ struct ndword // Turn off structure packing. -#if defined(_WIN32) && defined(_MSC_VER) +#if defined(_WIN32) && defined(MSVC_COMPILER) #pragma pack() #endif diff --git a/src/network/packet.cpp b/src/network/packet.cpp index 10adbb25a..f524c263f 100644 --- a/src/network/packet.cpp +++ b/src/network/packet.cpp @@ -815,12 +815,12 @@ void Packet::readStringASCII(wchar* buffer, uint length, bool includeNull) char* bufferReal = new char[(size_t)length + 1](); readStringASCII(bufferReal, length, includeNull); -#ifdef _MSC_VER +# ifdef MSVC_RUNTIME size_t aux; mbstowcs_s(&aux, buffer, length + 1, bufferReal, length); -#else +# else mbstowcs(buffer, bufferReal, length); -#endif +# endif delete[] bufferReal; #else diff --git a/src/resources/SphereSvr.rc b/src/resources/SphereSvr.rc index 7d99d47b0..4d087d7d9 100644 --- a/src/resources/SphereSvr.rc +++ b/src/resources/SphereSvr.rc @@ -13,14 +13,14 @@ # define WIN32_LEAN_AND_MEAN // include just windows.h without the other winapi headers, we'll add them manually when needed # endif -# ifdef _MSC_VER +# if defined(_MSC_VER) && !defined(__clang__) // Workaround to a possible VS compiler bug: instead of complaining if a macro expands to a "defined" macro, // it complains if a define macro contains the words "defined" in its name... # pragma warning(push) # pragma warning(disable: 5105) # endif # include -# ifdef _MSC_VER +# if defined(_MSC_VER) && !defined(__clang__) # pragma warning(pop) # endif @@ -89,12 +89,12 @@ IDR_MAINFRAME ICON "spheresvr.ico" // #ifdef APSTUDIO_INVOKED -1 TEXTINCLUDE +1 TEXTINCLUDE BEGIN "win_resource.h\0" END -2 TEXTINCLUDE +2 TEXTINCLUDE BEGIN "\r\n" "\0" diff --git a/src/resources/resource.h b/src/resources/resource.h deleted file mode 100644 index b406120f2..000000000 --- a/src/resources/resource.h +++ /dev/null @@ -1,43 +0,0 @@ -//{{NO_DEPENDENCIES}} -// File di inclusione generato con Microsoft Visual C++. -// Utilizzato da SphereSvr.rc -// -#define IDC_STATIC 0 -#define IDR_MAINFRAME 100 -#define IDR_ABOUT_BOX 101 -#define IDM_POP_TRAY 102 -#define IDM_POP_LOG 103 -#define IDC_STAT_STATS 201 -#define IDC_STAT_CLIENTS 202 -#define IDC_O_LOG_LEVEL 250 -#define IDC_O_LOG_CLIENTS 251 -#define IDC_O_LOG_GM_CMDS 252 -#define IDC_O_LOG_GM_PAGES 253 -#define IDC_O_LOG_SPEAK 254 -#define IDM_STATUS 528 -#define IDM_RESTORE 544 -#define IDM_MINIMIZE 560 -#define IDM_EDIT_COPY 580 -#define IDM_EXIT 582 -#define IDC_ABOUT_VERSION 1117 -#define IDC_ABOUT_COMPILER 1118 -#define IDC_ABOUT_MENASOFT_LINK 1119 -#define IDC_ABOUT_SPHERE_LINK 1120 -#define IDC_SETUP_PORT 4020 -#define IDC_SETUP_SCRIPTS 4021 -#define IDC_SETUP_SAVE 4022 -#define IDC_SETUP_LOG 4023 -#define IDC_SETUP_NAME 4024 -#define IDM_RESYNC_PAUSE 32784 - -// Next default values for new objects -// -#ifdef APSTUDIO_INVOKED -#ifndef APSTUDIO_READONLY_SYMBOLS -#define _APS_3D_CONTROLS 1 -#define _APS_NEXT_RESOURCE_VALUE 161 -#define _APS_NEXT_COMMAND_VALUE 32785 -#define _APS_NEXT_CONTROL_VALUE 4026 -#define _APS_NEXT_SYMED_VALUE 210 -#endif -#endif diff --git a/src/sphere/ntservice.cpp b/src/sphere/ntservice.cpp index 88857c81c..a346d593b 100644 --- a/src/sphere/ntservice.cpp +++ b/src/sphere/ntservice.cpp @@ -450,7 +450,7 @@ void CNTService::CmdMainStart() // FUNCTION: main() // ///////////////////////////////////////////////////////////////////////////////////// -#ifdef _MSC_VER +#ifdef MSVC_COMPILER int WINAPI WinMain(_In_ HINSTANCE hInstance, _In_opt_ HINSTANCE hPrevInstance, _In_ LPSTR lpCmdLine, _In_ int nCmdShow) #else int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow) diff --git a/src/sphere/ntservice.h b/src/sphere/ntservice.h index a064e41ab..124ffa518 100644 --- a/src/sphere/ntservice.h +++ b/src/sphere/ntservice.h @@ -8,14 +8,14 @@ #ifdef _WIN32 +#include "../common/common.h" -#ifndef _MSC_VER +#ifdef NON_MSVC_COMPILER #include #else #include // exception handling info. -#endif // _MSC_VER +#endif // NON_MSVC_COMPILER -#include "../common/common.h" extern class CNTService diff --git a/src/sphere/ntwindow.h b/src/sphere/ntwindow.h index 42d7730e0..2c4b75d18 100644 --- a/src/sphere/ntwindow.h +++ b/src/sphere/ntwindow.h @@ -23,10 +23,10 @@ extern struct CNTWindow : public AbstractSphereThread, public CSWindow, public C int nCmdShow; } _NTWInitParams; - virtual void onStart(); - virtual void terminate(bool ended); + virtual void onStart() override; + virtual void terminate(bool ended) override; virtual bool shouldExit() noexcept override; - virtual void tick(); + virtual void tick() override; bool NTWindow_Init(HINSTANCE hInstance, LPTSTR lpCmdLinel, int nCmdShow); void NTWindow_ExitServer(); @@ -41,7 +41,7 @@ extern struct CNTWindow : public AbstractSphereThread, public CSWindow, public C std::shared_mutex _mutexWindowTitle; void exitActions(); - + public: class CAboutDlg : public CDialogBase // CNTWindow::CAboutDlg { From ded506cde3f913ebd6d80567cbf4b1de299016f1 Mon Sep 17 00:00:00 2001 From: cbnolok Date: Thu, 3 Oct 2024 13:31:47 +0200 Subject: [PATCH 66/86] Updated .clang-format and .gitignore. --- .clang-format | 115 ++++++++++++++++++++++++-------------------------- .gitignore | 1 + 2 files changed, 56 insertions(+), 60 deletions(-) diff --git a/.clang-format b/.clang-format index 7e32248d7..1cc6ca616 100644 --- a/.clang-format +++ b/.clang-format @@ -1,30 +1,35 @@ +# Based on LLVM style with C++20 support BasedOnStyle: LLVM Language: Cpp Standard: c++20 + +# Tab and indent settings TabWidth: 4 IndentWidth: 4 UseTab: Never ColumnLimit: 160 +# Text line management #LineEndingStyle: LF -#MaxEmptyLinesToKeep: 3 +MaxEmptyLinesToKeep: 2 +InsertNewlineAtEOF: true -##-- Alignment -AlignAfterOpenBracket: AlwaysBreak +# Alignment settings +AlignAfterOpenBracket: DontAlign AlignConsecutiveAssignments: true AlignConsecutiveDeclarations: false #AlignConsecutiveTableGenDefinitionColons: # Enabled: true # AcrossEmptyLines: true # AcrossComments: false -AlignEscapedNewlines: Left # LeftWithLastLine # Right +AlignEscapedNewlines: Left AlignTrailingComments: Kind: Always OverEmptyLines: 1 DerivePointerAlignment: false PointerAlignment: Right -##-- Single line statements +# Single-line statements settings AllowShortBlocksOnASingleLine: false AllowShortCaseLabelsOnASingleLine: false AllowShortFunctionsOnASingleLine: None @@ -32,8 +37,8 @@ AllowShortIfStatementsOnASingleLine: Never AllowShortLambdasOnASingleLine: Inline AllowShortLoopsOnASingleLine: false -##-- Braces -BreakBeforeBraces: Custom #Allman +# Braces and wrapping settings +BreakBeforeBraces: Custom BraceWrapping: AfterCaseLabel: true AfterClass: false @@ -52,88 +57,78 @@ BraceWrapping: SplitEmptyNamespace: false Cpp11BracedListStyle: false -##-- Line breaks +# Line breaks and wrapping settings +#AllowAllParametersOfDeclarationOnNextLine: true #AllowBreakBeforeNoexceptSpecifier: OnlyWithParen -AlwaysBreakAfterDefinitionReturnType: All -AlwaysBreakAfterReturnType: None +AlwaysBreakAfterDefinitionReturnType: None # Keep return type on the same line if possible +AlwaysBreakAfterReturnType: None # Default value AlwaysBreakBeforeMultilineStrings: true -BreakAfterAttributes: Always AlwaysBreakTemplateDeclarations: true -BreakAfterJavaFieldAnnotations: false -BreakBeforeBinaryOperators: None +BreakAfterAttributes: Always +BreakBeforeBinaryOperators: None # Default value: No line break before binary operators BreakBeforeConceptDeclarations: Always BreakConstructorInitializers: AfterColon -#BreakInheritanceList: AfterColon -BreakBeforeTernaryOperators: false +BreakBeforeTernaryOperators: false # Default value BreakConstructorInitializersBeforeComma: true -BreakStringLiterals: false +#BreakInheritanceList: AfterColon +BreakStringLiterals: false # Default value +PackConstructorInitializers: NextLineOnly +PenaltyReturnTypeOnItsOwnLine: 200 # Prefer keeping return type on the same line if possible -##-- Indentation +# Indentation settings +#AccessModifierOffset: -4 +IndentAccessModifiers: false IndentCaseBlocks: false IndentCaseLabels: true IndentExternBlock: AfterExternBlock IndentGotoLabels: true IndentPPDirectives: AfterHash +IndentWrappedFunctionNames: false LambdaBodyIndentation: Signature NamespaceIndentation: Inner -##-- Spaces in/between statements/etc -MaxEmptyLinesToKeep: 2 -SeparateDefinitionBlocks: Always -SpaceAfterCStyleCast: false -SpaceAfterTemplateKeyword: false +# Spaces around statements settings +SpaceAfterCStyleCast: false # Default value +SpaceAfterTemplateKeyword: false # Default value #SpaceAroundPointerQualifiers: Left SpaceBeforeAssignmentOperators: true SpaceBeforeCpp11BracedList: true SpaceBeforeCtorInitializerColon: true SpaceBeforeInheritanceColon: true SpaceBeforeParens: ControlStatements -SpaceInEmptyParentheses: false -SpacesInAngles: false -SpacesInCStyleCastParentheses: false -SpacesInContainerLiterals: false -SpacesInParentheses: false -SpacesInSquareBrackets: false +SpaceInEmptyParentheses: false # Default value +SpacesInAngles: false # Default value +SpacesInCStyleCastParentheses: false # Default value +SpacesInContainerLiterals: false # Default value +SpacesInParentheses: false # Default value +SpacesInSquareBrackets: false # Default value - -##-- Code sections/blocks +# Macros settings #MacroBlockBegin: [regex -> EXC_TRY...] #MacroBlockEnd: +#StatementMacros: [-> ASSERT?] + +# Scopes settings FixNamespaceComments: true ShortNamespaceLines: 2 -#StatementMacros: [-> ASSERT?] -##-- Misc -AllowAllParametersOfDeclarationOnNextLine: true -AccessModifierOffset: -4 -BinPackArguments: false -BinPackParameters: false -ConstructorInitializerAllOnOneLineOrOnePerLine: false -DisableFormat: false -ExperimentalAutoDetectBinPacking: false -InsertNewlineAtEOF: true -KeepEmptyLinesAtTheStartOfBlocks: false +# Miscellaneous settings +SeparateDefinitionBlocks: Always ReflowComments: false -#-- Include order -#IncludeIsMainRegex: '$?' +# Include order #IncludeBlocks: Regroup +#IncludeIsMainRegex: '$?' IncludeCategories: #TODO: main include! - # Headers in "" with .h extension. - - Regex: '"([A-Za-z0-9\/-_])+\.h"' - Priority: 1 - # Headers in "" with .hpp extension. - - Regex: '"([A-Za-z0-9\/-_])+\.hpp"' - Priority: 2 - - # Headers in <> with .h extension. - - Regex: '<([A-Za-z0-9\/-_])+\.h>' - Priority: 10 - # Headers in <> with .hpp extension. - - Regex: '<([A-Za-z0-9\/-_])+\.hpp>' - Priority: 20 - # Headers in <> without extension. - - Regex: '<([A-Za-z0-9\/-_])+>' - Priority: 30 -SortIncludes: false #CaseSensitive + - Regex: '"([A-Za-z0-9\/-_])+\.h"' + Priority: 1 + - Regex: '"([A-Za-z0-9\/-_])+\.hpp"' + Priority: 2 + - Regex: '<([A-Za-z0-9\/-_])+\.h>' + Priority: 10 + - Regex: '<([A-Za-z0-9\/-_])+\.hpp>' + Priority: 20 + - Regex: '<([A-Za-z0-9\/-_])+>' + Priority: 30 +SortIncludes: false diff --git a/.gitignore b/.gitignore index 8fde82f30..a21d5394c 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,5 @@ # Ignore folders +/.cache /.git /.vscode *.vshistory* From a043502947a0330f9f76cfd41fd7f136ba566771 Mon Sep 17 00:00:00 2001 From: cbnolok Date: Thu, 3 Oct 2024 14:34:29 +0200 Subject: [PATCH 67/86] Fixed compilation errors. Made more (easily) cross-platform the AbstractThread code (looking also at BSD). --- CMakeLists.txt | 5 ++++- cmake/CompilerFlagsChecker.cmake | 18 +++++++++++++++++- lib/bcrypt/bcrypt/wrapper.c | 2 +- src/common/CException.cpp | 2 ++ src/common/CException.h | 4 ++-- src/common/sphere_library/sptr.h | 2 +- src/common/sphere_library/stypecast.h | 9 +++++---- src/sphere/threads.cpp | 27 ++++++++++++--------------- src/sphere/threads.h | 11 +++++++---- 9 files changed, 51 insertions(+), 29 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 9554694a9..491c597a2 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -99,7 +99,6 @@ set(CMAKE_CXX_FLAGS_RELEASE "") set(CMAKE_EXE_LINKER_FLAGS "") set(CMAKE_EXE_LINKER_FLAGS_DEBUG "") -set(CMAKE_EXE_LINKER_FLAGS_NIGHTLY "") set(CMAKE_EXE_LINKER_FLAGS_RELEASE "") ]] # Example: using MSVC, /RTC1 is globally added (all projects) to DEBUG builds. It's mostly fine, except in some cases where we don't want it... @@ -107,6 +106,10 @@ set(CMAKE_EXE_LINKER_FLAGS_RELEASE "") #STRING (REGEX REPLACE "/RTC(su|[1su])" "" CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG}") #STRING (REGEX REPLACE "/RTC(su|[1su])" "" CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG}") +# Also, it fails to create those predefined flags, which it needs, for custom build types (e.g. Nightly). +set(CMAKE_EXE_LINKER_FLAGS_NIGHTLY "") + + set(is_win32_app_linker) if(WIN32 AND NOT ${WIN32_SPAWN_CONSOLE}) set(is_win32_app_linker WIN32) # if not set, it defaults to console subsystem diff --git a/cmake/CompilerFlagsChecker.cmake b/cmake/CompilerFlagsChecker.cmake index 2cd570296..7bfb40fe0 100644 --- a/cmake/CompilerFlagsChecker.cmake +++ b/cmake/CompilerFlagsChecker.cmake @@ -16,6 +16,15 @@ if(NOT MSVC) ) list(APPEND base_compiler_options_warning -Werror;-Wall;-Wextra;-Wpedantic) + # Linker flags (warnings) + #check_cxx_compiler_flag("-Wl,--fatal-warnings" COMP_LINKER_HAS_FATAL_WARNINGS_V1) + #check_cxx_compiler_flag("-Wl,-fatal-warnings" COMP_LINKER_HAS_FATAL_WARNINGS_V2) + if(CMAKE_CXX_COMPILER_ID STREQUAL "AppleClang") + set(COMP_LINKER_HAS_FATAL_WARNINGS_V2 TRUE) + else() + set(COMP_LINKER_HAS_FATAL_WARNINGS_V1 TRUE) + endif() + # Compiler option flags. Common to both compilers, but older versions might not support the following. #check_cxx_compiler_flag("" COMP_HAS_) @@ -197,6 +206,13 @@ endif() # ---- GCC/Clang if(NOT MSVC) + if(COMP_LINKER_HAS_FATAL_WARNINGS_V1) + list(APPEND checked_linker_options_all "-Wl,--fatal-warnings") + endif() + if(COMP_LINKER_HAS_FATAL_WARNINGS_V2) + list(APPEND checked_linker_options_all "-Wl,-fatal_warnings") + endif() + if(COMP_HAS_FNO_EXPENSIVE_OPTIMIZATIONS) list(APPEND checked_compiler_options "-fno-expensive-optimizations") endif() @@ -452,7 +468,7 @@ if(NOT MSVC) ${checked_compiler_warnings_disabled} ) - list(APPEND list_explicit_linker_options_all ${checked_linker_options_all};-pthread;-dynamic;-Wl,--fatal-warnings) + list(APPEND list_explicit_linker_options_all ${checked_linker_options_all};-pthread;-dynamic) #string(JOIN " " string_checked_compiler_options_all ${list_checked_compiler_options_all}) #set(string_checked_compiler_options_all CACHE INTERNAL STRING) diff --git a/lib/bcrypt/bcrypt/wrapper.c b/lib/bcrypt/bcrypt/wrapper.c index 6a3503f5b..fe20e7577 100644 --- a/lib/bcrypt/bcrypt/wrapper.c +++ b/lib/bcrypt/bcrypt/wrapper.c @@ -50,7 +50,7 @@ extern struct crypt_data _ufc_foobar; char* mystrdup(const char* s) { const size_t len = strlen(s); - char* p = malloc(len) + 1; + char* p = (char*)(malloc(len + 1)); if (p) { //strcpy(p, s); diff --git a/src/common/CException.cpp b/src/common/CException.cpp index 683ae0239..5dcd8beac 100644 --- a/src/common/CException.cpp +++ b/src/common/CException.cpp @@ -77,12 +77,14 @@ static bool IsAbortImmediate() noexcept } #endif +[[noreturn]] void RaiseRecoverableAbort() { EXC_NOTIFY_DEBUGGER; SetAbortImmediate(false); std::abort(); } +[[noreturn]] void RaiseImmediateAbort() { EXC_NOTIFY_DEBUGGER; diff --git a/src/common/CException.h b/src/common/CException.h index a767cc666..99543be87 100644 --- a/src/common/CException.h +++ b/src/common/CException.h @@ -28,9 +28,9 @@ void SetExceptionTranslator(); void NotifyDebugger(); void SetAbortImmediate(bool on) noexcept; -bool AbortImmediate() noexcept; - +[[noreturn]] void RaiseRecoverableAbort(); +[[noreturn]] void RaiseImmediateAbort(); diff --git a/src/common/sphere_library/sptr.h b/src/common/sphere_library/sptr.h index ee34faaa6..ce9b396cc 100644 --- a/src/common/sphere_library/sptr.h +++ b/src/common/sphere_library/sptr.h @@ -3,7 +3,7 @@ // On Windows, Clang with MSVC runtime defines _MSC_VER! (But also __clang__). #ifndef NON_MSVC_COMPILER -# if !defined(_MSC_VER) || !defined(__clang__) +# if !defined(_MSC_VER) || defined(__clang__) # define NON_MSVC_COMPILER 1 # endif #endif diff --git a/src/common/sphere_library/stypecast.h b/src/common/sphere_library/stypecast.h index d367c41f1..1331a4a1e 100644 --- a/src/common/sphere_library/stypecast.h +++ b/src/common/sphere_library/stypecast.h @@ -499,7 +499,7 @@ constexpr uint32 usize_narrow_u32(const size_t source_val) noexcept #if SIZE_MAX == UINT64_MAX return n64_narrow_n32(source_val); #elif SIZE_MAX == UINT32_MAX - return a; + return source_val; #else # error "size_t is neither 8 nor 4 bytes?" #endif @@ -677,7 +677,7 @@ template int64 i64_from_u64_checked(T, bool) = delete; // disable i #if SIZE_MAX == UINT64_MAX return n64_narrow_n8_checked(source_val, should_assert); #elif SIZE_MAX == UINT32_MAX - return n32_narrow_n8_checked(source_val); + return n32_narrow_n8_checked(source_val, should_assert); #else # error "size_t is neither 8 nor 4 bytes?" #endif @@ -691,7 +691,7 @@ template int8 i8_from_usize_checked(T, bool) = delete; // disable i #if SIZE_MAX == UINT64_MAX return n64_narrow_n16_checked(source_val, should_assert); #elif SIZE_MAX == UINT32_MAX - return n32_narrow_n16_checked(source_val); + return n32_narrow_n16_checked(source_val, should_assert); #else # error "size_t is neither 8 nor 4 bytes?" #endif @@ -704,7 +704,7 @@ template int16 i16_from_usize_checked(T, bool) = delete; // disable #if SIZE_MAX == UINT64_MAX return i32_from_u32_clamping(n64_narrow_n32_checked(source_val, should_assert)); #elif SIZE_MAX == UINT32_MAX - return i32_from_u32_checked(n_alias_cast(source_val)); + return i32_from_u32_checked(n_alias_cast(source_val), should_assert); #else # error "size_t is neither 8 nor 4 bytes?" #endif @@ -717,6 +717,7 @@ template int32 i32_from_usize_checked(T, bool) = delete; // disable #if SIZE_MAX == UINT64_MAX return i64_from_u64_checked(n_alias_cast(source_val), should_assert); #elif SIZE_MAX == UINT32_MAX + (void)should_assert; return static_cast(source_val); // For sure it will fit #else # error "size_t is neither 8 nor 4 bytes?" diff --git a/src/sphere/threads.cpp b/src/sphere/threads.cpp index 77dba0d3b..204ed2e28 100644 --- a/src/sphere/threads.cpp +++ b/src/sphere/threads.cpp @@ -61,8 +61,7 @@ IThread::IThread() noexcept : // This is needed to prevent weak-vtables warning (puts the vtable in this translation unit instead of every translation unit) IThread::~IThread() noexcept = default; -#ifdef _WIN32 -/* +#if defined(_WIN32) && defined(MSVC_COMPILER) #pragma pack(push, 8) typedef struct tagTHREADNAME_INFO { @@ -72,12 +71,9 @@ typedef struct tagTHREADNAME_INFO DWORD dwFlags; } THREADNAME_INFO; #pragma pack(pop) -*/ -#ifdef MSVC_COMPILER static constexpr DWORD MS_VC_EXCEPTION = 0x406D1388; #endif -#endif void IThread::setThreadName(const char* name) { @@ -104,7 +100,7 @@ void IThread::setThreadName(const char* name) __except(EXCEPTION_EXECUTE_HANDLER) { } - #endif + #endif // MSVC_COMPILER #elif defined(__APPLE__) // Mac pthread_setname_np(name_trimmed); #elif !defined(_BSD) // Linux @@ -438,7 +434,6 @@ AbstractThread::AbstractThread(const char *name, IThread::Priority priority) : } m_threadSystemId = 0; Str_CopyLimitNull(m_name, name, sizeof(m_name)); - m_handle = SPHERE_THREADT_NULL; m_hangCheck = 0; _thread_selfTerminateAfterThisTick = true; m_terminateRequested = true; @@ -480,14 +475,16 @@ void AbstractThread::start() pthread_attr_t threadAttr; pthread_attr_init(&threadAttr); pthread_attr_setdetachstate(&threadAttr, PTHREAD_CREATE_DETACHED); - int result = pthread_create( &m_handle, &threadAttr, &runner, this ); + spherethread_t threadHandle{}; + int result = pthread_create( &threadHandle, &threadAttr, &runner, this ); pthread_attr_destroy(&threadAttr); if (result != 0) { - m_handle = 0; + m_handle = std::nullopt; throw CSError(LOGL_FATAL, 0, "Unable to spawn a new thread"); } + m_handle = threadHandle; #endif m_terminateEvent.reset(); @@ -506,10 +503,10 @@ void AbstractThread::terminate(bool ended) if (wasCurrentThread == false) { #ifdef _WIN32 - TerminateThread(m_handle, 0); - CloseHandle(m_handle); + TerminateThread(m_handle.value(), 0); + CloseHandle(m_handle.value()); #else - pthread_cancel(m_handle); // IBM say it so + pthread_cancel(m_handle.value()); // IBM say it so #endif } } @@ -517,7 +514,7 @@ void AbstractThread::terminate(bool ended) // Common things ThreadHolder::get().remove(this); m_threadSystemId = 0; - m_handle = SPHERE_THREADT_NULL; + m_handle = std::nullopt; // let everyone know we have been terminated m_terminateEvent.set(); @@ -650,7 +647,7 @@ SPHERE_THREADENTRY_RETNTYPE AbstractThread::runner(void *callerThread) bool AbstractThread::isActive() const { - return (m_handle != SPHERE_THREADT_NULL); + return m_handle.has_value(); } void AbstractThread::waitForClose() @@ -686,7 +683,7 @@ bool AbstractThread::isCurrentThread() const noexcept #ifdef _WIN32 return (getId() == ::GetCurrentThreadId()); #else - return pthread_equal(m_handle,pthread_self()); + return m_handle.has_value() && pthread_equal(m_handle.value(), pthread_self()); #endif } diff --git a/src/sphere/threads.h b/src/sphere/threads.h index 3534efbd6..1a2fb0598 100644 --- a/src/sphere/threads.h +++ b/src/sphere/threads.h @@ -34,15 +34,14 @@ #define SPHERE_THREADT_NULL nullptr #else typedef pthread_t spherethread_t; -#ifdef __APPLE__ +# ifdef __APPLE__ typedef uint64_t threadid_t; -#else +# else typedef pthread_t threadid_t; #endif #define SPHERE_THREADENTRY_RETNTYPE void * #define SPHERE_THREADENTRY_CALLTYPE - #define SPHERE_THREADT_NULL 0 #endif class IThread; @@ -219,7 +218,11 @@ class AbstractThread : public IThread char m_name[30]; static int m_threadsAvailable; - spherethread_t m_handle; + // pthread_t type is opaque (platform-defined). It can be an integer, a struct, a ptr something. Memset is the safest and more portable way. + //spherethread_t m_handle; + // Or, since we need here an "invalid" value, just use optional. + std::optional m_handle; + uint m_hangCheck; Priority m_priority; uint m_tickPeriod; From 9b81b0eaccc558aeddef26f570545561bb64c7f3 Mon Sep 17 00:00:00 2001 From: cbnolok Date: Thu, 3 Oct 2024 17:11:14 +0200 Subject: [PATCH 68/86] Refactored threads.h, removing useless matrioska interface class IThread. --- src/common/sphere_library/sstringobjs.cpp | 2 +- src/common/sphere_library/stypecast.h | 60 +++++-- src/game/CServer.cpp | 13 +- src/game/CServerConfig.cpp | 20 +-- src/game/CServerConfig.h | 2 +- src/game/spheresvr.cpp | 8 +- src/network/CNetState.cpp | 2 +- src/network/CNetworkInput.cpp | 2 +- src/network/CNetworkManager.cpp | 4 +- src/network/CNetworkOutput.cpp | 6 +- src/network/CNetworkThread.cpp | 12 +- src/network/PingServer.cpp | 2 +- src/network/linuxev.cpp | 2 +- src/sphere/ProfileTask.cpp | 2 +- src/sphere/UnixTerminal.cpp | 2 +- src/sphere/asyncdb.cpp | 2 +- src/sphere/ntservice.cpp | 2 +- src/sphere/ntwindow.cpp | 4 +- src/sphere/threads.cpp | 209 ++++++++++------------ src/sphere/threads.h | 182 ++++++++----------- 20 files changed, 259 insertions(+), 279 deletions(-) diff --git a/src/common/sphere_library/sstringobjs.cpp b/src/common/sphere_library/sstringobjs.cpp index 951b88923..765aeb009 100644 --- a/src/common/sphere_library/sstringobjs.cpp +++ b/src/common/sphere_library/sstringobjs.cpp @@ -34,7 +34,7 @@ static tchar* getUnsafeStringBuffer() noexcept tchar* Str_GetTemp() noexcept { - IThread *pThreadState = ThreadHolder::get().current(); + AbstractThread *pThreadState = ThreadHolder::get().current(); if (pThreadState) return static_cast(pThreadState)->allocateBuffer(); return getUnsafeStringBuffer(); diff --git a/src/common/sphere_library/stypecast.h b/src/common/sphere_library/stypecast.h index 1331a4a1e..d4143ec2a 100644 --- a/src/common/sphere_library/stypecast.h +++ b/src/common/sphere_library/stypecast.h @@ -509,11 +509,12 @@ constexpr uint32 usize_narrow_u32(const size_t source_val) noexcept [[nodiscard]] inline uint32 usize_narrow_u32_checked(const size_t source_val, bool should_assert) { - if (should_assert) + if (should_assert) { ASSERT(source_val <= std::numeric_limits::max()); - else if (source_val > std::numeric_limits::max()) + } + else if (source_val > std::numeric_limits::max()) { detail_stypecast::LogEventWarnWrapper("[Internal] Narrowing conversion from size_t to 32 bits unsigned integer will overflow.\n"); - + } return usize_narrow_u32(source_val); } @@ -572,10 +573,13 @@ uint32 usize_narrow_u32_checked(const size_t source_val, bool should_assert) int8 i8_from_u8_checked(const uint8 source_val, bool should_assert) // not clamping/capping { const bool would_overflow = (source_val > (uint8)std::numeric_limits::max()); - if (should_assert) + if (should_assert) { ASSERT(!would_overflow); - else if (would_overflow) + } + else if (would_overflow) { detail_stypecast::LogEventWarnWrapper("[Internal] Narrowing conversion from 8 bits unsigned integer to 8 bits signed integer will overflow.\n"); + } + return static_cast(source_val); } template int8 i8_from_u8_checked(T, bool) = delete; // disable implicit type conversion for the inpuT source_valrgument @@ -584,10 +588,12 @@ template int8 i8_from_u8_checked(T, bool) = delete; // disable impl int16 i8_from_u16_checked(const uint16 source_val, bool should_assert) // not clamping/capping { const bool would_overflow = (source_val > (uint16)std::numeric_limits::max()); - if (should_assert) + if (should_assert) { ASSERT(!would_overflow); - else if (would_overflow) + } + else if (would_overflow) { detail_stypecast::LogEventWarnWrapper("[Internal] Narrowing conversion from 16 bits unsigned integer to 8 bits signed integer will overflow.\n"); + } return static_cast(source_val); } @@ -597,10 +603,12 @@ template int16 i8_from_u16_checked(T, bool) = delete; // disable im int16 i16_from_u16_checked(const uint16 source_val, bool should_assert) // not clamping/capping { const bool would_overflow = (source_val > (uint16)std::numeric_limits::max()); - if (should_assert) + if (should_assert) { ASSERT(!would_overflow); - else if (would_overflow) + } + else if (would_overflow) { detail_stypecast::LogEventWarnWrapper("[Internal] Narrowing conversion from 16 bits unsigned integer to 16 bits signed integer will overflow.\n"); + } return static_cast(source_val); } @@ -610,10 +618,12 @@ template int16 i16_from_u16_checked(T, bool) = delete; // disable i int16 i16_from_u32_checked(const uint32 source_val, bool should_assert) // not clamping/capping { const bool would_overflow = (source_val > (uint32)std::numeric_limits::max()); - if (should_assert) + if (should_assert) { ASSERT(!would_overflow); - else if (would_overflow) + } + else if (would_overflow) { detail_stypecast::LogEventWarnWrapper("[Internal] Narrowing conversion from 32 bits unsigned integer to 16 bits signed integer will overflow.\n"); + } return static_cast(source_val); } @@ -623,10 +633,13 @@ template int16 i16_from_u32_checked(T, bool) = delete; // disable i int16 i16_from_u64_checked(const uint64 source_val, bool should_assert) // not clamping/capping { const bool would_overflow = (source_val > (uint64)std::numeric_limits::max()); - if (should_assert) + if (should_assert) { ASSERT(!would_overflow); - else if (would_overflow) + } + else if (would_overflow) { detail_stypecast::LogEventWarnWrapper("[Internal] Narrowing conversion from 64 bits unsigned integer to 16 bits signed integer will overflow.\n"); + } + return static_cast(source_val); } template int16 i16_from_u64_checked(T, bool) = delete; // disable implicit type conversion for the inpuT source_valrgument @@ -636,10 +649,13 @@ template int16 i16_from_u64_checked(T, bool) = delete; // disable i int32 i32_from_u32_checked(const uint32 source_val, bool should_assert) // not clamping/capping { const bool would_overflow = (source_val > (uint32)std::numeric_limits::max()); - if (should_assert) + if (should_assert) { ASSERT(!would_overflow); - else if (would_overflow) + } + else if (would_overflow) { detail_stypecast::LogEventWarnWrapper("[Internal] Narrowing conversion from 32 bits unsigned integer to 32 bits signed integer will overflow.\n"); + } + return static_cast(source_val); } template int32 i32_from_u32_checked(T, bool) = delete; // disable implicit type conversion for the inpuT source_valrgument @@ -648,10 +664,13 @@ template int32 i32_from_u32_checked(T, bool) = delete; // disable i int32 i32_from_u64_checked(const uint64 source_val, bool should_assert) // not clamping/capping { const bool would_overflow = (source_val > (uint64)std::numeric_limits::max()); - if (should_assert) + if (should_assert) { ASSERT(!would_overflow); - else if (would_overflow) + } + else if (would_overflow) { detail_stypecast::LogEventWarnWrapper("[Internal] Narrowing conversion from 64 bits unsigned integer to 32 bits signed integer will overflow.\n"); + } + return static_cast(source_val); } template int32 i32_from_u64_checked(T, bool) = delete; // disable implicit type conversion for the inpuT source_valrgument @@ -661,10 +680,13 @@ template int32 i32_from_u64_checked(T, bool) = delete; // disable i int64 i64_from_u64_checked(const uint64 source_val, bool should_assert) // not clamping/capping { const bool would_overflow = (source_val > (uint64)std::numeric_limits::max()); - if (should_assert) + if (should_assert) { ASSERT(!would_overflow); - else if (would_overflow) + } + else if (would_overflow) { detail_stypecast::LogEventWarnWrapper("[Internal] Narrowing conversion from 64 bits unsigned integer to 64 bits signed integer will overflow.\n"); + } + return static_cast(source_val); } template int64 i64_from_u64_checked(T, bool) = delete; // disable implicit type conversion for the inpuT source_valrgument diff --git a/src/game/CServer.cpp b/src/game/CServer.cpp index cbbb47a35..5b9bc5bca 100644 --- a/src/game/CServer.cpp +++ b/src/game/CServer.cpp @@ -975,11 +975,16 @@ bool CServer::OnConsoleCmd( CSString & sText, CTextConsole * pSrc ) size_t iThreadCount = ThreadHolder::get().getActiveThreads(); for ( size_t iThreads = 0; iThreads < iThreadCount; ++iThreads ) { - IThread * thrCurrent = ThreadHolder::get().getThreadAt(iThreads); + AbstractThread * thrCurrent = ThreadHolder::get().getThreadAt(iThreads); if (thrCurrent != nullptr) { - pSrc->SysMessagef("%" PRIuSIZE_T " - Id: %" PRIu64 ", Priority: %d, Name: %s.\n", - (iThreads + 1), (uint64)thrCurrent->getId(), thrCurrent->getPriority(), thrCurrent->getName()); + pSrc->SysMessagef( + "%" PRIuSIZE_T " - Id: %" PRIu64 ", Priority: %d, Name: %s.\n", + (iThreads + 1), + (uint64)thrCurrent->getId(), + enum_alias_cast(thrCurrent->getPriority()), + thrCurrent->getName() + ); } } } break; @@ -1362,7 +1367,7 @@ void CServer::ProfileDump( CTextConsole * pSrc, bool bDump ) size_t uiThreadCount = ThreadHolder::get().getActiveThreads(); for ( size_t iThreads = 0; iThreads < uiThreadCount; ++iThreads) { - IThread* thrCurrent = ThreadHolder::get().getThreadAt(iThreads); + AbstractThread* thrCurrent = ThreadHolder::get().getThreadAt(iThreads); if (thrCurrent == nullptr) continue; diff --git a/src/game/CServerConfig.cpp b/src/game/CServerConfig.cpp index b30cdb9f1..28bbb5a4c 100644 --- a/src/game/CServerConfig.cpp +++ b/src/game/CServerConfig.cpp @@ -317,7 +317,7 @@ CServerConfig::CServerConfig() // Networking _uiNetworkThreads = 0; // if there aren't the ini settings, by default we'll not use additional network threads - _uiNetworkThreadPriority= IThread::Disabled; + _iNetworkThreadPriority = enum_alias_cast(ThreadPriority::Disabled); m_fUseAsyncNetwork = 0; m_iNetMaxPings = 15; m_iNetHistoryTTLSeconds = 300; @@ -644,7 +644,7 @@ enum RC_TYPE RC_MYSQLTICKS, // m_fMySqlTicks RC_MYSQLUSER, // m_sMySqlUser RC_NETTTL, // m_iNetHistoryTTL - RC_NETWORKTHREADPRIORITY, // _uiNetworkThreadPriority + RC_NETWORKTHREADPRIORITY, // _iNetworkThreadPriority RC_NETWORKTHREADS, // _uiNetworkThreads RC_NORESROBE, RC_NOTOTIMEOUT, @@ -937,7 +937,7 @@ const CAssocReg CServerConfig::sm_szLoadKeys[RC_QTY + 1] { "MYSQLTICKS", { ELEM_BOOL, static_castOFFSETOF(CServerConfig,m_fMySqlTicks) }}, { "MYSQLUSER", { ELEM_CSTRING, static_castOFFSETOF(CServerConfig,m_sMySqlUser) }}, { "NETTTL", { ELEM_INT, static_castOFFSETOF(CServerConfig, m_iNetHistoryTTLSeconds) }}, - { "NETWORKTHREADPRIORITY", { ELEM_MASK_INT,static_castOFFSETOF(CServerConfig,_uiNetworkThreadPriority)}}, + { "NETWORKTHREADPRIORITY", { ELEM_MASK_INT,static_castOFFSETOF(CServerConfig,_iNetworkThreadPriority)}}, { "NETWORKTHREADS", { ELEM_MASK_INT,static_castOFFSETOF(CServerConfig,_uiNetworkThreads) }}, { "NORESROBE", { ELEM_BOOL, static_castOFFSETOF(CServerConfig,m_fNoResRobe) }}, { "NOTOTIMEOUT", { ELEM_INT, static_castOFFSETOF(CServerConfig,m_iNotoTimeout) }}, @@ -1483,15 +1483,15 @@ bool CServerConfig::r_LoadVal( CScript &s ) case RC_NETWORKTHREADPRIORITY: { - int priority = s.GetArgVal(); - if (priority < 1) - priority = IThread::Normal; - else if (priority > 4) - priority = IThread::RealTime; + int priority = s.GetArgVal(); + if (priority < 1) + priority = enum_alias_cast(ThreadPriority::Normal); + else if (priority > 4) + priority = enum_alias_cast(ThreadPriority::RealTime); else - priority = IThread::Low + (IThread::Priority)priority; + priority = enum_alias_cast(ThreadPriority::Low) + priority; - _uiNetworkThreadPriority = priority; + _iNetworkThreadPriority = priority; } break; case RC_WALKBUFFER: diff --git a/src/game/CServerConfig.h b/src/game/CServerConfig.h index 615bb6e99..f47025fc2 100644 --- a/src/game/CServerConfig.h +++ b/src/game/CServerConfig.h @@ -569,7 +569,7 @@ extern class CServerConfig : public CResourceHolder // network settings uint _uiNetworkThreads; // number of network threads to create - uint _uiNetworkThreadPriority; // priority of network threads + int _iNetworkThreadPriority; // priority of network threads int m_fUseAsyncNetwork; // 0=normal send, 1=async send, 2=async send for 4.0.0+ only int m_iNetMaxPings; // max pings before blocking an ip int m_iNetHistoryTTLSeconds; // time to remember an ip diff --git a/src/game/spheresvr.cpp b/src/game/spheresvr.cpp index 5b989a4de..38b696f56 100644 --- a/src/game/spheresvr.cpp +++ b/src/game/spheresvr.cpp @@ -173,7 +173,7 @@ static PingServer g_PingServer; // Main server loop MainThread::MainThread() - : AbstractSphereThread("T_Main", IThread::RealTime) + : AbstractSphereThread("T_Main", ThreadPriority::RealTime) { m_profile.EnableProfile(PROFILE_NETWORK_RX); m_profile.EnableProfile(PROFILE_CLIENTS); @@ -492,14 +492,14 @@ int _cdecl main( int argc, char * argv[] ) { // Ensure i have this to have context for ADDTOCALLSTACK and other operations. - const IThread* curthread = ThreadHolder::get().current(); + const AbstractThread* curthread = ThreadHolder::get().current(); ASSERT(curthread != nullptr); ASSERT(dynamic_cast(curthread)); (void)curthread; } #ifndef _WIN32 - IThread::setThreadName("T_SphereStartup"); + AbstractThread::setThreadName("T_SphereStartup"); g_UnixTerminal.start(); @@ -531,7 +531,7 @@ int _cdecl main( int argc, char * argv[] ) if (fShouldCoreRunInSeparateThread) { g_Main.start(); // Starts another thread to do all the work (it does Sphere_OnTick()) - IThread::setThreadName("T_Monitor"); + AbstractThread::setThreadName("T_Monitor"); Sphere_MainMonitorLoop(); // Use this thread to monitor if the others are stuck } else diff --git a/src/network/CNetState.cpp b/src/network/CNetState.cpp index 0ca402c38..ae3ecc506 100644 --- a/src/network/CNetState.cpp +++ b/src/network/CNetState.cpp @@ -242,7 +242,7 @@ void CNetState::markReadClosed(void) volatile DEBUGNETWORK(("%x:Client being closed by read-thread\n", m_id)); m_isReadClosed = true; - if (m_parent != nullptr && m_parent->getPriority() == IThread::Disabled) + if (m_parent != nullptr && m_parent->getPriority() == ThreadPriority::Disabled) m_parent->awaken(); } diff --git a/src/network/CNetworkInput.cpp b/src/network/CNetworkInput.cpp index 23380e34d..70f050b37 100644 --- a/src/network/CNetworkInput.cpp +++ b/src/network/CNetworkInput.cpp @@ -54,7 +54,7 @@ bool CNetworkInput::processInput() { // if the thread does not receive ticks, we must perform a quick select to see if we should // wake up the thread - if (m_thread->isActive() && m_thread->getPriority() == IThread::Disabled) + if (m_thread->isActive() && m_thread->getPriority() == ThreadPriority::Disabled) { fd_set fds; if (checkForData(fds)) diff --git a/src/network/CNetworkManager.cpp b/src/network/CNetworkManager.cpp index d38e00fa9..c2ee43980 100644 --- a/src/network/CNetworkManager.cpp +++ b/src/network/CNetworkManager.cpp @@ -391,7 +391,7 @@ void CNetworkManager::start(void) if (ntCount > 1) { // If we have more than one thread (this hasn't sense... at this point isThreaded should be == true) - char name[IThread::m_nameMaxLength]; + char name[AbstractThread::m_nameMaxLength]; snprintf(name, sizeof(name), "T_Net #%u", (uint)pThread->getId()); pThread->overwriteInternalThreadName(name); } @@ -453,7 +453,7 @@ void CNetworkManager::tick(void) // sent from CNetworkOutput::QueuePacketTransaction can be ignored // the safest solution to this is to send additional signals from here CNetworkThread* thread = state->getParentThread(); - if (thread != nullptr && state->hasPendingData() && thread->getPriority() == IThread::Disabled) + if (thread != nullptr && state->hasPendingData() && thread->getPriority() == ThreadPriority::Disabled) thread->awaken(); #endif continue; diff --git a/src/network/CNetworkOutput.cpp b/src/network/CNetworkOutput.cpp index 17c8fb1c5..445c24df1 100644 --- a/src/network/CNetworkOutput.cpp +++ b/src/network/CNetworkOutput.cpp @@ -126,7 +126,7 @@ bool CNetworkOutput::processOutput() if (packetsSent > 0) { // notify thread there could be more to process - if (m_thread->getPriority() == IThread::Disabled) + if (m_thread->getPriority() == ThreadPriority::Disabled) m_thread->awaken(); } @@ -173,7 +173,7 @@ size_t CNetworkOutput::flush(CNetState* state) // when this isn't the active thread, all we can do is raise a request to flush this // client later state->markFlush(true); - if (m_thread->getPriority() == IThread::Disabled) + if (m_thread->getPriority() == ThreadPriority::Disabled) m_thread->awaken(); return 0; @@ -647,6 +647,6 @@ void CNetworkOutput::QueuePacketTransaction(PacketTransaction* transaction) // notify thread CNetworkThread* thread = state->getParentThread(); - if (thread != nullptr && thread->getPriority() == IThread::Disabled) + if (thread != nullptr && thread->getPriority() == ThreadPriority::Disabled) thread->awaken(); } diff --git a/src/network/CNetworkThread.cpp b/src/network/CNetworkThread.cpp index bedb35de3..0ebb6db11 100644 --- a/src/network/CNetworkThread.cpp +++ b/src/network/CNetworkThread.cpp @@ -12,13 +12,13 @@ static const char* GenerateNetworkThreadName(size_t id) { char* name = Str_GetTemp(); - snprintf(name, IThread::m_nameMaxLength, "T_Net #%" PRIuSIZE_T, id); + snprintf(name, AbstractThread::m_nameMaxLength, "T_Net #%" PRIuSIZE_T, id); return name; } CNetworkThread::CNetworkThread(CNetworkManager* manager, size_t id) - : AbstractSphereThread(GenerateNetworkThreadName(id), IThread::Disabled), + : AbstractSphereThread(GenerateNetworkThreadName(id), ThreadPriority::Disabled), m_manager(manager), m_id(id), _iTimeLastStateDataCheck(0) { } @@ -31,7 +31,7 @@ void CNetworkThread::assignNetworkState(CNetState* state) { ADDTOCALLSTACK("CNetworkThread::assignNetworkState"); m_assignQueue.push(state); - if (getPriority() == IThread::Disabled) + if (getPriority() == ThreadPriority::Disabled) awaken(); } @@ -113,8 +113,8 @@ void CNetworkThread::tick(void) if (m_states.empty()) { // we haven't been assigned any clients, so go idle for now - if (getPriority() != IThread::Disabled) - setPriority(IThread::Low); + if (getPriority() != ThreadPriority::Disabled) + setPriority(ThreadPriority::Low); return; } @@ -122,7 +122,7 @@ void CNetworkThread::tick(void) processOutput(); // we're active, take priority - setPriority(static_cast(g_Cfg._uiNetworkThreadPriority)); + setPriority(static_cast(g_Cfg._iNetworkThreadPriority)); static constexpr int64 kiStateDataCheckPeriod = 10 * 1000; // 10 seconds, expressed in milliseconds const int64 iTimeCur = CSTime::GetMonotonicSysTimeMilli(); diff --git a/src/network/PingServer.cpp b/src/network/PingServer.cpp index 0c2c3ec50..2627c1227 100644 --- a/src/network/PingServer.cpp +++ b/src/network/PingServer.cpp @@ -6,7 +6,7 @@ static PingServer s_PingServer; // run the thread in RealTime as we need pings to be responded to ASAP -PingServer::PingServer() : AbstractSphereThread("PingServer", IThread::RealTime) +PingServer::PingServer() : AbstractSphereThread("PingServer", ThreadPriority::RealTime) { m_profile.EnableProfile(PROFILE_NETWORK_RX); m_profile.EnableProfile(PROFILE_NETWORK_TX); diff --git a/src/network/linuxev.cpp b/src/network/linuxev.cpp index 122d748ac..c946fcfe5 100644 --- a/src/network/linuxev.cpp +++ b/src/network/linuxev.cpp @@ -63,7 +63,7 @@ static void socketslave_cb(struct ev_loop *loop, struct ev_io *watcher, int reve static constexpr double kLoopCollectNetworkInputSeconds = 0.002; static constexpr double kLoopWaitBeforeNextCycleSeconds = 0.008; -LinuxEv::LinuxEv(void) : AbstractSphereThread("T_NetLoopOut", IThread::High) +LinuxEv::LinuxEv(void) : AbstractSphereThread("T_NetLoopOut", ThreadPriority::High) //, m_watchMainsock{} { // Right now, we use libev to send asynchronously packets to clients. diff --git a/src/sphere/ProfileTask.cpp b/src/sphere/ProfileTask.cpp index 500a837cf..9ff76d6b0 100644 --- a/src/sphere/ProfileTask.cpp +++ b/src/sphere/ProfileTask.cpp @@ -21,7 +21,7 @@ ProfileTask::ProfileTask(PROFILE_TYPE id) : if (th.closing()) return; - IThread* icontext = th.current(); + AbstractThread* icontext = th.current(); if (icontext == nullptr) { // Thread was deleted, manually or by app closing signal. diff --git a/src/sphere/UnixTerminal.cpp b/src/sphere/UnixTerminal.cpp index e3e961b13..f11449411 100644 --- a/src/sphere/UnixTerminal.cpp +++ b/src/sphere/UnixTerminal.cpp @@ -11,7 +11,7 @@ #endif -UnixTerminal::UnixTerminal() : AbstractSphereThread("T_UnixTerm", IThread::Highest), +UnixTerminal::UnixTerminal() : AbstractSphereThread("T_UnixTerm", ThreadPriority::Highest), #ifdef _USECURSES m_window(nullptr), #else diff --git a/src/sphere/asyncdb.cpp b/src/sphere/asyncdb.cpp index cff073390..d2685c9ad 100644 --- a/src/sphere/asyncdb.cpp +++ b/src/sphere/asyncdb.cpp @@ -6,7 +6,7 @@ CDataBaseAsyncHelper g_asyncHdb; -CDataBaseAsyncHelper::CDataBaseAsyncHelper(void) : AbstractSphereThread("AsyncDatabaseHelper", IThread::Low) +CDataBaseAsyncHelper::CDataBaseAsyncHelper(void) : AbstractSphereThread("AsyncDatabaseHelper", ThreadPriority::Low) { } diff --git a/src/sphere/ntservice.cpp b/src/sphere/ntservice.cpp index a346d593b..0e0bdb707 100644 --- a/src/sphere/ntservice.cpp +++ b/src/sphere/ntservice.cpp @@ -457,7 +457,7 @@ int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine #endif { UnreferencedParameter(hPrevInstance); - IThread::setThreadName("T_SphereStartup"); + AbstractThread::setThreadName("T_SphereStartup"); TCHAR *argv[32]; argv[0] = nullptr; diff --git a/src/sphere/ntwindow.cpp b/src/sphere/ntwindow.cpp index c9f8a049d..ce3a38b73 100644 --- a/src/sphere/ntwindow.cpp +++ b/src/sphere/ntwindow.cpp @@ -100,7 +100,7 @@ void CNTWindow::CStatusDlg::FillStats() size_t iThreadCount = ThreadHolder::get().getActiveThreads(); for ( size_t iThreads = 0; iThreads < iThreadCount; ++iThreads) { - IThread* thrCurrent = ThreadHolder::get().getThreadAt(iThreads); + AbstractThread* thrCurrent = ThreadHolder::get().getThreadAt(iThreads); if (thrCurrent == nullptr) continue; @@ -163,7 +163,7 @@ BOOL CNTWindow::CStatusDlg::DefDialogProc( UINT message, WPARAM wParam, LPARAM l return false; } -CNTWindow::CNTWindow() : AbstractSphereThread("T_ConsoleWindow", IThread::Highest), +CNTWindow::CNTWindow() : AbstractSphereThread("T_ConsoleWindow", ThreadPriority::Highest), _NTWInitParams{}, m_zCommands {{}} { _fKeepAliveAtShutdown = true; diff --git a/src/sphere/threads.cpp b/src/sphere/threads.cpp index 204ed2e28..9eb3d26f6 100644 --- a/src/sphere/threads.cpp +++ b/src/sphere/threads.cpp @@ -54,74 +54,6 @@ struct TemporaryStringThreadSafeStateHolder } }; -IThread::IThread() noexcept : - m_threadSystemId(0), m_threadHolderId(-1) - { }; - -// This is needed to prevent weak-vtables warning (puts the vtable in this translation unit instead of every translation unit) -IThread::~IThread() noexcept = default; - -#if defined(_WIN32) && defined(MSVC_COMPILER) -#pragma pack(push, 8) -typedef struct tagTHREADNAME_INFO -{ - DWORD dwType; - LPCSTR szName; - DWORD dwThreadID; - DWORD dwFlags; -} THREADNAME_INFO; -#pragma pack(pop) - -static constexpr DWORD MS_VC_EXCEPTION = 0x406D1388; -#endif - -void IThread::setThreadName(const char* name) -{ - // register the thread name - - // Unix uses prctl to set thread name - // thread name must be 16 bytes, zero-padded if shorter - char name_trimmed[m_nameMaxLength] = { '\0' }; // m_nameMaxLength = 16 - Str_CopyLimitNull(name_trimmed, name, m_nameMaxLength); - -#if defined(_WIN32) - #if defined(MSVC_COMPILER) // TODO: support thread naming when compiling with compilers other than Microsoft's - // Windows uses THREADNAME_INFO structure to set thread name - THREADNAME_INFO info; - info.dwType = 0x1000; - info.szName = name_trimmed; - info.dwThreadID = (DWORD)(-1); - info.dwFlags = 0; - - __try - { - RaiseException(MS_VC_EXCEPTION, 0, sizeof(info) / sizeof(ULONG_PTR), (ULONG_PTR*)&info); - } - __except(EXCEPTION_EXECUTE_HANDLER) - { - } - #endif // MSVC_COMPILER -#elif defined(__APPLE__) // Mac - pthread_setname_np(name_trimmed); -#elif !defined(_BSD) // Linux - prctl(PR_SET_NAME, name_trimmed, 0, 0, 0); -#elif defined(__FreeBSD__) || defined(__OpenBSD__) - pthread_set_name_np(getCurrentThreadId(), name_trimmed); -#elif defined(__NetBSD__) - pthread_setname_np(getCurrentThreadId(), "%s", name_trimmed); -#endif - - auto athr = static_cast(ThreadHolder::get().current()); - ASSERT(athr); - -#ifdef _DEBUG - g_Log.Event(LOGF_CONSOLE_ONLY|LOGM_DEBUG|LOGL_EVENT, - "Setting thread (ThreadHolder ID %d, internal name '%s') system name: '%s'.\n", - athr->m_threadHolderId, athr->getName(), name_trimmed); -#endif - athr->overwriteInternalThreadName(name_trimmed); -} - /** * ThreadHolder @@ -144,18 +76,18 @@ bool ThreadHolder::closing() noexcept return ret; } -IThread* ThreadHolder::current() noexcept +AbstractThread* ThreadHolder::current() noexcept { // Do not use ASSERTs here, would cause recursion. // RETRY_SHARED_LOCK_FOR_TASK is used to try to not make mutex lock fail and, if needed, // handle failure while allowing this function to be noexcept. - IThread* retval = nullptr; + AbstractThread* retval = nullptr; RETRY_SHARED_LOCK_FOR_TASK(m_mutex, lock, retval, - ([this, &lock]() -> IThread* + ([this, &lock]() -> AbstractThread* { - const threadid_t tid = IThread::getCurrentThreadSystemId(); + const threadid_t tid = AbstractThread::getCurrentThreadSystemId(); if (m_spherethreadpairs_systemid_ptr.empty()) [[unlikely]] @@ -166,7 +98,7 @@ IThread* ThreadHolder::current() noexcept return nullptr; } - auto thread = static_cast(DummySphereThread::getInstance()); + auto thread = static_cast(DummySphereThread::getInstance()); if (!thread) [[unlikely]] { @@ -200,7 +132,7 @@ IThread* ThreadHolder::current() noexcept RaiseImmediateAbort(); } - auto thread = static_cast(found->second); + auto thread = static_cast(found->second); ASSERT(thread->m_threadHolderId != -1); SphereThreadData *tdata = &(m_threads[thread->m_threadHolderId]); @@ -236,7 +168,7 @@ IThread* ThreadHolder::current() noexcept return retval; } -void ThreadHolder::push(IThread *thread) noexcept +void ThreadHolder::push(AbstractThread *thread) noexcept { bool fExceptionThrown = false; try @@ -244,8 +176,8 @@ void ThreadHolder::push(IThread *thread) noexcept auto sphere_thread = dynamic_cast(thread); if (!sphere_thread) { - //throw CSError(LOGL_FATAL, 0, "IThread not being an AbstractSphereThread?"); - STDERR_LOG("IThread not being an AbstractSphereThread?"); + //throw CSError(LOGL_FATAL, 0, "AbstractThread not being an AbstractSphereThread?"); + STDERR_LOG("AbstractThread not being an AbstractSphereThread?"); fExceptionThrown = true; } @@ -311,23 +243,7 @@ void ThreadHolder::push(IThread *thread) noexcept #endif } -/* -SphereThreadData* ThreadHolder::findThreadData(IThread* thread) noexcept -{ - // If checking for current thread, use another escamotage to retrieve it... - - // This should always run guarded by a MUTEX! - SimpleThreadLock lock(m_mutex); - for (size_t i = 0; i < m_threadCount; ++i) - { - if (m_threads[i].m_ptr == thread) - return &(m_threads[i]); - } - return nullptr; -} -*/ - -void ThreadHolder::remove(IThread *thread) CANTHROW +void ThreadHolder::remove(AbstractThread *thread) CANTHROW { if (!thread) throw CSError(LOGL_FATAL, 0, "thread == nullptr"); @@ -373,11 +289,11 @@ void ThreadHolder::markThreadsClosing() CANTHROW } } -IThread * ThreadHolder::getThreadAt(size_t at) noexcept +AbstractThread * ThreadHolder::getThreadAt(size_t at) noexcept { - IThread* retval = nullptr; + AbstractThread* retval = nullptr; RETRY_SHARED_LOCK_FOR_TASK(m_mutex, lock, retval, - ([this, at]() -> IThread* + ([this, at]() -> AbstractThread* { // MSVC: warning C5101: use of preprocessor directive in function-like macro argument list is undefined behavior. //#ifdef _DEBUG @@ -389,7 +305,7 @@ IThread * ThreadHolder::getThreadAt(size_t at) noexcept } //#endif - if ( at > getActiveThreads() ) + if ( at > getActiveThreads() ) [[unlikely]] { return nullptr; @@ -418,7 +334,8 @@ IThread * ThreadHolder::getThreadAt(size_t at) noexcept */ int AbstractThread::m_threadsAvailable = 0; -AbstractThread::AbstractThread(const char *name, IThread::Priority priority) : +AbstractThread::AbstractThread(const char *name, ThreadPriority priority) : + m_threadSystemId(0), m_threadHolderId(-1), _fKeepAliveAtShutdown(false), _fIsClosing(false) { if( AbstractThread::m_threadsAvailable == 0 ) @@ -733,7 +650,7 @@ void AbstractThread::onStart() ThreadHolder::get().push(this); - if (isActive()) // This thread has actually been spawned and the code is executing on a different thread + if (isActive()) // This thread has actually been spawned and the code is executing on a different thread setThreadName(getName()); #ifdef _DEBUG @@ -743,36 +660,36 @@ void AbstractThread::onStart() #endif } -void AbstractThread::setPriority(IThread::Priority pri) +void AbstractThread::setPriority(ThreadPriority pri) { - ASSERT(((pri >= IThread::Idle) && (pri <= IThread::RealTime)) || (pri == IThread::Disabled)); + ASSERT(((pri >= ThreadPriority::Idle) && (pri <= ThreadPriority::RealTime)) || (pri == ThreadPriority::Disabled)); m_priority = pri; // detect a sleep period for thread depending on priority switch( m_priority ) { - case IThread::Idle: + case ThreadPriority::Idle: m_tickPeriod = 1000; break; - case IThread::Low: + case ThreadPriority::Low: m_tickPeriod = 200; break; - case IThread::Normal: + case ThreadPriority::Normal: m_tickPeriod = 100; break; - case IThread::High: + case ThreadPriority::High: m_tickPeriod = 50; break; - case IThread::Highest: + case ThreadPriority::Highest: m_tickPeriod = 5; break; - case IThread::RealTime: + case ThreadPriority::RealTime: m_tickPeriod = 0; break; - case IThread::Disabled: + case ThreadPriority::Disabled: m_tickPeriod = AutoResetEvent::_kiInfinite; break; - }\ + } } bool AbstractThread::shouldExit() noexcept @@ -780,10 +697,71 @@ bool AbstractThread::shouldExit() noexcept return closing() || m_terminateRequested || _thread_selfTerminateAfterThisTick; } +void AbstractThread::setThreadName(const char* name) +{ + // register the thread name + + // Unix uses prctl to set thread name + // thread name must be 16 bytes, zero-padded if shorter + char name_trimmed[m_nameMaxLength] = { '\0' }; // m_nameMaxLength = 16 + Str_CopyLimitNull(name_trimmed, name, m_nameMaxLength); + +#if defined(_WIN32) +#if defined(MSVC_COMPILER) + // TODO: support thread naming when compiling with compilers other than Microsoft's + + // Windows uses THREADNAME_INFO structure to set thread name +#pragma pack(push, 8) + typedef struct tagTHREADNAME_INFO + { + DWORD dwType; + LPCSTR szName; + DWORD dwThreadID; + DWORD dwFlags; + } THREADNAME_INFO; +#pragma pack(pop) + static constexpr DWORD MS_VC_EXCEPTION = 0x406D1388; + + THREADNAME_INFO info; + info.dwType = 0x1000; + info.szName = name_trimmed; + info.dwThreadID = (DWORD)(-1); + info.dwFlags = 0; + + __try + { + RaiseException(MS_VC_EXCEPTION, 0, sizeof(info) / sizeof(ULONG_PTR), (ULONG_PTR*)&info); + } + __except(EXCEPTION_EXECUTE_HANDLER) + { + } +#endif // MSVC_COMPILER +#elif defined(__APPLE__) // Mac + pthread_setname_np(name_trimmed); +#elif !defined(_BSD) // Linux + prctl(PR_SET_NAME, name_trimmed, 0, 0, 0); +#elif defined(__FreeBSD__) || defined(__OpenBSD__) + pthread_set_name_np(getCurrentThreadId(), name_trimmed); +#elif defined(__NetBSD__) + pthread_setname_np(getCurrentThreadId(), "%s", name_trimmed); +#endif + + auto athr = static_cast(ThreadHolder::get().current()); + ASSERT(athr); + +#ifdef _DEBUG + g_Log.Event(LOGF_CONSOLE_ONLY|LOGM_DEBUG|LOGL_EVENT, + "Setting thread (ThreadHolder ID %d, internal name '%s') system name: '%s'.\n", + athr->m_threadHolderId, athr->getName(), name_trimmed); +#endif + athr->overwriteInternalThreadName(name_trimmed); +} + + /* * AbstractSphereThread */ -AbstractSphereThread::AbstractSphereThread(const char *name, Priority priority) +AbstractSphereThread::AbstractSphereThread(const char *name, ThreadPriority priority) : AbstractThread(name, priority) { #ifdef THREAD_TRACK_CALLSTACK @@ -804,7 +782,6 @@ AbstractSphereThread::~AbstractSphereThread() _fIsClosing = true; } - char *AbstractSphereThread::allocateBuffer() noexcept { auto* tsholder = TemporaryStringThreadSafeStateHolder::get(); @@ -976,7 +953,7 @@ void AbstractSphereThread::printStackTrace() noexcept DummySphereThread *DummySphereThread::_instance = nullptr; DummySphereThread::DummySphereThread() - : AbstractSphereThread("dummy", IThread::Normal) + : AbstractSphereThread("dummy", ThreadPriority::Normal) { } @@ -1016,7 +993,7 @@ StackDebugInformation::StackDebugInformation(const char *name) noexcept if (th.closing()) [[unlikely]] return; - IThread *icontext = th.current(); + AbstractThread *icontext = th.current(); if (icontext == nullptr) [[unlikely]] { @@ -1048,14 +1025,14 @@ StackDebugInformation::~StackDebugInformation() noexcept void StackDebugInformation::printStackTrace() noexcept // static { - IThread* pThreadState = ThreadHolder::get().current(); + AbstractThread* pThreadState = ThreadHolder::get().current(); if (pThreadState) static_cast(pThreadState)->printStackTrace(); } void StackDebugInformation::freezeCallStack(bool freeze) noexcept // static { - IThread* pThreadState = ThreadHolder::get().current(); + AbstractThread* pThreadState = ThreadHolder::get().current(); if (pThreadState) static_cast(pThreadState)->freezeCallStack(freeze); } diff --git a/src/sphere/threads.h b/src/sphere/threads.h index 1a2fb0598..2b72d6c4b 100644 --- a/src/sphere/threads.h +++ b/src/sphere/threads.h @@ -44,10 +44,10 @@ #define SPHERE_THREADENTRY_CALLTYPE #endif -class IThread; +class AbstractThread; // stores a value unique to each thread, intended to hold -// a pointer (e.g. the current IThread instance) +// a pointer (e.g. the current AbstractThread instance) template class TlsValue { @@ -131,92 +131,36 @@ T TlsValue::get() const #endif } +enum class ThreadPriority : int +{ + Idle, // tick 1000ms + Low, // tick 200ms + Normal, // tick 100ms + High, // tick 50ms + Highest, // tick 5ms + RealTime, // tick almost instantly + Disabled = 0xFF // tick never +}; -// Interface for threads. Almost always should be used instead of any implementing classes -class IThread +// Thread base implementation, without Sphere "extensions". +class AbstractThread { -public: // TODO: lazy - threadid_t m_threadSystemId; - int m_threadHolderId; + friend class ThreadHolder; + static int m_threadsAvailable; public: - enum Priority - { - Idle, // tick 1000ms - Low, // tick 200ms - Normal, // tick 100ms - High, // tick 50ms - Highest, // tick 5ms - RealTime, // tick almost instantly - Disabled = 0xFF // tick never - }; - - IThread() noexcept; - virtual ~IThread() noexcept; - - virtual threadid_t getId() const = 0; - virtual const char *getName() const = 0; - - virtual bool isActive() const = 0; - virtual bool checkStuck() = 0; - - virtual void start() = 0; - virtual void terminate(bool ended) = 0; - virtual void waitForClose() = 0; - - virtual void setPriority(Priority) = 0; - virtual Priority getPriority() const = 0; - - static inline threadid_t getCurrentThreadSystemId() noexcept - { -#if defined(_WIN32) - return ::GetCurrentThreadId(); -#elif defined(__APPLE__) - // On OSX, 'threadid_t' is not an integer but a '_opaque_pthread_t *'), so we need to resort to another method. - uint64_t threadid = 0; - pthread_threadid_np(pthread_self(), &threadid); - return threadid; -#else - return pthread_self(); -#endif - } - static inline bool isSameThreadId(threadid_t firstId, threadid_t secondId) noexcept - { -#if defined(_WIN32) || defined(__APPLE__) - return (firstId == secondId); -#else - return pthread_equal(firstId,secondId); -#endif - } - - inline bool isSameThread(threadid_t otherThreadId) const noexcept - { - return isSameThreadId(getCurrentThreadSystemId(), otherThreadId); - } - - static constexpr uint m_nameMaxLength = 16; // Unix support a max 16 bytes thread name. - static void setThreadName(const char* name); + static constexpr uint m_nameMaxLength = 16; // Unix support a max 16 bytes thread name. protected: - virtual bool shouldExit() noexcept = 0; -}; - - -// Thread implementation. See IThread for list of available methods. -class AbstractThread : public IThread -{ - friend class ThreadHolder; + threadid_t m_threadSystemId; + int m_threadHolderId; -protected: bool _fKeepAliveAtShutdown; volatile std::atomic_bool _thread_selfTerminateAfterThisTick; volatile std::atomic_bool _fIsClosing; - private: volatile std::atomic_bool m_terminateRequested; - char m_name[30]; - static int m_threadsAvailable; // pthread_t type is opaque (platform-defined). It can be an integer, a struct, a ptr something. Memset is the safest and more portable way. //spherethread_t m_handle; @@ -224,50 +168,81 @@ class AbstractThread : public IThread std::optional m_handle; uint m_hangCheck; - Priority m_priority; + ThreadPriority m_priority; uint m_tickPeriod; AutoResetEvent m_sleepEvent; ManualResetEvent m_terminateEvent; public: - AbstractThread(const char *name, Priority priority = IThread::Normal); + AbstractThread(const char *name, ThreadPriority priority = ThreadPriority::Normal); virtual ~AbstractThread(); AbstractThread(const AbstractThread& copy) = delete; AbstractThread& operator=(const AbstractThread& other) = delete; public: - virtual threadid_t getId() const noexcept override { return m_threadSystemId; } - virtual const char *getName() const noexcept override { return m_name; } + threadid_t getId() const noexcept { return m_threadSystemId; } + virtual const char *getName() const noexcept { return m_name; } - virtual bool isActive() const override; - virtual bool checkStuck() override; + virtual bool isActive() const; + virtual bool checkStuck(); - virtual void start() override; - virtual void terminate(bool ended) override; - virtual void waitForClose() override; + virtual void start(); + virtual void terminate(bool ended); + virtual void waitForClose(); void awaken(); - virtual void setPriority(Priority pri) override; - virtual Priority getPriority() const override { return m_priority; } + void setPriority(ThreadPriority pri); + ThreadPriority getPriority() const { return m_priority; } void overwriteInternalThreadName(const char* name) noexcept; bool isCurrentThread() const noexcept; + protected: + virtual void tick() = 0; + + // NOTE: this should not be too long-lasted function, so no world loading, etc here!!! + virtual void onStart(); + virtual bool shouldExit() noexcept; + + private: + void run(); + static SPHERE_THREADENTRY_RETNTYPE SPHERE_THREADENTRY_CALLTYPE runner(void *callerThread); + + public: + static void setThreadName(const char* name); + bool closing() noexcept { return _fIsClosing; } -protected: - virtual void tick() = 0; - // NOTE: this should not be too long-lasted function, so no world loading, etc here!!! - virtual void onStart(); - virtual bool shouldExit() noexcept override; + static inline threadid_t getCurrentThreadSystemId() noexcept + { +#if defined(_WIN32) + return ::GetCurrentThreadId(); +#elif defined(__APPLE__) + // On OSX, 'threadid_t' is not an integer but a '_opaque_pthread_t *'), so we need to resort to another method. + uint64_t threadid = 0; + pthread_threadid_np(pthread_self(), &threadid); + return threadid; +#else + return pthread_self(); +#endif + } + static inline bool isSameThreadId(threadid_t firstId, threadid_t secondId) noexcept + { +#if defined(_WIN32) || defined(__APPLE__) + return (firstId == secondId); +#else + return pthread_equal(firstId,secondId); +#endif + } - private: - void run(); - static SPHERE_THREADENTRY_RETNTYPE SPHERE_THREADENTRY_CALLTYPE runner(void *callerThread); + inline bool isSameThread(threadid_t otherThreadId) const noexcept + { + return isSameThreadId(getCurrentThreadSystemId(), otherThreadId); + } }; @@ -289,7 +264,7 @@ class AbstractSphereThread : public AbstractThread #endif public: - AbstractSphereThread(const char *name, Priority priority = IThread::Normal); + AbstractSphereThread(const char *name, ThreadPriority priority = ThreadPriority::Normal); virtual ~AbstractSphereThread(); AbstractSphereThread(const AbstractSphereThread& copy) = delete; @@ -344,8 +319,9 @@ class ThreadHolder { friend class AbstractThread; - struct SphereThreadData { - IThread *m_ptr; + struct SphereThreadData + { + AbstractThread *m_ptr; bool m_closed; }; using spherethreadlist_t = std::vector; @@ -365,7 +341,7 @@ class ThreadHolder friend void Sphere_ExitServer(void); void markThreadsClosing() CANTHROW; - //SphereThreadData* findThreadData(IThread* thread) noexcept; + //SphereThreadData* findThreadData(AbstractThread* thread) noexcept; public: static constexpr lpctstr m_sClassName = "ThreadHolder"; @@ -373,14 +349,14 @@ class ThreadHolder static ThreadHolder& get() noexcept; bool closing() noexcept; - // returns current working thread or DummySphereThread * if no IThread threads are running - IThread *current() noexcept; + // returns current working thread or DummySphereThread * if no AbstractThread threads are running + AbstractThread *current() noexcept; // records a thread to the list. Sould NOT be called, internal usage - void push(IThread *thread) noexcept; + void push(AbstractThread *thread) noexcept; // removes a thread from the list. Sould NOT be called, internal usage - void remove(IThread *thread) CANTHROW; + void remove(AbstractThread *thread) CANTHROW; // returns thread at i pos - IThread * getThreadAt(size_t at) noexcept; + AbstractThread * getThreadAt(size_t at) noexcept; // returns number of running threads. Sould NOT be called, unit tests usage inline size_t getActiveThreads() noexcept { return m_threadCount; } From f28983e4b234e8240dc315f06088332970822dd9 Mon Sep 17 00:00:00 2001 From: cbnolok Date: Thu, 3 Oct 2024 17:11:30 +0200 Subject: [PATCH 69/86] Updated .clang-format/tidy. --- .clang-format | 2 +- .clang-tidy | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/.clang-format b/.clang-format index 1cc6ca616..b85f0ee08 100644 --- a/.clang-format +++ b/.clang-format @@ -76,7 +76,7 @@ PackConstructorInitializers: NextLineOnly PenaltyReturnTypeOnItsOwnLine: 200 # Prefer keeping return type on the same line if possible # Indentation settings -#AccessModifierOffset: -4 +AccessModifierOffset: -4 IndentAccessModifiers: false IndentCaseBlocks: false IndentCaseLabels: true diff --git a/.clang-tidy b/.clang-tidy index d051527da..cfd245271 100644 --- a/.clang-tidy +++ b/.clang-tidy @@ -57,6 +57,8 @@ Checks: > CheckOptions: - key: 'clang-analyzer-core.NonNullParamChecker:assert_like_macro' value: 'DEBUG_ASSERT,ASSERT,PERSISTANT_ASSERT' + - key: 'clang-analyzer-config:noreturn_function' + value: 'RaiseImmediateAbort,RaiseRecoverableAbort' - { key: readability-identifier-naming.NamespaceCase, value: lower_case } - { key: readability-identifier-naming.ClassCase, value: CamelCase } - { key: readability-identifier-naming.StructCase, value: CamelCase } From 03ce5f6cc30df81d3a652d640a04efd31bad5f25 Mon Sep 17 00:00:00 2001 From: cbnolok Date: Fri, 4 Oct 2024 17:09:51 +0200 Subject: [PATCH 70/86] Added CSString::SetValFalse/True to have a unified way of setting 0 or 1 as a return value. Fixed regression for FOLLOWERSLOTS. --- cmake/CompilerFlagsChecker.cmake | 2 +- src/common/CDataBase.cpp | 2 +- src/common/CScriptObj.cpp | 8 ++++---- src/common/CScriptTriggerArgs.cpp | 2 +- src/common/ListDefContMap.cpp | 2 +- src/common/sphere_library/CSString.cpp | 18 +++++++++++++---- src/common/sphere_library/CSString.h | 10 +++++++++ src/game/CObjBase.cpp | 6 +++--- src/game/CServerConfig.cpp | 14 ++++++------- src/game/chars/CChar.cpp | 28 ++++++++++++++++---------- src/game/chars/CCharNPC.cpp | 4 ++-- src/game/chars/CCharPlayer.cpp | 4 ++-- src/game/clients/CClientEvent.cpp | 12 +++++------ src/game/clients/CParty.cpp | 4 ++-- src/game/components/CCChampion.cpp | 2 +- src/game/components/CCMultiMovable.cpp | 2 +- src/game/components/CCSpawn.cpp | 2 +- src/game/items/CItem.cpp | 2 +- src/game/items/CItemBase.cpp | 2 +- src/game/items/CItemMulti.cpp | 2 +- src/game/items/CItemShip.cpp | 4 ++-- src/game/items/CItemStone.cpp | 8 ++++---- 22 files changed, 83 insertions(+), 57 deletions(-) diff --git a/cmake/CompilerFlagsChecker.cmake b/cmake/CompilerFlagsChecker.cmake index 7bfb40fe0..b0e183dc0 100644 --- a/cmake/CompilerFlagsChecker.cmake +++ b/cmake/CompilerFlagsChecker.cmake @@ -18,7 +18,7 @@ if(NOT MSVC) # Linker flags (warnings) #check_cxx_compiler_flag("-Wl,--fatal-warnings" COMP_LINKER_HAS_FATAL_WARNINGS_V1) - #check_cxx_compiler_flag("-Wl,-fatal-warnings" COMP_LINKER_HAS_FATAL_WARNINGS_V2) + #check_cxx_compiler_flag("-Wl,-fatal_warnings" COMP_LINKER_HAS_FATAL_WARNINGS_V2) if(CMAKE_CXX_COMPILER_ID STREQUAL "AppleClang") set(COMP_LINKER_HAS_FATAL_WARNINGS_V2 TRUE) else() diff --git a/src/common/CDataBase.cpp b/src/common/CDataBase.cpp index 4f56d3a34..909ee56c8 100644 --- a/src/common/CDataBase.cpp +++ b/src/common/CDataBase.cpp @@ -403,7 +403,7 @@ bool CDataBase::r_WriteVal(lpctstr ptcKey, CSString &sVal, CTextConsole *pSrc, b { ptcKey += strlen(sm_szLoadKeys[index]); GETNONWHITESPACE(ptcKey); - sVal.FormatVal(0); + sVal.SetValFalse(); if ( ptcKey[0] != '\0' ) { diff --git a/src/common/CScriptObj.cpp b/src/common/CScriptObj.cpp index 684109e4d..73c5d2575 100644 --- a/src/common/CScriptObj.cpp +++ b/src/common/CScriptObj.cpp @@ -496,7 +496,7 @@ bool CScriptObj::r_WriteVal( lpctstr ptcKey, CSString &sVal, CTextConsole * pSrc if (pRef == nullptr) { // Invalid ref: just return 0, it isn't an error. - sVal.FormatVal(0); + sVal.SetValFalse(); return true; } @@ -516,7 +516,7 @@ bool CScriptObj::r_WriteVal( lpctstr ptcKey, CSString &sVal, CTextConsole * pSrc if (pRef == nullptr) // good command but bad reference. { - sVal.FormatVal(0); + sVal.SetValFalse(); return false; } return pRef->r_WriteVal( ptcKey, sVal, pSrc ); @@ -667,7 +667,7 @@ bool CScriptObj::r_WriteVal( lpctstr ptcKey, CSString &sVal, CTextConsole * pSrc if ( pVar ) sVal = pVar->GetValStr(); else if ( fZero ) - sVal = "0"; + sVal.SetValFalse(); } return true; case SSC_RESDEF0: @@ -679,7 +679,7 @@ bool CScriptObj::r_WriteVal( lpctstr ptcKey, CSString &sVal, CTextConsole * pSrc if ( pVar ) sVal = pVar->GetValStr(); else if ( fZero ) - sVal = "0"; + sVal.SetValFalse(); } return true; case SSC_DEFMSG: diff --git a/src/common/CScriptTriggerArgs.cpp b/src/common/CScriptTriggerArgs.cpp index 698e1269b..f967d1d32 100644 --- a/src/common/CScriptTriggerArgs.cpp +++ b/src/common/CScriptTriggerArgs.cpp @@ -543,7 +543,7 @@ bool CScriptTriggerArgs::r_WriteVal( lpctstr ptcKey, CSString &sVal, CTextConsol if ( pObj ) sVal.FormatHex(pObj->GetUID()); else - sVal.FormatVal(0); + sVal.SetValFalse(); } break; case AGC_S: diff --git a/src/common/ListDefContMap.cpp b/src/common/ListDefContMap.cpp index d66757261..7d092eafb 100644 --- a/src/common/ListDefContMap.cpp +++ b/src/common/ListDefContMap.cpp @@ -268,7 +268,7 @@ bool CListDefCont::AddElementStr(lpctstr ptcKey) if ( (m_listElements.size() + 1) >= INTPTR_MAX ) // overflow? is it even useful? return false; - REMOVE_QUOTES( ptcKey ); + REMOVE_QUOTES( ptcKey ); m_listElements.emplace_back( new CListDefContStr(m_Key.GetBuffer(), ptcKey) ); diff --git a/src/common/sphere_library/CSString.cpp b/src/common/sphere_library/CSString.cpp index 8ae01f185..fdd3db4c9 100644 --- a/src/common/sphere_library/CSString.cpp +++ b/src/common/sphere_library/CSString.cpp @@ -103,9 +103,9 @@ bool CSString::IsValid() const noexcept int CSString::Resize(int iNewLength, bool fPreciseSize) { - if (iNewLength >= m_iMaxLength) + const bool fValid = IsValid(); + if ((iNewLength >= m_iMaxLength) || !fValid) { - const bool fValid = IsValid(); #ifdef DEBUG_STRINGS gMemAmount -= m_iMaxLength; #endif @@ -131,9 +131,9 @@ int CSString::Resize(int iNewLength, bool fPreciseSize) { const int iMinLength = 1 + minimum(iNewLength, m_iLength); Str_CopyLimitNull(pNewData, m_pchData, iMinLength); - delete[] m_pchData; } - pNewData[m_iLength] = '\0'; + if (fValid) + delete[] m_pchData; m_pchData = pNewData; } ASSERT(m_pchData); @@ -142,6 +142,16 @@ int CSString::Resize(int iNewLength, bool fPreciseSize) return m_iLength; } +void CSString::SetValFalse() +{ + Copy("0"); +} + +void CSString::SetValTrue() +{ + Copy("1"); +} + // CSString:: Element access diff --git a/src/common/sphere_library/CSString.h b/src/common/sphere_library/CSString.h index 5537b4015..ce0949e0a 100644 --- a/src/common/sphere_library/CSString.h +++ b/src/common/sphere_library/CSString.h @@ -214,6 +214,16 @@ class CSString */ void SetAt(int nIndex, tchar ch); + /** + * @brief Sets the string to an integer false value (0), usually handy for scripts return values. + */ + void SetValFalse(); + + /** + * @brief Sets the string to an integer true value (1), usually handy for scripts return values. + */ + void SetValTrue(); + ///@} /** @name Modifiers: diff --git a/src/game/CObjBase.cpp b/src/game/CObjBase.cpp index fdec42ab5..cecbdb93a 100644 --- a/src/game/CObjBase.cpp +++ b/src/game/CObjBase.cpp @@ -1132,10 +1132,10 @@ bool CObjBase::r_WriteVal( lpctstr ptcKey, CSString &sVal, CTextConsole * pSrc, if ( pChar ) sVal.FormatVal(bCanSee ? pChar->CanSee(pObj) : pChar->CanSeeLOS(pt, nullptr, pChar->GetVisualRange(), flags)); else - sVal.FormatVal(0); + sVal.SetValFalse(); } else if ( !pChar ) // no char -> no see - sVal.FormatVal(0); + sVal.SetValFalse(); else // standart way src TO current object sVal.FormatVal(bCanSee ? pChar->CanSee(this) : pChar->CanSeeLOS(this, (word)(flags))); } @@ -1199,7 +1199,7 @@ bool CObjBase::r_WriteVal( lpctstr ptcKey, CSString &sVal, CTextConsole * pSrc, GETNONWHITESPACE( ptcKey ); CClient * pThisClient = pSrc->GetChar() ? ( pSrc->GetChar()->IsClientActive() ? pSrc->GetChar()->GetClientActive() : nullptr ) : nullptr; - sVal.FormatVal(0); + sVal.SetValFalse(); if ( pThisClient ) { diff --git a/src/game/CServerConfig.cpp b/src/game/CServerConfig.cpp index 28bbb5a4c..2cf770e64 100644 --- a/src/game/CServerConfig.cpp +++ b/src/game/CServerConfig.cpp @@ -1632,7 +1632,7 @@ bool CServerConfig::r_WriteVal( lpctstr ptcKey, CSString & sVal, CTextConsole * if ( !strnicmp(ptcKey, "MAP(", 4) ) { ptcKey += 4; - sVal.FormatVal(0); + sVal.SetValFalse(); // Parse the arguments after the round brackets tchar * pszArgsNext; @@ -1691,7 +1691,7 @@ bool CServerConfig::r_WriteVal( lpctstr ptcKey, CSString & sVal, CTextConsole * lpctstr pszCmd = ptcKey + 8; int iNumber = Exp_GetVal(pszCmd); SKIP_SEPARATORS(pszCmd); - sVal.FormatVal(0); + sVal.SetValFalse(); if (!*pszCmd) { @@ -1738,7 +1738,7 @@ bool CServerConfig::r_WriteVal( lpctstr ptcKey, CSString & sVal, CTextConsole * ptcKey = ptcKey + 3; int iMapNumber = Exp_GetVal(ptcKey); SKIP_SEPARATORS(ptcKey); - sVal.FormatVal(0); + sVal.SetValFalse(); if ( g_MapList.IsMapSupported(iMapNumber) ) { @@ -1784,7 +1784,7 @@ bool CServerConfig::r_WriteVal( lpctstr ptcKey, CSString & sVal, CTextConsole * size_t iNumber = Exp_GetVal(pszCmd); SKIP_SEPARATORS(pszCmd); - sVal.FormatVal(0); + sVal.SetValFalse(); for (size_t i = 0; i < g_World.m_Multis.size(); ++i) { @@ -1832,7 +1832,7 @@ bool CServerConfig::r_WriteVal( lpctstr ptcKey, CSString & sVal, CTextConsole * int iNumber = Exp_GetVal(pszCmd); SKIP_SEPARATORS(pszCmd); - sVal.FormatVal(0); + sVal.SetValFalse(); if (iNumber < 0 || iNumber >= (int) m_Functions.size()) //invalid index can potentially crash the server, this check is strongly needed { @@ -1879,7 +1879,7 @@ bool CServerConfig::r_WriteVal( lpctstr ptcKey, CSString & sVal, CTextConsole * size_t iNumber = Exp_GetVal(pszCmd); SKIP_SEPARATORS(pszCmd); - sVal.FormatVal(0); + sVal.SetValFalse(); for ( size_t i = 0; i < g_World.m_Stones.size(); ++i ) { @@ -1914,7 +1914,7 @@ bool CServerConfig::r_WriteVal( lpctstr ptcKey, CSString & sVal, CTextConsole * if (cli_num >= g_Serv.StatGet( SERV_STAT_CLIENTS )) return false; - sVal.FormatVal(0); + sVal.SetValFalse(); ClientIterator it; for (CClient* pClient = it.next(); pClient != nullptr; pClient = it.next()) { diff --git a/src/game/chars/CChar.cpp b/src/game/chars/CChar.cpp index 37058219e..4a327c08a 100644 --- a/src/game/chars/CChar.cpp +++ b/src/game/chars/CChar.cpp @@ -2360,7 +2360,7 @@ bool CChar::r_WriteVal( lpctstr ptcKey, CSString & sVal, CTextConsole * pSrc, bo return true; } - sVal.FormatVal(0); + sVal.SetValFalse(); ptcKey += 11; if (*ptcKey != '.') return false; @@ -2373,7 +2373,7 @@ bool CChar::r_WriteVal( lpctstr ptcKey, CSString & sVal, CTextConsole * pSrc, bo } // Access objects by ID. - if (*ptcKey != '.' || m_followers.empty()) + if (m_followers.empty()) return false; const uint uiIndex = Exp_GetUVal(ptcKey); @@ -2384,6 +2384,12 @@ bool CChar::r_WriteVal( lpctstr ptcKey, CSString & sVal, CTextConsole * pSrc, bo if (!pCharArg) return false; + if (*ptcKey == '\0') + { + sVal.SetValTrue(); + return true; + } + if (pCharArg->r_WriteVal(ptcKey, sVal, pSrc, fNoCallParent, fNoCallChildren)) return true; @@ -2403,7 +2409,7 @@ bool CChar::r_WriteVal( lpctstr ptcKey, CSString & sVal, CTextConsole * pSrc, bo return true; } - sVal.FormatVal(0); + sVal.SetValFalse(); ptcKey += 8; if ( *ptcKey == '.' ) @@ -2525,7 +2531,7 @@ bool CChar::r_WriteVal( lpctstr ptcKey, CSString & sVal, CTextConsole * pSrc, bo return true; } - sVal.FormatVal(0); + sVal.SetValFalse(); ptcKey += 8; if ( *ptcKey == '.' ) @@ -2630,7 +2636,7 @@ bool CChar::r_WriteVal( lpctstr ptcKey, CSString & sVal, CTextConsole * pSrc, bo --i; } - sVal = "0"; + sVal.SetValFalse(); delete[] pszFameAt0; return true; } @@ -2726,7 +2732,7 @@ bool CChar::r_WriteVal( lpctstr ptcKey, CSString & sVal, CTextConsole * pSrc, bo --i; } - sVal = "0"; + sVal.SetValFalse(); delete[] pszKarmaAt0; return true; } @@ -2812,12 +2818,12 @@ bool CChar::r_WriteVal( lpctstr ptcKey, CSString & sVal, CTextConsole * pSrc, bo CResourceQtyArray Resources; if ( Resources.Load(ptcKey) > 0 && SkillResourceTest( &Resources ) ) { - sVal.FormatVal(1); + sVal.SetValTrue(); return true; } } } - sVal.FormatVal(0); + sVal.SetValFalse(); return true; case CHC_CANMOVE: { @@ -2840,7 +2846,7 @@ bool CChar::r_WriteVal( lpctstr ptcKey, CSString & sVal, CTextConsole * pSrc, bo if ( pItem ) sVal.FormatHex(pItem->m_itFigurine.m_UID); else - sVal.FormatVal(0); + sVal.SetValFalse(); return true; } case CHC_MOVE: @@ -2886,7 +2892,7 @@ bool CChar::r_WriteVal( lpctstr ptcKey, CSString & sVal, CTextConsole * pSrc, bo if ( m_pPlayer != nullptr ) sVal = ( m_pParty != nullptr ) ? "1" : "0"; else - sVal = "0"; + sVal.SetValFalse(); return true; case CHC_ISMYPET: if (!m_pNPC) @@ -2904,7 +2910,7 @@ bool CChar::r_WriteVal( lpctstr ptcKey, CSString & sVal, CTextConsole * pSrc, bo sVal = IsDisconnected() ? "0" : "1"; return true; } - sVal = "0"; + sVal.SetValFalse(); return true; case CHC_ISSTUCK: { diff --git a/src/game/chars/CCharNPC.cpp b/src/game/chars/CCharNPC.cpp index d6cb5a6ac..8f855ef37 100644 --- a/src/game/chars/CCharNPC.cpp +++ b/src/game/chars/CCharNPC.cpp @@ -206,12 +206,12 @@ bool CCharNPC::r_WriteVal( CChar * pChar, lpctstr ptcKey, CSString & sVal ) default: if ( FindTableHeadSorted( ptcKey, CCharPlayer::sm_szLoadKeys, CPC_QTY ) >= 0 ) { - sVal = "0"; + sVal.SetValFalse(); return true; } if ( FindTableSorted( ptcKey, CClient::sm_szLoadKeys, CC_QTY ) >= 0 ) { - sVal = "0"; + sVal.SetValFalse(); return true; } return(false ); diff --git a/src/game/chars/CCharPlayer.cpp b/src/game/chars/CCharPlayer.cpp index dad515de2..5fa0e5ba6 100644 --- a/src/game/chars/CCharPlayer.cpp +++ b/src/game/chars/CCharPlayer.cpp @@ -198,7 +198,7 @@ bool CCharPlayer::r_WriteVal( CChar * pChar, lpctstr ptcKey, CSString & sVal ) if ( pMyGuild ) sVal.FormatHex((dword)pMyGuild->GetUID()); else - sVal.FormatVal(0); + sVal.SetValFalse(); return true; } else if ( *ptcKey == '.' ) @@ -335,7 +335,7 @@ bool CCharPlayer::r_WriteVal( CChar * pChar, lpctstr ptcKey, CSString & sVal ) default: if ( FindTableSorted( ptcKey, CCharNPC::sm_szLoadKeys, CNC_QTY ) >= 0 ) { - sVal = "0"; + sVal.SetValFalse(); return true; } return false; diff --git a/src/game/clients/CClientEvent.cpp b/src/game/clients/CClientEvent.cpp index 5764f0635..84177d14d 100644 --- a/src/game/clients/CClientEvent.cpp +++ b/src/game/clients/CClientEvent.cpp @@ -2236,7 +2236,7 @@ bool CDialogResponseArgs::r_WriteVal( lpctstr ptcKey, CSString &sVal, CTextConso ptcKey += 6; SKIP_SEPARATORS(ptcKey); - size_t iQty = m_CheckArray.size(); + const size_t iQty = m_CheckArray.size(); if ( ptcKey[0] == '\0' ) { sVal.FormatSTVal(iQty); @@ -2254,17 +2254,17 @@ bool CDialogResponseArgs::r_WriteVal( lpctstr ptcKey, CSString &sVal, CTextConso return true; } - dword dwNum = Exp_GetDWSingle( ptcKey ); + const dword dwNum = Exp_GetDWSingle( ptcKey ); SKIP_SEPARATORS(ptcKey); for ( uint i = 0; i < iQty; ++i ) { if ( dwNum == m_CheckArray[i] ) { - sVal = "1"; + sVal.SetValTrue(); return true; } } - sVal = "0"; + sVal.SetValFalse(); return true; } if ( ! strnicmp( ptcKey, "ARGTXT", 6 )) @@ -2272,14 +2272,14 @@ bool CDialogResponseArgs::r_WriteVal( lpctstr ptcKey, CSString &sVal, CTextConso ptcKey += 6; SKIP_SEPARATORS(ptcKey); - size_t iQty = m_TextArray.size(); + const size_t iQty = m_TextArray.size(); if ( ptcKey[0] == '\0' ) { sVal.FormatSTVal(iQty); return true; } - dword dwNum = Exp_GetDWSingle( ptcKey ); + const dword dwNum = Exp_GetDWSingle( ptcKey ); SKIP_SEPARATORS(ptcKey); for ( uint i = 0; i < iQty; ++i ) diff --git a/src/game/clients/CParty.cpp b/src/game/clients/CParty.cpp index 0a4dfdf91..047eeece0 100644 --- a/src/game/clients/CParty.cpp +++ b/src/game/clients/CParty.cpp @@ -614,7 +614,7 @@ bool CPartyDef::r_WriteVal( lpctstr ptcKey, CSString &sVal, CTextConsole *pSrc, { if ( pRef == nullptr ) // good command but bad link. { - sVal = "0"; + sVal.SetValFalse(); return true; } if ( ptcKey[0] == '\0' ) // we where just testing the ref. @@ -623,7 +623,7 @@ bool CPartyDef::r_WriteVal( lpctstr ptcKey, CSString &sVal, CTextConsole *pSrc, if ( pObj ) sVal.FormatHex((dword)pObj->GetUID()); else - sVal.FormatVal(1); + sVal.SetValTrue(); return true; } return pRef->r_WriteVal(ptcKey, sVal, pSrc); diff --git a/src/game/components/CCChampion.cpp b/src/game/components/CCChampion.cpp index b3b7cf164..98266c28a 100644 --- a/src/game/components/CCChampion.cpp +++ b/src/game/components/CCChampion.cpp @@ -959,7 +959,7 @@ bool CCChampion::r_WriteVal(lpctstr ptcKey, CSString& sVal, CTextConsole* pSrc) } else { - sVal.FormatVal(0); + sVal.SetValFalse(); } break; } diff --git a/src/game/components/CCMultiMovable.cpp b/src/game/components/CCMultiMovable.cpp index 53666a36b..95c8efc01 100644 --- a/src/game/components/CCMultiMovable.cpp +++ b/src/game/components/CCMultiMovable.cpp @@ -1317,7 +1317,7 @@ bool CCMultiMovable::r_WriteVal(lpctstr ptcKey, CSString & sVal, CTextConsole * if (pItemThis->m_itShip.m_Pilot.IsValidUID()) sVal.FormatHex(pItemThis->m_itShip.m_Pilot); else - sVal.FormatVal(0); + sVal.SetValFalse(); } break; diff --git a/src/game/components/CCSpawn.cpp b/src/game/components/CCSpawn.cpp index 746397e29..12ddc0cda 100644 --- a/src/game/components/CCSpawn.cpp +++ b/src/game/components/CCSpawn.cpp @@ -865,7 +865,7 @@ bool CCSpawn::r_WriteVal(lpctstr ptcKey, CSString & sVal, CTextConsole *pSrc) } else { - sVal.FormatVal(0); + sVal.SetValFalse(); } return true; } diff --git a/src/game/items/CItem.cpp b/src/game/items/CItem.cpp index e4696be88..4c1277f08 100644 --- a/src/game/items/CItem.cpp +++ b/src/game/items/CItem.cpp @@ -2805,7 +2805,7 @@ bool CItem::r_WriteVal( lpctstr ptcKey, CSString & sVal, CTextConsole * pSrc, bo if ( id != GetDispID() ) sVal.FormatHex( id ); else - sVal.FormatVal(0); + sVal.SetValFalse(); } break; case IC_HEIGHT: diff --git a/src/game/items/CItemBase.cpp b/src/game/items/CItemBase.cpp index ad6fc1cf6..1d888e94a 100644 --- a/src/game/items/CItemBase.cpp +++ b/src/game/items/CItemBase.cpp @@ -1364,7 +1364,7 @@ bool CItemBase::r_WriteVal( lpctstr ptcKey, CSString & sVal, CTextConsole * pSrc return false; if ( !CCPropsItemWeapon::CanSubscribe(this)) - sVal.FormatVal(0); + sVal.SetValFalse(); else sVal.FormatVal( m_layer == LAYER_HAND2 ); break; diff --git a/src/game/items/CItemMulti.cpp b/src/game/items/CItemMulti.cpp index e4b8c7b87..01cf07eca 100644 --- a/src/game/items/CItemMulti.cpp +++ b/src/game/items/CItemMulti.cpp @@ -2690,7 +2690,7 @@ bool CItemMulti::r_WriteVal(lpctstr ptcKey, CSString & sVal, CTextConsole * pSrc break; } } - sVal.FormatVal(0); + sVal.SetValFalse(); break; } case SHL_REGION: diff --git a/src/game/items/CItemShip.cpp b/src/game/items/CItemShip.cpp index 620a02209..db9bea489 100644 --- a/src/game/items/CItemShip.cpp +++ b/src/game/items/CItemShip.cpp @@ -158,7 +158,7 @@ bool CItemShip::r_WriteVal(lpctstr ptcKey, CSString & sVal, CTextConsole * pSrc, if (pItemHold) sVal.FormatHex(pItemHold->GetUID()); else - sVal.FormatVal(0); + sVal.SetValFalse(); } break; case IMCS_PLANK: @@ -174,7 +174,7 @@ bool CItemShip::r_WriteVal(lpctstr ptcKey, CSString & sVal, CTextConsole * pSrc, if (pTiller) sVal.FormatHex(pTiller->GetUID()); else - sVal.FormatVal(0); + sVal.SetValFalse(); } break; default: diff --git a/src/game/items/CItemStone.cpp b/src/game/items/CItemStone.cpp index 506f95078..3a51112bf 100644 --- a/src/game/items/CItemStone.cpp +++ b/src/game/items/CItemStone.cpp @@ -492,7 +492,7 @@ bool CItemStone::r_WriteVal( lpctstr ptcKey, CSString & sVal, CTextConsole * pSr SKIP_SEPARATORS(pszCmd); CStoneMember * pMember = static_cast (GetContainerHead()); - sVal.FormatVal(0); + sVal.SetValFalse(); for ( int i = 0 ; pMember != nullptr; pMember = pMember->GetNext() ) { @@ -515,7 +515,7 @@ bool CItemStone::r_WriteVal( lpctstr ptcKey, CSString & sVal, CTextConsole * pSr else if ( !strnicmp("memberfromuid.", ptcKey, 14) ) { lpctstr pszCmd = ptcKey + 14; - sVal.FormatVal(0); + sVal.SetValFalse(); if ( !pszCmd[0] ) return true; @@ -580,7 +580,7 @@ bool CItemStone::r_WriteVal( lpctstr ptcKey, CSString & sVal, CTextConsole * pSr SKIP_SEPARATORS(pszCmd); CStoneMember * pMember = static_cast (GetContainerHead()); - sVal.FormatVal(0); + sVal.SetValFalse(); for ( int i = 0 ; pMember != nullptr; pMember = pMember->GetNext() ) { @@ -603,7 +603,7 @@ bool CItemStone::r_WriteVal( lpctstr ptcKey, CSString & sVal, CTextConsole * pSr else if ( !strnicmp("guildfromuid.", ptcKey, 13) ) { lpctstr pszCmd = ptcKey + 13; - sVal.FormatVal(0); + sVal.SetValFalse(); if ( !pszCmd[0] ) return true; From 08db71d5450ebff064c10f6178da596e80019b86 Mon Sep 17 00:00:00 2001 From: cbnolok Date: Fri, 4 Oct 2024 17:56:02 +0200 Subject: [PATCH 71/86] Fixed status updates to client not happening if the death process was aborted. --- src/game/CWorldTicker.cpp | 12 ++++++- src/game/chars/CChar.h | 22 +++++++++--- src/game/chars/CCharAct.cpp | 67 +++++++++++++++++++++++++------------ 3 files changed, 73 insertions(+), 28 deletions(-) diff --git a/src/game/CWorldTicker.cpp b/src/game/CWorldTicker.cpp index 31c6af85c..659c4e4cc 100644 --- a/src/game/CWorldTicker.cpp +++ b/src/game/CWorldTicker.cpp @@ -167,7 +167,6 @@ void CWorldTicker::_InsertCharTicking(const int64 iTickNext, CChar* pChar) std::unique_lock lock(_mCharTickList.MT_CMUTEX); #endif - _mCharTickList.emplace(iTickNext, pChar); pChar->_iTimePeriodicTick = iTickNext; } @@ -228,7 +227,18 @@ void CWorldTicker::AddCharTicking(CChar* pChar, bool fNeedsLock) } if (iTickNext == iTickOld) + { +/* +#ifdef _DEBUG + auto it = std::find_if(_mCharTickList.begin(), _mCharTickList.end(), + [pChar](const std::pair& elem) { + return elem.second == pChar; + }); + DEBUG_ASSERT(it == _mCharTickList.end()); +#endif +*/ return; + } //if (iTickNext < CWorldGameTime::GetCurrentTime().GetTimeRaw()) // We do that to get them tick as sooner as possible // return; diff --git a/src/game/chars/CChar.h b/src/game/chars/CChar.h index 67580ceab..3ea4fa13f 100644 --- a/src/game/chars/CChar.h +++ b/src/game/chars/CChar.h @@ -1177,16 +1177,28 @@ public: void StatFlag_Mod(uint64 uiStatFlag, bool fMod) noexcept; virtual void Update(const CClient* pClientExclude = nullptr) override; virtual void Flip() override; + + void EatAnim(CItem* pItem, ushort uiQty); + bool Reveal( uint64 iFlags = 0 ); + void Jail( CTextConsole * pSrc, bool fSet, int iCell ); bool SetPoison( int iSkill, int iHits, CChar * pCharSrc ); bool SetPoisonCure( bool fExtra ); bool CheckCorpseCrime( CItemCorpse *pCorpse, bool fLooting, bool fTest ); CItemCorpse * FindMyCorpse( bool fIgnoreLOS = false, int iRadius = 2) const; CItemCorpse * MakeCorpse( bool fFrontFall ); - bool RaiseCorpse( CItemCorpse * pCorpse ); - bool Death(); - bool Reveal( uint64 iFlags = 0 ); - void Jail( CTextConsole * pSrc, bool fSet, int iCell ); - void EatAnim(CItem* pItem, ushort uiQty); + bool RaiseCorpse( CItemCorpse * pCorpse ); + + enum class DeathRequestResult + { + Success, + SuccessAndDelete, + AlreadyDead, + Aborted, + AbortedNoLog + }; + + DeathRequestResult Death(); + /** * @Brief I'm calling guards (Player speech) * diff --git a/src/game/chars/CCharAct.cpp b/src/game/chars/CCharAct.cpp index 897a1e55d..e8d4c8269 100644 --- a/src/game/chars/CCharAct.cpp +++ b/src/game/chars/CCharAct.cpp @@ -4285,20 +4285,20 @@ void CChar::SleepStart( bool fFrontFall ) // Cleaning myself (dispel, cure, dismounting ...). // Creating the corpse ( MakeCorpse() ). // Removing myself from view, generating Death packets. -// RETURN: -// true = successfully died -// false = something went wrong? i'm an NPC, just delete (excepting BONDED ones). -bool CChar::Death() +CChar::DeathRequestResult CChar::Death() { ADDTOCALLSTACK("CChar::Death"); - if ( IsStatFlag(STATF_DEAD|STATF_INVUL) ) - return true; + if ( IsStatFlag(STATF_DEAD) ) + return DeathRequestResult::AlreadyDead; + + if ( IsStatFlag(STATF_INVUL) ) + return DeathRequestResult::AbortedNoLog; if ( IsTrigUsed(TRIGGER_DEATH) ) { if ( OnTrigger(CTRIG_Death, this) == TRIGRET_RET_TRUE ) - return true; + return DeathRequestResult::Aborted; } //Dismount now. Later is may be too late and cause problems if ( m_pNPC ) @@ -4353,7 +4353,8 @@ bool CChar::Death() iKillStrLen += snprintf( pszKillStr + iKillStrLen, Str_TempLength() - iKillStrLen, "%s%c'%s'.", - iKillers ? ", " : "", (pKiller->m_pPlayer) ? 'P':'N', pKiller->GetNameWithoutIncognito() ); + iKillers ? ", " : "", + (pKiller->m_pPlayer) ? 'P':'N', pKiller->GetNameWithoutIncognito() ); ++iKillers; } @@ -4361,7 +4362,7 @@ bool CChar::Death() // Record the kill event for posterity if ( !iKillers ) - iKillStrLen += snprintf( pszKillStr + iKillStrLen, Str_TempLength() - iKillStrLen, "accident." ); + /*iKillStrLen +=*/ snprintf( pszKillStr + iKillStrLen, Str_TempLength() - iKillStrLen, "accident." ); if ( m_pPlayer ) g_Log.Event( LOGL_EVENT|LOGM_KILLS, "%s\n", pszKillStr ); if ( m_pParty ) @@ -4385,7 +4386,7 @@ bool CChar::Death() } // Create the corpse item - bool fFrontFall = g_Rand.GetVal(2); + bool fFrontFall = g_Rand.GetValFast(2); CItemCorpse * pCorpse = MakeCorpse(fFrontFall); if ( pCorpse ) { @@ -4406,14 +4407,14 @@ bool CChar::Death() { m_CanMask |= CAN_C_GHOST; UpdateMode(nullptr, true); - return true; + return DeathRequestResult::Success; } if ( pCorpse ) pCorpse->m_uidLink.InitUID(); NPC_PetClearOwners(); - return false; // delete the NPC + return DeathRequestResult::SuccessAndDelete; // delete the NPC } if ( m_pPlayer ) @@ -4495,7 +4496,7 @@ bool CChar::Death() } } - return true; + return DeathRequestResult::Success; } // Check if we are held in place. @@ -5916,8 +5917,26 @@ bool CChar::OnTickPeriodic() */ if (!IsStatFlag(STATF_DEAD) && (Stat_GetVal(STAT_STR) <= 0)) { - EXC_SET_BLOCK("death"); - return Death(); + EXC_SET_BLOCK("death?"); + const DeathRequestResult deathRes = Death(); + if ((deathRes != DeathRequestResult::Aborted) && (deathRes != DeathRequestResult::AbortedNoLog)) + { + if (deathRes == DeathRequestResult::AlreadyDead) + goto do_status_update; + if (deathRes == DeathRequestResult::SuccessAndDelete) + return false; + return true; + } + else + { +#ifdef _DEBUG + if (deathRes != DeathRequestResult::AbortedNoLog) + { + g_Log.EventEvent("Aborted char '%s' (0x%" PRIx32 " ) death.\n", GetName(), GetUID().GetObjUID()); + } +#endif + ; // Then, fall through. + } } // Stats regeneration @@ -5935,18 +5954,21 @@ bool CChar::OnTickPeriodic() if (IsClientActive()) { CClient* pClient = GetClientActive(); + // Players have a silly "always run" flag that gets stuck on. if ( (iTimeCur - pClient->m_timeLastEventWalk) > (2 * MSECS_PER_TENTH) ) { StatFlag_Clear(STATF_FLY); } - // Show returning anim for thowing weapons after throw it - if ((pClient->m_timeLastSkillThrowing > 0) && ((iTimeCur - pClient->m_timeLastSkillThrowing) > (2 * MSECS_PER_TENTH))) - { - pClient->m_timeLastSkillThrowing = 0; - if (pClient->m_pSkillThrowingTarg->IsValidUID()) - Effect(EFFECT_BOLT, pClient->m_SkillThrowingAnimID, pClient->m_pSkillThrowingTarg, 18, 1, false, pClient->m_SkillThrowingAnimHue, pClient->m_SkillThrowingAnimRender); - } + + // Show returning anim for thowing weapons after throw it + if ((pClient->m_timeLastSkillThrowing > 0) && ((iTimeCur - pClient->m_timeLastSkillThrowing) > (2 * MSECS_PER_TENTH))) + { + pClient->m_timeLastSkillThrowing = 0; + if (pClient->m_pSkillThrowingTarg->IsValidUID()) + Effect(EFFECT_BOLT, pClient->m_SkillThrowingAnimID, pClient->m_pSkillThrowingTarg, 18, 1, false, pClient->m_SkillThrowingAnimHue, pClient->m_SkillThrowingAnimRender); + } + // Check targeting timeout, if set if ((pClient->m_Targ_Timeout > 0) && ((iTimeCur - pClient->m_Targ_Timeout) > 0) ) { @@ -5961,6 +5983,7 @@ bool CChar::OnTickPeriodic() CheckLocationEffects(true); } +do_status_update: EXC_SET_BLOCK("update stats"); OnTickStatusUpdate(); EXC_CATCH; From 17ccf65639b15eb63a9df926d8af47987eaed2b3 Mon Sep 17 00:00:00 2001 From: cbnolok Date: Fri, 4 Oct 2024 19:40:13 +0200 Subject: [PATCH 72/86] Refactored Windows SEH handling. --- src/common/CException.cpp | 36 ++++++++++++++++++------------------ src/common/CException.h | 25 +++++++++++++++++-------- src/game/spheresvr.cpp | 9 ++------- src/sphere/threads.cpp | 4 ++++ 4 files changed, 41 insertions(+), 33 deletions(-) diff --git a/src/common/CException.cpp b/src/common/CException.cpp index 5dcd8beac..6cb0b57c3 100644 --- a/src/common/CException.cpp +++ b/src/common/CException.cpp @@ -1,6 +1,10 @@ #include "CException.h" +#ifdef WINDOWS_SHOULD_EMIT_CRASH_DUMP +#include "crashdump/crashdump.h" +#endif + #ifndef _WIN32 #include //#include // for pthread_exit @@ -66,6 +70,7 @@ static bool* _GetAbortImmediate() noexcept static bool _fIsAbortImmediate = true; return &_fIsAbortImmediate; } + void SetAbortImmediate(bool on) noexcept { *_GetAbortImmediate() = on; @@ -84,6 +89,7 @@ void RaiseRecoverableAbort() SetAbortImmediate(false); std::abort(); } + [[noreturn]] void RaiseImmediateAbort() { @@ -189,16 +195,16 @@ bool CAssert::GetErrorMessage(lptstr lpszError, uint uiMaxError) const #ifdef _WIN32 -CWinException::CWinException(uint uCode, size_t pAddress) : +CWinStructuredException::CWinStructuredException(uint uCode, size_t pAddress) : CSError(LOGL_CRIT, uCode, "Exception"), m_pAddress(pAddress) { } -CWinException::~CWinException() +CWinStructuredException::~CWinStructuredException() { } -bool CWinException::GetErrorMessage(lptstr lpszError, uint uiMaxError) const +bool CWinStructuredException::GetErrorMessage(lptstr lpszError, uint uiMaxError) const { lpctstr zMsg; switch ( m_hError ) @@ -238,7 +244,7 @@ static void _cdecl Sphere_Purecall_Handler() void SetPurecallHandler() { // We don't want sphere to immediately exit if something calls a pure virtual method. -#ifdef MSVC_RUNTIME +#ifdef MSVC_COMPILER _set_purecall_handler(Sphere_Purecall_Handler); #else // GCC handler for pure calls is __cxxabiv1::__cxa_pure_virtual. @@ -247,34 +253,28 @@ void SetPurecallHandler() #endif } -#if defined(_WIN32) && !defined(_DEBUG) - -#include "crashdump/crashdump.h" - -static void _cdecl Sphere_Exception_Windows( unsigned int id, struct _EXCEPTION_POINTERS* pData ) +#ifdef WINDOWS_SEH_EXCEPTION_MODEL +static void _cdecl Sphere_Structured_Exception_Windows( unsigned int id, struct _EXCEPTION_POINTERS* pData ) { -#ifndef _NO_CRASHDUMP +# ifdef WINDOWS_SHOULD_EMIT_CRASH_DUMP if ( CrashDump::IsEnabled() ) CrashDump::StartCrashDump(GetCurrentProcessId(), GetCurrentThreadId(), pData); +# endif -#endif // WIN32 gets an exception. size_t pCodeStart = (size_t)(byte *) &globalstartsymbol; // sync up to my MAP file. size_t pAddr = (size_t)pData->ExceptionRecord->ExceptionAddress; pAddr -= pCodeStart; - throw CWinException(id, pAddr); + throw CWinStructuredException(id, pAddr); } -#endif // _WIN32 && !_DEBUG - -void SetExceptionTranslator() +void SetWindowsStructuredExceptionTranslator() { -#ifdef MSVC_COMPILER - _set_se_translator( Sphere_Exception_Windows ); -#endif + _set_se_translator( Sphere_Structured_Exception_Windows ); } +#endif #ifndef _WIN32 static void _cdecl Signal_Hangup(int sig = 0) noexcept // If shutdown is initialized diff --git a/src/common/CException.h b/src/common/CException.h index 99543be87..71e8464d2 100644 --- a/src/common/CException.h +++ b/src/common/CException.h @@ -9,6 +9,17 @@ //#include "../sphere/threads.h" #include "CLog.h" +#if defined(_WIN32) && (defined(MSVC_COMPILER) || (defined(__MINGW32__) && defined(__SEH__))) +# define WINDOWS_SEH_EXCEPTION_MODEL 1 +#endif + +#if defined(WINDOWS_SEH_EXCEPTION_MODEL) && defined(_NIGHTLYBUILD) && !defined(_NO_CRASHDUMP) +// We don't want this for Release build because, in order to call _set_se_translator, we should set the /EHa +// compiler flag, which slows down code a bit. +// Also, the crash dump generating code works only when Structured Exception Handling is enabled +# define WINDOWS_SHOULD_EMIT_CRASH_DUMP 1 +#endif + // ------------------------------------------------------------------- // ------------------------------------------------------------------- @@ -18,7 +29,7 @@ extern "C" } void SetPurecallHandler(); -void SetExceptionTranslator(); +void SetWindowsStructuredExceptionTranslator(); #ifndef _WIN32 void SetUnixSignals( bool ); @@ -79,20 +90,18 @@ class CAssert : public CSError virtual bool GetErrorMessage(lptstr lpszError, uint uiMaxError ) const override; }; -#ifdef _WIN32 +#ifdef WINDOWS_SEH_EXCEPTION_MODEL // Catch and get details on the system exceptions. - class CWinException : public CSError + class CWinStructuredException : public CSError { public: static const char *m_sClassName; const size_t m_pAddress; - CWinException(uint uCode, size_t pAddress); - virtual ~CWinException(); - private: - CWinException& operator=(const CWinException& other); + CWinStructuredException(uint uCode, size_t pAddress); + virtual ~CWinStructuredException(); + CWinStructuredException& operator=(const CWinStructuredException& other) = delete; - public: virtual bool GetErrorMessage(lptstr lpszError, uint nMaxError) const override; }; #endif diff --git a/src/game/spheresvr.cpp b/src/game/spheresvr.cpp index 38b696f56..be7f4c857 100644 --- a/src/game/spheresvr.cpp +++ b/src/game/spheresvr.cpp @@ -71,12 +71,8 @@ GlobalInitializer::GlobalInitializer() //--- Exception handling - // Set exception catcher? -#if defined(MSVC_COMPILER) && !defined(_NIGHTLYBUILD) - // We don't need an exception translator for the Debug build, since that build would, generally, be used with a debugger. - // We don't want that for Release build either because, in order to call _set_se_translator, we should set the /EHa - // compiler flag, which slows down code a bit. - SetExceptionTranslator(); +#ifdef WINDOWS_SEH_EXCEPTION_MODEL + SetWindowsStructuredExceptionTranslator(); #endif // Set function to handle the invalid case where a pure virtual function is called. @@ -192,7 +188,6 @@ MainThread::MainThread() void MainThread::onStart() { AbstractSphereThread::onStart(); - SetExceptionTranslator(); } void MainThread::tick() diff --git a/src/sphere/threads.cpp b/src/sphere/threads.cpp index 9eb3d26f6..7c9306885 100644 --- a/src/sphere/threads.cpp +++ b/src/sphere/threads.cpp @@ -643,6 +643,10 @@ void AbstractThread::onStart() // when implemented in derived classes this method must always be called too, preferably before // the custom implementation +#ifdef WINDOWS_SEH_EXCEPTION_MODEL + SetWindowsStructuredExceptionTranslator(); +#endif + // we set the id here to ensure it is available before the first tick, otherwise there's // a small delay when setting it from AbstractThread::start and it's possible for the id // to not be set fast enough (particular when using pthreads) From af6516e5884168436385f31d9d0495a0384474b7 Mon Sep 17 00:00:00 2001 From: cbnolok Date: Sat, 5 Oct 2024 11:51:42 +0200 Subject: [PATCH 73/86] Fixed Windows compilation warning on Debug build, refactored _MAX_PATH. --- README.md | 4 ++-- src/common/CException.cpp | 4 ++-- src/common/CException.h | 12 +++++++--- src/common/CLog.cpp | 4 +--- src/common/CLog.h | 2 -- src/common/CScript.cpp | 8 +++---- src/common/CUOInstall.cpp | 2 +- src/common/CVarDefMap.cpp | 1 - src/common/common.h | 3 ++- src/common/os_unix.h | 22 +++++++++++++++--- src/common/os_windows.h | 12 +++++++++- src/common/resource/CResourceHolder.cpp | 12 +++++----- src/common/resource/CResourceHolder.h | 7 ------ src/common/resource/CResourceRef.cpp | 10 ++++++-- src/common/resource/sections/CWebPageDef.cpp | 6 ++--- src/common/sphere_library/CSFile.cpp | 2 +- src/common/sphere_library/CSFileList.cpp | 12 +++++----- src/common/sphere_library/CSWindow.cpp | 2 +- src/game/CServer.cpp | 24 ++++++++++---------- src/game/CServerConfig.cpp | 8 +++---- src/game/CWorld.cpp | 16 ++++++------- src/game/CWorldImport.cpp | 4 ++-- src/game/chars/CCharAct.cpp | 4 ++-- src/game/clients/CAccount.cpp | 6 ++--- src/game/clients/CClientLog.cpp | 4 ++-- src/game/clients/CClientMsg.cpp | 4 ++-- src/game/spheresvr.cpp | 2 +- src/sphere/ntservice.cpp | 2 +- src/sphere/ntwindow.cpp | 4 ++-- src/sphere/threads.cpp | 2 +- 30 files changed, 116 insertions(+), 89 deletions(-) diff --git a/README.md b/README.md index 67aabfb3a..d2f5e46fa 100644 --- a/README.md +++ b/README.md @@ -72,7 +72,7 @@ Most notable changes (right now) are: ### Required libraries (Windows) -+ `libmariadb.dll` (MariaDB Client v10.*package), found in `lib/bin/*cpu_architecture*/mariadb/libmariadb.dll` ++ `libmariadb.dll` (MariaDB Client v10.\* package), found in `lib/bin/*cpu_architecture*/mariadb/libmariadb.dll` ### Required libraries (Linux) @@ -156,7 +156,7 @@ Building will require more packages than the ones needed to run Sphere. #### Compiling on Linux -Just run the `make` command inside the `build` folder. You can pass the -jX argument (`make -jX`, where X is a number) to speed up the compilation and split the work between X threads. +Just run `cmake --build .` in the build directory (the one where you have asked CMake to create its files). ## Coding Notes (add as you wish to standardize the coding for new contributors) diff --git a/src/common/CException.cpp b/src/common/CException.cpp index 6cb0b57c3..202463459 100644 --- a/src/common/CException.cpp +++ b/src/common/CException.cpp @@ -193,7 +193,7 @@ bool CAssert::GetErrorMessage(lptstr lpszError, uint uiMaxError) const // -------------------------------------------------------------------------------- // -------------------------------------------------------------------------------- -#ifdef _WIN32 +#ifdef WINDOWS_SPHERE_SHOULD_HANDLE_STRUCTURED_EXCEPTIONS CWinStructuredException::CWinStructuredException(uint uCode, size_t pAddress) : CSError(LOGL_CRIT, uCode, "Exception"), m_pAddress(pAddress) @@ -253,7 +253,7 @@ void SetPurecallHandler() #endif } -#ifdef WINDOWS_SEH_EXCEPTION_MODEL +#ifdef WINDOWS_SPHERE_SHOULD_HANDLE_STRUCTURED_EXCEPTIONS static void _cdecl Sphere_Structured_Exception_Windows( unsigned int id, struct _EXCEPTION_POINTERS* pData ) { # ifdef WINDOWS_SHOULD_EMIT_CRASH_DUMP diff --git a/src/common/CException.h b/src/common/CException.h index 71e8464d2..b141afcd3 100644 --- a/src/common/CException.h +++ b/src/common/CException.h @@ -10,12 +10,16 @@ #include "CLog.h" #if defined(_WIN32) && (defined(MSVC_COMPILER) || (defined(__MINGW32__) && defined(__SEH__))) -# define WINDOWS_SEH_EXCEPTION_MODEL 1 +# define WINDOWS_HAS_SEH 1 #endif -#if defined(WINDOWS_SEH_EXCEPTION_MODEL) && defined(_NIGHTLYBUILD) && !defined(_NO_CRASHDUMP) +#if defined (WINDOWS_HAS_SEH) && defined(_NIGHTLYBUILD) // We don't want this for Release build because, in order to call _set_se_translator, we should set the /EHa // compiler flag, which slows down code a bit. +# define WINDOWS_SPHERE_SHOULD_HANDLE_STRUCTURED_EXCEPTIONS 1 +#endif + +#if defined(WINDOWS_SPHERE_SHOULD_HANDLE_STRUCTURED_EXCEPTIONS) && !defined(_NO_CRASHDUMP) // Also, the crash dump generating code works only when Structured Exception Handling is enabled # define WINDOWS_SHOULD_EMIT_CRASH_DUMP 1 #endif @@ -29,7 +33,9 @@ extern "C" } void SetPurecallHandler(); +#ifdef WINDOWS_SPHERE_SHOULD_HANDLE_STRUCTURED_EXCEPTIONS void SetWindowsStructuredExceptionTranslator(); +#endif #ifndef _WIN32 void SetUnixSignals( bool ); @@ -90,7 +96,7 @@ class CAssert : public CSError virtual bool GetErrorMessage(lptstr lpszError, uint uiMaxError ) const override; }; -#ifdef WINDOWS_SEH_EXCEPTION_MODEL +#ifdef WINDOWS_SPHERE_SHOULD_HANDLE_STRUCTURED_EXCEPTIONS // Catch and get details on the system exceptions. class CWinStructuredException : public CSError { diff --git a/src/common/CLog.cpp b/src/common/CLog.cpp index 4e90575ae..926dde738 100644 --- a/src/common/CLog.cpp +++ b/src/common/CLog.cpp @@ -75,7 +75,6 @@ int CEventLog::EventCustom(ConsoleTextColor iColor, dword dwMask, lpctstr pszFor return iret; } -#ifdef _DEBUG int CEventLog::EventEvent(lpctstr pszFormat, ...) noexcept { va_list vargs; @@ -84,7 +83,6 @@ int CEventLog::EventEvent(lpctstr pszFormat, ...) noexcept va_end(vargs); return iret; } -#endif //_DEBUG //------- @@ -265,7 +263,7 @@ int CLog::EventStr( dword dwMask, lpctstr pszMsg, ConsoleTextColor iLogColor) no } // Get the script context. (if there is one) - tchar szScriptContext[ _MAX_PATH + 16 ]; + tchar szScriptContext[ SPHERE_MAX_PATH + 16 ]; if ( !(dwMask & LOGM_NOCONTEXT) && m_pScriptContext ) { CScriptLineContext LineContext = m_pScriptContext->GetContext(); diff --git a/src/common/CLog.h b/src/common/CLog.h index a362e5ccc..fbb650620 100644 --- a/src/common/CLog.h +++ b/src/common/CLog.h @@ -71,9 +71,7 @@ class CEventLog int _cdecl EventError(lpctstr pszFormat, ...) noexcept __printfargs(2,3); int _cdecl EventWarn(lpctstr pszFormat, ...) noexcept __printfargs(2,3); int _cdecl EventCustom(ConsoleTextColor iColor, dword dwMask, lpctstr pszFormat, ...) noexcept __printfargs(4,5); -#ifdef _DEBUG int _cdecl EventEvent( lpctstr pszFormat, ... ) noexcept __printfargs(2,3); -#endif //_DEBUG CEventLog(); virtual ~CEventLog(); diff --git a/src/common/CScript.cpp b/src/common/CScript.cpp index 645ad19a0..352bc1680 100644 --- a/src/common/CScript.cpp +++ b/src/common/CScript.cpp @@ -374,7 +374,7 @@ bool CScriptKeyAlloc::ParseKey( lpctstr ptcKey, lpctstr pszVal ) if (ptcKey != m_pszKey) { // Invalid key, or not yet inited. - strcpy(m_pszKey, ptcKey); + Str_CopyLimitNull(m_pszKey, ptcKey, m_Mem.GetDataLength()); } m_pszArg = m_pszKey + lenkey; @@ -490,9 +490,9 @@ bool CScript::_Open( lpctstr ptcFilename, uint uiFlags ) lpctstr ptcExt = GetFilesExt(ptcFilename); if ( !ptcExt ) { - tchar ptcTemp[_MAX_PATH]; - Str_CopyLimit(ptcTemp, ptcFilename, _MAX_PATH-4); // -4 beause of SPHERE_SCRIPT, which is = ".scp" - strcat(ptcTemp, SPHERE_SCRIPT); + tchar ptcTemp[SPHERE_MAX_PATH]; + const size_t uiCopied = Str_CopyLimit(ptcTemp, ptcFilename, sizeof(ptcTemp) - SPHERE_SCRIPT_EXT_LEN); + Str_ConcatLimitNull(ptcTemp, SPHERE_SCRIPT_EXT, sizeof(ptcTemp) - uiCopied); _SetFilePath(ptcTemp); uiFlags |= OF_TEXT; } diff --git a/src/common/CUOInstall.cpp b/src/common/CUOInstall.cpp index 2240ced2c..f09727661 100644 --- a/src/common/CUOInstall.cpp +++ b/src/common/CUOInstall.cpp @@ -58,7 +58,7 @@ bool CUOInstall::FindInstall() return false; } - tchar szValue[ _MAX_PATH ]; + tchar szValue[ SPHERE_MAX_PATH ]; DWORD lSize = sizeof( szValue ); DWORD dwType = REG_SZ; lRet = RegQueryValueEx(hKey, "ExePath", nullptr, &dwType, (byte*)szValue, &lSize); diff --git a/src/common/CVarDefMap.cpp b/src/common/CVarDefMap.cpp index 3e99fae28..09d2b452b 100644 --- a/src/common/CVarDefMap.cpp +++ b/src/common/CVarDefMap.cpp @@ -2,7 +2,6 @@ #include "../common/CLog.h" #include "../game/CServer.h" #include "../game/CServerConfig.h" -#include "CException.h" #include "CExpression.h" #include "CScript.h" #include "CTextConsole.h" diff --git a/src/common/common.h b/src/common/common.h index fdf5a2f9e..deb52d81e 100644 --- a/src/common/common.h +++ b/src/common/common.h @@ -12,7 +12,8 @@ #define SPHERE_FILE "sphere" // file name prefix #define SPHERE_TITLE "SphereServer" -#define SPHERE_SCRIPT ".scp" +#define SPHERE_SCRIPT_EXT ".scp" +#define SPHERE_SCRIPT_EXT_LEN 4 #define SCRIPT_MAX_LINE_LEN 4096 // default size. #define SCRIPT_MAX_SECTION_LEN 128 diff --git a/src/common/os_unix.h b/src/common/os_unix.h index 684fba9ad..492ce9cd7 100644 --- a/src/common/os_unix.h +++ b/src/common/os_unix.h @@ -6,21 +6,37 @@ #ifndef _INC_OS_UNIX_H #define _INC_OS_UNIX_H +//#include // PATH_MAX #include // usleep #include // toupper, tolower //#define SLASH_PATH "/" -#ifndef _MAX_PATH // stdlib.h ? - #define _MAX_PATH 260 // max. length of full pathname + +// Max. length of full pathname + +/* +#if defined(PATH_MAX) // limits.h +# if PATH_MAX <= 0 +# define SPHERE_MAX_PATH 260 +# elif PATH_MAX > 1024 +# define SPHERE_MAX_PATH 1024 // Define a "big enough" max value, just to avoid the need of enormous char buffers. +# else +# define SPHERE_MAX_PATH PATH_MAX +# endif +#else +// If we want to keep compatibility with legacy Windows max path length. +# define SPHERE_MAX_PATH 260 #endif +*/ +// TODO: enable longer MAX_PATHs on both Linux and Windows, also checking that increasing that limit doesn't cause any buffer overflow. +#define SPHERE_MAX_PATH 260 #define _cdecl #define __cdecl #define FAR #define E_FAIL 0x80004005 // exception code -#define HANDLE dword /* cross-platform functions macros */ diff --git a/src/common/os_windows.h b/src/common/os_windows.h index 5a0d456e1..13e39d1b5 100644 --- a/src/common/os_windows.h +++ b/src/common/os_windows.h @@ -6,6 +6,17 @@ #ifndef _INC_OS_WINDOWS_H #define _INC_OS_WINDOWS_H +// Windows keeps this reduced limit for compatibility with older API calls and FAT32 path length... +// this limit includes the total length of the path, such as directories, subdirectories, and the filename, +// and it is constrained to 259 characters for the path itself, with the 260th character being reserved for the null terminator. +// On newer versions, Even though long paths are supported (via path prefix or application manifest - if Vista+), +// _MAX_PATH is not updated to reflect the new maximum path length (which can now be up to 32,767 characters). +// The long path feature requires the usage of the wide-character WinAPI calls and the \\?\ prefix. +#ifdef _MAX_PATH +# define SPHERE_MAX_PATH _MAX_PATH +#else +# define SPHERE_MAX_PATH 260 +#endif // _WIN32_WINNT version constants /* @@ -27,7 +38,6 @@ #define _WIN32_WINNT 0x0501 // By default we target Windows XP #endif - #undef FD_SETSIZE #define FD_SETSIZE 1024 // for max of n users ! default = 64 (FD: file descriptor) diff --git a/src/common/resource/CResourceHolder.cpp b/src/common/resource/CResourceHolder.cpp index 621628f1a..ea3322cfa 100644 --- a/src/common/resource/CResourceHolder.cpp +++ b/src/common/resource/CResourceHolder.cpp @@ -104,13 +104,13 @@ CResourceScript * CResourceHolder::AddResourceFile( lpctstr pszName ) ASSERT(pszName != nullptr); // Is this really just a dir name ? - if (strlen(pszName) >= _MAX_PATH) + if (strlen(pszName) >= SPHERE_MAX_PATH) throw CSError(LOGL_ERROR, 0, "Filename too long!"); - tchar szName[_MAX_PATH]; + tchar szName[SPHERE_MAX_PATH]; Str_CopyLimitNull(szName, pszName, sizeof(szName)); - tchar szTitle[_MAX_PATH]; + tchar szTitle[SPHERE_MAX_PATH]; lpctstr ptcTitle = CScript::GetFilesTitle(szName); ASSERT_ALWAYS(strlen(ptcTitle) < sizeof(szTitle)); Str_CopyLimitNull(szTitle, ptcTitle, sizeof(szTitle)); @@ -125,8 +125,8 @@ CResourceScript * CResourceHolder::AddResourceFile( lpctstr pszName ) if ( pszExt == nullptr ) { // No file extension provided, so append .scp to the filename - Str_ConcatLimitNull( szName, SPHERE_SCRIPT, sizeof(szName) ); - Str_ConcatLimitNull( szTitle, SPHERE_SCRIPT, sizeof(szTitle) ); + Str_ConcatLimitNull( szName, SPHERE_SCRIPT_EXT, sizeof(szName) ); + Str_ConcatLimitNull( szTitle, SPHERE_SCRIPT_EXT, sizeof(szTitle) ); } if ( ! strnicmp( szTitle, SPHERE_FILE "tables", strlen(SPHERE_FILE "tables"))) @@ -159,7 +159,7 @@ void CResourceHolder::AddResourceDir( lpctstr pszDirName ) if ( pszDirName[0] == '\0' ) return; - CSString sFilePath = CSFile::GetMergedFileName( pszDirName, "*" SPHERE_SCRIPT ); + CSString sFilePath = CSFile::GetMergedFileName( pszDirName, "*" SPHERE_SCRIPT_EXT ); CSFileList filelist; int iRet = filelist.ReadDir( sFilePath, false ); diff --git a/src/common/resource/CResourceHolder.h b/src/common/resource/CResourceHolder.h index a5c4b40d5..f4e5f8b33 100644 --- a/src/common/resource/CResourceHolder.h +++ b/src/common/resource/CResourceHolder.h @@ -71,11 +71,4 @@ class CResourceHolder : public CScriptObj CResourceHolder& operator=(const CResourceHolder& other) = delete; }; -inline lpctstr CResourceHolder::GetResourceBlockName( RES_TYPE restype ) // static -{ - if ( restype < 0 || restype >= RES_QTY ) - restype = RES_UNKNOWN; - return( sm_szResourceBlocks[restype] ); -} - #endif // _INC_CResourceHolder_H diff --git a/src/common/resource/CResourceRef.cpp b/src/common/resource/CResourceRef.cpp index 500a427ee..1697734d2 100644 --- a/src/common/resource/CResourceRef.cpp +++ b/src/common/resource/CResourceRef.cpp @@ -84,7 +84,6 @@ bool CResourceRefArray::r_LoadVal( CScript & s, RES_TYPE restype ) int iArgCount = Str_ParseCmds( pszCmd, ppBlocks, ARRAY_COUNT(ppBlocks)); for ( int i = 0; i < iArgCount; ++i ) { - std::shared_ptr pResourceDefRef; CResourceLink* pResourceLink = nullptr; pszCmd = ppBlocks[i]; @@ -128,7 +127,7 @@ bool CResourceRefArray::r_LoadVal( CScript & s, RES_TYPE restype ) if (pResourceLink == nullptr) { fRet = false; - DEBUG_ERR(("Unknown '%s' Resource '%s'\n", CResourceHolder::GetResourceBlockName(restype), pszCmd)); + g_Log.EventError("Unknown '%s' Resource '%s'\n", CResourceHolder::GetResourceBlockName(restype), pszCmd); } } @@ -198,6 +197,13 @@ size_t CResourceRefArray::FindResourceName( RES_TYPE restype, lpctstr ptcKey ) c return FindResourceID(pResourceLink->GetResourceID()); } +lpctstr CResourceHolder::GetResourceBlockName( RES_TYPE restype ) // static +{ + if ( restype < 0 || restype >= RES_QTY ) + restype = RES_UNKNOWN; + return sm_szResourceBlocks[restype]; +} + void CResourceRefArray::r_Write( CScript & s, lpctstr ptcKey ) const { ADDTOCALLSTACK_DEBUG("CResourceRefArray::r_Write"); diff --git a/src/common/resource/sections/CWebPageDef.cpp b/src/common/resource/sections/CWebPageDef.cpp index 9816ad0ef..518f17875 100644 --- a/src/common/resource/sections/CWebPageDef.cpp +++ b/src/common/resource/sections/CWebPageDef.cpp @@ -390,8 +390,8 @@ void CWebPageDef::WebPageLog() lpctstr pszExt = FileRead.GetFileExt(); - tchar szName[ _MAX_PATH ]; - Str_CopyLimitNull( szName, m_sDstFilePath, _MAX_PATH); + tchar szName[ SPHERE_MAX_PATH ]; + Str_CopyLimitNull( szName, m_sDstFilePath, SPHERE_MAX_PATH); szName[ m_sDstFilePath.GetLength() - strlen(pszExt) ] = '\0'; CSTime datetime = CSTime::GetCurrentTime(); @@ -780,7 +780,7 @@ void CWebPageDef::ServPage( CClient * pClient, tchar * pszPage, CSTime * pdateIf ADDTOCALLSTACK("CWebPageDef::ServPage"); // make sure this is a valid format for the request. - tchar szPageName[_MAX_PATH]; + tchar szPageName[SPHERE_MAX_PATH]; Str_GetBare( szPageName, pszPage, sizeof(szPageName), "!\"#$%&()*,:;<=>?[]^{|}-+'`" ); int iError = 404; diff --git a/src/common/sphere_library/CSFile.cpp b/src/common/sphere_library/CSFile.cpp index 27788a0a4..42d3bf124 100644 --- a/src/common/sphere_library/CSFile.cpp +++ b/src/common/sphere_library/CSFile.cpp @@ -434,7 +434,7 @@ CSString CSFile::GetMergedFileName( lpctstr pszBase, lpctstr pszName ) // static ADDTOCALLSTACK("CSFile::GetMergedFileName"); // Merge path and file name. - tchar ptcFilePath[ _MAX_PATH ]; + tchar ptcFilePath[ SPHERE_MAX_PATH ]; size_t len = 0; if ( pszBase && pszBase[0] ) { diff --git a/src/common/sphere_library/CSFileList.cpp b/src/common/sphere_library/CSFileList.cpp index bf3c46457..997540b25 100644 --- a/src/common/sphere_library/CSFileList.cpp +++ b/src/common/sphere_library/CSFileList.cpp @@ -56,7 +56,7 @@ int CSFileList::ReadDir( lpctstr pszFileDir, bool bShowError ) { ADDTOCALLSTACK("CSFileList::ReadDir"); // NOTE: It seems NOT to like the trailing \ alone - tchar szFileDir[_MAX_PATH]; + tchar szFileDir[SPHERE_MAX_PATH]; size_t len = Str_CopyLen(szFileDir, pszFileDir); #ifdef _WIN32 if ( len > 0 ) @@ -73,7 +73,7 @@ int CSFileList::ReadDir( lpctstr pszFileDir, bool bShowError ) if ( lFind == -1 ) #else - char szFilename[_MAX_PATH]; + char szFilename[SPHERE_MAX_PATH]; // Need to strip out the *.scp part for ( size_t i = len; i > 0; --i ) { @@ -110,15 +110,15 @@ int CSFileList::ReadDir( lpctstr pszFileDir, bool bShowError ) if ( fileinfo->d_name[0] == '.' ) continue; - const int ret = snprintf(szFilename, _MAX_PATH, "%s%s", szFileDir, fileinfo->d_name); - szFilename[_MAX_PATH - 1] = '\0'; - if ((ret < 0) || (ret > _MAX_PATH - 1)) + const int ret = snprintf(szFilename, SPHERE_MAX_PATH, "%s%s", szFileDir, fileinfo->d_name); + szFilename[SPHERE_MAX_PATH - 1] = '\0'; + if ((ret < 0) || (ret > SPHERE_MAX_PATH - 1)) { g_Log.EventError("Unable to concatenate the path (too long). Current file '%s'.\n", fileinfo->d_name); break; } len = strlen(szFilename); - if ( len > 4 && !strcmpi(&szFilename[len - 4], SPHERE_SCRIPT) ) + if ( (len > SPHERE_SCRIPT_EXT_LEN) && !strcmpi(&szFilename[len - SPHERE_SCRIPT_EXT_LEN], SPHERE_SCRIPT_EXT) ) AddTail(fileinfo->d_name); #endif } diff --git a/src/common/sphere_library/CSWindow.cpp b/src/common/sphere_library/CSWindow.cpp index 09c0da251..2b1dca8dd 100644 --- a/src/common/sphere_library/CSWindow.cpp +++ b/src/common/sphere_library/CSWindow.cpp @@ -252,7 +252,7 @@ void CWinApp::InitInstance(LPCTSTR pszAppName, HINSTANCE hInstance, LPTSTR lpszC m_hInstance = hInstance; m_lpCmdLine = lpszCmdLine; - char szFileName[_MAX_PATH]; + char szFileName[SPHERE_MAX_PATH]; if (! GetModuleFileName(m_hInstance, szFileName, sizeof(szFileName))) return; m_pszExeName = szFileName; diff --git a/src/game/CServer.cpp b/src/game/CServer.cpp index 5b9bc5bca..5e35bacd6 100644 --- a/src/game/CServer.cpp +++ b/src/game/CServer.cpp @@ -79,7 +79,7 @@ static void defragSphere(char *path) CSFileText inf; CSFile ouf; char file_buf[1024]; - char path_buf[_MAX_PATH], path_buf_2[_MAX_PATH]; + char path_buf[SPHERE_MAX_PATH], path_buf_2[SPHERE_MAX_PATH]; char *str_ptr = nullptr, *str_ptr_2 = nullptr; g_Log.Event(LOGM_INIT, "Defragmentation (UID alteration) of " SPHERE_TITLE " saves.\n" @@ -95,9 +95,9 @@ static void defragSphere(char *path) for ( uint i = 0; i < 3; ++i ) { Str_CopyLimitNull(path_buf, path, sizeof(path_buf)); - if ( i == 0 ) strcat(path_buf, SPHERE_FILE "statics" SPHERE_SCRIPT); - else if ( i == 1 ) strcat(path_buf, SPHERE_FILE "world" SPHERE_SCRIPT); - else strcat(path_buf, SPHERE_FILE "chars" SPHERE_SCRIPT); + if ( i == 0 ) strcat(path_buf, SPHERE_FILE "statics" SPHERE_SCRIPT_EXT); + else if ( i == 1 ) strcat(path_buf, SPHERE_FILE "world" SPHERE_SCRIPT_EXT); + else strcat(path_buf, SPHERE_FILE "chars" SPHERE_SCRIPT_EXT); g_Log.Event(LOGM_INIT, "Reading current UIDs: %s\n", path_buf); if ( !inf.Open(path_buf, OF_READ|OF_TEXT|OF_DEFAULTMODE) ) @@ -145,10 +145,10 @@ static void defragSphere(char *path) { Str_CopyLimitNull(path_buf, path, sizeof(path_buf)); if ( !i ) strcat(path_buf, SPHERE_FILE "accu.scp"); - else if ( i == 1 ) strcat(path_buf, SPHERE_FILE "chars" SPHERE_SCRIPT); - else if ( i == 2 ) strcat(path_buf, SPHERE_FILE "data" SPHERE_SCRIPT); - else if ( i == 3 ) strcat(path_buf, SPHERE_FILE "world" SPHERE_SCRIPT); - else if ( i == 4 ) strcat(path_buf, SPHERE_FILE "statics" SPHERE_SCRIPT); + else if ( i == 1 ) strcat(path_buf, SPHERE_FILE "chars" SPHERE_SCRIPT_EXT); + else if ( i == 2 ) strcat(path_buf, SPHERE_FILE "data" SPHERE_SCRIPT_EXT); + else if ( i == 3 ) strcat(path_buf, SPHERE_FILE "world" SPHERE_SCRIPT_EXT); + else if ( i == 4 ) strcat(path_buf, SPHERE_FILE "statics" SPHERE_SCRIPT_EXT); g_Log.Event(LOGM_INIT, "Updating UID-s in %s to %s.new\n", path_buf, path_buf); if ( !inf.Open(path_buf, OF_READ|OF_TEXT|OF_DEFAULTMODE) ) { @@ -1116,7 +1116,7 @@ bool CServer::OnConsoleCmd( CSString & sText, CTextConsole * pSrc ) if ( !strnicmp(pszText, "strip tng", 9) || !strnicmp(pszText, "tngstrip", 8)) { Str_CopyLimitNull(z, dirname, Str_TempLength()); - Str_ConcatLimitNull(z, "sphere_strip_tng" SPHERE_SCRIPT, Str_TempLength()); + Str_ConcatLimitNull(z, "sphere_strip_tng" SPHERE_SCRIPT_EXT, Str_TempLength()); if (pSrc != this) { pSrc->SysMessagef("StripFile is %s.\n", z); @@ -1198,7 +1198,7 @@ bool CServer::OnConsoleCmd( CSString & sText, CTextConsole * pSrc ) else if ( !strnicmp(pszText, "strip axis", 10) || !strnicmp(pszText, "strip", 5) ) { Str_CopyLimitNull(z, dirname, Str_TempLength()); - Str_ConcatLimitNull(z, "sphere_strip_axis" SPHERE_SCRIPT, Str_TempLength()); + Str_ConcatLimitNull(z, "sphere_strip_axis" SPHERE_SCRIPT_EXT, Str_TempLength()); if (pSrc != this) { pSrc->SysMessagef("StripFile is %s.\n", z); @@ -2494,7 +2494,7 @@ bool CServer::SocketsInit() // Initialize sockets // What are we listing our port as to the world. // Tell the admin what we know. - tchar szName[ _MAX_PATH ]; + tchar szName[ SPHERE_MAX_PATH ]; struct hostent * pHost = nullptr; int iRet = gethostname(szName, sizeof(szName)); @@ -2504,7 +2504,7 @@ bool CServer::SocketsInit() // Initialize sockets { pHost = gethostbyname(szName); if ( pHost && pHost->h_addr && pHost->h_name && pHost->h_name[0] ) - Str_CopyLimitNull(szName, pHost->h_name, _MAX_PATH); + Str_CopyLimitNull(szName, pHost->h_name, SPHERE_MAX_PATH); } g_Log.Event( LOGM_INIT, "Server started on hostname '%s'\n", szName); diff --git a/src/game/CServerConfig.cpp b/src/game/CServerConfig.cpp index 2cf770e64..6beadd6bd 100644 --- a/src/game/CServerConfig.cpp +++ b/src/game/CServerConfig.cpp @@ -4685,13 +4685,13 @@ bool CServerConfig::Load( bool fResync ) // Now load the *TABLES.SCP file. if ( ! fResync ) { - if ( ! OpenResourceFind( m_scpTables, SPHERE_FILE "tables" SPHERE_SCRIPT )) + if ( ! OpenResourceFind( m_scpTables, SPHERE_FILE "tables" SPHERE_SCRIPT_EXT )) { - g_Log.Event( LOGL_FATAL|LOGM_INIT, "Error opening table definitions file (" SPHERE_FILE "tables" SPHERE_SCRIPT ")...\n" ); + g_Log.Event( LOGL_FATAL|LOGM_INIT, "Error opening table definitions file (" SPHERE_FILE "tables" SPHERE_SCRIPT_EXT ")...\n" ); return false; } - g_Log.Event(LOGL_EVENT|LOGM_INIT, "Loading table definitions file (" SPHERE_FILE "tables" SPHERE_SCRIPT ")...\n"); + g_Log.Event(LOGL_EVENT|LOGM_INIT, "Loading table definitions file (" SPHERE_FILE "tables" SPHERE_SCRIPT_EXT ")...\n"); LoadResourcesOpen(&m_scpTables); m_scpTables.Close(); } @@ -4991,7 +4991,7 @@ bool CServerConfig::DumpUnscriptedItems( CTextConsole * pSrc, lpctstr pszFilenam return false; if ( pszFilename == nullptr || pszFilename[0] == '\0' ) - pszFilename = "unscripted_items" SPHERE_SCRIPT; + pszFilename = "unscripted_items" SPHERE_SCRIPT_EXT; else if ( strlen( pszFilename ) <= 4 ) return false; diff --git a/src/game/CWorld.cpp b/src/game/CWorld.cpp index 05134381d..df69a4ad9 100644 --- a/src/game/CWorld.cpp +++ b/src/game/CWorld.cpp @@ -725,7 +725,7 @@ void CWorld::GetBackupName( CSString & sArchive, lpctstr pszBaseDir, tchar chTyp pszBaseDir, iGroup, iCount&0x07, chType, - SPHERE_SCRIPT ); + SPHERE_SCRIPT_EXT ); } bool CWorld::OpenScriptBackup( CScript & s, lpctstr pszBaseDir, lpctstr pszBaseName, int iSaveCount ) // static @@ -741,7 +741,7 @@ bool CWorld::OpenScriptBackup( CScript & s, lpctstr pszBaseDir, lpctstr pszBaseN // rename previous save to archive name. CSString sSaveName; - sSaveName.Format( "%s" SPHERE_FILE "%s%s", pszBaseDir, pszBaseName, SPHERE_SCRIPT ); + sSaveName.Format( "%s" SPHERE_FILE "%s%s", pszBaseDir, pszBaseName, SPHERE_SCRIPT_EXT ); if ( iSaveCount > 0 ) { if ( ::rename(sSaveName, sArchive) ) @@ -1098,7 +1098,7 @@ bool CWorld::CheckAvailableSpaceForSave(bool fStatics) auto CalcPrevSavesSize = [=, &fSizeErr, &uiPreviousSaveSize](lpctstr ptcSaveName) -> void { struct stat st; - CSString strSaveFile = g_Cfg.m_sWorldBaseDir + SPHERE_FILE + ptcSaveName + SPHERE_SCRIPT; + CSString strSaveFile = g_Cfg.m_sWorldBaseDir + SPHERE_FILE + ptcSaveName + SPHERE_SCRIPT_EXT; if (!stat(strSaveFile.GetBuffer(), &st)) { const ullong uiCurSavefileSize = (ullong)st.st_size; @@ -1357,19 +1357,19 @@ bool CWorld::LoadWorld() // Load world from script // NOTE: WE MUST Sync these files ! CHAR and WORLD !!! CSString sStaticsName; - sStaticsName.Format("%s" SPHERE_FILE "statics" SPHERE_SCRIPT, static_cast(g_Cfg.m_sWorldBaseDir)); + sStaticsName.Format("%s" SPHERE_FILE "statics" SPHERE_SCRIPT_EXT, static_cast(g_Cfg.m_sWorldBaseDir)); CSString sWorldName; - sWorldName.Format("%s" SPHERE_FILE "world" SPHERE_SCRIPT, static_cast(g_Cfg.m_sWorldBaseDir)); + sWorldName.Format("%s" SPHERE_FILE "world" SPHERE_SCRIPT_EXT, static_cast(g_Cfg.m_sWorldBaseDir)); CSString sMultisName; - sMultisName.Format("%s" SPHERE_FILE "multis" SPHERE_SCRIPT, static_cast(g_Cfg.m_sWorldBaseDir)); + sMultisName.Format("%s" SPHERE_FILE "multis" SPHERE_SCRIPT_EXT, static_cast(g_Cfg.m_sWorldBaseDir)); CSString sCharsName; - sCharsName.Format("%s" SPHERE_FILE "chars" SPHERE_SCRIPT, static_cast(g_Cfg.m_sWorldBaseDir)); + sCharsName.Format("%s" SPHERE_FILE "chars" SPHERE_SCRIPT_EXT, static_cast(g_Cfg.m_sWorldBaseDir)); CSString sDataName; - sDataName.Format("%s" SPHERE_FILE "data" SPHERE_SCRIPT, static_cast(g_Cfg.m_sWorldBaseDir)); + sDataName.Format("%s" SPHERE_FILE "data" SPHERE_SCRIPT_EXT, static_cast(g_Cfg.m_sWorldBaseDir)); int iPrevSaveCount = m_iSaveCountID; for (;;) diff --git a/src/game/CWorldImport.cpp b/src/game/CWorldImport.cpp index 693d4c9d4..98ee09c38 100644 --- a/src/game/CWorldImport.cpp +++ b/src/game/CWorldImport.cpp @@ -816,7 +816,7 @@ bool CWorld::Import( lpctstr pszFilename, const CChar * pSrc, word wModeFlags, i fImport.m_pszArg1 = pszArg1; fImport.m_pszArg2 = pszArg2; - if ( ! strcmpi( pszFilename + (iLen - 4), ".WSC" )) + if ( ! strcmpi( pszFilename + (iLen - 4), ".WSC" )) { if ( ! fImport.ImportWSC(s, wModeFlags, dx, dy )) return false; @@ -844,7 +844,7 @@ bool CWorld::DumpAreas( CTextConsole * pSrc, lpctstr pszFilename ) return false; if ( pszFilename == nullptr || *pszFilename == '\0' ) - pszFilename = "map_all" SPHERE_SCRIPT; + pszFilename = "map_all" SPHERE_SCRIPT_EXT; else if ( strlen( pszFilename ) <= 4 ) return false; diff --git a/src/game/chars/CCharAct.cpp b/src/game/chars/CCharAct.cpp index e8d4c8269..e07bd77c0 100644 --- a/src/game/chars/CCharAct.cpp +++ b/src/game/chars/CCharAct.cpp @@ -5929,12 +5929,12 @@ bool CChar::OnTickPeriodic() } else { -#ifdef _DEBUG +//#ifdef _DEBUG if (deathRes != DeathRequestResult::AbortedNoLog) { g_Log.EventEvent("Aborted char '%s' (0x%" PRIx32 " ) death.\n", GetName(), GetUID().GetObjUID()); } -#endif +//#endif ; // Then, fall through. } } diff --git a/src/game/clients/CAccount.cpp b/src/game/clients/CAccount.cpp index a7a82c695..4d4eca1b0 100644 --- a/src/game/clients/CAccount.cpp +++ b/src/game/clients/CAccount.cpp @@ -73,7 +73,7 @@ bool CAccounts::Account_LoadAll( bool fChanges, bool fClearChanges ) char *z = Str_GetTemp(); pszBaseDir = g_Cfg.m_sAcctBaseDir.IsEmpty() ? g_Cfg.m_sWorldBaseDir : g_Cfg.m_sAcctBaseDir; - pszBaseName = ( fChanges ) ? (SPHERE_FILE "acct" SPHERE_SCRIPT) : (SPHERE_FILE "accu" SPHERE_SCRIPT); + pszBaseName = ( fChanges ) ? (SPHERE_FILE "acct" SPHERE_SCRIPT_EXT) : (SPHERE_FILE "accu" SPHERE_SCRIPT_EXT); Str_CopyLimitNull(z, pszBaseDir, Str_TempLength()); Str_ConcatLimitNull(z, pszBaseName, Str_TempLength()); @@ -104,7 +104,7 @@ bool CAccounts::Account_LoadAll( bool fChanges, bool fClearChanges ) if (!s.Open(nullptr, OF_WRITE | OF_TEXT | OF_DEFAULTMODE)) return false; - s.WriteString( "// Accounts are periodically moved to the " SPHERE_FILE "accu" SPHERE_SCRIPT " file.\n" + s.WriteString( "// Accounts are periodically moved to the " SPHERE_FILE "accu" SPHERE_SCRIPT_EXT " file.\n" "// All account changes should be made here.\n" "// Use the /ACCOUNT UPDATE command to force accounts to update.\n" ); @@ -142,7 +142,7 @@ bool CAccounts::Account_SaveAll() s.Printf("// " SPHERE_TITLE " %s accounts file\n" "// NOTE: This file cannot be edited while the server is running.\n" - "// Any file changes must be made to " SPHERE_FILE "accu" SPHERE_SCRIPT ". This is read in at save time.\n", + "// Any file changes must be made to " SPHERE_FILE "accu" SPHERE_SCRIPT_EXT ". This is read in at save time.\n", g_Serv.GetName()); for ( size_t i = 0; i < m_Accounts.size(); ++i ) diff --git a/src/game/clients/CClientLog.cpp b/src/game/clients/CClientLog.cpp index f3a84daf8..784ee801d 100644 --- a/src/game/clients/CClientLog.cpp +++ b/src/game/clients/CClientLog.cpp @@ -748,7 +748,7 @@ bool CClient::OnRxWebPageRequest( byte * pRequest, size_t uiLen ) tchar * ppRequest[4]; int iQtyArgs = Str_ParseCmds(ppLines[0], ppRequest, ARRAY_COUNT(ppRequest), " "); - if (( iQtyArgs < 2 ) || ( strlen(ppRequest[1]) >= _MAX_PATH )) + if (( iQtyArgs < 2 ) || ( strlen(ppRequest[1]) >= SPHERE_MAX_PATH )) return false; if ( strchr(ppRequest[1], '\r') || strchr(ppRequest[1], 0x0c) ) @@ -829,7 +829,7 @@ bool CClient::OnRxWebPageRequest( byte * pRequest, size_t uiLen ) // Host: localhost:2593\r\n // \r\n - tchar szPageName[_MAX_PATH]; + tchar szPageName[SPHERE_MAX_PATH]; if ( !Str_GetBare( szPageName, Str_TrimWhitespace(ppRequest[1]), sizeof(szPageName), "!\"#$%&()*,:;<=>?[]^{|}-+'`" ) ) return false; diff --git a/src/game/clients/CClientMsg.cpp b/src/game/clients/CClientMsg.cpp index 978b5affe..d2e6f6611 100644 --- a/src/game/clients/CClientMsg.cpp +++ b/src/game/clients/CClientMsg.cpp @@ -2722,7 +2722,7 @@ void CClient::SendPacket( tchar * ptcKey ) while ( *ptcKey ) { if ( packet->getLength() > SCRIPT_MAX_LINE_LEN - 4 ) - { // we won't get here because this lenght is enforced in all scripts + { // we won't get here because this length is enforced in all scripts DEBUG_ERR(("SENDPACKET too big.\n")); delete packet; @@ -2734,7 +2734,7 @@ void CClient::SendPacket( tchar * ptcKey ) if ( toupper(*ptcKey) == 'D' ) { ++ptcKey; - dword iVal = Exp_GetVal(ptcKey); + dword iVal = Exp_GetDWVal(ptcKey); packet->writeInt32(iVal); } diff --git a/src/game/spheresvr.cpp b/src/game/spheresvr.cpp index be7f4c857..d56b7680a 100644 --- a/src/game/spheresvr.cpp +++ b/src/game/spheresvr.cpp @@ -71,7 +71,7 @@ GlobalInitializer::GlobalInitializer() //--- Exception handling -#ifdef WINDOWS_SEH_EXCEPTION_MODEL +#ifdef WINDOWS_SPHERE_SHOULD_HANDLE_STRUCTURED_EXCEPTIONS SetWindowsStructuredExceptionTranslator(); #endif diff --git a/src/sphere/ntservice.cpp b/src/sphere/ntservice.cpp index 0e0bdb707..6e05dd8bf 100644 --- a/src/sphere/ntservice.cpp +++ b/src/sphere/ntservice.cpp @@ -252,7 +252,7 @@ void CNTService::ServiceStop() // PURPOSE: Installs the service on the local machine void CNTService::CmdInstallService() { - char szPath[_MAX_PATH * 2]; + char szPath[SPHERE_MAX_PATH * 2]; char szErr[256]; ReportEvent(EVENTLOG_INFORMATION_TYPE, 0, "Installing Service."); diff --git a/src/sphere/ntwindow.cpp b/src/sphere/ntwindow.cpp index ce3a38b73..d5804aa4a 100644 --- a/src/sphere/ntwindow.cpp +++ b/src/sphere/ntwindow.cpp @@ -748,7 +748,7 @@ LRESULT CNTWindow::OnNotify( int idCtrl, NMHDR * pnmh ) break; // use dclick to open the corresponding script file - TCHAR * pos = strstr(zTemp, SPHERE_SCRIPT); + TCHAR * pos = strstr(zTemp, SPHERE_SCRIPT_EXT); if ( pos != nullptr ) { // use two formats of file names: @@ -784,7 +784,7 @@ LRESULT CNTWindow::OnNotify( int idCtrl, NMHDR * pnmh ) // since certain files aren't listed, handle these separately if (filePath == nullptr) { - if ( strstr(SPHERE_FILE "tables" SPHERE_SCRIPT, start) ) + if ( strstr(SPHERE_FILE "tables" SPHERE_SCRIPT_EXT, start) ) { TCHAR * z = Str_GetTemp(); strcpy(z, g_Cfg.m_sSCPBaseDir); diff --git a/src/sphere/threads.cpp b/src/sphere/threads.cpp index 7c9306885..23119d208 100644 --- a/src/sphere/threads.cpp +++ b/src/sphere/threads.cpp @@ -643,7 +643,7 @@ void AbstractThread::onStart() // when implemented in derived classes this method must always be called too, preferably before // the custom implementation -#ifdef WINDOWS_SEH_EXCEPTION_MODEL +#ifdef WINDOWS_SPHERE_SHOULD_HANDLE_STRUCTURED_EXCEPTIONS SetWindowsStructuredExceptionTranslator(); #endif From 8643b0bb8734be628d6a284f0baded6fce1a84bc Mon Sep 17 00:00:00 2001 From: cbnolok Date: Sat, 5 Oct 2024 18:44:40 +0200 Subject: [PATCH 74/86] More refactoring, removed some macros from os_unix.h, renamed to uppercase some macros, converted some strcpy to safer variants. --- src/common/CDataBase.cpp | 4 +-- src/common/CDataBase.h | 4 +-- src/common/CException.cpp | 26 ++++++++++--------- src/common/CLog.cpp | 6 ++--- src/common/CLog.h | 16 ++++++------ src/common/CRect.cpp | 2 -- src/common/CScript.cpp | 6 ++--- src/common/CScript.h | 4 +-- src/common/CTextConsole.cpp | 2 +- src/common/CTextConsole.h | 2 +- src/common/CUOClientVersion.cpp | 2 -- src/common/common.h | 6 ++--- src/common/crashdump/crashdump.cpp | 2 +- src/common/crashdump/crashdump.h | 2 +- src/common/os_unix.h | 30 ++++++++-------------- src/common/os_windows.h | 8 +++--- src/common/sphere_library/CSFile.cpp | 4 +-- src/common/sphere_library/CSFileText.cpp | 4 +-- src/common/sphere_library/CSFileText.h | 4 +-- src/common/sphere_library/CSString.cpp | 2 +- src/common/sphere_library/CSString.h | 2 +- src/common/sphere_library/CSTime.cpp | 3 +-- src/common/sphere_library/sresetevents.cpp | 4 +++ src/game/CBase.cpp | 6 ++--- src/game/CServerDef.cpp | 2 +- src/game/CWorldCache.cpp | 4 +-- src/game/CWorldComm.cpp | 2 +- src/game/CWorldComm.h | 2 +- src/game/clients/CClientDialog.cpp | 4 ++- src/game/clients/CClientTooltip.cpp | 2 +- src/game/clients/CClientTooltip.h | 2 +- src/game/spheresvr.cpp | 8 +++--- src/network/CNetState.cpp | 2 +- src/network/CSocket.cpp | 6 ++--- src/sphere/ProfileData.cpp | 2 +- src/sphere/ntservice.cpp | 2 +- src/sphere/threads.cpp | 4 --- 37 files changed, 92 insertions(+), 101 deletions(-) diff --git a/src/common/CDataBase.cpp b/src/common/CDataBase.cpp index 909ee56c8..352359d24 100644 --- a/src/common/CDataBase.cpp +++ b/src/common/CDataBase.cpp @@ -167,7 +167,7 @@ bool CDataBase::query(const char *query, CVarDefMap & mapQueryResult) return false; } -bool __cdecl CDataBase::queryf(CVarDefMap & mapQueryResult, char *fmt, ...) +bool CDataBase::queryf(CVarDefMap & mapQueryResult, char *fmt, ...) { ADDTOCALLSTACK("CDataBase::queryf"); TemporaryString tsBuf; @@ -214,7 +214,7 @@ bool CDataBase::exec(const char *query) return false; } -bool __cdecl CDataBase::execf(char *fmt, ...) +bool CDataBase::execf(char *fmt, ...) { ADDTOCALLSTACK("CDataBase::execf"); TemporaryString tsBuf; diff --git a/src/common/CDataBase.h b/src/common/CDataBase.h index ee084ae50..d166cd70d 100644 --- a/src/common/CDataBase.h +++ b/src/common/CDataBase.h @@ -37,9 +37,9 @@ class CDataBase : public CScriptObj // select bool query(const char *query, CVarDefMap & mapQueryResult); // proceeds the query for SELECT - bool __cdecl queryf(CVarDefMap & mapQueryResult, char *fmt, ...) __printfargs(3,4); + bool queryf(CVarDefMap & mapQueryResult, char *fmt, ...) SPHERE_PRINTFARGS(3,4); bool exec(const char *query); // executes query (pretty faster) for ALTER, UPDATE, INSERT, DELETE, ... - bool __cdecl execf(char *fmt, ...) __printfargs(2,3); + bool execf(char *fmt, ...) SPHERE_PRINTFARGS(2,3); void addQueryResult(CSString & theFunction, CScriptTriggerArgs * theResult); // set / get / info methods diff --git a/src/common/CException.cpp b/src/common/CException.cpp index 202463459..6b41a9db0 100644 --- a/src/common/CException.cpp +++ b/src/common/CException.cpp @@ -235,7 +235,7 @@ void Assert_Fail( lpctstr pExp, lpctstr pFile, long long llLine ) throw CAssert(LOGL_CRIT, pExp, pFile, llLine); } -static void _cdecl Sphere_Purecall_Handler() +static void SPHERE_CDECL Sphere_Purecall_Handler() { // catch this special type of C++ exception as well. Assert_Fail("purecall", "unknown", 1); @@ -244,6 +244,7 @@ static void _cdecl Sphere_Purecall_Handler() void SetPurecallHandler() { // We don't want sphere to immediately exit if something calls a pure virtual method. + // Those functions set the behavior process-wide, so there's no need to call this on each thread. #ifdef MSVC_COMPILER _set_purecall_handler(Sphere_Purecall_Handler); #else @@ -254,7 +255,7 @@ void SetPurecallHandler() } #ifdef WINDOWS_SPHERE_SHOULD_HANDLE_STRUCTURED_EXCEPTIONS -static void _cdecl Sphere_Structured_Exception_Windows( unsigned int id, struct _EXCEPTION_POINTERS* pData ) +static void SPHERE_CDECL Sphere_Structured_Exception_Windows( unsigned int id, struct _EXCEPTION_POINTERS* pData ) { # ifdef WINDOWS_SHOULD_EMIT_CRASH_DUMP if ( CrashDump::IsEnabled() ) @@ -272,17 +273,18 @@ static void _cdecl Sphere_Structured_Exception_Windows( unsigned int id, struct void SetWindowsStructuredExceptionTranslator() { + // Process-wide, no need to call this on each thread. _set_se_translator( Sphere_Structured_Exception_Windows ); } #endif #ifndef _WIN32 -static void _cdecl Signal_Hangup(int sig = 0) noexcept // If shutdown is initialized +static void Signal_Hangup(int sig = 0) noexcept // If shutdown is initialized { UnreferencedParameter(sig); #ifdef THREAD_TRACK_CALLSTACK - static bool _Signal_Hangup_stack_printed = false; + static thread_local bool _Signal_Hangup_stack_printed = false; if (!_Signal_Hangup_stack_printed) { StackDebugInformation::printStackTrace(); @@ -296,13 +298,13 @@ static void _cdecl Signal_Hangup(int sig = 0) noexcept // If shutdown is initial g_Serv.SetExitFlag(SIGHUP); } -static void _cdecl Signal_Terminate(int sig = 0) noexcept // If shutdown is initialized +static void Signal_Terminate(int sig = 0) noexcept // If shutdown is initialized { g_Log.Event(LOGL_FATAL, "Server Unstable: %s signal received\n", strsignal(sig)); #ifdef THREAD_TRACK_CALLSTACK - static bool _Signal_Terminate_stack_printed = false; + static thread_local bool _Signal_Terminate_stack_printed = false; if (!_Signal_Terminate_stack_printed) { StackDebugInformation::printStackTrace(); @@ -350,7 +352,7 @@ static void _cdecl Signal_Terminate(int sig = 0) noexcept // If shutdown is init //exit(EXIT_FAILURE); // Having set the exit flag, all threads "should" terminate cleanly. } -static void _cdecl Signal_Break(int sig = 0) // signal handler attached when using secure mode +static void Signal_Break(int sig = 0) // signal handler attached when using secure mode { // Shouldn't be needed, since gdb consumes the signals itself and this code won't be executed //#ifdef _DEBUG @@ -371,7 +373,7 @@ static void _cdecl Signal_Break(int sig = 0) // signal handler attached when us } } -static void _cdecl Signal_Illegal_Instruction(int sig = 0) +static void Signal_Illegal_Instruction(int sig = 0) { #ifdef THREAD_TRACK_CALLSTACK StackDebugInformation::freezeCallStack(true); @@ -398,7 +400,7 @@ static void _cdecl Signal_Illegal_Instruction(int sig = 0) throw CSError(LOGL_FATAL, sig, strsignal(sig)); } -static void _cdecl Signal_Children(int sig = 0) +static void Signal_Children(int sig = 0) { UnreferencedParameter(sig); while (waitpid((pid_t)(-1), nullptr, WNOHANG) > 0) {} @@ -410,15 +412,15 @@ void SetUnixSignals( bool fSet ) // Signal handlers are installed only in sec { #ifdef _SANITIZERS - const bool fSan = true; + constexpr bool fSan = true; #else - const bool fSan = false; + constexpr bool fSan = false; #endif #ifdef _DEBUG const bool fDebugger = IsDebuggerPresent(); #else - const bool fDebugger = false; + constexpr bool fDebugger = false; #endif if (!fDebugger && !fSan) diff --git a/src/common/CLog.cpp b/src/common/CLog.cpp index 926dde738..364dadae5 100644 --- a/src/common/CLog.cpp +++ b/src/common/CLog.cpp @@ -358,7 +358,7 @@ int CLog::EventStr( dword dwMask, lpctstr pszMsg, ConsoleTextColor iLogColor) no CSTime CLog::sm_prevCatchTick; -void _cdecl CLog::CatchEvent( const CSError * pErr, lpctstr pszCatchContext, ... ) +void CLog::CatchEvent( const CSError * pErr, lpctstr pszCatchContext, ... ) { CSTime timeCurrent = CSTime::GetCurrentTime(); if ( sm_prevCatchTick.GetTime() == timeCurrent.GetTime() ) // prevent message floods. @@ -392,7 +392,7 @@ void _cdecl CLog::CatchEvent( const CSError * pErr, lpctstr pszCatchContext, ... va_start(vargs, pszCatchContext); uiLen += vsnprintf(szMsg + uiLen, sizeof(szMsg) - uiLen, pszCatchContext, vargs); - uiLen += snprintf (szMsg + uiLen, sizeof(szMsg) - uiLen, "\n"); + /*uiLen += */ snprintf (szMsg + uiLen, sizeof(szMsg) - uiLen, "\n"); EventStr(eSeverity, szMsg); va_end(vargs); @@ -405,7 +405,7 @@ void _cdecl CLog::CatchEvent( const CSError * pErr, lpctstr pszCatchContext, ... sm_prevCatchTick = timeCurrent; } -void _cdecl CLog::CatchStdException(const std::exception * pExc, lpctstr pszCatchContext, ...) +void CLog::CatchStdException(const std::exception * pExc, lpctstr pszCatchContext, ...) { tchar szMsg[512]; diff --git a/src/common/CLog.h b/src/common/CLog.h index fbb650620..27a100d74 100644 --- a/src/common/CLog.h +++ b/src/common/CLog.h @@ -66,12 +66,12 @@ class CEventLog int VEvent(dword dwMask, lpctstr pszFormat, ConsoleTextColor iColor, va_list args) noexcept; public: - int _cdecl Event( dword dwMask, lpctstr pszFormat, ... ) noexcept __printfargs(3,4); - int _cdecl EventDebug(lpctstr pszFormat, ...) noexcept __printfargs(2,3); - int _cdecl EventError(lpctstr pszFormat, ...) noexcept __printfargs(2,3); - int _cdecl EventWarn(lpctstr pszFormat, ...) noexcept __printfargs(2,3); - int _cdecl EventCustom(ConsoleTextColor iColor, dword dwMask, lpctstr pszFormat, ...) noexcept __printfargs(4,5); - int _cdecl EventEvent( lpctstr pszFormat, ... ) noexcept __printfargs(2,3); + int Event( dword dwMask, lpctstr pszFormat, ... ) noexcept SPHERE_PRINTFARGS(3,4); + int EventDebug(lpctstr pszFormat, ...) noexcept SPHERE_PRINTFARGS(2,3); + int EventError(lpctstr pszFormat, ...) noexcept SPHERE_PRINTFARGS(2,3); + int EventWarn(lpctstr pszFormat, ...) noexcept SPHERE_PRINTFARGS(2,3); + int EventCustom(ConsoleTextColor iColor, dword dwMask, lpctstr pszFormat, ...) noexcept SPHERE_PRINTFARGS(4,5); + int EventEvent( lpctstr pszFormat, ... ) noexcept SPHERE_PRINTFARGS(2,3); CEventLog(); virtual ~CEventLog(); @@ -119,8 +119,8 @@ public: bool OpenLog(lpctstr pszName = nullptr); bool IsLogged( dword dwMask ) const; virtual int EventStr( dword dwMask, lpctstr pszMsg, ConsoleTextColor iLogColor = CTCOL_DEFAULT ) noexcept final; // final: for now, it doesn't have any other virtual methods - void _cdecl CatchEvent( const CSError * pErr, lpctstr pszCatchContext, ... ) __printfargs(3,4); - void _cdecl CatchStdException( const std::exception * pExc, lpctstr pszCatchContext, ... ) __printfargs(3,4); + void CatchEvent( const CSError * pErr, lpctstr pszCatchContext, ... ) SPHERE_PRINTFARGS(3,4); + void CatchStdException( const std::exception * pExc, lpctstr pszCatchContext, ... ) SPHERE_PRINTFARGS(3,4); public: CLog(); diff --git a/src/common/CRect.cpp b/src/common/CRect.cpp index c25aea5a0..589fe09ac 100644 --- a/src/common/CRect.cpp +++ b/src/common/CRect.cpp @@ -1,7 +1,5 @@ #include "../game/uo_files/CUOMapList.h" #include "../game/CSectorList.h" -#include "../game/CServer.h" -#include "../game/CWorldMap.h" #include "CLog.h" #include "CRect.h" diff --git a/src/common/CScript.cpp b/src/common/CScript.cpp index 352bc1680..c7a4da969 100644 --- a/src/common/CScript.cpp +++ b/src/common/CScript.cpp @@ -841,7 +841,7 @@ CScriptLineContext CScript::GetContext() const return LineContext; } -bool _cdecl CScript::WriteSection( lpctstr ptcSection, ... ) +bool CScript::WriteSection( lpctstr ptcSection, ... ) { ADDTOCALLSTACK_DEBUG("CScript::WriteSection"); // Write out the section header. @@ -933,7 +933,7 @@ bool CScript::WriteKeyStr(lpctstr ptcKey, lpctstr ptcVal) return true; } -//void _cdecl CScript::WriteKeyFormat( lpctstr ptcKey, lpctstr pszVal, ... ) +//void CScript::WriteKeyFormat( lpctstr ptcKey, lpctstr pszVal, ... ) //{ // ADDTOCALLSTACK("CScript::WriteKeyFormat"); // tchar *pszTemp = Str_GetTemp(); @@ -945,7 +945,7 @@ bool CScript::WriteKeyStr(lpctstr ptcKey, lpctstr ptcVal) //} static thread_local tchar ptcWriteKeyBuf[SCRIPT_MAX_LINE_LEN]; -void _cdecl CScript::WriteKeyFormat(lpctstr ptcKey, lpctstr pszVal, ...) +void CScript::WriteKeyFormat(lpctstr ptcKey, lpctstr pszVal, ...) { ADDTOCALLSTACK_DEBUG("CScript::WriteKeyFormat"); va_list vargs; diff --git a/src/common/CScript.h b/src/common/CScript.h index 605f6156d..bb21601a0 100644 --- a/src/common/CScript.h +++ b/src/common/CScript.h @@ -159,8 +159,8 @@ public: CScriptLineContext GetContext() const; bool ReadKeyParse(); // Write stuff out to a script file. - bool _cdecl WriteSection(lpctstr pszSection, ...) __printfargs(2,3); - void _cdecl WriteKeyFormat(lpctstr ptcKey, lpctstr pszFormat, ...) __printfargs(3,4); + bool WriteSection(lpctstr pszSection, ...) SPHERE_PRINTFARGS(2,3); + void WriteKeyFormat(lpctstr ptcKey, lpctstr pszFormat, ...) SPHERE_PRINTFARGS(3,4); bool WriteKeySingle(lptstr ptcKey); bool WriteKeyStr(lpctstr ptcKey, lpctstr ptcVal); diff --git a/src/common/CTextConsole.cpp b/src/common/CTextConsole.cpp index b98c301e6..89fdbbf8b 100644 --- a/src/common/CTextConsole.cpp +++ b/src/common/CTextConsole.cpp @@ -139,7 +139,7 @@ void CTextConsole::VSysMessage( lpctstr pszFormat, va_list args ) const SysMessage(tsTemp.buffer()); } -void _cdecl CTextConsole::SysMessagef( lpctstr pszFormat, ... ) const +void CTextConsole::SysMessagef( lpctstr pszFormat, ... ) const { va_list vargs; va_start( vargs, pszFormat ); diff --git a/src/common/CTextConsole.h b/src/common/CTextConsole.h index 5429f4f85..4bd15f897 100644 --- a/src/common/CTextConsole.h +++ b/src/common/CTextConsole.h @@ -41,7 +41,7 @@ class CTextConsole virtual void SysMessage( lpctstr pszMessage ) const = 0; // Feed back message. void VSysMessage( lpctstr pszFormat, va_list args ) const; - void _cdecl SysMessagef( lpctstr pszFormat, ... ) const __printfargs(2,3); + void SysMessagef( lpctstr pszFormat, ... ) const SPHERE_PRINTFARGS(2,3); public: CTextConsole() { }; diff --git a/src/common/CUOClientVersion.cpp b/src/common/CUOClientVersion.cpp index 07113de19..56be65445 100644 --- a/src/common/CUOClientVersion.cpp +++ b/src/common/CUOClientVersion.cpp @@ -1,7 +1,5 @@ #include "CUOClientVersion.h" -#include "CExpression.h" #include "CLog.h" -#include "sphereproto.h" #include #include #include diff --git a/src/common/common.h b/src/common/common.h index deb52d81e..9932c6fd5 100644 --- a/src/common/common.h +++ b/src/common/common.h @@ -214,13 +214,13 @@ constexpr void UnreferencedParameter(T const&) noexcept { // (note: add 1 to index for non-static class methods because 'this' argument // is inserted in position 1) #ifdef MSVC_COMPILER - #define __printfargs(a,b) + #define SPHERE_PRINTFARGS(a,b) #else #ifdef __MINGW32__ // Clang doesn't have a way to switch from gnu or ms style printf arguments. It just depends on the runtime used. - #define __printfargs(a,b) __attribute__ ((format(gnu_printf, a, b))) + #define SPHERE_PRINTFARGS(a,b) __attribute__ ((format(gnu_printf, a, b))) #else - #define __printfargs(a,b) __attribute__ ((format(printf, a, b))) + #define SPHERE_PRINTFARGS(a,b) __attribute__ ((format(printf, a, b))) #endif #endif diff --git a/src/common/crashdump/crashdump.cpp b/src/common/crashdump/crashdump.cpp index 5f78264f2..3beb4ca5a 100644 --- a/src/common/crashdump/crashdump.cpp +++ b/src/common/crashdump/crashdump.cpp @@ -1,4 +1,4 @@ -#if defined(_WIN32) && !defined(_DEBUG) && !defined(_NO_CRASHDUMP) +#ifdef WINDOWS_SHOULD_EMIT_CRASH_DUMP #include "crashdump.h" diff --git a/src/common/crashdump/crashdump.h b/src/common/crashdump/crashdump.h index 0a8387722..5de0b33ef 100644 --- a/src/common/crashdump/crashdump.h +++ b/src/common/crashdump/crashdump.h @@ -1,4 +1,4 @@ -#if !defined(_INC_CRASHDUMP_H) && defined(_WIN32) && !defined(_DEBUG) && !defined(_NO_CRASHDUMP) +#ifdef WINDOWS_SHOULD_EMIT_CRASH_DUMP #define _INC_CRASHDUMP_H #include diff --git a/src/common/os_unix.h b/src/common/os_unix.h index 492ce9cd7..92eee09b3 100644 --- a/src/common/os_unix.h +++ b/src/common/os_unix.h @@ -6,7 +6,7 @@ #ifndef _INC_OS_UNIX_H #define _INC_OS_UNIX_H -//#include // PATH_MAX +//#include // PATH_MAX #include // usleep #include // toupper, tolower @@ -33,9 +33,8 @@ // TODO: enable longer MAX_PATHs on both Linux and Windows, also checking that increasing that limit doesn't cause any buffer overflow. #define SPHERE_MAX_PATH 260 -#define _cdecl -#define __cdecl -#define FAR +//#define SPHERE_CDECL __attribute__((cdecl)) +#define SPHERE_CDECL #define E_FAIL 0x80004005 // exception code @@ -47,17 +46,14 @@ #define HIWORD(l) ((word)((dword)(l) >> 16)) #define LOBYTE(w) ((byte)((dword)(w) & 0xff)) #define HIBYTE(w) ((byte)((dword)(w) >> 8)) -#define IsBadReadPtr( p, len ) ((p) == nullptr) -#define IsBadStringPtr( p, len ) ((p) == nullptr) -#define Sleep(mSec) usleep(mSec*1000) // arg is microseconds = 1/1000000 -#define SleepEx(mSec, unused) usleep(mSec*1000) // arg is microseconds = 1/1000000 #ifdef _BSD int getTimezone(); - #define _timezone getTimezone() + #define TIMEZONE getTimezone() #else - #define _timezone timezone + #define TIMEZONE timezone #endif + /* */ /* file handling definitions */ @@ -70,24 +66,18 @@ /* thread-specific definitions */ #define STDFUNC_GETPID getpid #define CRITICAL_SECTION pthread_mutex_t -#define Sleep(mSec) usleep(mSec*1000) // arg is microseconds = 1/1000000 -#define SleepEx(mSec, unused) usleep(mSec*1000) // arg is microseconds = 1/1000000 -/* */ - -#define ERROR_SUCCESS 0 -#define HKEY_LOCAL_MACHINE (( HKEY ) 0x80000002 ) +/* */ +#define SLEEP(mSec) usleep(mSec*1000) // arg is microseconds = 1/1000000 /* No portable UNIX/LINUX equiv to this. */ - -// The others, not inlined, are in common.cpp -inline void _strupr( tchar * pszStr ) +inline void _strupr( tchar * pszStr ) noexcept { for ( ; pszStr[0] != '\0'; ++pszStr ) *pszStr = toupper( *pszStr ); } -inline void _strlwr( tchar * pszStr ) +inline void _strlwr( tchar * pszStr ) noexcept { for ( ; pszStr[0] != '\0'; ++pszStr ) *pszStr = tolower( *pszStr ); diff --git a/src/common/os_windows.h b/src/common/os_windows.h index 13e39d1b5..c2c9f91cf 100644 --- a/src/common/os_windows.h +++ b/src/common/os_windows.h @@ -71,6 +71,7 @@ # pragma warning(pop) #endif +#define SPHERE_CDECL __cdecl /* file handling definitions */ #define STDFUNC_FILENO(_x_) _get_osfhandle(_fileno(_x_)) @@ -89,15 +90,16 @@ #endif #ifdef __MINGW32__ // No Microsoft compiler - #define _cdecl __cdecl - // Not defined for mingw. #define LSTATUS int - typedef void (__cdecl *_invalid_parameter_handler)(const wchar_t *,const wchar_t *,const wchar_t *,unsigned int,uintptr_t); + typedef void (SPHERE_CDECL *_invalid_parameter_handler)(const wchar_t *,const wchar_t *,const wchar_t *,unsigned int,uintptr_t); // Stuctured exception handling windows api not implemented on mingw. #define __except(P) catch(int) #endif // _MSC_VER +#define SLEEP Sleep +#define TIMEZONE _timezone + const OSVERSIONINFO * Sphere_GetOSInfo() noexcept; diff --git a/src/common/sphere_library/CSFile.cpp b/src/common/sphere_library/CSFile.cpp index 42d3bf124..513bf8793 100644 --- a/src/common/sphere_library/CSFile.cpp +++ b/src/common/sphere_library/CSFile.cpp @@ -442,9 +442,9 @@ CSString CSFile::GetMergedFileName( lpctstr pszBase, lpctstr pszName ) // static if (len && ptcFilePath[len - 1] != '\\' && ptcFilePath[len - 1] != '/') { #ifdef _WIN32 - strcat(ptcFilePath, "\\"); + ptcFilePath[len] = '\\'; #else - strcat(ptcFilePath, "/"); + ptcFilePath[len] = '/'; #endif } } diff --git a/src/common/sphere_library/CSFileText.cpp b/src/common/sphere_library/CSFileText.cpp index 686437c9f..adbfb8be4 100644 --- a/src/common/sphere_library/CSFileText.cpp +++ b/src/common/sphere_library/CSFileText.cpp @@ -155,7 +155,7 @@ bool CSFileText::IsEOF() const } -int _cdecl CSFileText::_Printf(lpctstr pFormat, ...) +int CSFileText::_Printf(lpctstr pFormat, ...) { ADDTOCALLSTACK("CSFileText::_Printf"); ASSERT(pFormat); @@ -167,7 +167,7 @@ int _cdecl CSFileText::_Printf(lpctstr pFormat, ...) return iRet; } -int _cdecl CSFileText::Printf( lpctstr pFormat, ... ) +int CSFileText::Printf( lpctstr pFormat, ... ) { ADDTOCALLSTACK("CSFileText::Printf"); ASSERT(pFormat); diff --git a/src/common/sphere_library/CSFileText.h b/src/common/sphere_library/CSFileText.h index f8912cad7..8727491b4 100644 --- a/src/common/sphere_library/CSFileText.h +++ b/src/common/sphere_library/CSFileText.h @@ -84,8 +84,8 @@ public: virtual bool IsEOF() const; * @param ... argument list. * @return total chars of the output. */ -protected: int _cdecl _Printf( lpctstr pFormat, ... ) __printfargs(2,3); -public: int _cdecl Printf(lpctstr pFormat, ...) __printfargs(2, 3); +protected: int _Printf( lpctstr pFormat, ... ) SPHERE_PRINTFARGS(2,3); +public: int Printf(lpctstr pFormat, ...) SPHERE_PRINTFARGS(2, 3); /** * @brief Reads data from the file. * @param pBuffer buffer where store the readed data. diff --git a/src/common/sphere_library/CSString.cpp b/src/common/sphere_library/CSString.cpp index fdd3db4c9..a0cc3b665 100644 --- a/src/common/sphere_library/CSString.cpp +++ b/src/common/sphere_library/CSString.cpp @@ -261,7 +261,7 @@ CSString& CSString::operator=(CSString&& s) noexcept // CSString:: Formatting -void _cdecl CSString::Format(lpctstr pStr, ...) +void CSString::Format(lpctstr pStr, ...) { va_list vargs; va_start(vargs, pStr); diff --git a/src/common/sphere_library/CSString.h b/src/common/sphere_library/CSString.h index ce0949e0a..26aedb428 100644 --- a/src/common/sphere_library/CSString.h +++ b/src/common/sphere_library/CSString.h @@ -307,7 +307,7 @@ class CSString * @param pStr formatted string. * @param ... list of values. */ - void _cdecl Format(lpctstr pStr, ...) __printfargs(2, 3); + void Format(lpctstr pStr, ...) SPHERE_PRINTFARGS(2, 3); /** * @brief Join a formated string (printf like) with values and copy into this. diff --git a/src/common/sphere_library/CSTime.cpp b/src/common/sphere_library/CSTime.cpp index 45d3ac118..7985f29a4 100644 --- a/src/common/sphere_library/CSTime.cpp +++ b/src/common/sphere_library/CSTime.cpp @@ -5,7 +5,6 @@ // #include "../../sphere/threads.h" -#include "../CLog.h" #include "sstring.h" #include "CSTime.h" #include @@ -257,7 +256,7 @@ std::tm CSTime::GetLocalTmPlain() const noexcept #endif #if defined(_WIN32) && defined (MSVC_COMPILER) -static void __cdecl invalidParameterHandler(const wchar_t* expression, const wchar_t* function, const wchar_t* file, uint line, uintptr_t pReserved) +static void SPHERE_CDECL invalidParameterHandler(const wchar_t* expression, const wchar_t* function, const wchar_t* file, uint line, uintptr_t pReserved) { // bad format has been specified UnreferencedParameter(expression); diff --git a/src/common/sphere_library/sresetevents.cpp b/src/common/sphere_library/sresetevents.cpp index aaa245093..bc4d875c3 100644 --- a/src/common/sphere_library/sresetevents.cpp +++ b/src/common/sphere_library/sresetevents.cpp @@ -39,7 +39,11 @@ void AutoResetEvent::wait(uint timeout) // if timeout is 0 then the thread's timeslice may not be given up as with normal // sleep methods - so we will check for this condition ourselves and use SleepEx // instead +#ifdef _WIN32 SleepEx(0, TRUE); +#else + SLEEP(0); +#endif return; } diff --git a/src/game/CBase.cpp b/src/game/CBase.cpp index cd0311d11..52773a54e 100644 --- a/src/game/CBase.cpp +++ b/src/game/CBase.cpp @@ -235,9 +235,9 @@ bool CBaseBaseDef::r_WriteVal( lpctstr ptcKey, CSString & sVal, CTextConsole * p tchar *pszTmp = Str_GetTemp(); m_BaseResources.WriteKeys( pszTmp, Str_TempLength(), index, fQtyOnly, fKeyOnly ); if ( fQtyOnly && pszTmp[0] == '\0' ) - strcpy( pszTmp, "0" ); - - sVal = pszTmp; + sVal.SetValFalse(); // '0' + else + sVal = pszTmp; } } else diff --git a/src/game/CServerDef.cpp b/src/game/CServerDef.cpp index 063600ca4..ec84ff743 100644 --- a/src/game/CServerDef.cpp +++ b/src/game/CServerDef.cpp @@ -54,7 +54,7 @@ CServerDef::CServerDef( lpctstr pszName, CSocketAddressIP dwIP ) : _iTimeCreate = CWorldGameTime::GetCurrentTime().GetTimeRaw(); // Set default time zone from UTC - m_TimeZone = (char)( _timezone / (60 * 60) ); // Greenwich mean time. + m_TimeZone = (char)( TIMEZONE / (60 * 60) ); // Greenwich mean time. m_eAccApp = ACCAPP_Unspecified; } diff --git a/src/game/CWorldCache.cpp b/src/game/CWorldCache.cpp index a5f3459b4..6873ee560 100644 --- a/src/game/CWorldCache.cpp +++ b/src/game/CWorldCache.cpp @@ -3,6 +3,7 @@ #include "uo_files/CUOMapList.h" #include "CWorldCache.h" + CWorldCache::CWorldCache() { _iTimeLastMapBlockCacheCheck = 0; @@ -11,8 +12,7 @@ CWorldCache::CWorldCache() _mapBlocks[i].reset(); } - -static int _GetMapBlocksCount(int iMap) +static int _GetMapBlocksCount(int iMap) noexcept { const int iXBlocks = g_MapList.GetMapSizeX(iMap) / UO_BLOCK_SIZE; const int iYBlocks = g_MapList.GetMapSizeY(iMap) / UO_BLOCK_SIZE; diff --git a/src/game/CWorldComm.cpp b/src/game/CWorldComm.cpp index d7d3f56a8..78713a5ca 100644 --- a/src/game/CWorldComm.cpp +++ b/src/game/CWorldComm.cpp @@ -235,7 +235,7 @@ void CWorldComm::Broadcast(lpctstr pMsg) // static Speak( nullptr, pMsg, HUE_TEXT_DEF, TALKMODE_BROADCAST, FONT_BOLD ); } -void __cdecl CWorldComm::Broadcastf(lpctstr pMsg, ...) // static +void CWorldComm::Broadcastf(lpctstr pMsg, ...) // static { // System broadcast in bold text ADDTOCALLSTACK("CWorldComm::Broadcastf"); diff --git a/src/game/CWorldComm.h b/src/game/CWorldComm.h index 065d101b7..6a365c54b 100644 --- a/src/game/CWorldComm.h +++ b/src/game/CWorldComm.h @@ -24,7 +24,7 @@ class CWorldComm static void SpeakUNICODE(const CObjBaseTemplate* pSrc, const nachar* pText, HUE_TYPE wHue, TALKMODE_TYPE mode, FONT_TYPE font, CLanguageID lang); static void Broadcast(lpctstr pMsg); - static void __cdecl Broadcastf(lpctstr pMsg, ...) __printfargs(1, 2); + static void Broadcastf(lpctstr pMsg, ...) SPHERE_PRINTFARGS(1, 2); }; diff --git a/src/game/clients/CClientDialog.cpp b/src/game/clients/CClientDialog.cpp index d75c49988..a7fd691ed 100644 --- a/src/game/clients/CClientDialog.cpp +++ b/src/game/clients/CClientDialog.cpp @@ -125,7 +125,9 @@ bool CClient::addGumpDialogProps( const CUID& uid ) addSkillWindow((SKILL_TYPE)(g_Cfg.m_iMaxSkill), true); tchar *pszMsg = Str_GetTemp(); - strcpy(pszMsg, pObj->IsItem() ? "D_ITEMPROP1" : "D_CHARPROP1" ); + Str_CopyLimitNull(pszMsg, + (pObj->IsItem() ? "D_ITEMPROP1" : "D_CHARPROP1"), + Str_TempLength()); CResourceID rid = g_Cfg.ResourceGetIDType(RES_DIALOG, pszMsg); if ( ! rid.IsValidUID()) diff --git a/src/game/clients/CClientTooltip.cpp b/src/game/clients/CClientTooltip.cpp index 036865271..5f72b3ffa 100644 --- a/src/game/clients/CClientTooltip.cpp +++ b/src/game/clients/CClientTooltip.cpp @@ -21,7 +21,7 @@ CClientTooltip::CClientTooltip(dword dwClilocID, int64 iArgs) snprintf(m_args, MAX_TOOLTIP_LEN - 1, "%" PRId64, iArgs); } -void __cdecl CClientTooltip::FormatArgs(lpctstr format, ...) +void CClientTooltip::FormatArgs(lpctstr format, ...) { va_list vargs; va_start( vargs, format ); diff --git a/src/game/clients/CClientTooltip.h b/src/game/clients/CClientTooltip.h index 350e02ada..0375961ab 100644 --- a/src/game/clients/CClientTooltip.h +++ b/src/game/clients/CClientTooltip.h @@ -28,7 +28,7 @@ class CClientTooltip CClientTooltip& operator=(const CClientTooltip& other) = delete; public: - void __cdecl FormatArgs(lpctstr format, ...) __printfargs(2,3); + void FormatArgs(lpctstr format, ...) SPHERE_PRINTFARGS(2,3); }; diff --git a/src/game/spheresvr.cpp b/src/game/spheresvr.cpp index d56b7680a..12708dc69 100644 --- a/src/game/spheresvr.cpp +++ b/src/game/spheresvr.cpp @@ -444,7 +444,7 @@ static void Sphere_MainMonitorLoop() if ( g_Serv.GetExitFlag() ) break; - Sleep(1000); + SLEEP(1000); } EXC_SET_BLOCK("Checks"); @@ -472,13 +472,13 @@ void atexit_handler() #ifdef _WIN32 int Sphere_MainEntryPoint( int argc, char *argv[] ) #else -int _cdecl main( int argc, char * argv[] ) +int main( int argc, char * argv[] ) #endif { static constexpr lpctstr m_sClassName = "main"; EXC_TRY("MAIN"); - const int atexit_handler_result = std::atexit(atexit_handler); // Handler will be called + const int atexit_handler_result = std::atexit(atexit_handler); // Handler will be called if (atexit_handler_result != 0) { g_Log.Event(LOGL_CRIT, "atexit handler registration failed.\n"); @@ -547,7 +547,7 @@ int _cdecl main( int argc, char * argv[] ) { while (g_NTWindow.isActive()) { - Sleep (100); + SLEEP(100); } } #endif diff --git a/src/network/CNetState.cpp b/src/network/CNetState.cpp index ae3ecc506..8623ed7c7 100644 --- a/src/network/CNetState.cpp +++ b/src/network/CNetState.cpp @@ -55,7 +55,7 @@ void CNetState::clear(void) g_Serv.StatDec(SERV_STAT_CLIENTS); const CONNECT_TYPE connectionType = m_client->GetConnectType(); - const LOG_TYPE logFlags = LOG_TYPE(LOGM_NOCONTEXT | LOGM_CLIENTS_LOG | LOGL_EVENT); + const LOG_TYPE logFlags = enum_alias_cast(LOGM_NOCONTEXT | LOGM_CLIENTS_LOG | LOGL_EVENT); const size_t uiClients = g_Serv.StatGet(SERV_STAT_CLIENTS); const lpctstr ptcAddress = m_peerAddress.GetAddrStr(); if (connectionType == CONNECT_LOGIN) diff --git a/src/network/CSocket.cpp b/src/network/CSocket.cpp index c99c40b05..9014f36bc 100644 --- a/src/network/CSocket.cpp +++ b/src/network/CSocket.cpp @@ -433,12 +433,12 @@ CSocketAddress CSocket::GetPeerName( ) const int CSocket::SetSockOpt( int nOptionName, const void * optval, int optlen, int nLevel ) const { // level = SOL_SOCKET and IPPROTO_TCP. - return( setsockopt( m_hSocket, nLevel, nOptionName, reinterpret_cast(optval), optlen )); + return( setsockopt( m_hSocket, nLevel, nOptionName, reinterpret_cast(optval), optlen )); } int CSocket::GetSockOpt( int nOptionName, void * optval, int * poptlen, int nLevel ) const { - return( getsockopt( m_hSocket, nLevel, nOptionName, reinterpret_cast(optval), reinterpret_cast(poptlen))); + return( getsockopt( m_hSocket, nLevel, nOptionName, reinterpret_cast(optval), reinterpret_cast(poptlen))); } #ifdef _WIN32 @@ -457,7 +457,7 @@ int CSocket::GetSockOpt( int nOptionName, void * optval, int * poptlen, int nLev { // TO BE CALLED IN CClient destructor !!! CancelIo(reinterpret_cast(m_hSocket)); - SleepEx(1, TRUE); + SleepEx(1, TRUE); } #else diff --git a/src/sphere/ProfileData.cpp b/src/sphere/ProfileData.cpp index 9789a3334..f57a17358 100644 --- a/src/sphere/ProfileData.cpp +++ b/src/sphere/ProfileData.cpp @@ -1,5 +1,5 @@ -#include "../common/sphere_library/CSTime.h" +//#include "../common/sphere_library/CSTime.h" #include "../game/CScriptProfiler.h" #include "ProfileData.h" #include "threads.h" diff --git a/src/sphere/ntservice.cpp b/src/sphere/ntservice.cpp index 6e05dd8bf..f1b643d02 100644 --- a/src/sphere/ntservice.cpp +++ b/src/sphere/ntservice.cpp @@ -408,7 +408,7 @@ void CNTService::CmdRemoveService() while ( QueryServiceStatus(schService, &m_sStatus) ) // wait the service to stop { if ( m_sStatus.dwCurrentState == SERVICE_STOP_PENDING ) - Sleep(1000); + SLEEP(1000); else break; } diff --git a/src/sphere/threads.cpp b/src/sphere/threads.cpp index 23119d208..9eb3d26f6 100644 --- a/src/sphere/threads.cpp +++ b/src/sphere/threads.cpp @@ -643,10 +643,6 @@ void AbstractThread::onStart() // when implemented in derived classes this method must always be called too, preferably before // the custom implementation -#ifdef WINDOWS_SPHERE_SHOULD_HANDLE_STRUCTURED_EXCEPTIONS - SetWindowsStructuredExceptionTranslator(); -#endif - // we set the id here to ensure it is available before the first tick, otherwise there's // a small delay when setting it from AbstractThread::start and it's possible for the id // to not be set fast enough (particular when using pthreads) From e194ba7dafc56528b423fc2f1966c754be9f4f3a Mon Sep 17 00:00:00 2001 From: cbnolok Date: Mon, 7 Oct 2024 15:06:47 +0200 Subject: [PATCH 75/86] Fixed path concat regression and fixed come cmake options being loaded before being set. --- CMakeLists.txt | 101 +++++++++--------- cmake/toolchains/Windows-MSVC.cmake | 42 +++++--- .../include/Windows-Clang_common.inc.cmake | 6 +- .../include/Windows-GNU_common.inc.cmake | 2 +- src/common/CException.h | 6 +- src/common/crashdump/crashdump.h | 2 + src/common/sphere_library/CSFile.cpp | 7 +- src/game/CServer.cpp | 2 +- src/game/spheresvr.cpp | 8 +- src/sphere/threads.cpp | 4 +- 10 files changed, 104 insertions(+), 76 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 491c597a2..445f0334b 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -3,47 +3,6 @@ cmake_minimum_required(VERSION 3.24) set(CMAKE_SUPPRESS_REGENERATION TRUE) # Supress the ZERO_CHECK generation -# -------------------- GUI checkboxes -------------------- -if(NOT MSVC) - set (CMAKE_BUILD_TYPE "Nightly" CACHE STRING "Which build type to build? Expected values: Debug, Nightly or Release.") -endif() - -option( - CMAKE_NO_GIT_REVISION - "Do not try to retrieve the current git revision. Useful for building source not git-cloned from Github." - FALSE -) -option(CROSSCOMPILE "Are we compiling for a different target architecture?" FALSE) -option( - RUNTIME_STATIC_LINK - "Statically link inside the executable the runtime libraries? (MSVC, libc/libcc, libstdc++)." - FALSE -) -option(CMAKE_EXPORT_COMPILE_COMMANDS "Export compiler commands to compile_commands.json" TRUE) - -set(predef_LIB_LIBEV_BUILD FALSE) -if(NOT WIN32) - set(predef_LIB_LIBEV_BUILD TRUE) -endif() -option(LIB_LIBEV_BUILD "Build libev." ${predef_LIB_LIBEV_BUILD}) -option(LIB_SQLITE_BUILD "Build sqlite." TRUE) -option(LIB_ZLIB_BUILD "Build zlib." TRUE) - -if(WIN32) - option(WIN32_SPAWN_CONSOLE "Spawn an additional console, useful for debugging." FALSE) -endif() - -option(USE_COMPILER_HARDENING_OPTIONS "Enable compiler (even runtime) safety checks and code hardening." FALSE) -option(USE_ASAN "Enable AddressSanitizer." FALSE) -option(USE_UBSAN "Enable Undefined Behavior Sanitizer." FALSE) -option(USE_LSAN "Enable LeakSanitizer." FALSE) -option(USE_MSAN "Enable MemorySanitizer." FALSE) - -set(ENABLED_SANITIZER CACHE INTERNAL BOOL FALSE) -if(USE_ASAN OR USE_MSAN OR USE_LSAN OR USE_MSAN) - set(ENABLED_SANITIZER TRUE) -endif() - # -------------------- Utility functions -------------------- function(booleanize_str_find VAR) @@ -63,9 +22,14 @@ if((NOT TOOLCHAIN_LOADED) AND (NOT ${CMAKE_TOOLCHAIN_FILE} STREQUAL "")) endif() message(STATUS "Scanning system build tools...") - project(SphereServer CXX C) # does a scan for C++ and C compilers +# If we have not specified a toolchain, let's detect which one we should use, using the detected arch. +# We need to do this after "project", otherwise CMake doesn't know where it's running. +if(NOT TOOLCHAIN_LOADED) + include("cmake/DetectDefaultToolchain.cmake") +endif() + # Setup global flags, to be done before creating targets. if(NOT DEFINED CMAKE_CXX_STANDARD) @@ -109,16 +73,57 @@ set(CMAKE_EXE_LINKER_FLAGS_RELEASE "") # Also, it fails to create those predefined flags, which it needs, for custom build types (e.g. Nightly). set(CMAKE_EXE_LINKER_FLAGS_NIGHTLY "") +# -------------------- GUI checkboxes -------------------- + +option( + CMAKE_NO_GIT_REVISION + "Do not try to retrieve the current git revision. Useful for building source not git-cloned from Github." + FALSE +) +option(CROSSCOMPILE "Are we compiling for a different target architecture?" FALSE) +option( + RUNTIME_STATIC_LINK + "Statically link inside the executable the runtime libraries? (MSVC, libc/libcc, libstdc++)." + FALSE +) +option(CMAKE_EXPORT_COMPILE_COMMANDS "Export compiler commands to compile_commands.json" TRUE) + +set(predef_LIB_LIBEV_BUILD FALSE) +if(NOT WIN32) + set(predef_LIB_LIBEV_BUILD TRUE) +endif() +option(LIB_LIBEV_BUILD "Build libev." ${predef_LIB_LIBEV_BUILD}) +option(LIB_SQLITE_BUILD "Build sqlite." TRUE) +option(LIB_ZLIB_BUILD "Build zlib." TRUE) + +if(WIN32) + option(WIN_SPAWN_CONSOLE "Spawn an additional console, useful for debugging." FALSE) + if(MSVC) + option(WIN_GENERATE_CRASHDUMP "For non-Debug builds, add Windows Structured Exception Handling and generate a Crash Dump if a fatal SE is thrown." FALSE) + endif() +endif() + +if(NOT MSVC) + option(USE_COMPILER_HARDENING_OPTIONS "Enable compiler (even runtime) safety checks and code hardening." FALSE) +endif() +option(USE_ASAN "Enable AddressSanitizer." FALSE) +option(USE_UBSAN "Enable Undefined Behavior Sanitizer." FALSE) +option(USE_LSAN "Enable LeakSanitizer." FALSE) +option(USE_MSAN "Enable MemorySanitizer." FALSE) + +set(ENABLED_SANITIZER CACHE INTERNAL BOOL FALSE) +if(USE_ASAN OR USE_MSAN OR USE_LSAN OR USE_MSAN) + set(ENABLED_SANITIZER TRUE) +endif() + + +# -------------------- Stuff to set right away, after having parsed the checkboxes/CLI arguments. set(is_win32_app_linker) -if(WIN32 AND NOT ${WIN32_SPAWN_CONSOLE}) +if(WIN32 AND NOT ${WIN_SPAWN_CONSOLE}) set(is_win32_app_linker WIN32) # if not set, it defaults to console subsystem endif() -# If we have not specified a toolchain, let's detect which one we should use, using the detected arch. -if(NOT TOOLCHAIN_LOADED) - include("cmake/DetectDefaultToolchain.cmake") -endif() # -------------------- Stuff that needs to be executed after PROJECT but before ADD_EXECUTABLE @@ -137,9 +142,9 @@ endif() # TODO: check if Ninja can handle different targets. if(SINGLE_TARGET) # If you want to manually specify the build type, call cmake with parameter: -DCMAKE_BUILD_TYPE=something - # TODO: add NightlyWithDebInfo ? message(STATUS "Single-target build system (${CMAKE_GENERATOR}) detected: generating multiple projects!") + set (CMAKE_BUILD_TYPE "Nightly" CACHE STRING "Set the build type. Expected values: Debug, Nightly or Release.") # Set only if unset. set_property(CACHE CMAKE_BUILD_TYPE PROPERTY STRINGS "Debug" "Nightly" "Release") if(NOT ${CMAKE_BUILD_TYPE} STREQUAL "") if( diff --git a/cmake/toolchains/Windows-MSVC.cmake b/cmake/toolchains/Windows-MSVC.cmake index 3994a6e7f..4df3bad9f 100644 --- a/cmake/toolchains/Windows-MSVC.cmake +++ b/cmake/toolchains/Windows-MSVC.cmake @@ -34,7 +34,7 @@ function(toolchain_exe_stuff) #-- Configure the Windows application type and add global linker flags. - if(${WIN32_SPAWN_CONSOLE}) + if(${WIN_SPAWN_CONSOLE}) add_link_options("LINKER:/ENTRY:WinMainCRTStartup") # Handled by is_win32_app_linker -> "LINKER:/SUBSYSTEM:CONSOLE" set(PREPROCESSOR_DEFS_EXTRA _WINDOWS_CONSOLE) #ELSE () @@ -102,16 +102,28 @@ function(toolchain_exe_stuff) endif() set(cxx_compiler_flags_common ${cxx_compiler_flags_common} /Zc:preprocessor ${local_msvc_compat_options}) - # Needed, otherwise throws a error... Regression? + # Needed, otherwise throws a error... Regression in CMake? set(CMAKE_C_FLAGS_DEBUG_INIT "" INTERNAL) set(CMAKE_CXX_FLAGS_DEBUG_INIT "" INTERNAL) + if(RUNTIME_STATIC_LINK) + set(local_msvc_cmdline_runtime_lib_debug /MTd) + set(local_msvc_cmdline_runtime_lib_nondebug /MT) + else() + set(local_msvc_cmdline_runtime_lib_debug /MDd) + set(local_msvc_cmdline_runtime_lib_nondebug /MD) + endif() + if(WIN_GENERATE_CRASHDUMP) + set(local_msvc_cmdline_exception_handler /EHa) + else() + set(local_msvc_exception_handler /EHsc) + endif() # gersemi: off target_compile_options(spheresvr PRIVATE ${cxx_compiler_flags_common} - $<$: $,/MT,/MD> /EHa /Oy /GL /GA /Gw /Gy /GF $,/O1 /Zi,/O2>> - $<$: $,/MT,/MD> /EHa /Oy /GL /GA /Gw /Gy /GF $,/O1 /Zi,/O2>> - $<$: $,/MTd,/MDd> /EHsc /Oy- /ob1 /Od /Gs $,/Zi,/ZI>> + $<$: ${local_msvc_cmdline_runtime_lib_nondebug} ${local_msvc_exception_handler} /Oy /GL /GA /Gw /Gy /GF $,/O1 /Zi,/O2>> + $<$: ${local_msvc_cmdline_runtime_lib_nondebug} ${local_msvc_exception_handler} /Oy /GL /GA /Gw /Gy /GF $,/O1 /Zi,/O2>> + $<$: ${local_msvc_cmdline_runtime_lib_debug} /EHsc /Oy- /ob1 /Od /Gs $,/Zi,/ZI>> # ASan (and compilation for ARM arch) doesn't support edit and continue option (ZI) ) # gersemi: on @@ -119,7 +131,6 @@ function(toolchain_exe_stuff) if("${ARCH}" STREQUAL "x86_64") target_compile_options(spheresvr PRIVATE /arch:SSE2) endif() - #-- Apply linker flags. # For some reason only THIS one isn't created, and CMake complains with an error... @@ -143,11 +154,13 @@ function(toolchain_exe_stuff) #-- Set define macros. # Common defines + #gersemi: off target_compile_definitions( spheresvr PRIVATE ${PREPROCESSOR_DEFS_EXTRA} - $<$>:_GITVERSION> + $<$>: + _GITVERSION> _CRT_SECURE_NO_WARNINGS # Temporary setting _CRT_SECURE_NO_WARNINGS to do not spam so much in the build proccess. _EXCEPTIONS_DEBUG @@ -157,15 +170,18 @@ function(toolchain_exe_stuff) # Removing WINSOCK warnings until the code gets updated or reviewed. # Per-build defines $<$>: - NDEBUG> + NDEBUG> $<$: - _NIGHTLYBUILD - THREAD_TRACK_CALLSTACK> + _NIGHTLYBUILD + THREAD_TRACK_CALLSTACK> $<$: - _DEBUG - THREAD_TRACK_CALLSTACK - _PACKETDUMP> + _DEBUG + THREAD_TRACK_CALLSTACK + _PACKETDUMP> + $<$: + WINDOWS_GENERATE_CRASHDUMP> ) + #gersemi: on #-- Custom output directory. diff --git a/cmake/toolchains/include/Windows-Clang_common.inc.cmake b/cmake/toolchains/include/Windows-Clang_common.inc.cmake index a01a37d09..bf2094af3 100644 --- a/cmake/toolchains/include/Windows-Clang_common.inc.cmake +++ b/cmake/toolchains/include/Windows-Clang_common.inc.cmake @@ -14,13 +14,13 @@ endfunction() function(toolchain_exe_stuff_common) #-- Configure the Windows application type and add global linker flags. - if(${WIN32_SPAWN_CONSOLE}) + if(${WIN_SPAWN_CONSOLE}) set(PREPROCESSOR_DEFS_EXTRA _WINDOWS_CONSOLE) if(${CLANG_USE_GCC_LINKER}) # --entry might not work - add_link_options("LINKER:--entry=WinMainCRTStartup") # Handled by is_win32_app_linker -> "LINKER:SHELL:-m$,CONSOLE,WINDOWS>" + add_link_options("LINKER:--entry=WinMainCRTStartup") # Handled by is_win32_app_linker -> "LINKER:SHELL:-m$,CONSOLE,WINDOWS>" else() - add_link_options("LINKER:/ENTRY:WinMainCRTStartup") # Handled by is_win32_app_linker -> "LINKER:SHELL:/SUBSYSTEM:$,CONSOLE,WINDOWS>" + add_link_options("LINKER:/ENTRY:WinMainCRTStartup") # Handled by is_win32_app_linker -> "LINKER:SHELL:/SUBSYSTEM:$,CONSOLE,WINDOWS>" endif() endif() diff --git a/cmake/toolchains/include/Windows-GNU_common.inc.cmake b/cmake/toolchains/include/Windows-GNU_common.inc.cmake index 0dfdb2968..c2a90d51f 100644 --- a/cmake/toolchains/include/Windows-GNU_common.inc.cmake +++ b/cmake/toolchains/include/Windows-GNU_common.inc.cmake @@ -9,7 +9,7 @@ function(toolchain_exe_stuff_common) #-- Configure the Windows application type. # Subsystem is already managed by is_win32_app_linker. GCC doesn't need us to specify the entry point. - #IF (${WIN32_SPAWN_CONSOLE}) + #IF (${WIN_SPAWN_CONSOLE}) # add_link_options ("LINKER:SHELL:-mconsole") # SET (PREPROCESSOR_DEFS_EXTRA _WINDOWS_CONSOLE) ##ELSE () diff --git a/src/common/CException.h b/src/common/CException.h index b141afcd3..4a121107f 100644 --- a/src/common/CException.h +++ b/src/common/CException.h @@ -13,13 +13,13 @@ # define WINDOWS_HAS_SEH 1 #endif -#if defined (WINDOWS_HAS_SEH) && defined(_NIGHTLYBUILD) +#if defined(WINDOWS_HAS_SEH) && defined(WINDOWS_GENERATE_CRASHDUMP) // We don't want this for Release build because, in order to call _set_se_translator, we should set the /EHa // compiler flag, which slows down code a bit. # define WINDOWS_SPHERE_SHOULD_HANDLE_STRUCTURED_EXCEPTIONS 1 -#endif +//#endif -#if defined(WINDOWS_SPHERE_SHOULD_HANDLE_STRUCTURED_EXCEPTIONS) && !defined(_NO_CRASHDUMP) +//2#if defined(WINDOWS_SPHERE_SHOULD_HANDLE_STRUCTURED_EXCEPTIONS) && defined(WINDOWS_GENERATE_CRASHDUMP) // Also, the crash dump generating code works only when Structured Exception Handling is enabled # define WINDOWS_SHOULD_EMIT_CRASH_DUMP 1 #endif diff --git a/src/common/crashdump/crashdump.h b/src/common/crashdump/crashdump.h index 5de0b33ef..401727ee7 100644 --- a/src/common/crashdump/crashdump.h +++ b/src/common/crashdump/crashdump.h @@ -3,6 +3,8 @@ #include +// TODO: enable creation of the crash dump also for mingw, since it can manage windows structured exceptions. + #ifndef WIN32_LEAN_AND_MEAN #define WIN32_LEAN_AND_MEAN // include just windows.h without the other winapi headers, we'll add them manually when needed #endif diff --git a/src/common/sphere_library/CSFile.cpp b/src/common/sphere_library/CSFile.cpp index 513bf8793..b652df0ec 100644 --- a/src/common/sphere_library/CSFile.cpp +++ b/src/common/sphere_library/CSFile.cpp @@ -438,14 +438,17 @@ CSString CSFile::GetMergedFileName( lpctstr pszBase, lpctstr pszName ) // static size_t len = 0; if ( pszBase && pszBase[0] ) { - len = Str_CopyLimitNull( ptcFilePath, pszBase, sizeof(ptcFilePath) - 1); // eventually, leave space for the (back)slash - if (len && ptcFilePath[len - 1] != '\\' && ptcFilePath[len - 1] != '/') + len = Str_CopyLimitNull(ptcFilePath, pszBase, sizeof(ptcFilePath) - 1); // eventually, leave space for the (back)slash + if ((len > 1) && (ptcFilePath[len - 1] != '\\') && (ptcFilePath[len - 1] != '/')) { + // Append the slash/backslash, overwriting the string terminator. #ifdef _WIN32 ptcFilePath[len] = '\\'; #else ptcFilePath[len] = '/'; #endif + // Add back the string terminator. We're sure we won't overflow since we passed sizeof(ptcFilePath) - 1. + ptcFilePath[len + 1] = '\0'; } } else diff --git a/src/game/CServer.cpp b/src/game/CServer.cpp index 5e35bacd6..e821780e3 100644 --- a/src/game/CServer.cpp +++ b/src/game/CServer.cpp @@ -2361,7 +2361,7 @@ bool CServer::CommandLine( int argc, tchar * argv[] ) } } continue; -#if defined(_WIN32) && !defined(_DEBUG) && !defined(_NO_CRASHDUMP) +#if defined(_WIN32) && !defined(_DEBUG) && defined(WINDOWS_GENERATE_CRASHDUMP) case 'E': CrashDump::Enable(); if (CrashDump::IsEnabled()) diff --git a/src/game/spheresvr.cpp b/src/game/spheresvr.cpp index 12708dc69..6f7fdeb5a 100644 --- a/src/game/spheresvr.cpp +++ b/src/game/spheresvr.cpp @@ -207,16 +207,16 @@ bool MainThread::shouldExit() noexcept static bool WritePidFile(int iMode = 0) { - lpctstr file = SPHERE_FILE ".pid"; + lpctstr fileName = SPHERE_FILE ".pid"; FILE* pidFile; if (iMode == 1) // delete { - return (STDFUNC_UNLINK(file) == 0); + return (STDFUNC_UNLINK(fileName) == 0); } else if (iMode == 2) // check for .pid file { - pidFile = fopen(file, "r"); + pidFile = fopen(fileName, "r"); if (pidFile) { g_Log.Event(LOGM_INIT, SPHERE_FILE ".pid already exists. Secondary launch or unclean shutdown?\n"); @@ -226,7 +226,7 @@ static bool WritePidFile(int iMode = 0) } else { - pidFile = fopen(file, "w"); + pidFile = fopen(fileName, "w"); if (pidFile) { pid_t spherepid = STDFUNC_GETPID(); diff --git a/src/sphere/threads.cpp b/src/sphere/threads.cpp index 9eb3d26f6..aacad6db1 100644 --- a/src/sphere/threads.cpp +++ b/src/sphere/threads.cpp @@ -178,7 +178,8 @@ void ThreadHolder::push(AbstractThread *thread) noexcept { //throw CSError(LOGL_FATAL, 0, "AbstractThread not being an AbstractSphereThread?"); STDERR_LOG("AbstractThread not being an AbstractSphereThread?"); - fExceptionThrown = true; + //fExceptionThrown = true; + goto soft_throw; } std::unique_lock lock(m_mutex); @@ -223,6 +224,7 @@ void ThreadHolder::push(AbstractThread *thread) noexcept if (fExceptionThrown) { +soft_throw: // Should never happen. RaiseImmediateAbort(); } From 621c62d5f92e3c09756ef90295f04f372cdab249 Mon Sep 17 00:00:00 2001 From: cbnolok Date: Sun, 13 Oct 2024 18:22:11 +0200 Subject: [PATCH 76/86] Fixed settings DIR and FLAGS not sending a full client update, minor change to client update packet. --- src/common/common.h | 27 +++++++++++++++++ src/common/resource/sections/CSkillDef.cpp | 6 ++-- src/common/sphere_library/CSObjList.cpp | 14 +++++++-- src/game/CObjBaseTemplate.h | 6 ++-- src/game/CSector.cpp | 2 +- src/game/CServer.cpp | 3 +- src/game/chars/CChar.cpp | 21 ++++++++----- src/game/chars/CChar.h | 12 +++++--- src/game/chars/CCharAct.cpp | 14 ++++----- src/game/chars/CCharNotoriety.cpp | 4 +-- src/game/chars/CCharSkill.cpp | 2 +- src/game/chars/CCharSpell.cpp | 6 ++-- src/game/chars/CCharStatus.cpp | 5 ++-- src/game/clients/CClientEvent.cpp | 2 +- src/game/items/CItem.cpp | 35 ++++++++++++++-------- src/game/items/CItem.h | 6 ++-- src/network/CClientIterator.cpp | 18 +++++++++++ src/network/CNetState.cpp | 2 +- src/network/CNetworkManager.cpp | 5 ++-- src/network/send.cpp | 6 ++-- 20 files changed, 138 insertions(+), 58 deletions(-) diff --git a/src/common/common.h b/src/common/common.h index 9932c6fd5..1b20d9a8b 100644 --- a/src/common/common.h +++ b/src/common/common.h @@ -140,6 +140,27 @@ constexpr T sign(const T n) noexcept #define maximum(x,y) ((x)>(y)?(x):(y)) // NOT to be used with functions! Store the result of the function in a variable first, otherwise the function will be executed twice! #define medium(x,y,z) ((x)>(y)?(x):((z)<(y)?(z):(y))) // NOT to be used with functions! Store the result of the function in a variable first, otherwise the function will be executed twice! +template +[[nodiscard]] +constexpr T saturating_sub(T a, T b) noexcept { + // Saturating subtraction. + + // Ensure T is an arithmetic type + static_assert(std::is_arithmetic_v, "T must be an arithmetic type"); + + // For unsigned types + if constexpr (std::is_unsigned_v) + return (a > b) ? a - b : 0; + // For signed types + else + { + if (b > 0 && a < std::numeric_limits::min() + b) + return std::numeric_limits::min(); // Saturate to minimum + return a - b; + } +} + +#define SATURATING_SUB_SELF(var, val) var = saturating_sub(var, val) /* End of arithmetic code */ @@ -197,6 +218,12 @@ constexpr void UnreferencedParameter(T const&) noexcept { #define FALLTHROUGH [[fallthrough]] #define NODISCARD [[nodiscard]] +#if defined(__GNUC__) || defined(__clang__) +# define RETURNS_NOTNULL [[gnu::returns_nonnull]] +#else +# define RETURNS_NOTNULL +#endif + #ifdef _DEBUG #define NOEXCEPT_NODEBUG #else diff --git a/src/common/resource/sections/CSkillDef.cpp b/src/common/resource/sections/CSkillDef.cpp index e64bebc22..621a75f53 100644 --- a/src/common/resource/sections/CSkillDef.cpp +++ b/src/common/resource/sections/CSkillDef.cpp @@ -191,10 +191,10 @@ bool CSkillDef::r_LoadVal( CScript &s ) m_vcDelay.Load( s.GetArgStr()); break; case SKC_FLAGS: - m_dwFlags = s.GetArgVal(); + m_dwFlags = s.GetArgDWVal(); break; case SKC_GROUP: - m_dwGroup = s.GetArgVal(); + m_dwGroup = s.GetArgDWVal(); break; case SKC_EFFECT: m_vcEffect.Load( s.GetArgStr()); @@ -246,4 +246,4 @@ bool CSkillDef::r_LoadVal( CScript &s ) EXC_ADD_SCRIPT; EXC_DEBUG_END; return false; -} \ No newline at end of file +} diff --git a/src/common/sphere_library/CSObjList.cpp b/src/common/sphere_library/CSObjList.cpp index 35fafb63d..a66cad392 100644 --- a/src/common/sphere_library/CSObjList.cpp +++ b/src/common/sphere_library/CSObjList.cpp @@ -56,18 +56,26 @@ CSObjListRec * CSObjList::GetContentAt( size_t index ) const void CSObjList::ClearContainer() { // delete all entries. + bool fSuccess = false; EXC_TRY("Deleting objects scheduled for deletion"); for (;;) // iterate the list. { CSObjListRec * pRec = GetContainerHead(); - if ( pRec == nullptr ) - break; + if ( pRec == nullptr ) { + fSuccess = true; + break; + } ASSERT( pRec->GetParent() == this ); delete pRec; } EXC_CATCH; - m_uiCount = 0; + if (fSuccess) { + ASSERT(m_uiCount == 0); + } + else { + m_uiCount = 0; + } m_pHead = nullptr; m_pTail = nullptr; } diff --git a/src/game/CObjBaseTemplate.h b/src/game/CObjBaseTemplate.h index af8a2ec44..adb470413 100644 --- a/src/game/CObjBaseTemplate.h +++ b/src/game/CObjBaseTemplate.h @@ -71,10 +71,12 @@ class CObjBaseTemplate : public CSObjContRec virtual int IsWeird() const; // Parent objects - virtual const CObjBaseTemplate* GetTopLevelObj() const { + [[nodiscard]] RETURNS_NOTNULL + virtual const CObjBaseTemplate* GetTopLevelObj() const { return this; } - virtual CObjBaseTemplate* GetTopLevelObj() { + [[nodiscard]] RETURNS_NOTNULL + virtual CObjBaseTemplate* GetTopLevelObj() { return this; } diff --git a/src/game/CSector.cpp b/src/game/CSector.cpp index bf6402cfe..c931c7715 100644 --- a/src/game/CSector.cpp +++ b/src/game/CSector.cpp @@ -284,7 +284,7 @@ bool CSector::r_LoadVal( CScript &s ) SetWeatherChance( false, s.HasArgs() ? s.GetArgVal() : -1 ); return true; case SC_FLAGS: - m_dwFlags = s.GetArgVal(); + m_dwFlags = s.GetArgDWVal(); return true; case SC_LIGHT: if ( g_Cfg.m_fAllowLightOverride ) diff --git a/src/game/CServer.cpp b/src/game/CServer.cpp index e821780e3..007c9890d 100644 --- a/src/game/CServer.cpp +++ b/src/game/CServer.cpp @@ -2540,7 +2540,8 @@ void CServer::_OnTick() EXC_TRY("Tick"); #ifndef _WIN32 - if (g_UnixTerminal.isReady()) + // This happens on T_Main, and not on T_UnixTerm. + if (g_UnixTerminal.isReady()) { tchar c = g_UnixTerminal.read(); if ( OnConsoleKey(m_sConsoleText, c, false) == 2 ) diff --git a/src/game/chars/CChar.cpp b/src/game/chars/CChar.cpp index 4a327c08a..a4ac213d8 100644 --- a/src/game/chars/CChar.cpp +++ b/src/game/chars/CChar.cpp @@ -1642,7 +1642,7 @@ void CChar::SetID( CREID_TYPE id ) if ( pHand ) GetPackSafe()->ContentAdd(pHand); } - UpdateMode(nullptr, true); + UpdateMode(true, nullptr); } @@ -3828,7 +3828,6 @@ bool CChar::r_LoadVal( CScript & s ) DIR_TYPE dir = static_cast(s.GetArgVal()); if (dir <= DIR_INVALID || dir >= DIR_QTY) dir = DIR_SE; - m_dirFace = dir; UpdateDir( dir ); } break; @@ -3856,8 +3855,16 @@ bool CChar::r_LoadVal( CScript & s ) break; } // Don't modify STATF_SAVEPARITY, STATF_PET, STATF_SPAWNED here - _uiStatFlag = (_uiStatFlag & (STATF_SAVEPARITY | STATF_PET | STATF_SPAWNED)) | (s.GetArgLLVal() & ~(STATF_SAVEPARITY | STATF_PET | STATF_SPAWNED)); - NotoSave_Update(); + static constexpr auto uiFlagsNoChange = (STATF_SAVEPARITY | STATF_PET | STATF_SPAWNED); + static constexpr auto uiFlagsRequireFullUpdate = (STATF_STONE | STATF_HIDDEN | STATF_DEAD); + const auto uiCurFlags = _uiStatFlag; + const auto uiNewFlags = s.GetArgULLVal(); + _uiStatFlag = (_uiStatFlag & uiFlagsNoChange) | (uiNewFlags & ~uiFlagsNoChange); + if (uiCurFlags != uiNewFlags) + { + const bool fDoFullUpdate = (uiCurFlags & uiFlagsRequireFullUpdate) != (uiNewFlags & uiFlagsRequireFullUpdate); + NotoSave_Update(fDoFullUpdate); + } break; } case CHC_FONT: @@ -4010,7 +4017,7 @@ bool CChar::r_LoadVal( CScript & s ) StatFlag_Mod(STATF_STONE,fSet); if ( fChange ) { - UpdateMode(nullptr, true); + UpdateMode(true, nullptr); if ( IsClientActive() ) m_pClient->addCharMove(this); } @@ -4636,7 +4643,7 @@ bool CChar::r_Verb( CScript &s, CTextConsole * pSrc ) // Execute command from sc if ( pSrc ) { _uiStatFlag = s.GetArgLLFlag( _uiStatFlag, STATF_INSUBSTANTIAL ); - UpdateMode(nullptr, true); + UpdateMode(true, nullptr); if ( IsStatFlag(STATF_INSUBSTANTIAL) ) { if ( IsClientActive() ) @@ -4923,7 +4930,7 @@ bool CChar::r_Verb( CScript &s, CTextConsole * pSrc ) // Execute command from sc if ( ! IsPlayableCharacter()) return false; SetHue( GetHue() ^ HUE_UNDERWEAR /*, false, pSrc*/ ); //call @Dye on underwear? - UpdateMode(); + UpdateMode(true, nullptr); break; case CHV_UNEQUIP: // uid return ItemBounce( CUID::ItemFindFromUID(s.GetArgVal()) ); diff --git a/src/game/chars/CChar.h b/src/game/chars/CChar.h index 3ea4fa13f..35a5edff1 100644 --- a/src/game/chars/CChar.h +++ b/src/game/chars/CChar.h @@ -495,8 +495,10 @@ public: void StatFlag_Mod(uint64 uiStatFlag, bool fMod) noexcept; bool IsVerticalSpace( const CPointMap& ptDest, bool fForceMount = false ) const; public: - virtual CObjBaseTemplate* GetTopLevelObj() override; - virtual const CObjBaseTemplate* GetTopLevelObj() const override; + [[nodiscard]] RETURNS_NOTNULL + virtual CObjBaseTemplate* GetTopLevelObj() override; + [[nodiscard]] RETURNS_NOTNULL + virtual const CObjBaseTemplate* GetTopLevelObj() const override; bool IsSwimming() const; bool MoveToRegion(CRegionWorld* pNewArea, bool fAllowReject); @@ -555,7 +557,7 @@ public: void StatFlag_Mod(uint64 uiStatFlag, bool fMod) noexcept; ANIM_TYPE GenerateAnimate(ANIM_TYPE action, bool fTranslate = true, bool fBackward = false, byte iFrameDelay = 0, byte iAnimLen = 7); bool UpdateAnimate(ANIM_TYPE action, bool fTranslate = true, bool fBackward = false, byte iFrameDelay = 0, byte iAnimLen = 7); - void UpdateMode( CClient * pExcludeClient = nullptr, bool fFull= false ); + void UpdateMode( bool fFull, CClient * pExcludeClient = nullptr); void UpdateSpeedMode(); void UpdateVisualRange(); void UpdateMove( const CPointMap & ptOld, CClient * pClientExclude = nullptr, bool bFull = false ); @@ -821,8 +823,10 @@ public: void StatFlag_Mod(uint64 uiStatFlag, bool fMod) noexcept; /** * @brief Clearing notoriety and update myself so everyone checks my noto again. + * + * @param fCharFullUpdate Should it do a full character entity update instead of a partial one? */ - void NotoSave_Update(); + void NotoSave_Update(bool fCharFullUpdate = false); /** * @brief Deleting myself and sending data again for given char. diff --git a/src/game/chars/CCharAct.cpp b/src/game/chars/CCharAct.cpp index e07bd77c0..b4c427f1a 100644 --- a/src/game/chars/CCharAct.cpp +++ b/src/game/chars/CCharAct.cpp @@ -2428,7 +2428,7 @@ bool CChar::UpdateAnimate(ANIM_TYPE action, bool fTranslate, bool fBackward , by // If character status has been changed // (Polymorph, war mode or hide), resend him -void CChar::UpdateMode( CClient * pExcludeClient, bool fFull ) +void CChar::UpdateMode( bool fFull, CClient * pExcludeClient ) { ADDTOCALLSTACK("CChar::UpdateMode"); @@ -3524,7 +3524,7 @@ bool CChar::Reveal( uint64 iFlags ) return false; m_StepStealth = 0; - UpdateMode(nullptr, true); + UpdateMode(true, nullptr); SysMessageDefault(DEFMSG_HIDING_REVEALED); return true; } @@ -4222,8 +4222,6 @@ bool CChar::SetPoison( int iSkill, int iHits, CChar * pCharSrc ) } } - - CClient *pClient = GetClientActive(); if ( pClient && IsSetOF(OF_Buffs) ) { @@ -4253,7 +4251,7 @@ void CChar::Wake() RaiseCorpse(pCorpse); StatFlag_Clear(STATF_SLEEPING); - UpdateMode(); + UpdateMode(false, nullptr); } // Sleep @@ -4277,7 +4275,7 @@ void CChar::SleepStart( bool fFrontFall ) SetID(_iPrev_id); StatFlag_Set(STATF_SLEEPING); StatFlag_Clear(STATF_HIDDEN); - UpdateMode(); + UpdateMode(false, nullptr); } // We died, calling @Death, removing trade windows. @@ -4406,7 +4404,7 @@ CChar::DeathRequestResult CChar::Death() if ( m_pNPC->m_bonded ) { m_CanMask |= CAN_C_GHOST; - UpdateMode(nullptr, true); + UpdateMode(true, nullptr); return DeathRequestResult::Success; } @@ -5686,7 +5684,7 @@ void CChar::OnTickStatusUpdate() if ( m_fStatusUpdate & SU_UPDATE_MODE ) { - UpdateMode(); + UpdateMode(false, nullptr); m_fStatusUpdate &= ~SU_UPDATE_MODE; } diff --git a/src/game/chars/CCharNotoriety.cpp b/src/game/chars/CCharNotoriety.cpp index e5d561103..c3880442b 100644 --- a/src/game/chars/CCharNotoriety.cpp +++ b/src/game/chars/CCharNotoriety.cpp @@ -712,13 +712,13 @@ void CChar::NotoSave_Clear() m_notoSaves.clear(); } -void CChar::NotoSave_Update() +void CChar::NotoSave_Update(bool fCharFullUpdate) { //ADDTOCALLSTACK_DEBUG("CChar::NotoSave_Update"); EXC_TRY("NotoSave_Update"); NotoSave_Clear(); - UpdateMode(); + UpdateMode(fCharFullUpdate, nullptr); UpdatePropertyFlag(); EXC_CATCH; diff --git a/src/game/chars/CCharSkill.cpp b/src/game/chars/CCharSkill.cpp index 5721611b1..fe11e036f 100644 --- a/src/game/chars/CCharSkill.cpp +++ b/src/game/chars/CCharSkill.cpp @@ -2438,7 +2438,7 @@ int CChar::Skill_Hiding( SKTRIG_TYPE stage ) ObjMessage(g_Cfg.GetDefaultMsg(DEFMSG_HIDING_SUCCESS), this); StatFlag_Set(STATF_HIDDEN); Reveal(STATF_INVISIBLE); // clear previous invisibility spell effect (this will not reveal the char because STATF_HIDDEN still set) - UpdateMode(nullptr, true); + UpdateMode(true, nullptr); if ( IsClientActive() ) { GetClientActive()->removeBuff( BI_HIDDEN ); diff --git a/src/game/chars/CCharSpell.cpp b/src/game/chars/CCharSpell.cpp index 8e7d62f1f..d68bf7da3 100644 --- a/src/game/chars/CCharSpell.cpp +++ b/src/game/chars/CCharSpell.cpp @@ -701,7 +701,7 @@ void CChar::Spell_Effect_Remove(CItem * pSpell) case LAYER_SPELL_Paralyze: StatFlag_Clear(STATF_FREEZE); - UpdateMode(); // immediately tell the client that now he's able to move (without this, it will be able to move only on next tick update) + UpdateMode(false, nullptr); // immediately tell the client that now he's able to move (without this, it will be able to move only on next tick update) if (pClient) pClient->removeBuff(BI_PARALYZE); return; @@ -1183,7 +1183,7 @@ void CChar::Spell_Effect_Add( CItem * pSpell ) StatFlag_Set(STATF_INVISIBLE); Reveal(STATF_HIDDEN); // clear previous Hiding skill effect (this will not reveal the char because STATF_Invisibility still set) UpdateModeFlag(); - UpdateMode(nullptr, true); + UpdateMode(true, nullptr); if (pClient && IsSetOF(OF_Buffs)) { pClient->removeBuff(BI_INVISIBILITY); @@ -1192,7 +1192,7 @@ void CChar::Spell_Effect_Add( CItem * pSpell ) return; case LAYER_SPELL_Paralyze: StatFlag_Set(STATF_FREEZE); - UpdateMode(); + UpdateMode(false, nullptr); if (pClient && IsSetOF(OF_Buffs)) { pClient->removeBuff(BI_PARALYZE); diff --git a/src/game/chars/CCharStatus.cpp b/src/game/chars/CCharStatus.cpp index 2dd9cfbdd..32c20165e 100644 --- a/src/game/chars/CCharStatus.cpp +++ b/src/game/chars/CCharStatus.cpp @@ -486,13 +486,14 @@ int CChar::GetStatPercent(STAT_TYPE i) const return IMulDiv(Stat_GetVal(i), 100, maxval); } - +[[nodiscard]] RETURNS_NOTNULL const CObjBaseTemplate* CChar::GetTopLevelObj() const { // Get the object that has a location in the world. (Ground level) return this; } +[[nodiscard]] RETURNS_NOTNULL CObjBaseTemplate* CChar::GetTopLevelObj() { // Get the object that has a location in the world. (Ground level) @@ -692,7 +693,7 @@ byte CChar::GetModeFlag( const CClient *pViewer ) const iFlags |= STATF_INVISIBLE; if ( IsStatFlag(iFlags) ) // Checking if I have any of these settings enabled on the ini and I have any of them, if so ... CHARMODE_INVIS is set and color applied. - mode |= CHARMODE_INVIS; //When sending CHARMODE_INVIS state to client, your character anim are grey + mode |= CHARMODE_INVIS; //When sending CHARMODE_INVIS state to client, your character anim are grey return mode; } diff --git a/src/game/clients/CClientEvent.cpp b/src/game/clients/CClientEvent.cpp index 84177d14d..c4ecc42ff 100644 --- a/src/game/clients/CClientEvent.cpp +++ b/src/game/clients/CClientEvent.cpp @@ -1032,7 +1032,7 @@ void CClient::Event_CombatMode( bool fWar ) // Only for switching to combat mode } addPlayerWarMode(); - m_pChar->UpdateMode( this, m_pChar->IsStatFlag( STATF_DEAD )); + m_pChar->UpdateMode(m_pChar->IsStatFlag(STATF_DEAD), this); } bool CClient::Event_Command(lpctstr pszCommand, TALKMODE_TYPE mode) diff --git a/src/game/items/CItem.cpp b/src/game/items/CItem.cpp index 4c1277f08..fba785497 100644 --- a/src/game/items/CItem.cpp +++ b/src/game/items/CItem.cpp @@ -367,7 +367,7 @@ CItem * CItem::CreateBase( ITEMID_TYPE id, IT_TYPE type ) // static ASSERT(pItem); pItem->SetType(type, false); - if (idErrorMsg && idErrorMsg != (ITEMID_TYPE)-1) + if (idErrorMsg && idErrorMsg != (ITEMID_TYPE)-1) DEBUG_ERR(("CreateBase invalid item ID=0%" PRIx32 ", defaulting to ID=0%" PRIx32 ". Created UID=0%" PRIx32 "\n", idErrorMsg, id, (dword)pItem->GetUID())); return pItem; @@ -1953,9 +1953,17 @@ lpctstr CItem::GetNameFull( bool fIdentified ) const // Who is it stolen from ? const CChar * pChar = m_uidLink.CharFind(); if ( pChar ) - len += snprintf(pTemp + len, Str_TempLength() - len, " (%s %s)", g_Cfg.GetDefaultMsg( DEFMSG_ITEMTITLE_STOLEN_FROM ), pChar->GetName()); - else - len += snprintf(pTemp + len, Str_TempLength() - len, " (%s)", g_Cfg.GetDefaultMsg( DEFMSG_ITEMTITLE_STOLEN ) ); + { + /*len +=*/ snprintf(pTemp + len, Str_TempLength() - len, + " (%s %s)", + g_Cfg.GetDefaultMsg( DEFMSG_ITEMTITLE_STOLEN_FROM ), pChar->GetName()); + } + else + { + /*len +=*/ snprintf(pTemp + len, Str_TempLength() - len, + " (%s)", + g_Cfg.GetDefaultMsg( DEFMSG_ITEMTITLE_STOLEN ) ); + } } return pTemp; @@ -4097,6 +4105,7 @@ CItem* CItem::GetTopContainer() return (pItem == this) ? nullptr : pItem; } +[[nodiscard]] RETURNS_NOTNULL const CObjBaseTemplate* CItem::GetTopLevelObj() const { // recursively get the item that is at "top" level. @@ -4108,6 +4117,7 @@ const CObjBaseTemplate* CItem::GetTopLevelObj() const return pObj->GetTopLevelObj(); } +[[nodiscard]] RETURNS_NOTNULL CObjBaseTemplate* CItem::GetTopLevelObj() { // recursively get the item that is at "top" level. @@ -5060,7 +5070,8 @@ lpctstr CItem::Use_SpyGlass( CChar * pUser ) const WEATHER_TYPE wtWeather = ptCoords.GetSector()->GetWeather(); byte iLight = ptCoords.GetSector()->GetLight(); CSString sSearch; - tchar *pResult = Str_GetTemp(); + tchar *pResult = Str_GetTemp(); + size_t uiResultStrAvailableLen = Str_TempLength(); // Weather bonus double rWeatherSight = wtWeather == WEATHER_RAIN ? (0.25 * bSight) : 0.0; @@ -5118,7 +5129,7 @@ lpctstr CItem::Use_SpyGlass( CChar * pUser ) const sSearch = g_Cfg.GetDefaultMsg(DEFMSG_USE_SPYGLASS_WEATHER); else sSearch = g_Cfg.GetDefaultMsg(DEFMSG_USE_SPYGLASS_NO_LAND); - Str_CopyLimitNull( pResult, sSearch, Str_TempLength() ); + SATURATING_SUB_SELF(uiResultStrAvailableLen, Str_CopyLimitNull( pResult, sSearch, uiResultStrAvailableLen )); break; } @@ -5182,7 +5193,7 @@ lpctstr CItem::Use_SpyGlass( CChar * pUser ) const sSearch.Format(g_Cfg.GetDefaultMsg(DEFMSG_SHIP_SEEN_SHIP_SINGLE), pBoatSighted->GetName(), CPointBase::sm_szDirs[dir]); else sSearch.Format(g_Cfg.GetDefaultMsg(DEFMSG_SHIP_SEEN_SHIP_MANY), CPointBase::sm_szDirs[dir]); - strcat( pResult, sSearch); + SATURATING_SUB_SELF(uiResultStrAvailableLen, Str_ConcatLimitNull(pResult, sSearch, uiResultStrAvailableLen)); } if (iItemSighted) // Report item sightings, also boats beyond the boat visibility range in the radar screen @@ -5203,8 +5214,8 @@ lpctstr CItem::Use_SpyGlass( CChar * pUser ) const else sSearch.Format(g_Cfg.GetDefaultMsg(DEFMSG_SHIP_SEEN_SPECIAL_DIR), pItemSighted->GetNameFull(false), static_cast(CPointBase::sm_szDirs[ dir ])); } - strcat( pResult, sSearch); - } + SATURATING_SUB_SELF(uiResultStrAvailableLen, Str_ConcatLimitNull(pResult, sSearch, uiResultStrAvailableLen)); + } // Check for creatures Area->RestartSearch(); @@ -5238,8 +5249,8 @@ lpctstr CItem::Use_SpyGlass( CChar * pUser ) const sSearch.Format(g_Cfg.GetDefaultMsg(DEFMSG_SHIP_SEEN_CREAT_SINGLE), CPointBase::sm_szDirs[dir] ); else sSearch.Format(g_Cfg.GetDefaultMsg(DEFMSG_SHIP_SEEN_CREAT_MANY), CPointBase::sm_szDirs[dir] ); - strcat( pResult, sSearch); - } + Str_ConcatLimitNull(pResult, sSearch, uiResultStrAvailableLen); + } return pResult; } @@ -5553,7 +5564,7 @@ bool CItem::OnSpellEffect( SPELL_TYPE spell, CChar * pCharSrc, int iSkillLevel, spell = (SPELL_TYPE)(Args.m_iN1); iSkillLevel = (int)(Args.m_iN2); pSpellDef = g_Cfg.GetSpellDef( spell ); - + ASSERT(pSpellDef); if ( IsType(IT_WAND) ) // try to recharge the wand. { diff --git a/src/game/items/CItem.h b/src/game/items/CItem.h index 1ee537082..7377fdc5a 100644 --- a/src/game/items/CItem.h +++ b/src/game/items/CItem.h @@ -770,8 +770,10 @@ protected: virtual void _SetTimeout(int64 iMsecs) override final; bool MoveToCheck(const CPointMap & pt, CChar * pCharMover = nullptr ); virtual bool MoveNearObj( const CObjBaseTemplate *pItem, ushort uiSteps = 0 ) override; - virtual CObjBaseTemplate* GetTopLevelObj() override; - virtual const CObjBaseTemplate* GetTopLevelObj() const override; + [[nodiscard]] RETURNS_NOTNULL + virtual CObjBaseTemplate* GetTopLevelObj() override; + [[nodiscard]] RETURNS_NOTNULL + virtual const CObjBaseTemplate* GetTopLevelObj() const override; CObjBase * GetContainer() const noexcept; CItem * GetTopContainer(); diff --git a/src/network/CClientIterator.cpp b/src/network/CClientIterator.cpp index ee861577b..93e9e4d25 100644 --- a/src/network/CClientIterator.cpp +++ b/src/network/CClientIterator.cpp @@ -8,6 +8,24 @@ ClientIterator::ClientIterator(const CNetworkManager* network) { m_network = (network == nullptr ? &g_NetworkManager : network); m_nextClient = static_cast (m_network->m_clients.GetContainerHead()); + +#ifdef _DEBUG + const uint uiCnt = (uint)g_NetworkManager.m_clients.GetContentCount(); + //g_Log.EventWarn("Client count: %u.\n", uiCnt); + uint uiCntReal = 0; + if (CClient *pCliLoop = m_nextClient) + { + //g_Log.EventEvent("Start counting.\n"); + do ++ uiCntReal; + while ((pCliLoop = pCliLoop->GetNext()) != nullptr); + } + //g_Log.EventWarn("Actual clients in list: %u.\n", uiCntReal); + if (uiCnt != uiCntReal) + { + g_Log.EventWarn("Client count mismatch!.\n"); + EXC_NOTIFY_DEBUGGER; + } +#endif } ClientIterator::~ClientIterator() diff --git a/src/network/CNetState.cpp b/src/network/CNetState.cpp index 8623ed7c7..eec21d7fb 100644 --- a/src/network/CNetState.cpp +++ b/src/network/CNetState.cpp @@ -54,8 +54,8 @@ void CNetState::clear(void) { g_Serv.StatDec(SERV_STAT_CLIENTS); + static constexpr LOG_TYPE logFlags = enum_alias_cast(LOGM_NOCONTEXT | LOGM_CLIENTS_LOG | LOGL_EVENT); const CONNECT_TYPE connectionType = m_client->GetConnectType(); - const LOG_TYPE logFlags = enum_alias_cast(LOGM_NOCONTEXT | LOGM_CLIENTS_LOG | LOGL_EVENT); const size_t uiClients = g_Serv.StatGet(SERV_STAT_CLIENTS); const lpctstr ptcAddress = m_peerAddress.GetAddrStr(); if (connectionType == CONNECT_LOGIN) diff --git a/src/network/CNetworkManager.cpp b/src/network/CNetworkManager.cpp index c2ee43980..ca558b289 100644 --- a/src/network/CNetworkManager.cpp +++ b/src/network/CNetworkManager.cpp @@ -426,10 +426,11 @@ void CNetworkManager::tick(void) if (!pClient || (pClient->GetConnectType() == CONNECT_UNK)) { const int64 iTimeSinceConnectionMs = iCurSysTimeMs - state->m_iConnectionTimeMs; - if (iTimeSinceConnectionMs > g_Cfg._iTimeoutIncompleteConnectionMs) + const int64 iTimeoutIncompleteConnectionMs = g_Cfg._iTimeoutIncompleteConnectionMs; + if (iTimeSinceConnectionMs > iTimeoutIncompleteConnectionMs) { EXC_SET_BLOCK("mark closed for timeout"); - g_Log.Event(LOGM_CLIENTS_LOG | LOGL_EVENT, + g_Log.Event(LOGM_CLIENTS_LOG | LOGL_WARN, // LOGM_NOCONTEXT "%x:Force closing connection from IP %s. Reason: timed out before completing login.\n", state->id(), state->m_peerAddress.GetAddrStr()); //state->markReadClosed(); diff --git a/src/network/send.cpp b/src/network/send.cpp index b70bc8527..50856ed42 100644 --- a/src/network/send.cpp +++ b/src/network/send.cpp @@ -134,7 +134,7 @@ PacketObjectStatus::PacketObjectStatus(const CClient* target, CObjBase* object) const CNetState * state = target->GetNetState(); const CChar *character = target->GetChar(); - CChar *objectChar = object->IsChar() ? static_cast(object) : nullptr; + CChar *objectChar = object->IsChar() ? static_cast(object) : nullptr; bool fCanRename = false; byte version = 0; @@ -199,7 +199,7 @@ PacketObjectStatus::PacketObjectStatus(const CClient* target, CObjBase* object) writeInt16(iHitsMax); // Max hit points writeBool(fCanRename); writeByte(version); - if (state->isClientEnhanced() && objectChar && objectChar->IsPlayableCharacter()) + if (state->isClientEnhanced() && objectChar && objectChar->IsClientType() /*objectChar->IsPlayableCharacter()*/) { // The Enhanced Client wants the char race and other things when showing paperdolls (otherwise the interface throws an "unnoticeable" internal error) WriteVersionSpecific(target, objectChar, version); @@ -211,7 +211,7 @@ PacketObjectStatus::PacketObjectStatus(const CClient* target, CObjBase* object) void PacketObjectStatus::WriteVersionSpecific(const CClient* target, CChar* other, byte version) { - bool fElemental = IsSetCombatFlags(COMBAT_ELEMENTAL_ENGINE); + const bool fElemental = IsSetCombatFlags(COMBAT_ELEMENTAL_ENGINE); const CCharBase * otherDefinition = other->Char_GetDef(); const CCPropsChar* pCCPChar = other->GetComponentProps(); const CCPropsChar* pBaseCCPChar = otherDefinition->GetComponentProps(); From 8d57444f5b59108b26dff2bf752bf5965f0674b7 Mon Sep 17 00:00:00 2001 From: Jhobean <51728381+Jhobean@users.noreply.github.com> Date: Mon, 14 Oct 2024 05:16:28 -0400 Subject: [PATCH 77/86] Add @petrelease trigger (#1302) --- Changelog.txt | 3 +++ src/game/CObjBase.h | 1 + src/game/chars/CChar.cpp | 1 + src/game/chars/CCharNPCPet.cpp | 10 ++++++++++ src/tables/triggers.tbl | 1 + 5 files changed, 16 insertions(+) diff --git a/Changelog.txt b/Changelog.txt index eb900a6b8..034689fd8 100644 --- a/Changelog.txt +++ b/Changelog.txt @@ -3911,3 +3911,6 @@ Added: 'H' shortcut for variables to get the value as hexadecimal. CURFOLLOWER.DELUID: The same as .DEL/DELETE, just removed the pet via its UID. CURFOLLOWER.DELINDEX: Removes the pet via its id in the (cur)follower list for that owner. - Added: spells with SPELLFLAG_SUMMON now accept LOCAL.FollowerSlotsOverride in the triggers @Success and @SpellSuccess. Default value (do not override): -1. + +13-10-2024, Jhobean +- Added: @PetRelease trigger work like @petdesert and return 1 to prevent the pet from being released. diff --git a/src/game/CObjBase.h b/src/game/CObjBase.h index 7a94ef5e1..e34a42979 100644 --- a/src/game/CObjBase.h +++ b/src/game/CObjBase.h @@ -1170,6 +1170,7 @@ enum CTRIG_TYPE : short CTRIG_PayGold, // I'm going to give out money for a service (Skill Training, hiring...). CTRIG_PersonalSpace, // i just got stepped on by other char. CTRIG_PetDesert, // I'm deserting from my owner ( starving, being hit by him ...). + CTRIG_PetRelease, // I have been released by my owner. CTRIG_Profile, // someone hit the profile button for me. CTRIG_ReceiveItem, // I was just handed an item (Not yet checked if i want it). CTRIG_RegenStat, // Hits/mana/stam/food regeneration. diff --git a/src/game/chars/CChar.cpp b/src/game/chars/CChar.cpp index a4ac213d8..c1b95127a 100644 --- a/src/game/chars/CChar.cpp +++ b/src/game/chars/CChar.cpp @@ -169,6 +169,7 @@ lpctstr const CChar::sm_szTrigName[CTRIG_QTY+1] = // static "@PayGold", // I'm going to give out money for a service (Skill Training, hiring...). "@PersonalSpace", // +i just got stepped on by other char. "@PetDesert", // I just went wild again + "@PetRelease", // I just been released by my master "@Profile", // someone hit the profile button for me. "@ReceiveItem", // I was just handed an item (Not yet checked if i want it) "@RegenStat", // Regenerating any stat diff --git a/src/game/chars/CCharNPCPet.cpp b/src/game/chars/CCharNPCPet.cpp index a9ce07c0a..91e65ff6a 100644 --- a/src/game/chars/CCharNPCPet.cpp +++ b/src/game/chars/CCharNPCPet.cpp @@ -857,6 +857,16 @@ void CChar::NPC_PetRelease() if (!m_pNPC) return; + CChar* pCharOwn = NPC_PetGetOwner(); + if (!pCharOwn) + return; + + if (IsTrigUsed(TRIGGER_PETRELEASE)) + { + if (OnTrigger(CTRIG_PetRelease, pCharOwn, nullptr) == TRIGRET_RET_TRUE) + return; + } + if (IsStatFlag(STATF_CONJURED) || (m_pNPC->m_bonded && IsStatFlag(STATF_DEAD))) { Effect(EFFECT_XYZ, ITEMID_FX_TELE_VANISH, this, 10, 15); diff --git a/src/tables/triggers.tbl b/src/tables/triggers.tbl index b81dc78ff..a200f613a 100644 --- a/src/tables/triggers.tbl +++ b/src/tables/triggers.tbl @@ -156,6 +156,7 @@ ADD(PARTYREMOVE) ADD(PAYGOLD) ADD(PERSONALSPACE) ADD(PETDESERT) +ADD(PETRELEASE) ADD(PICKUP_GROUND) ADD(PICKUP_PACK) ADD(PICKUP_SELF) From 9703cefd606de51e17278ad89e108c93a5ff7067 Mon Sep 17 00:00:00 2001 From: Jhobean <51728381+Jhobean@users.noreply.github.com> Date: Mon, 14 Oct 2024 15:51:22 -0400 Subject: [PATCH 78/86] Fix Typo error on Call Stack (#1308) --- src/game/CObjBase.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/game/CObjBase.cpp b/src/game/CObjBase.cpp index cecbdb93a..7cef3e945 100644 --- a/src/game/CObjBase.cpp +++ b/src/game/CObjBase.cpp @@ -3253,7 +3253,7 @@ bool CObjBase::_CanTick(bool fParentGoingToSleep) const void CObjBase::ResendTooltip(bool fSendFull, bool fUseCache) { - ADDTOCALLSTACK("CObjBase::UpdatePropertyFlag"); + ADDTOCALLSTACK("CObjBase::ResendTooltip"); // Send tooltip packet to all nearby clients if (g_Serv.IsLoading()) From f05188948bf1dfe5da7e4ccead089e1d0e55c441 Mon Sep 17 00:00:00 2001 From: Gladie Date: Mon, 14 Oct 2024 21:52:19 +0200 Subject: [PATCH 79/86] Registration of Packet 0xBE (#1304) --- src/common/sphereproto.h | 1 + src/network/CPacketManager.cpp | 1 + src/network/receive.cpp | 11 +++++++++++ src/network/receive.h | 14 ++++++++++++++ 4 files changed, 27 insertions(+) diff --git a/src/common/sphereproto.h b/src/common/sphereproto.h index ab1a3aaed..b9bbb908e 100644 --- a/src/common/sphereproto.h +++ b/src/common/sphereproto.h @@ -139,6 +139,7 @@ enum XCMD_TYPE // XCMD_* messages are unique in both directions. XCMD_MailMsg = 0xbb, XCMD_Season = 0xbc, XCMD_ClientVersion = 0xbd, + XCMD_AssistVersion = 0xbe, XCMD_ExtData = 0xbf, // 0xC0 XCMD_EffectEx = 0xc0, diff --git a/src/network/CPacketManager.cpp b/src/network/CPacketManager.cpp index 77a7f2ca3..35986c224 100644 --- a/src/network/CPacketManager.cpp +++ b/src/network/CPacketManager.cpp @@ -82,6 +82,7 @@ void PacketManager::registerStandardPackets(void) registerPacket(XCMD_CharProfile, new PacketProfileReq()); // profile read/write request registerPacket(XCMD_MailMsg, new PacketMailMessage()); // registerPacket(XCMD_ClientVersion, new PacketClientVersion()); // client version + registerPacket(XCMD_AssistVersion, new PacketAssistVersion()); // assist version registerPacket(XCMD_ExtData, new PacketExtendedCommand()); // registerPacket(XCMD_PromptUNICODE, new PacketPromptResponseUnicode()); // prompt response (unicode) registerPacket(XCMD_ViewRange, new PacketViewRange()); // diff --git a/src/network/receive.cpp b/src/network/receive.cpp index f78aef4f0..50e36e308 100644 --- a/src/network/receive.cpp +++ b/src/network/receive.cpp @@ -2497,6 +2497,17 @@ bool PacketClientVersion::onReceive(CNetState* net) return true; } +/*************************************************************************** +* +* +* Packet 0xBD : PacketAssistVersion assist version +* +* +***************************************************************************/ +PacketAssistVersion::PacketAssistVersion() : Packet(0) +{ +} +PacketAssistVersion::~PacketAssistVersion() = default; /*************************************************************************** * diff --git a/src/network/receive.h b/src/network/receive.h index 4f7c65400..f464c8a6e 100644 --- a/src/network/receive.h +++ b/src/network/receive.h @@ -722,6 +722,20 @@ class PacketClientVersion : public Packet virtual bool onReceive(CNetState* net); }; +/*************************************************************************** + * + * + * Packet 0xBE : PacketAssistVersion assist version + * + * + ***************************************************************************/ +class PacketAssistVersion : public Packet +{ +public: + PacketAssistVersion(); + virtual ~PacketAssistVersion(); +}; + /*************************************************************************** * * From f93d9182c929d572d50e3c7551bbd01a8489bc87 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Caner=20K=C4=B1l=C4=B1=C3=A7o=C4=9Flu?= Date: Sat, 26 Oct 2024 14:48:54 +0300 Subject: [PATCH 80/86] Memory OnTick link char if not, the skill will not fail. If the memory owner is not present, skills do not fail when taking damage, but if the memory owner is alive, skills fail when taking damage. Tested. --- Changelog.txt | 4 ++++ src/game/chars/CCharSpell.cpp | 24 +++++++++++++++++------- 2 files changed, 21 insertions(+), 7 deletions(-) diff --git a/Changelog.txt b/Changelog.txt index 034689fd8..a2d01923b 100644 --- a/Changelog.txt +++ b/Changelog.txt @@ -3914,3 +3914,7 @@ Added: 'H' shortcut for variables to get the value as hexadecimal. 13-10-2024, Jhobean - Added: @PetRelease trigger work like @petdesert and return 1 to prevent the pet from being released. + +26-10-2024, canerksk +- Fixed: Memory OnTick link char if not, the skill will not fail. + If the memory owner is not present, skills do not fail when taking damage, but if the memory owner is alive, skills fail when taking damage. \ No newline at end of file diff --git a/src/game/chars/CCharSpell.cpp b/src/game/chars/CCharSpell.cpp index d68bf7da3..3e83b5210 100644 --- a/src/game/chars/CCharSpell.cpp +++ b/src/game/chars/CCharSpell.cpp @@ -1982,13 +1982,23 @@ bool CChar::Spell_Equip_OnTick( CItem * pItem ) iDmgType = (DAMAGE_TYPE)(ResGetIndex((dword)Args.m_VarsLocal.GetKeyNum("DamageType"))); if (iDmgType > 0 && iEffect > 0) // This is necessary if we have a spell that is harmful but does no damage periodically. { - OnTakeDamage(iEffect, pItem->m_uidLink.CharFind(), iDmgType, - (iDmgType & (DAMAGE_HIT_BLUNT | DAMAGE_HIT_PIERCE | DAMAGE_HIT_SLASH)) ? 100 : 0, - (iDmgType & DAMAGE_FIRE) ? 100 : 0, - (iDmgType & DAMAGE_COLD) ? 100 : 0, - (iDmgType & DAMAGE_POISON) ? 100 : 0, - (iDmgType & DAMAGE_ENERGY) ? 100 : 0, - spell); + // + CChar *pLinkedChar = pItem->m_uidLink.CharFind(); + if (pLinkedChar == nullptr) + { + // pLinkedChar = this; // If it is not alive or deleted, should it be like it is self-damaging? Note: Under the OnTakeDamage() + Skill_Fail(); // If the memory does not belong to a creature, or if the creature is dead or deleted, skills do not take effect on damage taken. + } + + OnTakeDamage(iEffect, + pLinkedChar, + iDmgType, + (iDmgType & (DAMAGE_HIT_BLUNT | DAMAGE_HIT_PIERCE | DAMAGE_HIT_SLASH)) ? 100 : 0, + (iDmgType & DAMAGE_FIRE) ? 100 : 0, + (iDmgType & DAMAGE_COLD) ? 100 : 0, + (iDmgType & DAMAGE_POISON) ? 100 : 0, + (iDmgType & DAMAGE_ENERGY) ? 100 : 0, + spell); } } else if (pSpellDef->IsSpellType(SPELLFLAG_HEAL)) From 67de95e3301d8f4e9ae78cbec6101ceda691fd31 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Caner=20K=C4=B1l=C4=B1=C3=A7o=C4=9Flu?= Date: Sat, 26 Oct 2024 14:50:24 +0300 Subject: [PATCH 81/86] The entity was jumping frames in flooded pet commands (come, guard) --- Changelog.txt | 5 ++++- src/game/chars/CCharNPCPet.cpp | 14 ++++++++++---- 2 files changed, 14 insertions(+), 5 deletions(-) diff --git a/Changelog.txt b/Changelog.txt index a2d01923b..94cc77f73 100644 --- a/Changelog.txt +++ b/Changelog.txt @@ -3917,4 +3917,7 @@ Added: 'H' shortcut for variables to get the value as hexadecimal. 26-10-2024, canerksk - Fixed: Memory OnTick link char if not, the skill will not fail. - If the memory owner is not present, skills do not fail when taking damage, but if the memory owner is alive, skills fail when taking damage. \ No newline at end of file + If the memory owner is not present, skills do not fail when taking damage, but if the memory owner is alive, skills fail when taking damage. + +- Fixed: The entity was jumping frames in flooded pet commands (come, guard) + \ No newline at end of file diff --git a/src/game/chars/CCharNPCPet.cpp b/src/game/chars/CCharNPCPet.cpp index 91e65ff6a..0b9ef724c 100644 --- a/src/game/chars/CCharNPCPet.cpp +++ b/src/game/chars/CCharNPCPet.cpp @@ -173,14 +173,20 @@ bool CChar::NPC_OnHearPetCmd( lpctstr pszCmd, CChar *pSrc, bool fAllPets ) break; case PC_GUARD_ME: - m_Act_UID = pSrc->GetUID(); - Skill_Start(NPCACT_GUARD_TARG); + if ((m_Act_UID != pSrc->GetUID()) || (Skill_GetActive() != NPCACT_GUARD_TARG)) // When you do all guard flood, the mount jumps one frame. + { + m_Act_UID = pSrc->GetUID(); + Skill_Start(NPCACT_GUARD_TARG); + } break; case PC_COME: case PC_FOLLOW_ME: - m_Act_UID = pSrc->GetUID(); - Skill_Start(NPCACT_FOLLOW_TARG); + if ((m_Act_UID != pSrc->GetUID()) || (Skill_GetActive() != NPCACT_FOLLOW_TARG)) // When you do all come flood, the mount jumps one frame. + { + m_Act_UID = pSrc->GetUID(); + Skill_Start(NPCACT_FOLLOW_TARG); + } break; case PC_FOLLOW: From 6d27afb5e10dab59418720a72bd4df7d661230f2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Caner=20K=C4=B1l=C4=B1=C3=A7o=C4=9Flu?= Date: Fri, 8 Nov 2024 15:45:04 +0300 Subject: [PATCH 82/86] ITEMMEMORYEQUIP is not triggered in many default memories. Previously, many memories did not have morex information, but now for some reason many memories have morex information and for this reason the trigger was not triggered in almost most of the memories, the morex query was removed. Also, the slang did not represent the memory item, --- Changelog.txt | 5 ++++- src/game/chars/CCharAct.cpp | 9 ++++++--- 2 files changed, 10 insertions(+), 4 deletions(-) diff --git a/Changelog.txt b/Changelog.txt index 94cc77f73..6e94dc88e 100644 --- a/Changelog.txt +++ b/Changelog.txt @@ -3920,4 +3920,7 @@ Added: 'H' shortcut for variables to get the value as hexadecimal. If the memory owner is not present, skills do not fail when taking damage, but if the memory owner is alive, skills fail when taking damage. - Fixed: The entity was jumping frames in flooded pet commands (come, guard) - \ No newline at end of file + +08-11-2024 +- Fixed: ITEMMEMORYEQUIP is not triggered in many default memories. + Previously, many memories did not have morex information, but now for some reason many memories have morex information and for this reason the trigger was not triggered in almost most of the memories, the morex query was removed. Also, the slang did not represent the memory item. \ No newline at end of file diff --git a/src/game/chars/CCharAct.cpp b/src/game/chars/CCharAct.cpp index b4c427f1a..d6bf5d4e1 100644 --- a/src/game/chars/CCharAct.cpp +++ b/src/game/chars/CCharAct.cpp @@ -280,11 +280,14 @@ void CChar::LayerAdd( CItem * pItem, LAYER_TYPE layer ) return; } - if (!pItem->IsTypeSpellable() && !pItem->m_itSpell.m_spell && !pItem->IsType(IT_WAND)) // can this item have a spell effect ? If so we do not send - { + //if (!pItem->IsTypeSpellable() && !pItem->m_itSpell.m_spell && !pItem->IsType(IT_WAND)) // can this item have a spell effect ? If so we do not send + // Since most of the memories came with a morex information by default, almost no memory was triggered. + if (!(pItem->IsTypeSpellable() || pItem->IsType(IT_WAND))) + { if ((IsTrigUsed(TRIGGER_MEMORYEQUIP)) || (IsTrigUsed(TRIGGER_ITEMMEMORYEQUIP))) { - CScriptTriggerArgs pArgs; + //CScriptTriggerArgs pArgs; + CScriptTriggerArgs pArgs(pItem); // added "argo" argument pArgs.m_iN1 = layer; if (pItem->OnTrigger(ITRIG_MemoryEquip, this, &pArgs) == TRIGRET_RET_TRUE) { From b231c12fe3c5d6024ce53e67fddb8f93b30900aa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Caner=20K=C4=B1l=C4=B1=C3=A7o=C4=9Flu?= Date: Wed, 27 Nov 2024 09:00:43 +0300 Subject: [PATCH 83/86] bank hear fix (#1332) If you are around an entity that you own and you are trying to open a bank next to a bank, the "bank" command is perceived as a pet command and the bank does not open. There is no problem when you type "bank" after mounting the mount, but "bank" does not work when you dismount. (Issue #1331) tested. --- Changelog.txt | 3 +++ src/game/clients/CClientEvent.cpp | 9 +++++++++ 2 files changed, 12 insertions(+) diff --git a/Changelog.txt b/Changelog.txt index 034689fd8..a5ad6c508 100644 --- a/Changelog.txt +++ b/Changelog.txt @@ -3914,3 +3914,6 @@ Added: 'H' shortcut for variables to get the value as hexadecimal. 13-10-2024, Jhobean - Added: @PetRelease trigger work like @petdesert and return 1 to prevent the pet from being released. + +07-11-2024, canerksk +- Fixed: If you are around an entity that you own and you are trying to open a bank next to a bank, the "bank" command is perceived as a pet command and the bank does not open. There is no problem when you type "bank" after mounting the mount, but "bank" does not work when you dismount. (Issue #1331) \ No newline at end of file diff --git a/src/game/clients/CClientEvent.cpp b/src/game/clients/CClientEvent.cpp index c4ecc42ff..491ec1962 100644 --- a/src/game/clients/CClientEvent.cpp +++ b/src/game/clients/CClientEvent.cpp @@ -1988,6 +1988,15 @@ void CClient::Event_Talk_Common(lpctstr pszText) // PC speech break; } */ + // NPC's with special key words ? + if (pChar->m_pNPC) + { + if (pChar->m_pNPC->m_Brain == NPCBRAIN_BANKER) + { + if (FindStrWord(pszText, "BANK") > 0) + break; + } + } } if ( !pChar ) From 35f665fb168cfe6a457e6361aa1fe0cc860a61eb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Caner=20K=C4=B1l=C4=B1=C3=A7o=C4=9Flu?= Date: Wed, 27 Nov 2024 09:11:03 +0300 Subject: [PATCH 84/86] Added NOREJOIN tag for corpses (#1318) * Added TAG.NOREJOIN tag for corpses If the NOREJOIN tag is 1, the player cannot come back to life on that corpse. That is, the player comes back to life but not on the corpse. This tag does not prevent the player from coming back to life, it just prevents them from respawning on that corpse. The player always comes back to life, but not on that corpse. --- Changelog.txt | 8 ++++++-- src/game/items/CItemCorpse.cpp | 2 ++ 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/Changelog.txt b/Changelog.txt index a5ad6c508..2ac6be2ae 100644 --- a/Changelog.txt +++ b/Changelog.txt @@ -3915,5 +3915,9 @@ Added: 'H' shortcut for variables to get the value as hexadecimal. 13-10-2024, Jhobean - Added: @PetRelease trigger work like @petdesert and return 1 to prevent the pet from being released. -07-11-2024, canerksk -- Fixed: If you are around an entity that you own and you are trying to open a bank next to a bank, the "bank" command is perceived as a pet command and the bank does not open. There is no problem when you type "bank" after mounting the mount, but "bank" does not work when you dismount. (Issue #1331) \ No newline at end of file +27-11-2024, canerksk +- Added: Added NOREJOIN tag for corpses, If the NOREJOIN tag is one, the player cannot come back to life on that corpse. That is, the player comes back to life but not on the corpse. + This tag does not prevent the player from coming back to life, it just prevents them from respawning on that corpse. The player always comes back to life, but not on that corpse. + +27-11-2024, canerksk +- Fixed: If you are around an entity that you own and you are trying to open a bank next to a bank, the "bank" command is perceived as a pet command and the bank does not open. There is no problem when you type "bank" after mounting the mount, but "bank" does not work when you dismount. (Issue #1331) diff --git a/src/game/items/CItemCorpse.cpp b/src/game/items/CItemCorpse.cpp index 75c5b57c0..95b837923 100644 --- a/src/game/items/CItemCorpse.cpp +++ b/src/game/items/CItemCorpse.cpp @@ -150,6 +150,8 @@ CItemCorpse *CChar::FindMyCorpse( bool ignoreLOS, int iRadius ) const break; if ( !pItem->IsType(IT_CORPSE) ) continue; + if (pItem->m_TagDefs.GetKeyNum("NOREJOIN")) // The owner should not rejoin this body even if resurrected on top of it. + continue; CItemCorpse *pCorpse = dynamic_cast(pItem); if ( !pCorpse || (pCorpse->m_uidLink != GetUID()) ) continue; From 69302c6f19a13a8c6439730e0d42ca406d2686d1 Mon Sep 17 00:00:00 2001 From: cbnolok Date: Wed, 27 Nov 2024 20:03:30 +0100 Subject: [PATCH 85/86] Fixed MacOS compilation error Caused by changes in mariadb-c-connector homebrew packaging. --- cmake/toolchains/include/OSX-AppleClang_common.inc.cmake | 2 ++ 1 file changed, 2 insertions(+) diff --git a/cmake/toolchains/include/OSX-AppleClang_common.inc.cmake b/cmake/toolchains/include/OSX-AppleClang_common.inc.cmake index 699b50881..efc752811 100644 --- a/cmake/toolchains/include/OSX-AppleClang_common.inc.cmake +++ b/cmake/toolchains/include/OSX-AppleClang_common.inc.cmake @@ -17,6 +17,8 @@ function(toolchain_exe_stuff_common) HINT "/usr/local/opt/mariadb-connector-c/lib/mariadb" "/opt/homebrew/var/mariadb-connector-c/lib/mariadb" + "/opt/homebrew/opt/mariadb-connector-c/lib/mariadb" + "/opt/homebrew/opt/mariadb-connector-c/lib" "/opt/homebrew/lib/mariadb" ) message(STATUS "Library ${lib_name}: ${lib_${lib_name}_with_path}") From 8cff3e038354496239a6d3735a40761db012fc2b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Caner=20K=C4=B1l=C4=B1=C3=A7o=C4=9Flu?= Date: Wed, 27 Nov 2024 22:20:33 +0300 Subject: [PATCH 86/86] RANGE is complete for skills with distance query MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit All skills that have a distance query have been adjusted to take the RANGE values ​​of that skill. --- Changelog.txt | 17 +++++ src/game/chars/CChar.cpp | 4 +- src/game/chars/CCharSkill.cpp | 119 +++++++++++++++++++++++++++------- 3 files changed, 116 insertions(+), 24 deletions(-) diff --git a/Changelog.txt b/Changelog.txt index 034689fd8..d9ed1797b 100644 --- a/Changelog.txt +++ b/Changelog.txt @@ -3914,3 +3914,20 @@ Added: 'H' shortcut for variables to get the value as hexadecimal. 13-10-2024, Jhobean - Added: @PetRelease trigger work like @petdesert and return 1 to prevent the pet from being released. + +27-11-2024, canerksk +- Added: All skills that have a distance query have been adjusted to take the RANGE values ​​of that skill. + All skills to be used in RANGE; + BLACKSMITHING + MINING // It was added before. + FISHING // It was added before. + LUMBERJACKING // It was added before. + PEACEMAKING + ENTICEMENT + PROVOCATION + COOKING + TAMING + THROWING + SNOOPING + STEALING + Also added BREATH.MAXDIST to Breath. If this property is not given, the default is 14 distance. diff --git a/src/game/chars/CChar.cpp b/src/game/chars/CChar.cpp index c1b95127a..fad039269 100644 --- a/src/game/chars/CChar.cpp +++ b/src/game/chars/CChar.cpp @@ -2510,7 +2510,7 @@ bool CChar::r_WriteVal( lpctstr ptcKey, CSString & sVal, CTextConsole * pSrc, bo } case CHC_BREATH: { - if( !strnicmp(ptcKey, "BREATH.DAM", 10) ) + if (!strnicmp(ptcKey, "BREATH.MAXDIST", 14) || !strnicmp(ptcKey, "BREATH.DAM", 10)) { CVarDefCont * pVar = GetDefKey(ptcKey, true); sVal.FormatLLVal(pVar ? pVar->GetValNum() : 0); @@ -3808,7 +3808,7 @@ bool CChar::r_LoadVal( CScript & s ) break; case CHC_BREATH: { - if ( !strnicmp(ptcKey, "BREATH.DAM", 10) || !strnicmp(ptcKey, "BREATH.HUE", 10) || !strnicmp(ptcKey, "BREATH.ANIM", 11) || !strnicmp(ptcKey, "BREATH.TYPE", 11) || !strnicmp(ptcKey, "BREATH.DAMTYPE", 14)) + if ( !strnicmp(ptcKey, "BREATH.MAXDIST", 14) || !strnicmp(ptcKey, "BREATH.DAM", 10) || !strnicmp(ptcKey, "BREATH.HUE", 10) || !strnicmp(ptcKey, "BREATH.ANIM", 11) || !strnicmp(ptcKey, "BREATH.TYPE", 11) || !strnicmp(ptcKey, "BREATH.DAMTYPE", 14)) { SetDefNum(s.GetKey(), s.GetArgLLVal()); return true; diff --git a/src/game/chars/CCharSkill.cpp b/src/game/chars/CCharSkill.cpp index fe11e036f..4a344e817 100644 --- a/src/game/chars/CCharSkill.cpp +++ b/src/game/chars/CCharSkill.cpp @@ -1078,10 +1078,21 @@ bool CChar::Skill_Mining_Smelt( CItem * pItemOre, CItem * pItemTarg ) return true; } - if ( pItemTarg != nullptr && pItemTarg->IsTopLevel() && pItemTarg->IsType( IT_FORGE )) - m_Act_p = pItemTarg->GetTopPoint(); - else - m_Act_p = CWorldMap::FindItemTypeNearby( GetTopPoint(), IT_FORGE, 3, false ); + if (pItemTarg != nullptr && pItemTarg->IsTopLevel() && pItemTarg->IsType(IT_FORGE)) + { + m_Act_p = pItemTarg->GetTopPoint(); + } + else + { + CSkillDef *pSkillDef = g_Cfg.GetSkillDef(SKILL_BLACKSMITHING); + int iMaxRange = pSkillDef->m_Range; + if (!iMaxRange) + { + g_Log.EventError("Blacksmith skill doesn't have a value for RANGE, defaulting to 3\n"); + iMaxRange = 3; + } + m_Act_p = CWorldMap::FindItemTypeNearby(GetTopPoint(), IT_FORGE, iMaxRange, false); + } if ( !m_Act_p.IsValidPoint() || !CanTouch(m_Act_p)) { @@ -1405,7 +1416,7 @@ int CChar::Skill_Mining( SKTRIG_TYPE stage ) const CSkillDef *pSkillDef = g_Cfg.GetSkillDef(SKILL_MINING); const int iTargRange = GetTopPoint().GetDist(m_Act_p); int iMaxRange = pSkillDef->m_Range; - if ( !iMaxRange ) + if (!iMaxRange) { g_Log.EventError("Mining skill doesn't have a value for RANGE, defaulting to 2\n"); iMaxRange = 2; @@ -1501,7 +1512,7 @@ int CChar::Skill_Fishing( SKTRIG_TYPE stage ) CSkillDef *pSkillDef = g_Cfg.GetSkillDef(SKILL_FISHING); int iTargRange = GetTopPoint().GetDist(m_Act_p); int iMaxRange = pSkillDef->m_Range; - if ( !iMaxRange ) + if (!iMaxRange) { g_Log.EventError("Fishing skill doesn't have a value for RANGE, defaulting to 4\n"); iMaxRange = 4; @@ -1603,7 +1614,7 @@ int CChar::Skill_Lumberjack( SKTRIG_TYPE stage ) CSkillDef *pSkillDef = g_Cfg.GetSkillDef(SKILL_LUMBERJACKING); int iTargRange = GetTopPoint().GetDist(m_Act_p); int iMaxRange = pSkillDef->m_Range; - if ( !pSkillDef->m_Range ) + if (!iMaxRange) { g_Log.EventError("Lumberjacking skill doesn't have a value for RANGE, defaulting to 2\n"); iMaxRange = 2; @@ -1825,7 +1836,15 @@ int CChar::Skill_Peacemaking( SKTRIG_TYPE stage ) { int peace = Skill_GetAdjusted(SKILL_PEACEMAKING); int iRadius = ( peace / 100 ) + 2; // 2..12 - auto Area = CWorldSearchHolder::GetInstance(GetTopPoint(), iRadius); + + CSkillDef *pSkillDef = g_Cfg.GetSkillDef(SKILL_PEACEMAKING); + int iMaxRadius = pSkillDef->m_Range; + if (!iMaxRadius) + { + //g_Log.EventError("Peacemaking skill doesn't have a value for RANGE, defaulting to (Peacemaking skill level / 100 + 2) \n"); + iMaxRadius = iRadius; + } + auto Area = CWorldSearchHolder::GetInstance(GetTopPoint(), iMaxRadius); for (;;) { CChar *pChar = Area->GetChar(); @@ -1951,9 +1970,15 @@ int CChar::Skill_Enticement( SKTRIG_TYPE stage ) SysMessagef("%s %s.", pChar->GetName(), g_Cfg.GetDefaultMsg(DEFMSG_ENTICEMENT_BATTLE)); return -SKTRIG_ABORT; } - + CSkillDef *pSkillDef = g_Cfg.GetSkillDef(SKILL_ENTICEMENT); + int iMaxRange = pSkillDef->m_Range; + if (!iMaxRange) + { + //g_Log.EventError("Enticement skill doesn't have a value for RANGE, defaulting 3\n"); + iMaxRange = 3; + } pChar->m_Act_p = GetTopPoint(); - pChar->NPC_WalkToPoint( ( pChar->m_Act_p.GetDist(pChar->GetTopPoint()) > 3) ); + pChar->NPC_WalkToPoint((pChar->m_Act_p.GetDist(pChar->GetTopPoint()) > iMaxRange)); return 0; } @@ -1969,6 +1994,9 @@ int CChar::Skill_Provocation(SKTRIG_TYPE stage) // m_Act_Prv_UID = provoke this person // m_Act_UID = against this person. + CSkillDef *pSkillDef = g_Cfg.GetSkillDef(SKILL_PROVOCATION); + int iMaxRange = pSkillDef->m_Range; + if ( stage == SKTRIG_ABORT ) return -SKTRIG_ABORT; @@ -2070,8 +2098,14 @@ int CChar::Skill_Provocation(SKTRIG_TYPE stage) pCharProv->Memory_AddObjTypes(this, MEMORY_AGGREIVED|MEMORY_IRRITATEDBY); + if (!iMaxRange) + { + //g_Log.EventError("Provocation skill doesn't have a value for RANGE, defaulting to UO_MAP_VIEW_SIGHT(14) \n"); + iMaxRange = UO_MAP_VIEW_SIGHT; + } + // If out of range we might get attacked ourself. - if ( (pCharProv->GetTopDist3D(pCharTarg) > UO_MAP_VIEW_SIGHT) || (pCharProv->GetTopDist3D(this) > UO_MAP_VIEW_SIGHT) ) + if ((pCharProv->GetTopDist3D(pCharTarg) > iMaxRange) || (pCharProv->GetTopDist3D(this) > iMaxRange)) { // Check that only "evil" monsters attack provoker back if ( pCharProv->Noto_IsEvil() ) @@ -2183,7 +2217,13 @@ int CChar::Skill_Cooking( SKTRIG_TYPE stage ) // m_Act_p = the heat source // m_Act_UID = the skill tool - int iMaxDist = 3; + CSkillDef *pSkillDef = g_Cfg.GetSkillDef(SKILL_COOKING); + int iMaxDist = pSkillDef->m_Range; + if (!iMaxDist) + { + g_Log.EventError("Cooking skill doesn't have a value for RANGE, defaulting to 3\n"); + iMaxDist = 3; + } if ( stage == SKTRIG_START ) { @@ -2239,10 +2279,13 @@ int CChar::Skill_Taming( SKTRIG_TYPE stage ) } CSkillDef* pSkillDef = g_Cfg.GetSkillDef(SKILL_TAMING); - if (pSkillDef->m_Range <= 0) - pSkillDef->m_Range = 10; - - if ( GetTopDist3D(pChar) > pSkillDef->m_Range) + int iMaxRange = pSkillDef->m_Range; + if (!iMaxRange) + { + g_Log.EventError("Taming skill doesn't have a value for RANGE, defaulting to 10\n"); + iMaxRange = 10; + } + if (GetTopDist3D(pChar) > iMaxRange) { SysMessageDefault( DEFMSG_TAMING_REACH ); return -SKTRIG_QTY; @@ -3237,8 +3280,16 @@ int CChar::Skill_Act_Breath( SKTRIG_TYPE stage ) return -SKTRIG_QTY; const CPointMap& pntMe = GetTopPoint(); - if ( pntMe.GetDist( m_Act_p ) > UO_MAP_VIEW_SIGHT ) - m_Act_p.StepLinePath( pntMe, UO_MAP_VIEW_SIGHT ); + + int iMaxDist = (int)(GetDefNum("BREATH.MAXDIST", true)); + if (!iMaxDist) + { + //g_Log.EventError("Breath skill doesn't have a value for RANGE, defaulting to UO_MAP_VIEW_SIGHT(14) \n"); + iMaxDist = UO_MAP_VIEW_SIGHT; + } + + if (pntMe.GetDist(m_Act_p) > iMaxDist) + m_Act_p.StepLinePath(pntMe, iMaxDist); int iDamage = (int)(GetDefNum("BREATH.DAM", true)); @@ -3319,8 +3370,17 @@ int CChar::Skill_Act_Throwing( SKTRIG_TYPE stage ) return -SKTRIG_QTY; const CPointMap pntMe(GetTopPoint()); - if ( pntMe.GetDist( m_Act_p ) > UO_MAP_VIEW_SIGHT ) - m_Act_p.StepLinePath( pntMe, UO_MAP_VIEW_SIGHT ); + + CSkillDef *pSkillDef = g_Cfg.GetSkillDef(SKILL_THROWING); + int iMaxRange = pSkillDef->m_Range; + if (!iMaxRange) + { + //g_Log.EventError("Throwing skill doesn't have a value for RANGE, defaulting to UO_MAP_VIEW_SIGHT(14) \n"); + iMaxRange = UO_MAP_VIEW_SIGHT; + } + + if (pntMe.GetDist(m_Act_p) > iMaxRange) + m_Act_p.StepLinePath(pntMe, iMaxRange); SoundChar( CRESND_GETHIT ); @@ -4055,7 +4115,15 @@ int CChar::Skill_Snooping(SKTRIG_TYPE stage) if (!IsTakeCrime(pCont, &pCharMark) || pCharMark == nullptr) return 0; // Not a crime really. - if (GetTopDist3D(pCharMark) > 1) + CSkillDef *pSkillDef = g_Cfg.GetSkillDef(SKILL_SNOOPING); + int iMaxRange = pSkillDef->m_Range; + if (!iMaxRange) + { + g_Log.EventError("Snooping skill doesn't have a value for RANGE, defaulting to 1\n"); + iMaxRange = 1; + } + + if (GetTopDist3D(pCharMark) > iMaxRange) { SysMessageDefault(DEFMSG_SNOOPING_REACH); return (-SKTRIG_QTY); @@ -4207,7 +4275,14 @@ int CChar::Skill_Stealing(SKTRIG_TYPE stage) bool fGround = false; if (pCharMark != nullptr) { - if (GetTopDist3D(pCharMark) > 2) + CSkillDef *pSkillDef = g_Cfg.GetSkillDef(SKILL_STEALING); + int iMaxRange = pSkillDef->m_Range; + if (!iMaxRange) + { + g_Log.EventError("Stealing skill doesn't have a value for RANGE, defaulting to 2\n"); + iMaxRange = 2; + } + if (GetTopDist3D(pCharMark) > iMaxRange) { SysMessageDefault(DEFMSG_STEALING_MARK); return -SKTRIG_QTY;