Cuberite
A lightweight, fast and extensible game server for Minecraft
FireworksSerializer.cpp
Go to the documentation of this file.
1 
2 #include "Globals.h"
3 #include "FireworksSerializer.h"
4 #include "../WorldStorage/FastNBT.h"
5 #include "../BlockType.h"
6 
7 
8 
9 
10 
11 void cFireworkItem::WriteToNBTCompound(const cFireworkItem & a_FireworkItem, cFastNBTWriter & a_Writer, const ENUM_ITEM_TYPE a_Type)
12 {
13  switch (a_Type)
14  {
16  {
17  a_Writer.BeginCompound("Fireworks");
18  a_Writer.AddByte("Flight", static_cast<Byte>(a_FireworkItem.m_FlightTimeInTicks / 20));
19  a_Writer.BeginList("Explosions", TAG_Compound);
20  a_Writer.BeginCompound("");
21  a_Writer.AddByte("Flicker", a_FireworkItem.m_HasFlicker);
22  a_Writer.AddByte("Trail", a_FireworkItem.m_HasTrail);
23  a_Writer.AddByte("Type", a_FireworkItem.m_Type);
24  if (!a_FireworkItem.m_Colours.empty())
25  {
26  a_Writer.AddIntArray("Colors", a_FireworkItem.m_Colours.data(), a_FireworkItem.m_Colours.size());
27  }
28  if (!a_FireworkItem.m_FadeColours.empty())
29  {
30  a_Writer.AddIntArray("FadeColors", a_FireworkItem.m_FadeColours.data(), a_FireworkItem.m_FadeColours.size());
31  }
32  a_Writer.EndCompound();
33  a_Writer.EndList();
34  a_Writer.EndCompound();
35  break;
36  }
38  {
39  a_Writer.BeginCompound("Explosion");
40  a_Writer.AddByte("Flicker", a_FireworkItem.m_HasFlicker);
41  a_Writer.AddByte("Trail", a_FireworkItem.m_HasTrail);
42  a_Writer.AddByte("Type", a_FireworkItem.m_Type);
43  if (!a_FireworkItem.m_Colours.empty())
44  {
45  a_Writer.AddIntArray("Colors", a_FireworkItem.m_Colours.data(), a_FireworkItem.m_Colours.size());
46  }
47  if (!a_FireworkItem.m_FadeColours.empty())
48  {
49  a_Writer.AddIntArray("FadeColors", a_FireworkItem.m_FadeColours.data(), a_FireworkItem.m_FadeColours.size());
50  }
51  a_Writer.EndCompound();
52  break;
53  }
54  default: ASSERT(!"Unhandled firework item!"); break;
55  }
56 }
57 
58 
59 
60 
61 
62 void cFireworkItem::ParseFromNBT(cFireworkItem & a_FireworkItem, const cParsedNBT & a_NBT, int a_TagIdx, const ENUM_ITEM_TYPE a_Type)
63 {
64  if (a_TagIdx < 0)
65  {
66  return;
67  }
68 
69  switch (a_Type)
70  {
72  {
73  for (int explosiontag = a_NBT.GetFirstChild(a_TagIdx); explosiontag >= 0; explosiontag = a_NBT.GetNextSibling(explosiontag))
74  {
75  eTagType TagType = a_NBT.GetType(explosiontag);
76  if (TagType == TAG_Byte) // Custon name tag
77  {
78  AString ExplosionName = a_NBT.GetName(explosiontag);
79 
80  if (ExplosionName == "Flicker")
81  {
82  a_FireworkItem.m_HasFlicker = (a_NBT.GetByte(explosiontag) == 1);
83  }
84  else if (ExplosionName == "Trail")
85  {
86  a_FireworkItem.m_HasTrail = (a_NBT.GetByte(explosiontag) == 1);
87  }
88  else if (ExplosionName == "Type")
89  {
90  a_FireworkItem.m_Type = a_NBT.GetByte(explosiontag);
91  }
92  }
93  else if (TagType == TAG_IntArray)
94  {
95  AString ExplosionName = a_NBT.GetName(explosiontag);
96 
97  if (ExplosionName == "Colors")
98  {
99  // Divide by four as data length returned in bytes
100  size_t DataLength = a_NBT.GetDataLength(explosiontag);
101  // round to the next highest multiple of four
102  DataLength -= DataLength % 4;
103  if (DataLength == 0)
104  {
105  continue;
106  }
107 
108  const auto * ColourData = (a_NBT.GetData(explosiontag));
109  for (size_t i = 0; i < DataLength; i += 4)
110  {
111  a_FireworkItem.m_Colours.push_back(GetBEInt(ColourData + i));
112  }
113  }
114  else if (ExplosionName == "FadeColors")
115  {
116  size_t DataLength = a_NBT.GetDataLength(explosiontag) / 4;
117  // round to the next highest multiple of four
118  DataLength -= DataLength % 4;
119  if (DataLength == 0)
120  {
121  continue;
122  }
123 
124  const auto * FadeColourData = (a_NBT.GetData(explosiontag));
125  for (size_t i = 0; i < DataLength; i += 4)
126  {
127  a_FireworkItem.m_FadeColours.push_back(GetBEInt(FadeColourData + i));
128  }
129  }
130  }
131  }
132  break;
133  }
135  {
136  for (int fireworkstag = a_NBT.GetFirstChild(a_TagIdx); fireworkstag >= 0; fireworkstag = a_NBT.GetNextSibling(fireworkstag))
137  {
138  eTagType TagType = a_NBT.GetType(fireworkstag);
139  if (TagType == TAG_Byte) // Custon name tag
140  {
141  if (a_NBT.GetName(fireworkstag) == "Flight")
142  {
143  a_FireworkItem.m_FlightTimeInTicks = a_NBT.GetByte(fireworkstag) * 20;
144  }
145  }
146  else if ((TagType == TAG_List) && (a_NBT.GetName(fireworkstag) == "Explosions"))
147  {
148  int ExplosionsChild = a_NBT.GetFirstChild(fireworkstag);
149  if ((a_NBT.GetType(ExplosionsChild) == TAG_Compound) && (a_NBT.GetName(ExplosionsChild).empty()))
150  {
151  ParseFromNBT(a_FireworkItem, a_NBT, ExplosionsChild, E_ITEM_FIREWORK_STAR);
152  }
153  }
154  }
155  break;
156  }
157  default: ASSERT(!"Unhandled firework item!"); break;
158  }
159 }
160 
161 
162 
163 
164 
166 {
167  AString Result;
168  for (const auto col: a_FireworkItem.m_Colours)
169  {
170  Result.append(fmt::format(FMT_STRING("{};"), col));
171  }
172  return Result;
173 }
174 
175 
176 
177 
178 
179 void cFireworkItem::ColoursFromString(const AString & a_String, cFireworkItem & a_FireworkItem)
180 {
181  AStringVector Split = StringSplit(a_String, ";");
182 
183  for (size_t itr = 0; itr < Split.size(); ++itr)
184  {
185  if (Split[itr].empty())
186  {
187  continue;
188  }
189 
190  a_FireworkItem.m_Colours.push_back(atoi(Split[itr].c_str()));
191  }
192 }
193 
194 
195 
196 
197 
199 {
200  AString Result;
201  for (const auto col: a_FireworkItem.m_FadeColours)
202  {
203  Result.append(fmt::format(FMT_STRING("{};"), col));
204  }
205  return Result;
206 }
207 
208 
209 
210 
211 
212 void cFireworkItem::FadeColoursFromString(const AString & a_String, cFireworkItem & a_FireworkItem)
213 {
214  AStringVector Split = StringSplit(a_String, ";");
215 
216  for (size_t itr = 0; itr < Split.size(); ++itr)
217  {
218  if (Split[itr].empty())
219  {
220  continue;
221  }
222 
223  a_FireworkItem.m_FadeColours.push_back(atoi(Split[itr].c_str()));
224  }
225 }
226 
227 
228 
229 
230 
232 {
233  /*
234  Colours are supposed to be calculated via: R << 16 + G << 8 + B
235  However, the RGB values fireworks use aren't the same as the ones for dyes (the ones listed in the MC Wiki)
236  Therefore, here is a list of numbers gotten via the Protocol Proxy
237  */
238 
239  switch (a_DyeMeta)
240  {
241  case E_META_DYE_BLACK: return 0x1E1B1B;
242  case E_META_DYE_RED: return 0xB3312C;
243  case E_META_DYE_GREEN: return 0x3B511A;
244  case E_META_DYE_BROWN: return 0x51301A;
245  case E_META_DYE_BLUE: return 0x253192;
246  case E_META_DYE_PURPLE: return 0x7B2FBE;
247  case E_META_DYE_CYAN: return 0x287697;
248  case E_META_DYE_LIGHTGRAY: return 0xABABAB;
249  case E_META_DYE_GRAY: return 0x434343;
250  case E_META_DYE_PINK: return 0xD88198;
251  case E_META_DYE_LIGHTGREEN: return 0x41CD34;
252  case E_META_DYE_YELLOW: return 0xDECF2A;
253  case E_META_DYE_LIGHTBLUE: return 0x6689D3;
254  case E_META_DYE_MAGENTA: return 0xC354CD;
255  case E_META_DYE_ORANGE: return 0xEB8844;
256  case E_META_DYE_WHITE: return 0xF0F0F0;
257  default: ASSERT(!"Unhandled dye meta whilst trying to get colour code for fireworks!"); return 0;
258  }
259 }
ENUM_ITEM_TYPE
Definition: BlockType.h:295
@ E_ITEM_FIREWORK_STAR
Definition: BlockType.h:448
@ E_ITEM_FIREWORK_ROCKET
Definition: BlockType.h:447
@ E_META_DYE_GRAY
Definition: BlockType.h:1053
@ E_META_DYE_PURPLE
Definition: BlockType.h:1050
@ E_META_DYE_WHITE
Definition: BlockType.h:1060
@ E_META_DYE_RED
Definition: BlockType.h:1046
@ E_META_DYE_BLACK
Definition: BlockType.h:1045
@ E_META_DYE_BLUE
Definition: BlockType.h:1049
@ E_META_DYE_LIGHTBLUE
Definition: BlockType.h:1057
@ E_META_DYE_BROWN
Definition: BlockType.h:1048
@ E_META_DYE_LIGHTGRAY
Definition: BlockType.h:1052
@ E_META_DYE_GREEN
Definition: BlockType.h:1047
@ E_META_DYE_YELLOW
Definition: BlockType.h:1056
@ E_META_DYE_MAGENTA
Definition: BlockType.h:1058
@ E_META_DYE_CYAN
Definition: BlockType.h:1051
@ E_META_DYE_LIGHTGREEN
Definition: BlockType.h:1055
@ E_META_DYE_ORANGE
Definition: BlockType.h:1059
@ E_META_DYE_PINK
Definition: BlockType.h:1054
unsigned char NIBBLETYPE
The datatype used by nibbledata (meta, light, skylight)
Definition: ChunkDef.h:44
#define ASSERT(x)
Definition: Globals.h:276
unsigned char Byte
Definition: Globals.h:161
int GetBEInt(const std::byte *const a_Mem)
Reads four bytes from the specified memory location and interprets them as BigEndian int.
AStringVector StringSplit(const AString &str, const AString &delim)
Split the string at any of the listed delimiters.
Definition: StringUtils.cpp:55
std::vector< AString > AStringVector
Definition: StringUtils.h:12
std::string AString
Definition: StringUtils.h:11
eTagType
Definition: FastNBT.h:30
@ TAG_IntArray
Definition: FastNBT.h:43
@ TAG_List
Definition: FastNBT.h:41
@ TAG_Byte
Definition: FastNBT.h:33
@ TAG_Compound
Definition: FastNBT.h:42
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
const std::byte * GetData(int a_Tag) const
Returns the data stored in this tag.
Definition: FastNBT.h:191
int GetFirstChild(int a_Tag) const
Returns the first child of the specified tag, or -1 if none / not applicable.
Definition: FastNBT.h:169
AString GetName(int a_Tag) const
Returns the tag's name.
Definition: FastNBT.h:293
eTagType GetType(int a_Tag) const
Definition: FastNBT.h:210
unsigned char GetByte(int a_Tag) const
Returns the value stored in a Byte tag.
Definition: FastNBT.h:220
size_t GetDataLength(int a_Tag) const
Returns the length of the tag's data, in bytes.
Definition: FastNBT.h:182
void AddByte(const AString &a_Name, unsigned char a_Value)
Definition: FastNBT.cpp:551
void EndList(void)
Definition: FastNBT.cpp:536
void BeginList(const AString &a_Name, eTagType a_ChildrenType)
Definition: FastNBT.cpp:512
void AddIntArray(const AString &a_Name, const Int32 *a_Value, size_t a_NumElements)
Definition: FastNBT.cpp:652
void EndCompound(void)
Definition: FastNBT.cpp:499
void BeginCompound(const AString &a_Name)
Definition: FastNBT.cpp:481
std::vector< int > m_FadeColours
static AString FadeColoursToString(const cFireworkItem &a_FireworkItem)
Converts the firework's vector of fade colours into a string of values separated by a semicolon.
static void FadeColoursFromString(const AString &a_String, cFireworkItem &a_FireworkItem)
Parses a string containing encoded firework fade colours and populates a FireworkItem with it.
std::vector< int > m_Colours
static void WriteToNBTCompound(const cFireworkItem &a_FireworkItem, cFastNBTWriter &a_Writer, const ENUM_ITEM_TYPE a_Type)
Writes firework NBT data to a Writer object.
static AString ColoursToString(const cFireworkItem &a_FireworkItem)
Converts the firework's vector of colours into a string of values separated by a semicolon.
static void ParseFromNBT(cFireworkItem &a_FireworkItem, const cParsedNBT &a_NBT, int a_TagIdx, const ENUM_ITEM_TYPE a_Type)
Reads NBT data from a NBT object and populates a FireworkItem with it.
static int GetVanillaColourCodeFromDye(NIBBLETYPE a_DyeMeta)
Returns a colour code for fireworks used by the network code.
static void ColoursFromString(const AString &a_String, cFireworkItem &a_FireworkItem)
Parses a string containing encoded firework colours and populates a FireworkItem with it.