Skip to content

Commit 7e8ff64

Browse files
Added header/cpp files for txt files.
1 parent 48dddac commit 7e8ff64

8 files changed

Lines changed: 21627 additions & 0 deletions

File tree

.gitignore

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,9 @@ dropsolver
1010
dropsolverbase
1111
dropsolver.exe
1212
dropsolver.pdb
13+
test
14+
test.exe
15+
test.pdb
1316
*.txt
1417
!atomic.txt
1518
!atomicbase.txt

build.sh

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,3 +3,4 @@ g++ dropsim.cpp -o dropsim -std=c++17 -O3 -pthread -march=native
33
g++ dropsim.cpp -o dropsimbase -D"BASETC=1" -std=c++17 -O3 -pthread -march=native
44
g++ dropsolver.cpp -o dropsolver -std=c++17 -O3 -pthread -march=native
55
g++ dropsolver.cpp -o dropsolverbase -D"BASETC=1" -std=c++17 -O3 -pthread -march=native
6+
g++ test.cpp txtrotw.cpp -o test -std=c++17 -g -O3 -pthread -march=native

generateheaders.php

Lines changed: 271 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,271 @@
1+
<?php
2+
3+
/**
4+
* @file
5+
* Generate header files for all TXT files in the txt/ directory.
6+
*/
7+
8+
$typedefs = [];
9+
10+
function cid(string $name, string $altname, bool $pascalcase = TRUE) : string {
11+
$newname = trim(preg_replace('/[^a-z0-9_ ]+/i', ' ', $name), ' ');
12+
$newname = $pascalcase && str_contains($newname, ' ') ? ucwords($newname) : $newname;
13+
$newname = str_replace(' ', '', $newname);
14+
15+
if (!$newname) {
16+
$newname = "$altname";
17+
}
18+
19+
if (is_numeric($newname[0]) || in_array($newname, [
20+
// C++ reserved keywords.
21+
'alignas',
22+
'alignof',
23+
'and',
24+
'and_eq',
25+
'asm',
26+
'auto',
27+
'bitand',
28+
'bitor',
29+
'bool',
30+
'break',
31+
'case',
32+
'catch',
33+
'char',
34+
'char8_t',
35+
'char16_t',
36+
'char32_t',
37+
'class',
38+
'compl',
39+
'concept',
40+
'const',
41+
'const_cast',
42+
'consteval',
43+
'constexpr',
44+
'constinit',
45+
'continue',
46+
'co_await',
47+
'co_return',
48+
'co_yield',
49+
'decltype',
50+
'default',
51+
'delete',
52+
'do',
53+
'double',
54+
'dynamic_cast',
55+
'else',
56+
'enum',
57+
'explicit',
58+
'export',
59+
'extern',
60+
'false',
61+
'float',
62+
'for',
63+
'friend',
64+
'goto',
65+
'if',
66+
'inline',
67+
'int',
68+
'long',
69+
'mutable',
70+
'namespace',
71+
'new',
72+
'noexcept',
73+
'not',
74+
'not_eq',
75+
'nullptr',
76+
'operator',
77+
'or',
78+
'or_eq',
79+
'private',
80+
'protected',
81+
'public',
82+
'register',
83+
'reinterpret_cast',
84+
'requires',
85+
'return',
86+
'short',
87+
'signed',
88+
'sizeof',
89+
'static',
90+
'static_assert',
91+
'static_cast',
92+
'struct',
93+
'switch',
94+
'template',
95+
'this',
96+
'thread_local',
97+
'throw',
98+
'true',
99+
'try',
100+
'typedef',
101+
'typeid',
102+
'typename',
103+
'union',
104+
'unsigned',
105+
'using',
106+
'virtual',
107+
'void',
108+
'volatile',
109+
'wchar_t',
110+
'while',
111+
'xor_eq',
112+
])) {
113+
$newname = "_$newname";
114+
}
115+
116+
return $newname;
117+
}
118+
119+
foreach ([
120+
['ROTW', 'txtrotw', 'txt/*.txt'],
121+
['BASE', 'txtbase', 'txt/base/*.txt'],
122+
] as [$namespace, $filebase, $path]) {
123+
foreach (glob(__DIR__ . '/' . $path) as $i => $file) {
124+
$name = cid(basename($file, '.txt'), "txt_$i");
125+
126+
$handle = fopen($file, 'r');
127+
$header = fgets($handle);
128+
$headers = explode("\t", trim($header));
129+
130+
foreach ($headers as $i => $header) {
131+
$headers[$i] = $header;
132+
}
133+
134+
$headerTypes = array_map(fn () => 'void', $headers);
135+
136+
while (($line = fgets($handle)) !== false) {
137+
$values = explode("\t", trim($line));
138+
139+
foreach ($values as $i => $value) {
140+
if (isset($headerTypes[$i])) {
141+
if ($value !== '') {
142+
if (is_numeric($value)) {
143+
if ($headerTypes[$i] === 'void') {
144+
$headerTypes[$i] = 'int32_t';
145+
}
146+
}
147+
else {
148+
$headerTypes[$i] = 'std::string';
149+
}
150+
}
151+
}
152+
}
153+
}
154+
155+
fclose($handle);
156+
157+
$typedefs[$name] = array_combine($headers, $headerTypes);
158+
}
159+
160+
$output = <<<CPP
161+
#include <cstdint>
162+
#include <string>
163+
#include <vector>
164+
165+
namespace D2::$namespace {
166+
CPP;
167+
168+
$output .= "\n\n";
169+
170+
foreach ($typedefs as $name => $fields) {
171+
$name = 't_' . $name;
172+
$output .= " struct $name {\n";
173+
174+
$i = 0;
175+
foreach ($fields as $field => $type) {
176+
if ($type === 'void') {
177+
$output .= " // Unused column: $field\n";
178+
}
179+
else {
180+
$field = cid($field, "field_$field", FALSE);
181+
$default_value = $type === 'std::string' ? '""' : '0';
182+
$output .= " $type $field = $default_value;\t// Column $i\n";
183+
}
184+
$i++;
185+
}
186+
187+
$output .= "\n size_t read(const char* line);\n";
188+
$output .= " static std::vector<$name> readfile(std::string filename);\n";
189+
190+
$output .= " };\n\n";
191+
}
192+
193+
$output .= "}\n";
194+
195+
file_put_contents(__DIR__ . '/' . $filebase . '.h', $output);
196+
197+
$output = <<<CPP
198+
#include "$filebase.h"
199+
#include <string>
200+
#include <vector>
201+
#include <fstream>
202+
#include <sstream>
203+
204+
namespace D2::$namespace {
205+
CPP;
206+
207+
$output .= "\n\n";
208+
209+
foreach ($typedefs as $name => $fields) {
210+
$name = 't_' . $name;
211+
212+
$output .= <<<CPP
213+
size_t $name::read(const char* line) {
214+
std::vector<std::string> values;
215+
std::stringstream ss(line);
216+
std::string value;
217+
218+
while (std::getline(ss, value, '\\t')) {
219+
values.push_back(value);
220+
}
221+
CPP;
222+
$output .= "\n\n";
223+
224+
$i = 0;
225+
foreach ($fields as $field => $type) {
226+
if ($type !== 'void') {
227+
$field = cid($field, "field_$field", FALSE);
228+
$output .= " if (values.size() > $i) { ";
229+
if ($type === 'int32_t') {
230+
$output .= "$field = values[$i][0] == '\\0' ? 0 : std::stoi(values[$i]);";
231+
}
232+
else {
233+
$output .= "$field = values[$i];";
234+
}
235+
$output .= " }\n";
236+
}
237+
$i++;
238+
}
239+
240+
$output .= "\n return values.size();\n }\n\n";
241+
242+
$output .= <<<CPP
243+
std::vector<$name> $name::readfile(std::string filename) {
244+
std::vector<$name> ret;
245+
std::ifstream file(filename);
246+
247+
if (!file.is_open()) {
248+
return ret; // Return empty vector if file cannot be opened
249+
}
250+
251+
std::string line;
252+
if (!std::getline(file, line)) {
253+
return ret; // Return empty vector if file is empty
254+
}
255+
while (std::getline(file, line)) {
256+
$name v;
257+
v.read(line.c_str());
258+
ret.push_back(v);
259+
}
260+
261+
return ret;
262+
}
263+
CPP;
264+
265+
$output .= "\n\n";
266+
}
267+
268+
$output .= "}\n";
269+
270+
file_put_contents(__DIR__ . '/' . $filebase . '.cpp', $output);
271+
}

test.cpp

Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
#include <iostream>
2+
#include <string>
3+
#include <unordered_map>
4+
#include "txtrotw.h"
5+
6+
// Main takes first parameter as treasure class name
7+
int main(int argc, char* argv[]) {
8+
if (argc < 2) {
9+
std::cerr << "Usage: " << argv[0] << " <item code>" << std::endl;
10+
return 1;
11+
}
12+
13+
for (int i = 1; i < argc; i++) {
14+
std::string itemCode = argv[i];
15+
16+
std::unordered_map<std::string, D2::ROTW::t_armor> armor;
17+
std::unordered_map<std::string, D2::ROTW::t_weapons> weapons;
18+
std::unordered_map<std::string, D2::ROTW::t_misc> misc;
19+
20+
for (auto &entry : D2::ROTW::t_armor::readfile("txt/armor.txt")) {
21+
armor[entry.code] = entry;
22+
}
23+
24+
for (auto &entry : D2::ROTW::t_weapons::readfile("txt/weapons.txt")) {
25+
weapons[entry.code] = entry;
26+
}
27+
28+
for (auto &entry : D2::ROTW::t_misc::readfile("txt/misc.txt")) {
29+
misc[entry.code] = entry;
30+
}
31+
32+
if (armor.find(itemCode) != armor.end()) {
33+
std::cout << "Found armor: " << armor[itemCode].name << std::endl;
34+
std::cout << "Level: " << armor[itemCode].level << std::endl;
35+
36+
if (armor[itemCode].levelreq) {
37+
std::cout << "Level Requirement: " << armor[itemCode].levelreq << std::endl;
38+
}
39+
40+
std::cout << "AC: " << armor[itemCode].minac << "-" << armor[itemCode].maxac << std::endl;
41+
} else if (weapons.find(itemCode) != weapons.end()) {
42+
std::cout << "Found weapon: " << weapons[itemCode].name << std::endl;
43+
std::cout << "Level: " << weapons[itemCode].level << std::endl;
44+
45+
if (weapons[itemCode].levelreq) {
46+
std::cout << "Level Requirement: " << weapons[itemCode].levelreq << std::endl;
47+
}
48+
49+
if (weapons[itemCode].mindam || weapons[itemCode].maxdam) {
50+
std::cout << "Damage: " << weapons[itemCode].mindam << "-" << weapons[itemCode].maxdam << std::endl;
51+
}
52+
53+
if (weapons[itemCode]._2handmindam || weapons[itemCode]._2handmaxdam) {
54+
std::cout << "2h Damage: " << weapons[itemCode]._2handmindam << "-" << weapons[itemCode]._2handmaxdam << std::endl;
55+
}
56+
57+
std::cout << "Speed: " << weapons[itemCode].speed << std::endl;
58+
} else if (misc.find(itemCode) != misc.end()) {
59+
std::cout << "Found misc item: " << misc[itemCode].name << std::endl;
60+
std::cout << "Level: " << misc[itemCode].level << std::endl;
61+
62+
if (misc[itemCode].levelreq) {
63+
std::cout << "Level Requirement: " << misc[itemCode].levelreq << std::endl;
64+
}
65+
66+
if (misc[itemCode].stackable) {
67+
std::cout << "Stack Size: " << misc[itemCode].minstack << "-" << misc[itemCode].maxstack << std::endl;
68+
}
69+
} else {
70+
std::cout << "Item code not found: " << itemCode << std::endl;
71+
}
72+
73+
if (i < argc - 1) {
74+
std::cout << std::endl;
75+
}
76+
}
77+
}

0 commit comments

Comments
 (0)