Skip to content

Commit 8eeede6

Browse files
committed
Attempt to fix a huge shortcoming that leads directly to manually doing all of the work again. System now reads every module into a class name to preset name set map and module name pair list and uses gathered information to properly attribute mod parts to the mod, or "Base.rte" otherwise. This should massively shrink the set of constant references which need to be manually corrected. Code could use comments, probably.
1 parent 805274e commit 8eeede6

File tree

1 file changed

+102
-12
lines changed

1 file changed

+102
-12
lines changed

src/main.zig

Lines changed: 102 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ const page_allocator = std.heap.page_allocator;
99
const Allocator = std.mem.Allocator;
1010
const ArenaAllocator = std.heap.ArenaAllocator;
1111
const ArrayList = std.ArrayList;
12-
const HashMap = std.hash_map.HashMap;
12+
const StringArrayHashMap = std.StringArrayHashMap;
1313
const MultiArrayList = std.MultiArrayList;
1414
const Scanner = std.json.Scanner;
1515
const StringHashMap = std.hash_map.StringHashMap;
@@ -124,6 +124,13 @@ const IniFolder = struct {
124124
folders: ArrayList(IniFolder),
125125
};
126126

127+
// A module space is a list of mappings, ClassName to PresetName-set.
128+
// As well as a module name, taken from the actual folder name.
129+
const ModuleSpace = struct {
130+
entityDefinitions: *StringArrayHashMap(*StringArrayHashMap(void)),
131+
moduleName: []const u8,
132+
};
133+
127134
/// Updated by `convert()` to record what it is doing.
128135
/// If `convert()` crashed, look inside this struct to see why and where it did.
129136
pub const Diagnostics = struct {
@@ -292,7 +299,10 @@ pub fn convert(input_folder_path_: []const u8, output_folder_path_: []const u8,
292299

293300
const ini_deinlining_rules = try parseIniDeinliningRules(rules_folder_path, allocator);
294301
std.log.info("Applying INI de-inlining rules...\n", .{});
295-
try applyIniDeinliningRules(allocator, ini_deinlining_rules, &file_tree);
302+
const entityDefinitionSets: *ArrayList(*ModuleSpace) = try allocator.create(ArrayList(*ModuleSpace));
303+
entityDefinitionSets.* = ArrayList(*ModuleSpace).init(allocator);
304+
try populateEntityDefinitionSets(allocator, &file_tree, entityDefinitionSets);
305+
try applyIniDeinliningRules(allocator, ini_deinlining_rules, &file_tree, entityDefinitionSets);
296306

297307
std.log.info("Updating INI file tree...\n", .{});
298308
try updateIniFileTree(&file_tree, allocator);
@@ -1399,15 +1409,80 @@ fn parseIniDeinliningRules(rules_folder_path: []const u8, allocator: Allocator)
13991409
return try parseFromSliceLeaky([][]const u8, allocator, text, .{});
14001410
}
14011411

1402-
fn applyIniDeinliningRules(allocator: Allocator, ini_deinlining_rules: [][]const u8, file_tree: *IniFolder) !void {
1403-
for (ini_deinlining_rules) |property| {
1404-
try applyIniDeinliningRulesRecursivelyFolder(allocator, file_tree, property);
1412+
fn populateEntityDefinitionSets(allocator: Allocator, file_tree: *IniFolder, modules: *ArrayList(*ModuleSpace)) !void {
1413+
for (file_tree.folders.items) |*folder| {
1414+
const entityDefinitions: *StringArrayHashMap(*StringArrayHashMap(void)) = try allocator.create(StringArrayHashMap(*StringArrayHashMap(void)));
1415+
entityDefinitions.* = StringArrayHashMap(*StringArrayHashMap(void)).init(allocator);
1416+
1417+
try populateEntityDefinitionSetsRecursively(allocator, folder, entityDefinitions);
1418+
1419+
const module: *ModuleSpace = try allocator.create(ModuleSpace);
1420+
module.* = ModuleSpace{
1421+
.moduleName = folder.name,
1422+
.entityDefinitions = entityDefinitions,
1423+
};
1424+
1425+
try modules.append(module);
1426+
}
1427+
}
1428+
1429+
fn populateEntityDefinitionSetsRecursively(allocator: Allocator, moduleFolder: *IniFolder, entitySpace: *StringArrayHashMap(*StringArrayHashMap(void))) !void {
1430+
for (moduleFolder.folders.items) |*folder| {
1431+
try populateEntityDefinitionSetsRecursively(allocator, folder, entitySpace);
1432+
}
1433+
1434+
for (moduleFolder.files.items) |*file| {
1435+
for (file.ast.items) |*node| {
1436+
try populateEntityDefinitionSetsNode(allocator, node, entitySpace);
1437+
}
14051438
}
14061439
}
14071440

1408-
fn applyIniDeinliningRulesRecursivelyFolder(allocator: Allocator, file_tree: *IniFolder, property: []const u8) !void {
1441+
fn populateEntityDefinitionSetsNode(allocator: Allocator, serialNode: *Node, entitySpace: *StringArrayHashMap(*StringArrayHashMap(void))) !void {
1442+
// Assume this isn't an Entity with a PresetName.
1443+
var presetName: ?[]const u8 = null;
1444+
1445+
// Find out if it does specify a PresetName, and record it if so.
1446+
for (serialNode.children.items) |*node| {
1447+
if (node.property) |nodeProperty| {
1448+
if (strEql(nodeProperty, "PresetName")) {
1449+
if (node.value) |nodeValue| {
1450+
presetName = nodeValue;
1451+
}
1452+
}
1453+
}
1454+
}
1455+
1456+
// If this has a specified PresetName, then this is an Entity from this module, which will be useful for accurate de-inlining.
1457+
if (presetName) |presetNameNonOptional| {
1458+
if (serialNode.value) |serialNodeValue| {
1459+
var presetSpace: *StringArrayHashMap(void) = entitySpace.get(serialNodeValue) orelse emplaceEntitySpace: {
1460+
const presetSpace: *StringArrayHashMap(void) = try allocator.create(StringArrayHashMap(void));
1461+
presetSpace.* = StringArrayHashMap(void).init(allocator);
1462+
try entitySpace.put(serialNodeValue, presetSpace);
1463+
break :emplaceEntitySpace presetSpace;
1464+
};
1465+
1466+
try presetSpace.put(presetNameNonOptional, {});
1467+
}
1468+
}
1469+
1470+
for (serialNode.children.items) |*node| {
1471+
try populateEntityDefinitionSetsNode(allocator, node, entitySpace);
1472+
}
1473+
}
1474+
1475+
fn applyIniDeinliningRules(allocator: Allocator, ini_deinlining_rules: [][]const u8, file_tree: *IniFolder, modules: *ArrayList(*ModuleSpace)) !void {
1476+
for (file_tree.folders.items, 0..) |*moduleFolder, moduleID| {
1477+
for (ini_deinlining_rules) |property| {
1478+
try applyIniDeinliningRulesRecursivelyFolder(allocator, moduleFolder, property, modules.items[moduleID]);
1479+
}
1480+
}
1481+
}
1482+
1483+
fn applyIniDeinliningRulesRecursivelyFolder(allocator: Allocator, file_tree: *IniFolder, property: []const u8, moduleSpace: *ModuleSpace) !void {
14091484
for (file_tree.folders.items) |*folder| {
1410-
try applyIniDeinliningRulesRecursivelyFolder(allocator, folder, property);
1485+
try applyIniDeinliningRulesRecursivelyFolder(allocator, folder, property, moduleSpace);
14111486
}
14121487

14131488
for (file_tree.files.items) |*file| {
@@ -1421,7 +1496,7 @@ fn applyIniDeinliningRulesRecursivelyFolder(allocator: Allocator, file_tree: *In
14211496
// Why necessary? Because some unused inis use the word "Particle" as a root property.
14221497
for (node.children.items) |*child| {
14231498
// Deinlining a definition into the file will push the current object further forward.
1424-
const insertionApplied: bool = try applyIniDeinliningRulesRecursivelyNode(allocator, child, property, file, node.*);
1499+
const insertionApplied: bool = try applyIniDeinliningRulesRecursivelyNode(allocator, child, property, file, node.*, moduleSpace);
14251500

14261501
// We want to read the object again, since we stopped after the deinline, but we also want to read the definition that was deinlined.
14271502
// So decrement i.
@@ -1434,7 +1509,7 @@ fn applyIniDeinliningRulesRecursivelyFolder(allocator: Allocator, file_tree: *In
14341509
}
14351510
}
14361511

1437-
fn applyIniDeinliningRulesRecursivelyNode(allocator: Allocator, node: *Node, property: []const u8, file: *IniFile, rootParent: Node) !bool {
1512+
fn applyIniDeinliningRulesRecursivelyNode(allocator: Allocator, node: *Node, property: []const u8, file: *IniFile, rootParent: Node, moduleSpace: *ModuleSpace) !bool {
14381513
// If this has a property, and:
14391514
if (node.property) |node_property| {
14401515
// If it matches the property given, and:
@@ -1472,7 +1547,10 @@ fn applyIniDeinliningRulesRecursivelyNode(allocator: Allocator, node: *Node, pro
14721547
// Assume that nothing is invalidated.
14731548
var invalidationFlag = false;
14741549
if (presetNameOptional) |presetName| {
1550+
// Special case Loadouts
14751551
if (!strEql(rootParent.property.?, "AddLoadout")) {
1552+
moduleName = moduleSpace.moduleName;
1553+
14761554
const duplicateNode = Node{
14771555
.property = "AddEffect",
14781556
.value = node.value,
@@ -1484,10 +1562,22 @@ fn applyIniDeinliningRulesRecursivelyNode(allocator: Allocator, node: *Node, pro
14841562
try file.ast.insert(determinedIndex, duplicateNode);
14851563

14861564
invalidationFlag = true;
1565+
} else {
1566+
if (moduleSpace.entityDefinitions.get(className)) |presetNameSpace| {
1567+
if (presetNameSpace.get(presetName) != null) {
1568+
moduleName = moduleSpace.moduleName;
1569+
}
1570+
}
14871571
}
14881572

14891573
node.value = try allocPrint(allocator, "{s}/{s}/{s}", .{ className, moduleName, presetName });
14901574
} else if (copyOfNameOptional) |copyOfName| {
1575+
if (moduleSpace.entityDefinitions.get(className)) |presetNameSpace| {
1576+
if (presetNameSpace.get(copyOfName) != null) {
1577+
moduleName = moduleSpace.moduleName;
1578+
}
1579+
}
1580+
14911581
node.value = try allocPrint(allocator, "{s}/{s}/{s}", .{ className, moduleName, copyOfName });
14921582
} else {
14931583
node.value = "None";
@@ -1506,7 +1596,7 @@ fn applyIniDeinliningRulesRecursivelyNode(allocator: Allocator, node: *Node, pro
15061596

15071597
// Since this isn't a malformed constant reference, check the same for this' children.
15081598
for (node.children.items) |*child| {
1509-
const sequenceInvalidated = try applyIniDeinliningRulesRecursivelyNode(allocator, child, property, file, rootParent);
1599+
const sequenceInvalidated = try applyIniDeinliningRulesRecursivelyNode(allocator, child, property, file, rootParent, moduleSpace);
15101600

15111601
// We have discovered an inline definition, and corrected it, which we must immediately signal to the caller.
15121602
if (sequenceInvalidated) {
@@ -2480,8 +2570,8 @@ fn writeAstRecursively(node: *Node, buffered_writer: anytype, depth: usize) !voi
24802570
}
24812571

24822572
if (node.value) |value| {
2483-
try writeBuffered(buffered_writer, value);
2484-
}
2573+
try writeBuffered(buffered_writer, value);
2574+
}
24852575

24862576
if (node.comments.items.len > 0) {
24872577
if (node.property != null) {

0 commit comments

Comments
 (0)