1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
|
#include "Globals.h"
#include "RecipeMapper.h"
#include "../Root.h"
cRecipeMapper::cRecipeMapper(void)
{
AString path = "Protocol";
auto contents = cFile::GetFolderContents(path);
for (const auto & content: contents)
{
auto fullName = path + cFile::PathSeparator() + content;
if (cFile::IsFolder(fullName))
{
loadRecipes(content);
}
}
}
void cRecipeMapper::loadRecipes(const AString & a_ProtocolVersion)
{
cFile f;
if (!f.Open("Protocol/" + a_ProtocolVersion + "/base.recipes.txt", cFile::fmRead))
{
LOGWARNING("Cannot open file \"Protocol/%s/base.recipes.txt\", no recipe book recipes will be available!", a_ProtocolVersion);
return;
}
AString Everything;
if (!f.ReadRestOfFile(Everything))
{
LOGWARNING("Cannot read file \"Protocol/%s/base.recipes.txt\", no recipe book recipes will be available!", a_ProtocolVersion);
return;
}
f.Close();
// Split it into lines, then process each line as a single recipe:
AStringVector Split = StringSplit(Everything, "\n");
m_ProtocolVersionMap[a_ProtocolVersion] = {};
const auto & RecipeNameMap = cRoot::Get()->GetCraftingRecipes()->GetRecipeNameMap();
int LineNum = 1;
for (AStringVector::const_iterator itr = Split.begin(); itr != Split.end(); ++itr, ++LineNum)
{
// Remove anything after a '#' sign and trim away the whitespace:
AString Recipe = TrimString(itr->substr(0, itr->find('#')));
if (Recipe.empty())
{
// Empty recipe
continue;
}
AddRecipeLine(a_ProtocolVersion, LineNum, Recipe, RecipeNameMap);
}
LOG("Loaded %s %zu recipe book", a_ProtocolVersion, m_ProtocolVersionMap[a_ProtocolVersion].size());
}
cRecipeMapper::~cRecipeMapper()
{
}
void cRecipeMapper::AddRecipeLine(const AString & a_ProtocolVersion, int a_LineNum, const AString & a_RecipeLine, const std::map<AString, UInt32> & a_RecipeNameMap)
{
AStringVector Sides = StringSplit(a_RecipeLine, " ");
UInt32 Id;
if (Sides.size() != 2)
{
LOGINFO("Recipe incompletely configured %s", a_RecipeLine);
return;
}
StringToInteger<UInt32>(Sides[0], Id);
auto RecipeIndex = a_RecipeNameMap.find(Sides[1]);
if (RecipeIndex == a_RecipeNameMap.end())
{
return;
}
m_ProtocolVersionMap[a_ProtocolVersion].emplace(Id, RecipeIndex->second);
}
std::optional<UInt32> cRecipeMapper::GetProtocolRecipeId(UInt32 a_RecipeId, UInt32 a_ProtocolVersion)
{
auto ProtocolMap = m_ProtocolVersionMap.find(cRoot::Get()->GetProtocolVersionTextFromInt(static_cast<int>(a_ProtocolVersion)));
if (ProtocolMap == m_ProtocolVersionMap.end())
{
return {};
}
for (const auto & item: ProtocolMap->second)
{
if (item.second == a_RecipeId)
{
return item.first;
}
}
return {};
}
std::optional<UInt32> cRecipeMapper::GetCuberiteRecipeId(UInt32 a_ProtocolRecipeId, UInt32 a_ProtocolVersion)
{
auto ProtocolMap = m_ProtocolVersionMap.find(cRoot::Get()->GetProtocolVersionTextFromInt(static_cast<int>(a_ProtocolVersion)));
if (ProtocolMap == m_ProtocolVersionMap.end())
{
return {};
}
auto Element = ProtocolMap->second.find(a_ProtocolRecipeId);
if (Element != ProtocolMap->second.end())
{
return Element->second;
}
return {};
}
|