diff --git a/src/engine/server/server.cpp b/src/engine/server/server.cpp
index 96790858..a34d89cc 100644
--- a/src/engine/server/server.cpp
+++ b/src/engine/server/server.cpp
@@ -336,14 +336,14 @@ CPlayerData *CServer::GetPlayerData(int ClientID, int ColorID)
return pData;
else
{
- CPlayerData *pNewData = new CPlayerData(m_aClients[ClientID].m_aName, ColorID);
+ CPlayerData *pNewData = new CPlayerData(m_aClients[ClientID].m_aName, ColorID, Storage());
m_pPlayerData->Add(pNewData);
return pNewData;
}
}
else
{
- m_pPlayerData = new CPlayerData(m_aClients[ClientID].m_aName, ColorID);
+ m_pPlayerData = new CPlayerData(m_aClients[ClientID].m_aName, ColorID, Storage());
return m_pPlayerData;
}
diff --git a/src/engine/shared/linewriter.cpp b/src/engine/shared/linewriter.cpp
new file mode 100644
index 00000000..8b1df272
--- /dev/null
+++ b/src/engine/shared/linewriter.cpp
@@ -0,0 +1,22 @@
+#include "linewriter.h"
+
+CLineWriter::CLineWriter(IOHANDLE IO)
+{
+ m_IO = IO;
+}
+
+CLineWriter::~CLineWriter()
+{
+ Shutdown();
+}
+
+void CLineWriter::Shutdown()
+{
+ io_write_newline(m_IO);
+ io_close(m_IO);
+}
+
+void CLineWriter::Write(const char *pStr)
+{
+ io_write(m_IO, pStr, str_length(pStr));
+}
\ No newline at end of file
diff --git a/src/engine/shared/linewriter.h b/src/engine/shared/linewriter.h
new file mode 100644
index 00000000..9b9adbd8
--- /dev/null
+++ b/src/engine/shared/linewriter.h
@@ -0,0 +1,18 @@
+#ifndef ENGINE_SHARED_LINEWRITER_H
+#define ENGINE_SHARED_LINEWRITER_H
+#include
+
+class CLineWriter
+{
+ IOHANDLE m_IO;
+
+public:
+ CLineWriter(IOHANDLE IO);
+ ~CLineWriter();
+
+ void Shutdown();
+
+ void Write(const char *pStr);
+ void WriteNewLine() { io_write_newline(m_IO); }
+};
+#endif
diff --git a/src/game/server/entities/character.cpp b/src/game/server/entities/character.cpp
index fd54c530..3cc56063 100644
--- a/src/game/server/entities/character.cpp
+++ b/src/game/server/entities/character.cpp
@@ -304,6 +304,8 @@ void CCharacter::SaveData()
else
pData->m_aWeaponType[i] = 0;
}
+
+ pData->SaveToFile();
char aBuf[256];
str_format(aBuf, sizeof(aBuf), "Data save - color=%d", GetPlayer()->GetColorID());
@@ -1209,6 +1211,7 @@ void CCharacter::GiveStartWeapon()
// load saved weapons
CPlayerData *pData = GameServer()->Server()->GetPlayerData(GetPlayer()->GetCID(), GetPlayer()->GetColorID());
+ pData->LoadDataFromFile();
bool GotItems = false;
diff --git a/src/game/server/playerdata.cpp b/src/game/server/playerdata.cpp
index ce43d28b..f0748486 100644
--- a/src/game/server/playerdata.cpp
+++ b/src/game/server/playerdata.cpp
@@ -1,9 +1,16 @@
#include
#include
+#include
+#include
+#include
+#include
+
+#include
+
#include "playerdata.h"
-CPlayerData::CPlayerData(const char *pName, int ColorID)
+CPlayerData::CPlayerData(const char *pName, int ColorID, IStorage *pStorage)
{
m_pChild1 = 0;
m_pChild2 = 0;
@@ -11,6 +18,8 @@ CPlayerData::CPlayerData(const char *pName, int ColorID)
str_copy(m_aName, pName, 16);
m_ColorID = ColorID;
+ m_pStorage = pStorage;
+ LoadDataFromFile();
Reset();
}
@@ -108,4 +117,96 @@ void CPlayerData::Reset()
m_Gold = 0;
m_HighestLevel = 0;
m_HighestLevelSeed = 0;
+}
+
+void CPlayerData::LoadDataFromFile()
+{
+ if (!g_Config.m_SvSavePlayerdata)
+ return;
+
+ char aFilename[32];
+ str_format(aFilename, sizeof(aFilename), "playerdatas/%s_%d.acc", m_aName, m_ColorID);
+
+ IOHANDLE File = m_pStorage->OpenFile(aFilename, IOFLAG_READ, IStorage::TYPE_ALL);
+ if(!File)
+ {
+ SaveToFile(); // Create file
+ return;
+ }
+ CLineReader LineReader;
+ LineReader.Init(File);
+
+ // read each line
+ while(char *pLine = LineReader.Get())
+ {
+ // skip blank/empty lines as well as comments
+ if(str_length(pLine) > 0 && pLine[0] != '#' && pLine[0] != '\n' && pLine[0] != '\r'
+ && pLine[0] != '\t' && pLine[0] != '\v' && pLine[0] != ' ')
+ {
+ // TODO: Ugly, rewrite this
+ if(!str_comp_num(pLine, "Weapon: ", 8)) sscanf(pLine, "Weapon: %d %d %d %d %d %d %d %d %d %d %d %d", &(m_aWeaponType[0]), &(m_aWeaponType[1]), &(m_aWeaponType[2]), &(m_aWeaponType[3]), &(m_aWeaponType[4]), &(m_aWeaponType[5]), &(m_aWeaponType[6]), &(m_aWeaponType[7]), &(m_aWeaponType[8]), &(m_aWeaponType[9]), &(m_aWeaponType[10]), &(m_aWeaponType[11]));
+ if(!str_comp_num(pLine, "Ammo: ", 6)) sscanf(pLine, "Ammo: %d %d %d %d %d %d %d %d %d %d %d %d", &(m_aWeaponAmmo[0]), &(m_aWeaponAmmo[1]), &(m_aWeaponAmmo[2]), &(m_aWeaponAmmo[3]), &(m_aWeaponAmmo[4]), &(m_aWeaponAmmo[5]), &(m_aWeaponAmmo[6]), &(m_aWeaponAmmo[7]), &(m_aWeaponAmmo[8]), &(m_aWeaponAmmo[9]), &(m_aWeaponAmmo[10]), &(m_aWeaponAmmo[11]));
+ if(!str_comp_num(pLine, "Armor: ", 7)) sscanf(pLine, "Armor: %d", &m_Armor);
+ if(!str_comp_num(pLine, "Kits: ", 6)) sscanf(pLine, "Kits: %d", &m_Kits);
+ if(!str_comp_num(pLine, "Score: ", 7)) sscanf(pLine, "Score: %d", &m_Score);
+ if(!str_comp_num(pLine, "Gold: ", 6)) sscanf(pLine, "Gold: %d", &m_Gold);
+ if(!str_comp_num(pLine, "HighestLevelSeed: ", 18)) sscanf(pLine, "HighestLevelSeed: %d", &m_HighestLevelSeed);
+ else if(!str_comp_num(pLine, "HighestLevel: ", 14)) sscanf(pLine, "HighestLevel: %d", &m_HighestLevel);
+ }
+ }
+
+
+ io_close(File);
+}
+
+void CPlayerData::SaveToFile()
+{
+ if (!g_Config.m_SvSavePlayerdata)
+ return;
+
+ m_pStorage->CreateFolder("playerdatas", IStorage::TYPE_SAVE);
+
+ char aFilename[32];
+ str_format(aFilename, sizeof(aFilename), "playerdatas/%s_%d.acc", m_aName, m_ColorID);
+
+ IOHANDLE File = m_pStorage->OpenFile(aFilename, IOFLAG_WRITE, IStorage::TYPE_SAVE);
+ if(!File)
+ return;
+
+ CLineWriter Writer(File);
+
+ char aBuf[256];
+
+#define WRITE_LINE_INT(w, x) \
+ do \
+ { \
+ str_format(aBuf, sizeof(aBuf), "%d", x); \
+ (w).Write(aBuf); \
+ } while(0)
+
+ // Warning! Weapon Type change
+ Writer.Write("Weapon:");
+ for (int i = 0; i < 12; i++)
+ {
+ Writer.Write(" ");
+ WRITE_LINE_INT(Writer, m_aWeaponType[i]);
+ }
+ Writer.Write("\nAmmo:");
+ for (int i = 0; i < 12; i++)
+ {
+ Writer.Write(" ");
+ WRITE_LINE_INT(Writer, m_aWeaponAmmo[i]);
+ }
+
+ Writer.Write("\nArmor: "); WRITE_LINE_INT(Writer, m_Armor);
+
+ Writer.Write("\nKits: "); WRITE_LINE_INT(Writer, m_Kits);
+
+ Writer.Write("\nScore: "); WRITE_LINE_INT(Writer, m_Score);
+
+ Writer.Write("\nGold: "); WRITE_LINE_INT(Writer, m_Gold);
+
+ Writer.Write("\nHighestLevel: "); WRITE_LINE_INT(Writer, m_HighestLevel);
+
+ Writer.Write("\nHighestLevelSeed: "); WRITE_LINE_INT(Writer, m_HighestLevelSeed);
}
\ No newline at end of file
diff --git a/src/game/server/playerdata.h b/src/game/server/playerdata.h
index 1f51eefa..c0712584 100644
--- a/src/game/server/playerdata.h
+++ b/src/game/server/playerdata.h
@@ -8,8 +8,10 @@ class CPlayerData
CPlayerData *m_pChild1;
CPlayerData *m_pChild2;
+ IStorage *m_pStorage;
+
public:
- CPlayerData(const char *pName, int ColorID);
+ CPlayerData(const char *pName, int ColorID, IStorage *pStorage);
void Die();
void Reset();
@@ -35,6 +37,9 @@ class CPlayerData
int GetHighScore(int Score);
int GetPlayerCount(int Score);
+
+ void LoadDataFromFile();
+ void SaveToFile();
};
#endif
diff --git a/src/game/variables.h b/src/game/variables.h
index 55fc5a98..c28c4bac 100644
--- a/src/game/variables.h
+++ b/src/game/variables.h
@@ -150,6 +150,8 @@ MACRO_CONFIG_INT(SvBroadcastLock, sv_broadcastlock, 3, 0, 5, CFGFLAG_SERVER, "Br
MACRO_CONFIG_INT(SvRandomMaps, sv_random_maps, 1, 0, 1, CFGFLAG_SERVER, "Random select map in maps list (1 = on, 0 = off)")
+MACRO_CONFIG_INT(SvSavePlayerdata, sv_save_playerdata, 0, 0, 1, CFGFLAG_SERVER, "Save player data to a file")
+
// debug
#ifdef CONF_DEBUG // this one can crash the server if not used correctly