diff --git a/src/gui/windows/save_creation.zig b/src/gui/windows/save_creation.zig index 31ee00ad..341cf77c 100644 --- a/src/gui/windows/save_creation.zig +++ b/src/gui/windows/save_creation.zig @@ -44,16 +44,48 @@ fn createWorld(_: usize) void { }; } +fn findValidFolderName(allocator: NeverFailingAllocator, name: []const u8) []const u8 { + // Remove illegal ASCII characters: + const escapedName = main.stackAllocator.alloc(u8, name.len); + defer main.stackAllocator.free(escapedName); + for(name, 0..) |char, i| { + escapedName[i] = switch(char) { + 'a'...'z', + 'A'...'Z', + '0'...'9', + '_', + '-', + '.', + ' ' => char, + 128...255 => char, + else => '-', + }; + } + + // Avoid duplicates: + var resultName = main.stackAllocator.dupe(u8, escapedName); + defer main.stackAllocator.free(resultName); + var i: usize = 0; + while(true) { + const resultPath = std.fmt.allocPrint(main.stackAllocator.allocator, "saves/{s}", .{resultName}) catch unreachable; + defer main.stackAllocator.free(resultPath); + + var dir = std.fs.cwd().openDir(resultPath, .{}) catch break; + dir.close(); + + main.stackAllocator.free(resultName); + resultName = std.fmt.allocPrint(main.stackAllocator.allocator, "{s}_{}", .{escapedName, i}) catch unreachable; + i += 1; + } + return allocator.dupe(u8, resultName); +} + fn flawedCreateWorld() !void { const worldName = textInput.currentString.items; - const worldPath = worldName; // TODO: Make sure that only valid file name characters are used, and add a check to allow different worlds of the same name. + const worldPath = findValidFolderName(main.stackAllocator, worldName); + defer main.stackAllocator.free(worldPath); const saveFolder = std.fmt.allocPrint(main.stackAllocator.allocator, "saves/{s}", .{worldPath}) catch unreachable; defer main.stackAllocator.free(saveFolder); - if(std.fs.cwd().openDir(saveFolder, .{})) |_dir| { - var dir = _dir; - dir.close(); - return error.AlreadyExists; - } else |_| {} try main.files.makeDir(saveFolder); { const generatorSettingsPath = std.fmt.allocPrint(main.stackAllocator.allocator, "saves/{s}/generatorSettings.zig.zon", .{worldPath}) catch unreachable; diff --git a/src/gui/windows/save_selection.zig b/src/gui/windows/save_selection.zig index ef102032..055e2ce9 100644 --- a/src/gui/windows/save_selection.zig +++ b/src/gui/windows/save_selection.zig @@ -94,33 +94,6 @@ fn openFolder(index: usize) void { main.files.openDirInWindow(path); } -fn parseEscapedFolderName(allocator: NeverFailingAllocator, name: []const u8) []const u8 { - var result = main.List(u8).init(allocator); - defer result.deinit(); - var i: u32 = 0; - while(i < name.len) : (i += 1) { - if(name[i] == '_') { - var val: u21 = 0; - for(0..4) |_| { - i += 1; - if(i < name.len) { - val = val*16 + switch(name[i]) { - '0'...'9' => name[i] - '0', - 'a'...'f' => name[i] - 'a' + 10, - 'A'...'F' => name[i] - 'A' + 10, - else => 0, - }; - } - } - var buf: [4]u8 = undefined; - result.appendSlice(buf[0 .. std.unicode.utf8Encode(val, &buf) catch 0]); // TODO: Change this to full unicode rather than using this broken utf-16 converter. - } else { - result.append(name[i]); - } - } - return result.toOwnedSlice(); -} - pub fn update() void { if(needsUpdate) { needsUpdate = false; @@ -157,13 +130,10 @@ pub fn onOpen() void { }; defer worldInfo.deinit(main.stackAllocator); - const decodedName = parseEscapedFolderName(main.stackAllocator, entry.name); - defer main.stackAllocator.free(decodedName); - worldList.append(main.globalAllocator, .{ .fileName = main.globalAllocator.dupe(u8, entry.name), .lastUsedTime = worldInfo.get(i64, "lastUsedTime", 0), - .name = main.globalAllocator.dupe(u8, worldInfo.get([]const u8, "", decodedName)), + .name = main.globalAllocator.dupe(u8, worldInfo.get([]const u8, "name", entry.name)), }); } }