diff --git a/src/gui/windows/save_creation.zig b/src/gui/windows/save_creation.zig index e2f669e6..4f0a356b 100644 --- a/src/gui/windows/save_creation.zig +++ b/src/gui/windows/save_creation.zig @@ -13,6 +13,7 @@ const Button = @import("../components/Button.zig"); const HorizontalList = @import("../components/HorizontalList.zig"); const Label = @import("../components/Label.zig"); const TextInput = @import("../components/TextInput.zig"); +const CheckBox = @import("../components/CheckBox.zig"); const VerticalList = @import("../components/VerticalList.zig"); pub var window = GuiWindow { @@ -23,6 +24,20 @@ const padding: f32 = 8; var textInput: *TextInput = undefined; +var gamemode: main.game.Gamemode = .creative; +var gamemodeInput: *Button = undefined; + +var allowCheats: bool = true; + +fn gamemodeCallback(_: usize) void { + gamemode = std.meta.intToEnum(main.game.Gamemode, @intFromEnum(gamemode) + 1) catch @enumFromInt(0); + gamemodeInput.child.label.updateText(@tagName(gamemode)); +} + +fn allowCheatsCallback(allow: bool) void { + allowCheats = allow; +} + fn createWorld(_: usize) void { flawedCreateWorld() catch |err| { std.log.err("Error while creating new world: {s}", .{@errorName(err)}); @@ -59,6 +74,17 @@ fn flawedCreateWorld() !void { generatorSettings.put("climateWavelengths", climateWavelengths); try main.files.writeZon(generatorSettingsPath, generatorSettings); } + { + const gamerulePath = std.fmt.allocPrint(main.stackAllocator.allocator, "saves/{s}/gamerules.zig.zon", .{worldName}) catch unreachable; + defer main.stackAllocator.free(gamerulePath); + const gamerules = main.ZonElement.initObject(main.stackAllocator); + defer gamerules.deinit(main.stackAllocator); + + gamerules.put("default_gamemode", @tagName(gamemode)); + gamerules.put("cheats", allowCheats); + + try main.files.writeZon(gamerulePath, gamerules); + } { // Make assets subfolder const assetsPath = std.fmt.allocPrint(main.stackAllocator.allocator, "saves/{s}/assets", .{worldName}) catch unreachable; defer main.stackAllocator.free(assetsPath); @@ -83,6 +109,12 @@ pub fn onOpen() void { const name = std.fmt.bufPrint(&buf, "Save{}", .{num}) catch unreachable; textInput = TextInput.init(.{0, 0}, 128, 22, name, .{.callback = &createWorld}); list.add(textInput); + + gamemodeInput = Button.initText(.{0, 0}, 128, @tagName(gamemode), .{.callback = &gamemodeCallback}); + list.add(gamemodeInput); + + list.add(CheckBox.init(.{0, 0}, 128, "Allow Cheats", true, &allowCheatsCallback)); + list.add(Button.initText(.{0, 0}, 128, "Create World", .{.callback = &createWorld})); list.finish(.center); diff --git a/src/server/server.zig b/src/server/server.zig index ceac4154..c475a5d6 100644 --- a/src/server/server.zig +++ b/src/server/server.zig @@ -467,8 +467,12 @@ pub fn connectInternal(user: *User) void { pub fn messageFrom(msg: []const u8, source: *User) void { // MARK: message if(msg[0] == '/') { // Command. - std.log.info("User \"{s}\" executed command \"{s}\"", .{source.name, msg}); // TODO use color \033[0;32m - command.execute(msg[1..], source); + if (world.?.allowCheats) { + std.log.info("User \"{s}\" executed command \"{s}\"", .{source.name, msg}); // TODO use color \033[0;32m + command.execute(msg[1..], source); + } else { + source.sendMessage("Commands are not allowed because cheats are disabled"); + } } else { const newMessage = std.fmt.allocPrint(main.stackAllocator.allocator, "[{s}ยง#ffffff] {s}", .{source.name, msg}) catch unreachable; defer main.stackAllocator.free(newMessage); diff --git a/src/server/world.zig b/src/server/world.zig index 5646dbf5..73265eb6 100644 --- a/src/server/world.zig +++ b/src/server/world.zig @@ -428,6 +428,9 @@ pub const ServerWorld = struct { // MARK: ServerWorld doGameTimeCycle: bool = true, gravity: f32 = earthGravity, + defaultGamemode: main.game.Gamemode = undefined, + allowCheats: bool = undefined, + seed: u64, name: []const u8, spawn: Vec3i = undefined, @@ -528,6 +531,11 @@ pub const ServerWorld = struct { // MARK: ServerWorld try files.writeZon(try std.fmt.bufPrint(&buf, "saves/{s}/palette.zig.zon", .{name}), self.blockPalette.save(arenaAllocator)); try files.writeZon(try std.fmt.bufPrint(&buf, "saves/{s}/biome_palette.zig.zon", .{name}), self.biomePalette.save(arenaAllocator)); + var gamerules = files.readToZon(arenaAllocator, try std.fmt.bufPrint(&buf, "saves/{s}/gamerules.zig.zon", .{name})) catch ZonElement.initObject(arenaAllocator); + + self.defaultGamemode = std.meta.stringToEnum(main.game.Gamemode, gamerules.get([]const u8, "default_gamemode", "creative")) orelse .creative; + self.allowCheats = gamerules.get(bool, "cheats", true); + self.chunkManager = try ChunkManager.init(self, generatorSettings); errdefer self.chunkManager.deinit(); return self; @@ -774,10 +782,12 @@ pub const ServerWorld = struct { // MARK: ServerWorld const player = &user.player; if(playerData == .null) { player.pos = @floatFromInt(self.spawn); + + main.items.Inventory.Sync.setGamemode(user, self.defaultGamemode); } else { player.loadFrom(playerData.getChild("entity")); - main.items.Inventory.Sync.setGamemode(user, std.meta.stringToEnum(main.game.Gamemode, playerData.get([]const u8, "gamemode", "survival")) orelse .survival); + main.items.Inventory.Sync.setGamemode(user, std.meta.stringToEnum(main.game.Gamemode, playerData.get([]const u8, "gamemode", @tagName(self.defaultGamemode))) orelse self.defaultGamemode); } }