Cuberite
A lightweight, fast and extensible game server for Minecraft
BlockType.cpp
Go to the documentation of this file.
1 // BlockType.cpp
2 
3 // Implements the helper functions for converting Block Type string to int etc.
4 
5 #include "Globals.h"
6 #include "IniFile.h"
7 #include "Item.h"
8 #include "Mobs/Monster.h"
9 
10 
11 
12 
13 
15 {
16  // Making the map case-insensitive:
17  struct Comparator
18  {
19  bool operator ()(const AString & a_Item1, const AString & a_Item2) const
20  {
21  return (NoCaseCompare(a_Item1, a_Item2) > 0);
22  }
23  } ;
24 
25  typedef std::map<AString, std::pair<short, short>, Comparator> ItemMap;
26 
27 public:
28 
30  {
31  cIniFile Ini;
32  if (!Ini.ReadFile("items.ini"))
33  {
34  return;
35  }
36  int KeyID = Ini.FindKey("Items");
37  if (KeyID == cIniFile::noID)
38  {
39  return;
40  }
41  int NumValues = Ini.GetNumValues(KeyID);
42  for (int i = 0; i < NumValues; i++)
43  {
44  AString Name = Ini.GetValueName(KeyID, i);
45  if (Name.empty())
46  {
47  continue;
48  }
49  AString Value = Ini.GetValue(KeyID, i);
50  AddToMap(Name, Value);
51  } // for i - Ini.Values[]
52  }
53 
54 
55  int Resolve(const AString & a_ItemName)
56  {
57  ItemMap::iterator itr = m_Map.find(a_ItemName);
58  if (itr == m_Map.end())
59  {
60  return -1;
61  }
62  return itr->second.first;
63  }
64 
65 
66  bool ResolveItem(const AString & a_ItemName, cItem & a_Item)
67  {
68  // Split into parts divided by either ':' or '^'
69  AStringVector Split = StringSplitAndTrim(a_ItemName, ":^");
70  if (Split.empty())
71  {
72  return false;
73  }
74 
75  ItemMap::iterator itr = m_Map.find(Split[0]);
76  if (itr != m_Map.end())
77  {
78  // Resolved as a string, assign the type and the default damage / count
79  a_Item.m_ItemType = itr->second.first;
80  a_Item.m_ItemDamage = itr->second.second;
81  if (a_Item.m_ItemDamage == -1)
82  {
83  a_Item.m_ItemDamage = 0;
84  }
85  }
86  else
87  {
88  // Not a resolvable string, try pure numbers: "45:6", "45^6" etc.
89  if (!StringToInteger(Split[0], a_Item.m_ItemType))
90  {
91  // Parsing the number failed
92  return false;
93  }
94  }
95 
96  // Parse the damage, if present:
97  if (Split.size() < 2)
98  {
99  // Not present, set the item as valid and return success:
100  a_Item.m_ItemCount = 1;
101  return true;
102  }
103 
104  if (!StringToInteger(Split[1], a_Item.m_ItemDamage))
105  {
106  // Parsing the number failed
107  return false;
108  }
109  a_Item.m_ItemCount = 1;
110  return true;
111  }
112 
113 
114  AString Desolve(short a_ItemType, short a_ItemDamage)
115  {
116  // First try an exact match, both ItemType and ItemDamage ("birchplanks=5:2"):
117  for (ItemMap::iterator itr = m_Map.begin(), end = m_Map.end(); itr != end; ++itr)
118  {
119  if ((itr->second.first == a_ItemType) && (itr->second.second == a_ItemDamage))
120  {
121  return itr->first;
122  }
123  } // for itr - m_Map[]
124 
125  // There is no exact match, try matching ItemType only ("planks=5"):
126  if (a_ItemDamage == 0)
127  {
128  for (ItemMap::iterator itr = m_Map.begin(), end = m_Map.end(); itr != end; ++itr)
129  {
130  if ((itr->second.first == a_ItemType) && (itr->second.second == -1))
131  {
132  return itr->first;
133  }
134  } // for itr - m_Map[]
135  }
136 
137  // No match at all, synthesize a string ("5:1"):
138  AString res;
139  if (a_ItemDamage == -1)
140  {
141  res = fmt::format(FMT_STRING("{}"), a_ItemType);
142  }
143  else
144  {
145  res = fmt::format(FMT_STRING("{}:{}"), a_ItemType, a_ItemDamage);
146  }
147  return res;
148  }
149 
150 
151 protected:
153 
154 
155  void AddToMap(const AString & a_Name, const AString & a_Value)
156  {
157  AStringVector Split = StringSplit(a_Value, ":");
158  if (Split.size() == 1)
159  {
160  Split = StringSplit(a_Value, "^");
161  }
162  if (Split.empty())
163  {
164  return;
165  }
166  short ItemType;
167  if (!StringToInteger(Split[0], ItemType))
168  {
169  ASSERT(!"Invalid item type");
170  }
171  short ItemDamage = -1;
172  if (Split.size() > 1 && !StringToInteger(Split[1], ItemDamage))
173  {
174  ASSERT(!"Invalid item damage");
175  }
176  m_Map[a_Name] = std::make_pair(ItemType, ItemDamage);
177  }
178 } ;
179 
180 
181 
182 
184 {
185  static cBlockIDMap IDMap;
186  return IDMap;
187 }
188 
189 
190 
191 
192 
193 /*
194 // Quick self-test:
195 class Tester
196 {
197 public:
198  Tester(void)
199  {
200  cItem Item;
201  gsBlockIDMap.ResolveItem("charcoal", Item);
202  AString Charcoal = gsBlockIDMap.Desolve(Item.m_ItemType, Item.m_ItemDamage);
203  ASSERT(Charcoal == "charcoal");
204  }
205 } test;
206 //*/
207 
208 
209 
210 
211 
212 int BlockStringToType(const AString & a_BlockTypeString)
213 {
214  int res = atoi(a_BlockTypeString.c_str());
215  if ((res != 0) || (a_BlockTypeString.compare("0") == 0))
216  {
217  // It was a valid number, return that
218  return res;
219  }
220 
221  return GetBlockIDMap().Resolve(TrimString(a_BlockTypeString));
222 }
223 
224 
225 
226 
227 
228 bool StringToItem(const AString & a_ItemTypeString, cItem & a_Item)
229 {
230  AString ItemName = TrimString(a_ItemTypeString);
231  if (ItemName.substr(0, 10) == "minecraft:")
232  {
233  ItemName = ItemName.substr(10);
234  }
235 
236  return GetBlockIDMap().ResolveItem(ItemName, a_Item);
237 }
238 
239 
240 
241 
242 
243 AString ItemToString(const cItem & a_Item)
244 {
245  return GetBlockIDMap().Desolve(a_Item.m_ItemType, a_Item.m_ItemDamage);
246 }
247 
248 
249 
250 
251 
252 AString ItemTypeToString(short a_ItemType)
253 {
254  return GetBlockIDMap().Desolve(a_ItemType, -1);
255 }
256 
257 
258 
259 
260 
262 {
263  return fmt::format(FMT_STRING("{}:{} * {:d}"), ItemToString(a_Item), a_Item.m_ItemDamage, a_Item.m_ItemCount);
264 }
265 
266 
267 
268 
269 
270 cItem GetIniItemSet(cIniFile & a_IniFile, const char * a_Section, const char * a_Key, const char * a_Default)
271 {
272  AString ItemStr = a_IniFile.GetValueSet(a_Section, a_Key, a_Default);
273  cItem res;
274  if (!StringToItem(ItemStr, res))
275  {
276  res.Empty();
277  }
278  return res;
279 }
280 
281 
282 
283 
284 
285 
int BlockStringToType(const AString &a_BlockTypeString)
Translates a blocktype string into blocktype.
Definition: BlockType.cpp:212
static cBlockIDMap & GetBlockIDMap()
Definition: BlockType.cpp:183
AString ItemToString(const cItem &a_Item)
Translates a full item into a string.
Definition: BlockType.cpp:243
cItem GetIniItemSet(cIniFile &a_IniFile, const char *a_Section, const char *a_Key, const char *a_Default)
Returns a cItem representing the item described in an IniFile's value; if the value doesn't exist,...
Definition: BlockType.cpp:270
bool StringToItem(const AString &a_ItemTypeString, cItem &a_Item)
Translates an itemtype string into an item.
Definition: BlockType.cpp:228
AString ItemToFullString(const cItem &a_Item)
Translates a full item into a fully-specified string (including meta and count).
Definition: BlockType.cpp:261
AString ItemTypeToString(short a_ItemType)
Translates itemtype into a string.
Definition: BlockType.cpp:252
#define ASSERT(x)
Definition: Globals.h:276
AStringVector StringSplitAndTrim(const AString &str, const AString &delim)
Split the string at any of the listed delimiters and trim each value.
AString TrimString(const AString &str)
Trims whitespace at both ends of the string.
AStringVector StringSplit(const AString &str, const AString &delim)
Split the string at any of the listed delimiters.
Definition: StringUtils.cpp:55
int NoCaseCompare(const AString &s1, const AString &s2)
Case-insensitive string comparison.
std::vector< AString > AStringVector
Definition: StringUtils.h:12
std::string AString
Definition: StringUtils.h:11
bool StringToInteger(const AString &a_str, T &a_Num)
Parses any integer type.
Definition: StringUtils.h:143
ItemMap m_Map
Definition: BlockType.cpp:152
void AddToMap(const AString &a_Name, const AString &a_Value)
Definition: BlockType.cpp:155
cBlockIDMap(void)
Definition: BlockType.cpp:29
AString Desolve(short a_ItemType, short a_ItemDamage)
Definition: BlockType.cpp:114
std::map< AString, std::pair< short, short >, Comparator > ItemMap
Definition: BlockType.cpp:25
int Resolve(const AString &a_ItemName)
Definition: BlockType.cpp:55
bool ResolveItem(const AString &a_ItemName, cItem &a_Item)
Definition: BlockType.cpp:66
bool operator()(const AString &a_Item1, const AString &a_Item2) const
Definition: BlockType.cpp:19
int FindKey(const AString &keyname) const
Returns index of specified key, or noID if not found.
Definition: IniFile.cpp:243
AString GetValue(const AString &keyname, const AString &valuename, const AString &defValue="") const override
Get the value at the specified key and value, returns defValue on failure.
Definition: IniFile.cpp:485
int GetNumValues(const AString &keyname) const
Definition: IniFile.cpp:322
bool ReadFile(const AString &a_FileName, bool a_AllowExampleRedirect=true)
Reads the contents of the specified ini file If the file doesn't exist and a_AllowExampleRedirect is ...
Definition: IniFile.cpp:50
@ noID
Definition: IniFile.h:72
AString GetValueName(const AString &keyname, const int valueID) const
Definition: IniFile.cpp:349
AString GetValueSet(const AString &keyname, const AString &valuename, const AString &defValue="") override
Gets the value; if not found, write the default to the repository.
Definition: IniFile.cpp:526
Definition: Item.h:37
char m_ItemCount
Definition: Item.h:164
short m_ItemType
Definition: Item.h:163
void Empty(void)
Empties the item and frees up any dynamic storage used by the internals.
Definition: Item.cpp:63
short m_ItemDamage
Definition: Item.h:165