const input = require('fs').readFileSync('./blocks.txt', 'UTF-8');
const lines = input.split("\n");
String.prototype.appendIfPresent = function(other, otherwise='') {
if (this.length > 0) {
return this + other;
} else {
return this + otherwise;
}
}
const parseCommaList = list => {
const output = [];
let parenDepth = 0;
let inString = false;
let lastSplit = 0;
for (let i = 0; i < list.length; ++i) {
const c = list[i];
if (!inString && c == '(') {
parenDepth++;
} else if (!inString && c == ')') {
parenDepth--;
} else if (c == '"') {
inString = !inString;
} else if (parenDepth == 0 && c == ',') {
output.push(list.slice(lastSplit, i).trim());
lastSplit = i + 1;
}
}
if (lastSplit != list.length) {
output.push(list.slice(lastSplit, list.length).trim());
}
return output;
}
let i = -1;
const results = [];
const ignoredEnums = ['MaterialColor', 'DyeColor'];
for (const line of lines) {
++i;
const parsed = line.match(/([A-Z_]+) = register\("([a-zA-Z_0-9]+)", new ([A-za-z0-9_]+)\((.*?)\)\);/);
const [_, name, namespace_name, class_name, args_raw] = parsed;
const args = parseCommaList(args_raw);
let properties = null;
const otherArgs = [];
for (const arg of args) {
if (arg.startsWith('Block.Properties.of')) {
const [constructor, material] = arg.match(/Block\.Properties\.of\(Material\.([a-zA-Z0-9_]+).*?\)/);
const props = arg.slice(constructor.length).split(').').map(x => x.startsWith('.') ? x.slice(1) : x).filter(x => x.length > 0).map(x => x.endsWith(')') ? x : x + ')');
const rustArgs = props.map(property => {
if (property == 'noCollission()') {
return 'has_collision: false, can_occlude: false';
} else if (property == 'noOcclusion()') {
return 'can_occlude: false';
} else if (property.startsWith('friction')) {
return `friction: ${parseFloat(property.match(/friction\((.*?)\)/)[1]).toFixed(2)}`;
} else if (property.startsWith('speedFactor')) {
return `speed_factor: ${parseFloat(property.match(/speedFactor\((.*?)\)/)[1]).toFixed(2)}`;
} else if (property.startsWith('jumpFactor')) {
return `jump_factor: ${parseFloat(property.match(/jumpFactor\((.*?)\)/)[1]).toFixed(2)}`;
} else if (property.startsWith('lightLevel')) {
return `light_emission: ${property.match(/lightLevel\((.*?)\)/)[1]}`;
} else if (property.startsWith('strength')) {
const match = property.match(/strength\((.*?)(?:, (.*?))?\)/);
const resistance = parseFloat(match[2] || match[1]);
return `destroy_time: ${parseFloat(match[1]).toFixed(2)}, explosion_resistance: ${(resistance > 0 ? resistance : 0.0).toFixed(2)}`;
} else if (property == 'instabreak()') {
return ''; } else if (property == 'randomTicks()') {
return 'is_ticking: true';
} else if (property == 'dynamicShape()') {
return 'dynamic_shape: true';
} else if (property == 'noDrops()') {
return ''; } else if (property.startsWith('dropsLike')) {
return `drops: ${property.match(/dropsLike\((.*?)\)/)[1]}.drops.clone()`;
} else if (property.startsWith('sound')) {
return ''; } else throw property;
}).filter(x => x.length > 0).join(', ').split(', ');
properties = { material, rustArgs };
} else if (arg.startsWith('Block.Properties.copy')) {
properties = arg.match(/Block.Properties.copy\((.*?)\)/)[1];
} else if (ignoredEnums.find(x => arg.startsWith(x))) {
} else {
otherArgs.push(arg);
}
results[i] = { name, namespace_name, class_name, properties, otherArgs };
}
}
for (const i in results) {
if (typeof results[i].properties == 'string') { results[i].properties = results.find(x => x.name == results[i].properties).properties;
}
}
results.forEach(result => {
const stateName = `BlockState${result.namespace_name.split('_').map(x => x[0].toUpperCase() + x.slice(1)).join('')}`
const output = ` lazy_static! { pub static ref ${result.name}: Block = { Arc::new(BlockT { default_state: Some(Box::new(${stateName}::default())), material: materials::${result.properties.material}.clone(), ${result.properties.rustArgs.join(', ').appendIfPresent(', ', ' ')}..Default::default() }) }; }`;
console.log(output);
});
results.forEach(result => {
const output = ` registry.insert("minecraft:${result.namespace_name}", ${result.name}.clone());`;
console.log(output);
});