diff --git a/src/assets.zig b/src/assets.zig index 554adaa3..45ef292c 100644 --- a/src/assets.zig +++ b/src/assets.zig @@ -473,7 +473,7 @@ pub const Palette = struct { // MARK: Palette var loadedAssets: bool = false; -pub fn loadWorldAssets(assetFolder: []const u8, blockPalette: *Palette, itemPalette: *Palette, biomePalette: *Palette) !void { // MARK: loadWorldAssets() +pub fn loadWorldAssets(assetFolder: []const u8, blockPalette: *Palette, itemPalette: *Palette, toolPalette: *Palette, biomePalette: *Palette) !void { // MARK: loadWorldAssets() if(loadedAssets) return; // The assets already got loaded by the server. loadedAssets = true; @@ -575,10 +575,17 @@ pub fn loadWorldAssets(assetFolder: []const u8, blockPalette: *Palette, itemPale try assignBlockItem(stringId); } + for(toolPalette.palette.items) |id| { + registerTool(assetFolder, id, worldAssets.tools.get(id) orelse .null); + } + // tools: iterator = worldAssets.tools.iterator(); while(iterator.next()) |entry| { - registerTool(assetFolder, entry.key_ptr.*, entry.value_ptr.*); + const id = entry.key_ptr.*; + if(items_zig.hasRegisteredTool(id)) continue; + registerTool(assetFolder, id, entry.value_ptr.*); + toolPalette.add(id); } // block drops: diff --git a/src/game.zig b/src/game.zig index 101d9b94..969d63a6 100644 --- a/src/game.zig +++ b/src/game.zig @@ -655,6 +655,7 @@ pub const World = struct { // MARK: World connected: bool = true, blockPalette: *assets.Palette = undefined, itemPalette: *assets.Palette = undefined, + toolPalette: *assets.Palette = undefined, biomePalette: *assets.Palette = undefined, itemDrops: ClientItemDropManager = undefined, playerBiome: Atomic(*const main.server.terrain.biomes.Biome) = undefined, @@ -692,6 +693,7 @@ pub const World = struct { // MARK: World self.itemDrops.deinit(); self.blockPalette.deinit(); self.itemPalette.deinit(); + self.toolPalette.deinit(); self.biomePalette.deinit(); self.manager.deinit(); main.server.stop(); @@ -713,9 +715,11 @@ pub const World = struct { // MARK: World errdefer self.biomePalette.deinit(); self.itemPalette = try assets.Palette.init(main.globalAllocator, zon.getChild("itemPalette"), null); errdefer self.itemPalette.deinit(); + self.toolPalette = try assets.Palette.init(main.globalAllocator, zon.getChild("toolPalette"), null); + errdefer self.toolPalette.deinit(); self.spawn = zon.get(Vec3f, "spawn", .{0, 0, 0}); - try assets.loadWorldAssets("serverAssets", self.blockPalette, self.itemPalette, self.biomePalette); + try assets.loadWorldAssets("serverAssets", self.blockPalette, self.itemPalette, self.toolPalette, self.biomePalette); Player.id = zon.get(u32, "player_id", std.math.maxInt(u32)); Player.inventory = Inventory.init(main.globalAllocator, 32, .normal, .{.playerInventory = Player.id}); Player.loadFrom(zon.getChild("player")); diff --git a/src/items.zig b/src/items.zig index fc8495a7..0409224a 100644 --- a/src/items.zig +++ b/src/items.zig @@ -828,6 +828,10 @@ pub fn hasRegistered(id: []const u8) bool { return reverseIndices.contains(id); } +pub fn hasRegisteredTool(id: []const u8) bool { + return toolTypes.contains(id); +} + pub fn toolTypeIterator() std.StringHashMap(ToolType).ValueIterator { return toolTypes.valueIterator(); } diff --git a/src/network.zig b/src/network.zig index 0a8ca522..8a52df0c 100644 --- a/src/network.zig +++ b/src/network.zig @@ -686,6 +686,7 @@ pub const Protocols = struct { zonObject.put("spawn", main.server.world.?.spawn); zonObject.put("blockPalette", main.server.world.?.blockPalette.storeToZon(main.stackAllocator)); zonObject.put("itemPalette", main.server.world.?.itemPalette.storeToZon(main.stackAllocator)); + zonObject.put("toolPalette", main.server.world.?.toolPalette.storeToZon(main.stackAllocator)); zonObject.put("biomePalette", main.server.world.?.biomePalette.storeToZon(main.stackAllocator)); const outData = zonObject.toStringEfficient(main.stackAllocator, &[1]u8{stepServerData}); diff --git a/src/server/world.zig b/src/server/world.zig index bbb4d933..3af9f5a9 100644 --- a/src/server/world.zig +++ b/src/server/world.zig @@ -16,6 +16,7 @@ const Vec3i = vec.Vec3i; const Vec3d = vec.Vec3d; const Vec3f = vec.Vec3f; const terrain = server.terrain; +const NeverFailingAllocator = main.heap.NeverFailingAllocator; const server = @import("server.zig"); const User = server.User; @@ -419,6 +420,7 @@ pub const ServerWorld = struct { // MARK: ServerWorld itemDropManager: ItemDropManager = undefined, blockPalette: *main.assets.Palette = undefined, itemPalette: *main.assets.Palette = undefined, + toolPalette: *main.assets.Palette = undefined, biomePalette: *main.assets.Palette = undefined, chunkManager: ChunkManager = undefined, @@ -515,29 +517,27 @@ pub const ServerWorld = struct { // MARK: ServerWorld self.wio = WorldIO.init(try files.openDir(try std.fmt.allocPrint(arenaAllocator.allocator, "saves/{s}", .{path})), self); errdefer self.wio.deinit(); - const blockPaletteZon = files.readToZon(arenaAllocator, try std.fmt.allocPrint(arenaAllocator.allocator, "saves/{s}/palette.zig.zon", .{path})) catch .null; - self.blockPalette = try main.assets.Palette.init(main.globalAllocator, blockPaletteZon, "cubyz:air"); + self.blockPalette = try loadPalette(arenaAllocator, path, "palette", "cubyz:air"); errdefer self.blockPalette.deinit(); - std.log.info("Loaded save block palette with {} blocks.", .{self.blockPalette.size()}); - const itemPaletteZon = files.readToZon(arenaAllocator, try std.fmt.allocPrint(arenaAllocator.allocator, "saves/{s}/item_palette.zig.zon", .{path})) catch .null; - self.itemPalette = try main.assets.Palette.init(main.globalAllocator, itemPaletteZon, null); + self.itemPalette = try loadPalette(arenaAllocator, path, "item_palette", null); errdefer self.itemPalette.deinit(); - std.log.info("Loaded save item palette with {} items.", .{self.itemPalette.size()}); - const biomePaletteZon = files.readToZon(arenaAllocator, try std.fmt.allocPrint(arenaAllocator.allocator, "saves/{s}/biome_palette.zig.zon", .{path})) catch .null; - self.biomePalette = try main.assets.Palette.init(main.globalAllocator, biomePaletteZon, null); + self.toolPalette = try loadPalette(arenaAllocator, path, "tool_palette", null); + errdefer self.toolPalette.deinit(); + + self.biomePalette = try loadPalette(arenaAllocator, path, "biome_palette", null); errdefer self.biomePalette.deinit(); - std.log.info("Loaded save biome palette with {} biomes.", .{self.biomePalette.size()}); errdefer main.assets.unloadAssets(); self.seed = try self.wio.loadWorldSeed(); - try main.assets.loadWorldAssets(try std.fmt.allocPrint(arenaAllocator.allocator, "saves/{s}/assets/", .{path}), self.blockPalette, self.itemPalette, self.biomePalette); + try main.assets.loadWorldAssets(try std.fmt.allocPrint(arenaAllocator.allocator, "saves/{s}/assets/", .{path}), self.blockPalette, self.itemPalette, self.toolPalette, self.biomePalette); // Store the block palette now that everything is loaded. try files.writeZon(try std.fmt.allocPrint(arenaAllocator.allocator, "saves/{s}/palette.zig.zon", .{path}), self.blockPalette.storeToZon(arenaAllocator)); - try files.writeZon(try std.fmt.allocPrint(arenaAllocator.allocator, "saves/{s}/biome_palette.zig.zon", .{path}), self.biomePalette.storeToZon(arenaAllocator)); try files.writeZon(try std.fmt.allocPrint(arenaAllocator.allocator, "saves/{s}/item_palette.zig.zon", .{path}), self.itemPalette.storeToZon(arenaAllocator)); + try files.writeZon(try std.fmt.allocPrint(arenaAllocator.allocator, "saves/{s}/tool_palette.zig.zon", .{path}), self.toolPalette.storeToZon(arenaAllocator)); + try files.writeZon(try std.fmt.allocPrint(arenaAllocator.allocator, "saves/{s}/biome_palette.zig.zon", .{path}), self.biomePalette.storeToZon(arenaAllocator)); var gamerules = files.readToZon(arenaAllocator, try std.fmt.allocPrint(arenaAllocator.allocator, "saves/{s}/gamerules.zig.zon", .{path})) catch ZonElement.initObject(arenaAllocator); @@ -549,6 +549,15 @@ pub const ServerWorld = struct { // MARK: ServerWorld return self; } + pub fn loadPalette(allocator: NeverFailingAllocator, worldName: []const u8, paletteName: []const u8, firstEntry: ?[]const u8) !*Palette { + const path = try std.fmt.allocPrint(main.stackAllocator.allocator, "saves/{s}/{s}.zig.zon", .{worldName, paletteName}); + defer main.stackAllocator.allocator.free(path); + const paletteZon = files.readToZon(allocator, path) catch .null; + const palette = try main.assets.Palette.init(main.globalAllocator, paletteZon, firstEntry); + std.log.info("Loaded {s} with {} entries.", .{paletteName, palette.size()}); + return palette; + } + pub fn deinit(self: *ServerWorld) void { self.forceSave() catch |err| { std.log.err("Error while saving the world: {s}", .{@errorName(err)}); @@ -567,6 +576,7 @@ pub const ServerWorld = struct { // MARK: ServerWorld self.itemDropManager.deinit(); self.blockPalette.deinit(); self.itemPalette.deinit(); + self.toolPalette.deinit(); self.biomePalette.deinit(); self.wio.deinit(); main.globalAllocator.free(self.path);