Cuberite
A lightweight, fast and extensible game server for Minecraft
ScoreboardSerializer.cpp
Go to the documentation of this file.
1 
2 // ScoreboardSerializer.cpp
3 
4 
5 #include "Globals.h"
6 #include "ScoreboardSerializer.h"
7 #include "OSSupport/GZipFile.h"
8 #include "FastNBT.h"
9 
10 #include "../Scoreboard.h"
11 
12 
13 
14 
15 
17  m_ScoreBoard(a_ScoreBoard)
18 {
19  auto DataPath = fmt::format(FMT_STRING("{}{}data"), a_WorldName, cFile::PathSeparator());
20  m_Path = DataPath + cFile::PathSeparator() + "scoreboard.dat";
21  cFile::CreateFolder(DataPath);
22 }
23 
24 
25 
26 
27 
29 {
30  try
31  {
32  const auto Data = GZipFile::ReadRestOfFile(m_Path);
33  const cParsedNBT NBT(Data.GetView());
34 
35  if (!NBT.IsValid())
36  {
37  // NBT Parsing failed
38  return false;
39  }
40 
41  return LoadScoreboardFromNBT(NBT);
42  }
43  catch (const std::exception & Oops)
44  {
45  LOGWARNING("Failed to load scoreboard from \"%s\": %s", m_Path.c_str(), Oops.what());
46  return false;
47  }
48 }
49 
50 
51 
52 
53 
55 {
56  cFastNBTWriter Writer;
57  SaveScoreboardToNBT(Writer);
58  Writer.Finish();
59 
60 #ifndef NDEBUG
61  cParsedNBT TestParse(Writer.GetResult());
62  ASSERT(TestParse.IsValid());
63 #endif // !NDEBUG
64 
65  GZipFile::Write(m_Path, Writer.GetResult());
66 
67  return true;
68 }
69 
70 
71 
72 
73 
75 {
76  a_Writer.BeginCompound("data");
77 
78  a_Writer.BeginList("Objectives", TAG_Compound);
79 
80  for (cScoreboard::cObjectiveMap::const_iterator it = m_ScoreBoard->m_Objectives.begin(); it != m_ScoreBoard->m_Objectives.end(); ++it)
81  {
82  const cObjective & Objective = it->second;
83 
84  a_Writer.BeginCompound("");
85 
86  a_Writer.AddString("CriteriaName", cObjective::TypeToString(Objective.GetType()));
87 
88  a_Writer.AddString("DisplayName", Objective.GetDisplayName());
89  a_Writer.AddString("Name", it->first);
90 
91  a_Writer.EndCompound();
92  }
93 
94  a_Writer.EndList(); // Objectives
95 
96  a_Writer.BeginList("PlayerScores", TAG_Compound);
97 
98  for (cScoreboard::cObjectiveMap::const_iterator it = m_ScoreBoard->m_Objectives.begin(); it != m_ScoreBoard->m_Objectives.end(); ++it)
99  {
100  const cObjective & Objective = it->second;
101 
102  for (cObjective::cScoreMap::const_iterator it2 = Objective.m_Scores.begin(); it2 != Objective.m_Scores.end(); ++it2)
103  {
104  a_Writer.BeginCompound("");
105 
106  a_Writer.AddInt("Score", it2->second);
107 
108  a_Writer.AddString("Name", it2->first);
109  a_Writer.AddString("Objective", it->first);
110 
111  a_Writer.EndCompound();
112  }
113  }
114 
115  a_Writer.EndList(); // PlayerScores
116 
117  a_Writer.BeginList("Teams", TAG_Compound);
118 
119  for (cScoreboard::cTeamMap::const_iterator it = m_ScoreBoard->m_Teams.begin(); it != m_ScoreBoard->m_Teams.end(); ++it)
120  {
121  const cTeam & Team = it->second;
122 
123  a_Writer.BeginCompound("");
124 
125  a_Writer.AddByte("AllowFriendlyFire", Team.AllowsFriendlyFire() ? 1 : 0);
126  a_Writer.AddByte("SeeFriendlyInvisibles", Team.CanSeeFriendlyInvisible() ? 1 : 0);
127 
128  a_Writer.AddString("DisplayName", Team.GetDisplayName());
129  a_Writer.AddString("Name", it->first);
130 
131  a_Writer.AddString("Prefix", Team.GetPrefix());
132  a_Writer.AddString("Suffix", Team.GetSuffix());
133 
134  a_Writer.BeginList("Players", TAG_String);
135 
136  for (cTeam::cPlayerNameSet::const_iterator it2 = Team.m_Players.begin(); it2 != Team.m_Players.end(); ++it2)
137  {
138  a_Writer.AddString("", *it2);
139  }
140 
141  a_Writer.EndList();
142 
143  a_Writer.EndCompound();
144  }
145 
146  a_Writer.EndList(); // Teams
147 
148  a_Writer.BeginCompound("DisplaySlots");
149 
151  a_Writer.AddString("slot_0", (Objective == nullptr) ? "" : Objective->GetName());
152 
154  a_Writer.AddString("slot_1", (Objective == nullptr) ? "" : Objective->GetName());
155 
157  a_Writer.AddString("slot_2", (Objective == nullptr) ? "" : Objective->GetName());
158 
159  a_Writer.EndCompound(); // DisplaySlots
160 
161  a_Writer.EndCompound(); // Data
162 }
163 
164 
165 
166 
167 
169 {
170  int Data = a_NBT.FindChildByName(0, "data");
171  if (Data < 0)
172  {
173  return false;
174  }
175 
176  int Objectives = a_NBT.FindChildByName(Data, "Objectives");
177  if (Objectives < 0)
178  {
179  return false;
180  }
181 
182  for (int Child = a_NBT.GetFirstChild(Objectives); Child >= 0; Child = a_NBT.GetNextSibling(Child))
183  {
184  AString CriteriaName, DisplayName, Name;
185 
186  int CurrLine = a_NBT.FindChildByName(Child, "CriteriaName");
187  if (CurrLine >= 0)
188  {
189  CriteriaName = a_NBT.GetString(CurrLine);
190  }
191 
192  CurrLine = a_NBT.FindChildByName(Child, "DisplayName");
193  if (CurrLine >= 0)
194  {
195  DisplayName = a_NBT.GetString(CurrLine);
196  }
197 
198  CurrLine = a_NBT.FindChildByName(Child, "Name");
199  if (CurrLine >= 0)
200  {
201  Name = a_NBT.GetString(CurrLine);
202  }
203 
205 
206  m_ScoreBoard->RegisterObjective(Name, DisplayName, Type);
207  }
208 
209  int PlayerScores = a_NBT.FindChildByName(Data, "PlayerScores");
210  if (PlayerScores < 0)
211  {
212  return false;
213  }
214 
215  for (int Child = a_NBT.GetFirstChild(PlayerScores); Child >= 0; Child = a_NBT.GetNextSibling(Child))
216  {
217  AString Name, ObjectiveName;
218 
219  cObjective::Score Score = 0;
220 
221  int CurrLine = a_NBT.FindChildByName(Child, "Score");
222  if (CurrLine >= 0)
223  {
224  Score = a_NBT.GetInt(CurrLine);
225  }
226 
227  CurrLine = a_NBT.FindChildByName(Child, "Name");
228  if (CurrLine >= 0)
229  {
230  Name = a_NBT.GetString(CurrLine);
231  }
232 
233  CurrLine = a_NBT.FindChildByName(Child, "Objective");
234  if (CurrLine >= 0)
235  {
236  ObjectiveName = a_NBT.GetString(CurrLine);
237  }
238 
239  cObjective * Objective = m_ScoreBoard->GetObjective(ObjectiveName);
240 
241  if (Objective)
242  {
243  Objective->SetScore(Name, Score);
244  }
245  }
246 
247  int Teams = a_NBT.FindChildByName(Data, "Teams");
248  if (Teams < 0)
249  {
250  return false;
251  }
252 
253  for (int Child = a_NBT.GetFirstChild(Teams); Child >= 0; Child = a_NBT.GetNextSibling(Child))
254  {
255  AString Name, DisplayName, Prefix, Suffix;
256 
257  bool AllowsFriendlyFire = true, CanSeeFriendlyInvisible = false;
258 
259  int CurrLine = a_NBT.FindChildByName(Child, "Name");
260  if ((CurrLine >= 0) && (a_NBT.GetType(CurrLine) == TAG_String))
261  {
262  Name = a_NBT.GetString(CurrLine);
263  }
264 
265  CurrLine = a_NBT.FindChildByName(Child, "DisplayName");
266  if ((CurrLine >= 0) && (a_NBT.GetType(CurrLine) == TAG_String))
267  {
268  DisplayName = a_NBT.GetString(CurrLine);
269  }
270 
271  CurrLine = a_NBT.FindChildByName(Child, "Prefix");
272  if ((CurrLine >= 0) && (a_NBT.GetType(CurrLine) == TAG_String))
273  {
274  Prefix = a_NBT.GetString(CurrLine);
275  }
276 
277  CurrLine = a_NBT.FindChildByName(Child, "Suffix");
278  if ((CurrLine >= 0) && (a_NBT.GetType(CurrLine) == TAG_String))
279  {
280  Suffix = a_NBT.GetString(CurrLine);
281  }
282 
283  CurrLine = a_NBT.FindChildByName(Child, "AllowFriendlyFire");
284  if ((CurrLine >= 0) && (a_NBT.GetType(CurrLine) == TAG_Int))
285  {
286  AllowsFriendlyFire = (a_NBT.GetInt(CurrLine) != 0);
287  }
288 
289  CurrLine = a_NBT.FindChildByName(Child, "SeeFriendlyInvisibles");
290  if ((CurrLine >= 0) && (a_NBT.GetType(CurrLine) == TAG_Int))
291  {
292  CanSeeFriendlyInvisible = (a_NBT.GetInt(CurrLine) != 0);
293  }
294 
295  cTeam * Team = m_ScoreBoard->RegisterTeam(Name, DisplayName, Prefix, Suffix);
296 
297  Team->SetFriendlyFire(AllowsFriendlyFire);
298  Team->SetCanSeeFriendlyInvisible(CanSeeFriendlyInvisible);
299 
300  int Players = a_NBT.FindChildByName(Child, "Players");
301  if (Players < 0)
302  {
303  continue;
304  }
305 
306  for (int ChildB = a_NBT.GetFirstChild(Players); ChildB >= 0; ChildB = a_NBT.GetNextSibling(ChildB))
307  {
308  Team->AddPlayer(a_NBT.GetString(ChildB));
309  }
310  }
311 
312  int DisplaySlots = a_NBT.FindChildByName(Data, "DisplaySlots");
313  if (DisplaySlots < 0)
314  {
315  return false;
316  }
317 
318  int CurrLine = a_NBT.FindChildByName(DisplaySlots, "slot_0");
319  if (CurrLine >= 0)
320  {
321  AString Name = a_NBT.GetString(CurrLine);
322 
324  }
325 
326  CurrLine = a_NBT.FindChildByName(DisplaySlots, "slot_1");
327  if (CurrLine >= 0)
328  {
329  AString Name = a_NBT.GetString(CurrLine);
330 
332  }
333 
334  CurrLine = a_NBT.FindChildByName(DisplaySlots, "slot_2");
335  if (CurrLine >= 0)
336  {
337  AString Name = a_NBT.GetString(CurrLine);
338 
340  }
341 
342  return true;
343 }
344 
345 
346 
347 
348 
349 
350 
351 
#define ASSERT(x)
Definition: Globals.h:276
void LOGWARNING(std::string_view a_Format, const Args &... args)
Definition: LoggerSimple.h:67
std::string AString
Definition: StringUtils.h:11
@ TAG_String
Definition: FastNBT.h:40
@ TAG_Compound
Definition: FastNBT.h:42
@ TAG_Int
Definition: FastNBT.h:35
void Write(const std::string &a_FileName, ContiguousByteBufferView a_Contents)
Writes a_Contents into file, compressing it along the way.
Definition: GZipFile.cpp:27
Compression::Result ReadRestOfFile(const std::string &a_FileName)
Reads the rest of the file and returns the decompressed contents.
Definition: GZipFile.cpp:14
static bool CreateFolder(const AString &a_FolderPath)
Creates a new folder with the specified name.
Definition: File.cpp:454
static char PathSeparator()
Definition: File.h:42
cScoreMap m_Scores
Definition: Scoreboard.h:106
static eType StringToType(const AString &a_Name)
Definition: Scoreboard.cpp:41
eType GetType(void) const
Definition: Scoreboard.h:70
void SetScore(const AString &a_Name, Score a_Score)
Sets the score of the specified player.
Definition: Scoreboard.cpp:121
const AString & GetName(void) const
Definition: Scoreboard.h:72
static AString TypeToString(eType a_Type)
Definition: Scoreboard.cpp:16
const AString & GetDisplayName(void) const
Definition: Scoreboard.h:73
const AString & GetDisplayName(void) const
Definition: Scoreboard.h:158
cPlayerNameSet m_Players
Definition: Scoreboard.h:187
const AString & GetPrefix(void) const
Definition: Scoreboard.h:161
bool CanSeeFriendlyInvisible(void) const
Definition: Scoreboard.h:156
void SetCanSeeFriendlyInvisible(bool a_Flag)
Definition: Scoreboard.h:165
const AString & GetSuffix(void) const
Definition: Scoreboard.h:162
bool AllowsFriendlyFire(void) const
Definition: Scoreboard.h:155
void SetFriendlyFire(bool a_Flag)
Definition: Scoreboard.h:164
bool AddPlayer(const AString &a_Name)
Adds a new player to the team.
Definition: Scoreboard.cpp:213
cObjective * GetObjective(const AString &a_Name)
Retrieves the objective with the specified name, nullptr if not found.
Definition: Scoreboard.cpp:339
cTeam * RegisterTeam(const AString &a_Name, const AString &a_DisplayName, const AString &a_Prefix, const AString &a_Suffix)
Registers a new team, returns the cTeam instance, nullptr on name collision.
Definition: Scoreboard.cpp:359
cObjectiveMap m_Objectives
Definition: Scoreboard.h:284
cObjective * GetObjectiveIn(eDisplaySlot a_Slot)
Definition: Scoreboard.cpp:479
cObjective * RegisterObjective(const AString &a_Name, const AString &a_DisplayName, cObjective::eType a_Type)
Registers a new scoreboard objective, returns the cObjective instance, nullptr on name collision.
Definition: Scoreboard.cpp:285
void SetDisplay(const AString &a_Objective, eDisplaySlot a_Slot)
Definition: Scoreboard.cpp:454
cTeamMap m_Teams
Definition: Scoreboard.h:287
Parses and contains the parsed data Also implements data accessor functions for tree traversal and va...
Definition: FastNBT.h:153
int GetNextSibling(int a_Tag) const
Returns the next sibling of the specified tag, or -1 if none.
Definition: FastNBT.h:175
int GetFirstChild(int a_Tag) const
Returns the first child of the specified tag, or -1 if none / not applicable.
Definition: FastNBT.h:169
bool IsValid(void) const
Definition: FastNBT.h:157
eTagType GetType(int a_Tag) const
Definition: FastNBT.h:210
int FindChildByName(int a_Tag, const AString &a_Name) const
Returns the direct child tag of the specified name, or -1 if no such tag.
Definition: FastNBT.h:199
Int32 GetInt(int a_Tag) const
Returns the value stored in an Int tag.
Definition: FastNBT.h:234
AString GetString(int a_Tag) const
Returns the value stored in a String tag.
Definition: FastNBT.h:280
void AddByte(const AString &a_Name, unsigned char a_Value)
Definition: FastNBT.cpp:551
void AddInt(const AString &a_Name, Int32 a_Value)
Definition: FastNBT.cpp:572
void Finish(void)
Definition: FastNBT.cpp:674
void AddString(const AString &a_Name, std::string_view a_Value)
Definition: FastNBT.cpp:616
void EndList(void)
Definition: FastNBT.cpp:536
void BeginList(const AString &a_Name, eTagType a_ChildrenType)
Definition: FastNBT.cpp:512
void EndCompound(void)
Definition: FastNBT.cpp:499
void BeginCompound(const AString &a_Name)
Definition: FastNBT.cpp:481
ContiguousByteBufferView GetResult(void) const
Definition: FastNBT.h:351
cScoreboardSerializer(const AString &a_WorldName, cScoreboard *a_ScoreBoard)
bool Load(void)
Try to load the scoreboard.
bool Save(void)
Try to save the scoreboard.
void SaveScoreboardToNBT(cFastNBTWriter &a_Writer)
bool LoadScoreboardFromNBT(const cParsedNBT &a_NBT)