import * as fs from 'node:fs'; import { EXTENSION, INDENT } from './common'; import { getStructure, setCppAllowed } from './map'; // Output Directory let outputDirectory = process.argv[2]; if (!outputDirectory) { outputDirectory = `${__dirname}/../out`; } fs.rmSync(outputDirectory, {force: true, recursive: true}); fs.mkdirSync(outputDirectory, {recursive: true}); // Main function loadSymbols() { // Load const files = fs.readdirSync(`${__dirname}/../symbols`); const structureObjects = []; for (const file of files) { if (file.endsWith(EXTENSION)) { // Get Name const parts = file.split('/'); let name = parts[parts.length - 1]!; name = name.substring(0, name.length - EXTENSION.length); // Structures structureObjects.push(getStructure(name)); } } // Sort structureObjects.sort((a, b) => { if (a.getName() > b.getName()) { return 1; } else if (a.getName() < b.getName()) { return -1; } else { return 0; } }); // Return return structureObjects; } function makeHeader(output: string, allowCpp: boolean) { // Set Mode setCppAllowed(allowCpp); // Load Symbols const structureObjects = loadSymbols(); // Forward Declarations let forwardDeclarations = '// Forward Declarations\n'; for (const structure of structureObjects) { const name = structure.getName(); forwardDeclarations += `typedef struct ${name} ${name};\n`; } // Sort Structures By Dependency while (true) { let valid = true; // Loop Through Structures for (const structure of structureObjects) { // Loop Through Dependencies const currentIndex = structureObjects.indexOf(structure); for (const dependency of structure.getDependencies()) { // Compare Current And Dependency Index const obj = getStructure(dependency); const dependencyIndex = structureObjects.indexOf(obj); if (dependencyIndex > currentIndex) { // Dependency Must Be Moved structureObjects.splice(dependencyIndex, 1); structureObjects.splice(currentIndex, 0, obj); valid = false; break; } } // Check If Any Changes Were Made if (!valid) { break; } } // Check If Any Changes Were Made if (valid) { break; } } // Generate Code let structures = ''; for (const structure of structureObjects) { const name = structure.getName(); structures += `\n// ${name}\n`; try { structures += structure.generate(); } catch (e) { console.log(`Error Generating Header: ${name}: ${e instanceof Error ? e.stack : e}`); process.exit(1); } } // Write let result = ''; result += '#pragma once\n'; result += '\n'; result += forwardDeclarations; result += '\n// Init\n'; result += 'void init_symbols();'; result += '\n// Extra Definitions\n'; result += fs.readFileSync(`${__dirname}/../symbols/extra.h`, {encoding: 'utf8'}).trim() + '\n'; result += structures; fs.writeFileSync(output, result); } // Run makeHeader(`${outputDirectory}/minecraft_c.h`, false); makeHeader(`${outputDirectory}/minecraft_cpp.h`, true); // Generate Compiled Code function makeCompiledCode(output: string) { // Set Mode setCppAllowed(true); // Load Symbols const structureObjects = loadSymbols(); // Generate let declarations = ''; let init = ''; for (const structure of structureObjects) { const name = structure.getName(); declarations += `\n// ${name}\n`; init += `\n${INDENT}// ${name}\n`; try { const code = structure.generateCode(); declarations += code.functions; init += code.init; } catch (e) { console.log(`Error Generating Code: ${name}: ${e instanceof Error ? e.stack : e}`); process.exit(1); } } // Write let result = ''; result += '#include "minecraft.h"\n'; result += '\n// Init\n'; result += 'void init_symbols() {'; result += init; result += '}\n'; result += declarations; fs.writeFileSync(output, result); } makeCompiledCode(`${outputDirectory}/minecraft.cpp`); // Create Main Header function makeMainHeader(output: string) { let result = ''; result += '#pragma once\n'; result += '#pragma GCC diagnostic push\n'; result += '#pragma GCC diagnostic ignored "-Wunused-variable"\n'; result += '#pragma GCC diagnostic ignored "-Wunused-function"\n'; result += 'typedef unsigned char uchar;\n'; result += 'typedef unsigned int uint;\n'; result += '#include \n'; result += '#include \n'; result += '#include \n'; result += '#ifndef __cplusplus\n'; result += 'typedef unsigned char bool;\n'; result += '#include "minecraft_c.h"\n'; result += '#else\n'; result += '#include \n'; result += '#include \n'; result += 'extern "C" {\n'; result += '#include "minecraft_cpp.h"\n'; result += '}\n'; result += '#endif\n'; result += '#pragma GCC diagnostic pop\n'; fs.writeFileSync(output, result); } makeMainHeader(`${outputDirectory}/minecraft.h`);