Browse Source

Split network player sync and hero save file

pull/6257/head
Anders Jenbo 3 years ago
parent
commit
efa51993e3
  1. 64
      Source/msg.cpp
  2. 2
      Source/msg.h
  3. 14
      Source/multi.cpp
  4. 217
      Source/pack.cpp
  5. 51
      Source/pack.h
  6. 26
      Source/pfile.cpp
  7. 6
      test/writehero_test.cpp

64
Source/msg.cpp

@ -970,19 +970,6 @@ bool IsPItemValid(const TCmdPItem &message)
return IsItemAvailable(static_cast<_item_indexes>(SDL_SwapLE16(message.def.wIndx)));
}
void PrepareItemForNetwork(const Item &item, TItem &messageItem)
{
messageItem.bId = item._iIdentified ? 1 : 0;
messageItem.bDur = item._iDurability;
messageItem.bMDur = item._iMaxDur;
messageItem.bCh = item._iCharges;
messageItem.bMCh = item._iMaxCharges;
messageItem.wValue = SDL_SwapLE16(item._ivalue);
messageItem.wToHit = SDL_SwapLE16(item._iPLToHit);
messageItem.wMaxDam = SDL_SwapLE16(item._iMaxDam);
messageItem.dwBuff = SDL_SwapLE32(item.dwBuff);
}
void PrepareEarForNetwork(const Item &item, TEar &ear)
{
ear.bCursval = item._ivalue | ((item._iCurs - ICURS_EAR_SORCERER) << 6);
@ -1025,25 +1012,6 @@ void PrepareItemForNetwork(const Item &item, TCmdChItem &message)
PrepareItemForNetwork(item, message.item);
}
void RecreateItem(const Player &player, const TItem &messageItem, Item &item)
{
const uint32_t dwBuff = SDL_SwapLE32(messageItem.dwBuff);
RecreateItem(player, item,
static_cast<_item_indexes>(SDL_SwapLE16(messageItem.wIndx)), SDL_SwapLE16(messageItem.wCI),
SDL_SwapLE32(messageItem.dwSeed), SDL_SwapLE16(messageItem.wValue), (dwBuff & CF_HELLFIRE) != 0);
if (messageItem.bId != 0)
item._iIdentified = true;
item._iMaxDur = messageItem.bMDur;
item._iDurability = ClampDurability(item, messageItem.bDur);
item._iMaxCharges = clamp<int>(messageItem.bMCh, 0, item._iMaxCharges);
item._iCharges = clamp<int>(messageItem.bCh, 0, item._iMaxCharges);
if (gbIsHellfire) {
item._iPLToHit = ClampToHit(item, SDL_SwapLE16(messageItem.wToHit));
item._iMaxDam = ClampMaxDam(item, SDL_SwapLE16(messageItem.wMaxDam));
}
item.dwBuff = dwBuff;
}
void RecreateItem(const Player &player, const TCmdPItem &message, Item &item)
{
if (message.def.wIndx == SDL_SwapLE16(IDI_EAR))
@ -2359,6 +2327,38 @@ size_t OnOpenGrave(const TCmd *pCmd)
} // namespace
void PrepareItemForNetwork(const Item &item, TItem &messageItem)
{
messageItem.bId = item._iIdentified ? 1 : 0;
messageItem.bDur = item._iDurability;
messageItem.bMDur = item._iMaxDur;
messageItem.bCh = item._iCharges;
messageItem.bMCh = item._iMaxCharges;
messageItem.wValue = SDL_SwapLE16(item._ivalue);
messageItem.wToHit = SDL_SwapLE16(item._iPLToHit);
messageItem.wMaxDam = SDL_SwapLE16(item._iMaxDam);
messageItem.dwBuff = SDL_SwapLE32(item.dwBuff);
}
void RecreateItem(const Player &player, const TItem &messageItem, Item &item)
{
const uint32_t dwBuff = SDL_SwapLE32(messageItem.dwBuff);
RecreateItem(player, item,
static_cast<_item_indexes>(SDL_SwapLE16(messageItem.wIndx)), SDL_SwapLE16(messageItem.wCI),
SDL_SwapLE32(messageItem.dwSeed), SDL_SwapLE16(messageItem.wValue), (dwBuff & CF_HELLFIRE) != 0);
if (messageItem.bId != 0)
item._iIdentified = true;
item._iMaxDur = messageItem.bMDur;
item._iDurability = ClampDurability(item, messageItem.bDur);
item._iMaxCharges = clamp<int>(messageItem.bMCh, 0, item._iMaxCharges);
item._iCharges = clamp<int>(messageItem.bCh, 0, item._iMaxCharges);
if (gbIsHellfire) {
item._iPLToHit = ClampToHit(item, SDL_SwapLE16(messageItem.wToHit));
item._iMaxDam = ClampMaxDam(item, SDL_SwapLE16(messageItem.wMaxDam));
}
item.dwBuff = dwBuff;
}
void ClearLastSentPlayerCmd()
{
lastSentPlayerCmd = {};

2
Source/msg.h

@ -720,6 +720,8 @@ struct TBuffer {
extern uint8_t gbBufferMsgs;
extern int dwRecCount;
void PrepareItemForNetwork(const Item &item, TItem &messageItem);
void RecreateItem(const Player &player, const TItem &messageItem, Item &item);
void msg_send_drop_pkt(int pnum, int reason);
bool msg_wait_resync();
void run_delta_info();

14
Source/multi.cpp

@ -349,12 +349,10 @@ void ProcessTmsgs()
void SendPlayerInfo(int pnum, _cmd_id cmd)
{
PlayerPack pPack;
PlayerNetPack packed;
Player &myPlayer = *MyPlayer;
PackPlayer(&pPack, myPlayer, true, true);
pPack.friendlyMode = myPlayer.friendlyMode ? 1 : 0;
pPack.isOnSetLevel = myPlayer.plrIsOnSetLevel;
multi_send_zero_packet(pnum, cmd, reinterpret_cast<byte *>(&pPack), sizeof(PlayerPack));
PackNetPlayer(packed, myPlayer);
multi_send_zero_packet(pnum, cmd, reinterpret_cast<byte *>(&packed), sizeof(PlayerNetPack));
}
void SetupLocalPositions()
@ -803,7 +801,7 @@ bool NetInit(bool bSinglePlayer)
void recv_plrinfo(int pnum, const TCmdPlrInfoHdr &header, bool recv)
{
static PlayerPack PackedPlayerBuffer[MAX_PLRS];
static PlayerNetPack PackedPlayerBuffer[MAX_PLRS];
assert(pnum >= 0 && pnum < MAX_PLRS);
Player &player = Players[pnum];
@ -831,11 +829,9 @@ void recv_plrinfo(int pnum, const TCmdPlrInfoHdr &header, bool recv)
sgwPackPlrOffsetTbl[pnum] = 0;
PlayerLeftMsg(pnum, false);
if (!UnPackPlayer(&packedPlayer, player, true)) {
if (!UnPackNetPlayer(packedPlayer, player)) {
return;
}
player.friendlyMode = packedPlayer.friendlyMode != 0;
player.plrIsOnSetLevel = packedPlayer.isOnSetLevel != 0;
if (!recv) {
return;

217
Source/pack.cpp

@ -78,7 +78,7 @@ void PackItem(ItemPack &packedItem, const Item &item, bool isHellfire)
}
}
void PackPlayer(PlayerPack *pPack, const Player &player, bool manashield, bool netSync)
void PackPlayer(PlayerPack *pPack, const Player &player)
{
memset(pPack, 0, sizeof(*pPack));
pPack->destAction = player.destAction;
@ -114,14 +114,14 @@ void PackPlayer(PlayerPack *pPack, const Player &player, bool manashield, bool n
for (int i = 0; i < NUM_INVLOC; i++) {
const Item &item = player.InvBody[i];
bool isHellfire = netSync ? ((item.dwBuff & CF_HELLFIRE) != 0) : gbIsHellfire;
bool isHellfire = gbIsHellfire;
PackItem(pPack->InvBody[i], item, isHellfire);
}
pPack->_pNumInv = player._pNumInv;
for (int i = 0; i < pPack->_pNumInv; i++) {
const Item &item = player.InvList[i];
bool isHellfire = netSync ? ((item.dwBuff & CF_HELLFIRE) != 0) : gbIsHellfire;
bool isHellfire = gbIsHellfire;
PackItem(pPack->InvList[i], item, isHellfire);
}
@ -130,7 +130,7 @@ void PackPlayer(PlayerPack *pPack, const Player &player, bool manashield, bool n
for (int i = 0; i < MaxBeltItems; i++) {
const Item &item = player.SpdList[i];
bool isHellfire = netSync ? ((item.dwBuff & CF_HELLFIRE) != 0) : gbIsHellfire;
bool isHellfire = gbIsHellfire;
PackItem(pPack->SpdList[i], item, isHellfire);
}
@ -139,11 +139,53 @@ void PackPlayer(PlayerPack *pPack, const Player &player, bool manashield, bool n
pPack->pDamAcFlags = SDL_SwapLE32(static_cast<uint32_t>(player.pDamAcFlags));
pPack->pDiabloKillLevel = SDL_SwapLE32(player.pDiabloKillLevel);
pPack->bIsHellfire = gbIsHellfire ? 1 : 0;
pPack->pManaShield = 0;
}
void PackNetPlayer(PlayerNetPack &packed, const Player &player)
{
packed.plrlevel = player.plrlevel;
packed.px = player.position.tile.x;
packed.py = player.position.tile.y;
strcpy(packed.pName, player._pName);
packed.pClass = static_cast<int8_t>(player._pClass);
packed.pBaseStr = player._pBaseStr;
packed.pBaseMag = player._pBaseMag;
packed.pBaseDex = player._pBaseDex;
packed.pBaseVit = player._pBaseVit;
packed.pLevel = player._pLevel;
packed.pStatPts = player._pStatPts;
packed.pExperience = SDL_SwapLE32(player._pExperience);
packed.pGold = SDL_SwapLE32(player._pGold);
packed.pHPBase = SDL_SwapLE32(player._pHPBase);
packed.pMaxHPBase = SDL_SwapLE32(player._pMaxHPBase);
packed.pManaBase = SDL_SwapLE32(player._pManaBase);
packed.pMaxManaBase = SDL_SwapLE32(player._pMaxManaBase);
packed.pMemSpells = SDL_SwapLE64(player._pMemSpells);
for (int i = 0; i < MAX_SPELLS; i++)
packed.pSplLvl[i] = player._pSplLvl[i];
for (int i = 0; i < NUM_INVLOC; i++)
PrepareItemForNetwork(player.InvBody[i], packed.InvBody[i]);
packed._pNumInv = player._pNumInv;
for (int i = 0; i < packed._pNumInv; i++)
PrepareItemForNetwork(player.InvList[i], packed.InvList[i]);
if (!gbIsMultiplayer || manashield)
pPack->pManaShield = SDL_SwapLE32(player.pManaShield);
else
pPack->pManaShield = 0;
for (int i = 0; i < InventoryGridCells; i++)
packed.InvGrid[i] = player.InvGrid[i];
for (int i = 0; i < MaxBeltItems; i++)
PrepareItemForNetwork(player.SpdList[i], packed.SpdList[i]);
packed.wReflections = SDL_SwapLE16(player.wReflections);
packed.pDifficulty = player.pDifficulty;
packed.pDamAcFlags = player.pDamAcFlags;
packed.pDiabloKillLevel = player.pDiabloKillLevel;
packed.pManaShield = player.pManaShield;
packed.friendlyMode = player.friendlyMode ? 1 : 0;
packed.isOnSetLevel = player.plrIsOnSetLevel;
}
void UnPackItem(const ItemPack &packedItem, const Player &player, Item &item, bool isHellfire)
@ -207,38 +249,21 @@ void UnPackItem(const ItemPack &packedItem, const Player &player, Item &item, bo
}
}
bool UnPackPlayer(const PlayerPack *pPack, Player &player, bool netSync)
void UnPackPlayer(const PlayerPack *pPack, Player &player)
{
Point position { pPack->px, pPack->py };
if (!InDungeonBounds(position)) {
return false;
}
uint8_t dungeonLevel = pPack->plrlevel;
if (dungeonLevel >= NUMLEVELS) {
return false;
}
if (pPack->pClass >= enum_size<HeroClass>::value) {
return false;
}
auto heroClass = static_cast<HeroClass>(pPack->pClass);
if (pPack->pLevel > MaxCharacterLevel || pPack->pLevel < 1) {
return false;
}
uint32_t difficulty = SDL_SwapLE32(pPack->pDifficulty);
if (difficulty > DIFF_LAST) {
return false;
}
player._pLevel = pPack->pLevel;
player = {};
player._pLevel = clamp<int8_t>(pPack->pLevel, 1, MaxCharacterLevel);
player._pMaxHPBase = SDL_SwapLE32(pPack->pMaxHPBase);
player._pHPBase = SDL_SwapLE32(pPack->pHPBase);
player._pMaxHP = player._pMaxHPBase;
player._pHitPoints = player._pHPBase;
player.position.tile = position;
player.position.future = position;
player.setLevel(dungeonLevel);
player.setLevel(pPack->plrlevel);
player._pClass = heroClass;
player._pClass = static_cast<HeroClass>(clamp<uint8_t>(pPack->pClass, 0, enum_size<HeroClass>::value - 1));
ClrPlrPath(player);
player.destAction = ACTION_NONE;
@ -259,12 +284,9 @@ bool UnPackPlayer(const PlayerPack *pPack, Player &player, bool netSync)
player._pStatPts = pPack->pStatPts;
player._pExperience = SDL_SwapLE32(pPack->pExperience);
player._pGold = SDL_SwapLE32(pPack->pGold);
player._pMaxHPBase = SDL_SwapLE32(pPack->pMaxHPBase);
player._pHPBase = SDL_SwapLE32(pPack->pHPBase);
player._pBaseToBlk = PlayersData[static_cast<std::size_t>(player._pClass)].blockBonus;
if (!netSync)
if ((int)(player._pHPBase & 0xFFFFFFC0) < 64)
player._pHPBase = 64;
if ((int)(player._pHPBase & 0xFFFFFFC0) < 64)
player._pHPBase = 64;
player._pMaxManaBase = SDL_SwapLE32(pPack->pMaxManaBase);
player._pManaBase = SDL_SwapLE32(pPack->pManaBase);
@ -275,41 +297,120 @@ bool UnPackPlayer(const PlayerPack *pPack, Player &player, bool netSync)
for (int i = 37; i < 47; i++)
player._pSplLvl[i] = pPack->pSplLvl2[i - 37];
for (int i = 0; i < NUM_INVLOC; i++) {
auto packedItem = pPack->InvBody[i];
bool isHellfire = netSync ? ((packedItem.dwBuff & CF_HELLFIRE) != 0) : (pPack->bIsHellfire != 0);
UnPackItem(packedItem, player, player.InvBody[i], isHellfire);
}
bool isHellfire = pPack->bIsHellfire != 0;
for (int i = 0; i < NUM_INVLOC; i++)
UnPackItem(pPack->InvBody[i], player, player.InvBody[i], isHellfire);
player._pNumInv = pPack->_pNumInv;
for (int i = 0; i < player._pNumInv; i++) {
auto packedItem = pPack->InvList[i];
bool isHellfire = netSync ? ((packedItem.dwBuff & CF_HELLFIRE) != 0) : (pPack->bIsHellfire != 0);
UnPackItem(packedItem, player, player.InvList[i], isHellfire);
}
for (int i = 0; i < player._pNumInv; i++)
UnPackItem(pPack->InvList[i], player, player.InvList[i], isHellfire);
for (int i = 0; i < InventoryGridCells; i++)
player.InvGrid[i] = pPack->InvGrid[i];
VerifyGoldSeeds(player);
for (int i = 0; i < MaxBeltItems; i++) {
auto packedItem = pPack->SpdList[i];
bool isHellfire = netSync ? ((packedItem.dwBuff & CF_HELLFIRE) != 0) : (pPack->bIsHellfire != 0);
UnPackItem(packedItem, player, player.SpdList[i], isHellfire);
}
for (int i = 0; i < MaxBeltItems; i++)
UnPackItem(pPack->SpdList[i], player, player.SpdList[i], isHellfire);
CalcPlrInv(player, false);
player.wReflections = SDL_SwapLE16(pPack->wReflections);
player.pDiabloKillLevel = SDL_SwapLE32(pPack->pDiabloKillLevel);
player.pBattleNet = pPack->pBattleNet != 0;
player.pManaShield = false;
uint32_t difficulty = SDL_SwapLE32(pPack->pDifficulty);
player.pDifficulty = static_cast<_difficulty>(clamp<uint32_t>(difficulty, 0, DIFF_LAST));
player.pDamAcFlags = static_cast<ItemSpecialEffectHf>(SDL_SwapLE32(static_cast<uint32_t>(pPack->pDamAcFlags)));
}
bool UnPackNetPlayer(const PlayerNetPack &packed, Player &player)
{
Point position { packed.px, packed.py };
if (!InDungeonBounds(position)) {
return false;
}
uint8_t dungeonLevel = packed.plrlevel;
if (dungeonLevel >= NUMLEVELS) {
return false;
}
if (packed.pClass >= enum_size<HeroClass>::value) {
return false;
}
if (packed.pLevel > MaxCharacterLevel || packed.pLevel < 1) {
return false;
}
uint8_t difficulty = packed.pDifficulty;
if (difficulty > DIFF_LAST) {
return false;
}
player._pLevel = packed.pLevel;
player.position.tile = position;
player.position.future = position;
player.setLevel(dungeonLevel);
player._pClass = static_cast<HeroClass>(packed.pClass);
ClrPlrPath(player);
player.destAction = ACTION_NONE;
strcpy(player._pName, packed.pName);
InitPlayer(player, true);
player._pBaseStr = packed.pBaseStr;
player._pStrength = packed.pBaseStr;
player._pBaseMag = packed.pBaseMag;
player._pMagic = packed.pBaseMag;
player._pBaseDex = packed.pBaseDex;
player._pDexterity = packed.pBaseDex;
player._pBaseVit = packed.pBaseVit;
player._pVitality = packed.pBaseVit;
player._pStatPts = packed.pStatPts;
player._pExperience = SDL_SwapLE32(packed.pExperience);
player._pGold = SDL_SwapLE32(packed.pGold);
player._pMaxHPBase = SDL_SwapLE32(packed.pMaxHPBase);
player._pHPBase = SDL_SwapLE32(packed.pHPBase);
player._pBaseToBlk = PlayersData[static_cast<std::size_t>(player._pClass)].blockBonus;
player._pMaxManaBase = SDL_SwapLE32(packed.pMaxManaBase);
player._pManaBase = SDL_SwapLE32(packed.pManaBase);
player._pMemSpells = SDL_SwapLE64(packed.pMemSpells);
for (int i = 0; i < MAX_SPELLS; i++)
player._pSplLvl[i] = packed.pSplLvl[i];
for (int i = 0; i < NUM_INVLOC; i++)
RecreateItem(player, packed.InvBody[i], player.InvBody[i]);
player._pNumInv = packed._pNumInv;
for (int i = 0; i < player._pNumInv; i++)
RecreateItem(player, packed.InvList[i], player.InvList[i]);
for (int i = 0; i < InventoryGridCells; i++)
player.InvGrid[i] = packed.InvGrid[i];
for (int i = 0; i < MaxBeltItems; i++)
RecreateItem(player, packed.SpdList[i], player.SpdList[i]);
CalcPlrInv(player, false);
player.wReflections = SDL_SwapLE16(packed.wReflections);
player.pTownWarps = 0;
player.pDungMsgs = 0;
player.pDungMsgs2 = 0;
player.pLvlLoad = 0;
player.pDiabloKillLevel = SDL_SwapLE32(pPack->pDiabloKillLevel);
player.pBattleNet = pPack->pBattleNet != 0;
player.pManaShield = pPack->pManaShield != 0;
player.pDiabloKillLevel = packed.pDiabloKillLevel;
player.pManaShield = packed.pManaShield != 0;
player.pDifficulty = static_cast<_difficulty>(difficulty);
player.pDamAcFlags = static_cast<ItemSpecialEffectHf>(SDL_SwapLE32(static_cast<uint32_t>(pPack->pDamAcFlags)));
player.pDamAcFlags = packed.pDamAcFlags;
player.friendlyMode = packed.friendlyMode != 0;
player.plrIsOnSetLevel = packed.isOnSetLevel != 0;
return true;
}

51
Source/pack.h

@ -9,6 +9,7 @@
#include "inv.h"
#include "items.h"
#include "msg.h"
#include "player.h"
namespace devilution {
@ -24,7 +25,7 @@ struct ItemPack {
uint8_t bCh;
uint8_t bMCh;
uint16_t wValue;
int32_t dwBuff;
uint32_t dwBuff;
};
struct PlayerPack {
@ -67,24 +68,56 @@ struct PlayerPack {
uint8_t pDungMsgs2;
/** The format the charater is in, 0: Diablo, 1: Hellfire */
int8_t bIsHellfire;
int8_t bReserved; // For future use
uint8_t reserved; // For future use
uint16_t wReflections;
int16_t wReserved2; // For future use
uint8_t reserved2[2]; // For future use
uint8_t pSplLvl2[10]; // Hellfire spells
int16_t wReserved8; // For future use
uint32_t pDiabloKillLevel;
uint32_t pDifficulty;
uint32_t pDamAcFlags; // `ItemSpecialEffectHf` is 1 byte but this is 4 bytes.
/**@brief Only used in multiplayer sync (SendPlayerInfo/recv_plrinfo). Never used in save games (single- or multiplayer). */
uint32_t pDamAcFlags; // `ItemSpecialEffectHf` is 1 byte but this is 4 bytes.
uint8_t reserved3[20]; // For future use
};
struct PlayerNetPack {
uint8_t plrlevel;
uint8_t px;
uint8_t py;
char pName[PlayerNameLength];
uint8_t pClass;
uint8_t pBaseStr;
uint8_t pBaseMag;
uint8_t pBaseDex;
uint8_t pBaseVit;
int8_t pLevel;
uint8_t pStatPts;
uint32_t pExperience;
int32_t pGold;
int32_t pHPBase;
int32_t pMaxHPBase;
int32_t pManaBase;
int32_t pMaxManaBase;
uint8_t pSplLvl[MAX_SPELLS];
uint64_t pMemSpells;
TItem InvBody[NUM_INVLOC];
TItem InvList[InventoryGridCells];
int8_t InvGrid[InventoryGridCells];
uint8_t _pNumInv;
TItem SpdList[MaxBeltItems];
uint8_t pManaShield;
uint16_t wReflections;
uint8_t pDiabloKillLevel;
uint8_t pDifficulty;
ItemSpecialEffectHf pDamAcFlags;
uint8_t friendlyMode;
/**@brief Only used in multiplayer sync (SendPlayerInfo/recv_plrinfo). Never used in save games (single- or multiplayer). */
uint8_t isOnSetLevel;
uint8_t dwReserved[18]; // For future use
};
#pragma pack(pop)
void PackPlayer(PlayerPack *pPack, const Player &player, bool manashield, bool netSync);
bool UnPackPlayer(const PlayerPack *pPack, Player &player, bool netSync);
void PackPlayer(PlayerPack *pPack, const Player &player);
void UnPackPlayer(const PlayerPack *pPack, Player &player);
void PackNetPlayer(PlayerNetPack &packed, const Player &player);
bool UnPackNetPlayer(const PlayerNetPack &packed, Player &player);
/**
* @brief Save the attributes needed to recreate this item into an ItemPack struct

26
Source/pfile.cpp

@ -482,7 +482,7 @@ void pfile_write_hero(SaveWriter &saveWriter, bool writeGameData)
PlayerPack pkplr;
Player &myPlayer = *MyPlayer;
PackPlayer(&pkplr, myPlayer, !gbIsMultiplayer, false);
PackPlayer(&pkplr, myPlayer);
EncodeHero(saveWriter, &pkplr);
if (!gbVanilla) {
SaveHotkeys(saveWriter, myPlayer);
@ -643,16 +643,13 @@ bool pfile_ui_set_hero_infos(bool (*uiAddHeroInfo)(_uiheroinfo *))
Player &player = Players[0];
player = {};
UnPackPlayer(&pkplr, player);
LoadHeroItems(player);
RemoveEmptyInventory(player);
CalcPlrInv(player, false);
if (UnPackPlayer(&pkplr, player, false)) {
LoadHeroItems(player);
RemoveEmptyInventory(player);
CalcPlrInv(player, false);
Game2UiPlayer(player, &uihero, hasSaveGame);
uiAddHeroInfo(&uihero);
}
Game2UiPlayer(player, &uihero, hasSaveGame);
uiAddHeroInfo(&uihero);
}
}
}
@ -696,7 +693,7 @@ bool pfile_ui_save_create(_uiheroinfo *heroinfo)
Player &player = Players[0];
CreatePlayer(player, heroinfo->heroclass);
CopyUtf8(player._pName, heroinfo->name, PlayerNameLength);
PackPlayer(&pkplr, player, true, false);
PackPlayer(&pkplr, player);
EncodeHero(saveWriter, &pkplr);
Game2UiPlayer(player, heroinfo, false);
if (!gbVanilla) {
@ -719,8 +716,6 @@ bool pfile_delete_save(_uiheroinfo *heroInfo)
void pfile_read_player_from_save(uint32_t saveNum, Player &player)
{
player = {};
PlayerPack pkplr;
{
std::optional<SaveReader> archive = OpenSaveArchive(saveNum);
@ -734,10 +729,7 @@ void pfile_read_player_from_save(uint32_t saveNum, Player &player)
pkplr.bIsHellfire = gbIsHellfireSaveGame ? 1 : 0;
}
if (!UnPackPlayer(&pkplr, player, false)) {
return;
}
UnPackPlayer(&pkplr, player);
LoadHeroItems(player);
RemoveEmptyInventory(player);
CalcPlrInv(player, false);

6
test/writehero_test.cpp

@ -53,8 +53,6 @@ void SwapLE(PlayerPack &player)
SwapLE(item);
}
player.wReflections = SDL_SwapLE16(player.wReflections);
player.wReserved2 = SDL_SwapLE16(player.wReserved2);
player.wReserved8 = SDL_SwapLE16(player.wReserved8);
player.pDiabloKillLevel = SDL_SwapLE32(player.pDiabloKillLevel);
player.pDifficulty = SDL_SwapLE32(player.pDifficulty);
player.pDamAcFlags = SDL_SwapLE32(player.pDamAcFlags);
@ -377,15 +375,13 @@ TEST(Writehero, pfile_write_hero)
Players.resize(1);
MyPlayerId = 0;
MyPlayer = &Players[MyPlayerId];
*MyPlayer = {};
_uiheroinfo info {};
strcpy(info.name, "TestPlayer");
info.heroclass = HeroClass::Rogue;
pfile_ui_save_create(&info);
PlayerPack pks;
PackPlayerTest(&pks);
UnPackPlayer(&pks, *MyPlayer, true);
UnPackPlayer(&pks, *MyPlayer);
AssertPlayer(Players[0]);
pfile_write_hero();

Loading…
Cancel
Save