From 1180f60d1e1a72c74bfec54d22171d2f6d2daf41 Mon Sep 17 00:00:00 2001 From: staphen Date: Sat, 17 May 2025 18:57:27 -0400 Subject: [PATCH] Reduce cognitive complexity in DeltaLoadLevel() --- Source/msg.cpp | 279 +++++++++++++++++++++++++++---------------------- 1 file changed, 152 insertions(+), 127 deletions(-) diff --git a/Source/msg.cpp b/Source/msg.cpp index 183efe93e..017f97ce8 100644 --- a/Source/msg.cpp +++ b/Source/msg.cpp @@ -294,6 +294,13 @@ Item ItemLimbo; /** @brief Last sent player command for the local player. */ TCmdLocParam5 lastSentPlayerCmd; +void RecreateItem(const Player &player, const TCmdPItem &message, Item &item); + +bool IsMonsterDeltaValid(const DMonsterStr &monster) +{ + return InDungeonBounds(monster.position) && monster.hitPoints >= 0; +} + bool IsPortalDeltaValid(const DPortal &portal) { const WorldTilePosition position { portal.x, portal.y }; @@ -798,6 +805,147 @@ void DeltaImportData(_cmd_id cmd, uint32_t recvOffset, int pnum) sgbDeltaChunks++; } +void DeltaLoadSpawnedMonsters(const DLevel &deltaLevel) +{ + for (const auto &deltaSpawnedMonster : deltaLevel.spawnedMonsters) { + const auto &monsterData = deltaSpawnedMonster.second; + LoadDeltaSpawnedMonster(deltaSpawnedMonster.second.typeIndex, deltaSpawnedMonster.first, monsterData.seed, monsterData.golemOwnerPlayerId, monsterData.golemSpellLevel); + assert(deltaLevel.monster[deltaSpawnedMonster.first].position.x != 0xFF); + } +} + +void DeltaLoadEnemies(const DLevel &deltaLevel) +{ + for (size_t i = 0; i < MaxMonsters; i++) { + const DMonsterStr &deltaMonster = deltaLevel.monster[i]; + if (!IsMonsterDeltaValid(deltaMonster)) + continue; + if (deltaMonster.hitPoints == 0) + continue; + Monster &monster = Monsters[i]; + if (IsEnemyValid(i, deltaMonster.menemy)) + decode_enemy(monster, deltaMonster.menemy); + if (monster.position.tile != Point { 0, 0 } && monster.position.tile != GolemHoldingCell) + monster.occupyTile(monster.position.tile, false); + if (monster.type().type == MT_GOLEM) { + GolumAi(monster); + monster.flags |= (MFLAG_TARGETS_MONSTER | MFLAG_GOLEM); + } else { + M_StartStand(monster, monster.direction); + } + monster.activeForTicks = deltaMonster.mactive; + } +} + +void DeltaLoadMonsters(const DLevel &deltaLevel) +{ + for (size_t i = 0; i < MaxMonsters; i++) { + const DMonsterStr &deltaMonster = deltaLevel.monster[i]; + if (!IsMonsterDeltaValid(deltaMonster)) + continue; + + Monster &monster = Monsters[i]; + M_ClearSquares(monster); + { + const WorldTilePosition position = deltaMonster.position; + monster.position.tile = position; + monster.position.old = position; + monster.position.future = position; + if (monster.lightId != NO_LIGHT) + ChangeLightXY(monster.lightId, position); + } + + monster.hitPoints = SDL_SwapLE32(deltaMonster.hitPoints); + monster.whoHit = deltaMonster.mWhoHit; + if (deltaMonster.hitPoints != 0) + continue; + + M_ClearSquares(monster); + if (monster.ai != MonsterAIID::Diablo) { + if (monster.isUnique()) { + AddCorpse(monster.position.tile, monster.corpseId, monster.direction); + } else { + AddCorpse(monster.position.tile, monster.type().corpseId, monster.direction); + } + } + monster.isInvalid = true; + M_UpdateRelations(monster); + } + + // Calling this here ensures that monster hitpoints + // are synced before attempting to validate enemy IDs + DeltaLoadEnemies(deltaLevel); +} + +void DeltaLoadObjects(DLevel &deltaLevel) +{ + for (auto it = deltaLevel.object.begin(); it != deltaLevel.object.end();) { + Object *object = FindObjectAtPosition(it->first); + if (object == nullptr) { + it = deltaLevel.object.erase(it); + continue; + } + + switch (it->second.bCmd) { + case CMD_OPENDOOR: + case CMD_OPERATEOBJ: + DeltaSyncOpObject(*object); + it++; + break; + case CMD_CLOSEDOOR: + DeltaSyncCloseObj(*object); + it++; + break; + case CMD_BREAKOBJ: + DeltaSyncBreakObj(*object); + it++; + break; + default: + it = deltaLevel.object.erase(it); // discard invalid commands + break; + } + } + + for (int i = 0; i < ActiveObjectCount; i++) { + Object &object = Objects[ActiveObjects[i]]; + if (object.IsTrap()) { + UpdateTrapState(object); + } + } +} + +void DeltaLoadItems(const DLevel &deltaLevel) +{ + for (const TCmdPItem &deltaItem : deltaLevel.item) { + if (deltaItem.bCmd == CMD_INVALID) + continue; + + if (deltaItem.bCmd == TCmdPItem::PickedUpItem) { + int activeItemIndex = FindGetItem( + SDL_SwapLE32(deltaItem.def.dwSeed), + static_cast<_item_indexes>(SDL_SwapLE16(deltaItem.def.wIndx)), + SDL_SwapLE16(deltaItem.def.wCI)); + if (activeItemIndex != -1) { + const auto &position = Items[ActiveItems[activeItemIndex]].position; + if (dItem[position.x][position.y] == ActiveItems[activeItemIndex] + 1) + dItem[position.x][position.y] = 0; + DeleteItem(activeItemIndex); + } + } + if (deltaItem.bCmd == TCmdPItem::DroppedItem) { + int ii = AllocateItem(); + auto &item = Items[ii]; + RecreateItem(*MyPlayer, deltaItem, item); + + int x = deltaItem.x; + int y = deltaItem.y; + item.position = GetItemPosition({ x, y }); + dItem[item.position.x][item.position.y] = static_cast(ii + 1); + RespawnItem(Items[ii], false); + } + } +} + size_t OnLevelData(const TCmdPlrInfoHdr &message, size_t maxCmdSize, const Player &player) { const uint16_t wBytes = SDL_SwapLE16(message.wBytes); @@ -2627,11 +2775,6 @@ void DeltaClearLevel(uint8_t level) LocalLevels.erase(level); } -bool DeltaMonsterIsValid(const DMonsterStr &monster) -{ - return InDungeonBounds(monster.position) && monster.hitPoints >= 0; -} - void delta_kill_monster(const Monster &monster, Point position, const Player &player) { if (!gbIsMultiplayer) @@ -2778,137 +2921,19 @@ void DeltaLoadLevel() uint8_t localLevel = GetLevelForMultiplayer(*MyPlayer); DLevel &deltaLevel = GetDeltaLevel(localLevel); if (leveltype != DTYPE_TOWN) { - for (auto &deltaSpawnedMonster : deltaLevel.spawnedMonsters) { - auto &monsterData = deltaSpawnedMonster.second; - LoadDeltaSpawnedMonster(deltaSpawnedMonster.second.typeIndex, deltaSpawnedMonster.first, monsterData.seed, monsterData.golemOwnerPlayerId, monsterData.golemSpellLevel); - assert(deltaLevel.monster[deltaSpawnedMonster.first].position.x != 0xFF); - } - - for (size_t i = 0; i < MaxMonsters; i++) { - DMonsterStr &deltaMonster = deltaLevel.monster[i]; - if (!DeltaMonsterIsValid(deltaMonster)) - continue; - - Monster &monster = Monsters[i]; - M_ClearSquares(monster); - { - const WorldTilePosition position = deltaMonster.position; - monster.position.tile = position; - monster.position.old = position; - monster.position.future = position; - if (monster.lightId != NO_LIGHT) - ChangeLightXY(monster.lightId, position); - } - - monster.hitPoints = SDL_SwapLE32(deltaMonster.hitPoints); - monster.whoHit = deltaMonster.mWhoHit; - if (deltaMonster.hitPoints == 0) { - M_ClearSquares(monster); - if (monster.ai != MonsterAIID::Diablo) { - if (monster.isUnique()) { - AddCorpse(monster.position.tile, monster.corpseId, monster.direction); - } else { - AddCorpse(monster.position.tile, monster.type().corpseId, monster.direction); - } - } - monster.isInvalid = true; - M_UpdateRelations(monster); - } - } - - // Separate loop ensures that monster hitpoints are - // synced before attempting to validate enemy IDs - for (size_t i = 0; i < MaxMonsters; i++) { - DMonsterStr &deltaMonster = deltaLevel.monster[i]; - if (!DeltaMonsterIsValid(deltaMonster)) - continue; - if (deltaMonster.hitPoints == 0) - continue; - Monster &monster = Monsters[i]; - if (IsEnemyValid(i, deltaMonster.menemy)) - decode_enemy(monster, deltaMonster.menemy); - if (monster.position.tile != Point { 0, 0 } && monster.position.tile != GolemHoldingCell) - monster.occupyTile(monster.position.tile, false); - if (monster.type().type == MT_GOLEM) { - GolumAi(monster); - monster.flags |= (MFLAG_TARGETS_MONSTER | MFLAG_GOLEM); - } else { - M_StartStand(monster, monster.direction); - } - monster.activeForTicks = deltaMonster.mactive; - } + DeltaLoadSpawnedMonsters(deltaLevel); + DeltaLoadMonsters(deltaLevel); auto localLevelIt = LocalLevels.find(localLevel); if (localLevelIt != LocalLevels.end()) memcpy(AutomapView, &localLevelIt->second, sizeof(AutomapView)); else memset(AutomapView, 0, sizeof(AutomapView)); - } - - if (leveltype != DTYPE_TOWN) { - for (auto it = deltaLevel.object.begin(); it != deltaLevel.object.end();) { - Object *object = FindObjectAtPosition(it->first); - if (object == nullptr) { - it = deltaLevel.object.erase(it); - continue; - } - switch (it->second.bCmd) { - case CMD_OPENDOOR: - case CMD_OPERATEOBJ: - DeltaSyncOpObject(*object); - it++; - break; - case CMD_CLOSEDOOR: - DeltaSyncCloseObj(*object); - it++; - break; - case CMD_BREAKOBJ: - DeltaSyncBreakObj(*object); - it++; - break; - default: - it = deltaLevel.object.erase(it); // discard invalid commands - break; - } - } - - for (int i = 0; i < ActiveObjectCount; i++) { - Object &object = Objects[ActiveObjects[i]]; - if (object.IsTrap()) { - UpdateTrapState(object); - } - } + DeltaLoadObjects(deltaLevel); } - for (const TCmdPItem &deltaItem : deltaLevel.item) { - if (deltaItem.bCmd == CMD_INVALID) - continue; - - if (deltaItem.bCmd == TCmdPItem::PickedUpItem) { - int activeItemIndex = FindGetItem( - SDL_SwapLE32(deltaItem.def.dwSeed), - static_cast<_item_indexes>(SDL_SwapLE16(deltaItem.def.wIndx)), - SDL_SwapLE16(deltaItem.def.wCI)); - if (activeItemIndex != -1) { - const auto &position = Items[ActiveItems[activeItemIndex]].position; - if (dItem[position.x][position.y] == ActiveItems[activeItemIndex] + 1) - dItem[position.x][position.y] = 0; - DeleteItem(activeItemIndex); - } - } - if (deltaItem.bCmd == TCmdPItem::DroppedItem) { - int ii = AllocateItem(); - auto &item = Items[ii]; - RecreateItem(*MyPlayer, deltaItem, item); - - int x = deltaItem.x; - int y = deltaItem.y; - item.position = GetItemPosition({ x, y }); - dItem[item.position.x][item.position.y] = static_cast(ii + 1); - RespawnItem(Items[ii], false); - } - } + DeltaLoadItems(deltaLevel); } void NetSendCmd(bool bHiPri, _cmd_id bCmd)