mirror of
https://github.com/PixelGuys/Cubyz.git
synced 2025-08-03 19:28:49 -04:00
Handle errors locally instead of letting them bubble up into the main functions.
This commit is contained in:
parent
05769cc765
commit
74c896c969
@ -15,18 +15,23 @@ var commonItems: std.StringHashMap(JsonElement) = undefined;
|
||||
var commonRecipes: main.List([]const u8) = undefined;
|
||||
|
||||
/// Reads json files recursively from all subfolders.
|
||||
pub fn readAllJsonFilesInAddons(externalAllocator: NeverFailingAllocator, addons: main.List(std.fs.Dir), addonNames: main.List([]const u8), subPath: []const u8, output: *std.StringHashMap(JsonElement)) !void {
|
||||
pub fn readAllJsonFilesInAddons(externalAllocator: NeverFailingAllocator, addons: main.List(std.fs.Dir), addonNames: main.List([]const u8), subPath: []const u8, output: *std.StringHashMap(JsonElement)) void {
|
||||
for(addons.items, addonNames.items) |addon, addonName| {
|
||||
var dir = addon.openDir(subPath, .{.iterate = true}) catch |err| {
|
||||
if(err == error.FileNotFound) continue;
|
||||
return err;
|
||||
if(err != error.FileNotFound) {
|
||||
std.log.err("Could not open addon directory {s}: {s}", .{subPath, @errorName(err)});
|
||||
}
|
||||
continue;
|
||||
};
|
||||
defer dir.close();
|
||||
|
||||
var walker = try dir.walk(main.globalAllocator.allocator);
|
||||
var walker = dir.walk(main.globalAllocator.allocator) catch unreachable;
|
||||
defer walker.deinit();
|
||||
|
||||
while(try walker.next()) |entry| {
|
||||
while(walker.next() catch |err| blk: {
|
||||
std.log.err("Got error while iterating addon directory {s}: {s}", .{subPath, @errorName(err)});
|
||||
break :blk null;
|
||||
}) |entry| {
|
||||
if(entry.kind == .file and std.ascii.endsWithIgnoreCase(entry.basename, ".json")) {
|
||||
const folderName = addonName;
|
||||
const id: []u8 = externalAllocator.alloc(u8, folderName.len + 1 + entry.path.len - 5);
|
||||
@ -41,30 +46,41 @@ pub fn readAllJsonFilesInAddons(externalAllocator: NeverFailingAllocator, addons
|
||||
}
|
||||
}
|
||||
|
||||
const file = try dir.openFile(entry.path, .{});
|
||||
const file = dir.openFile(entry.path, .{}) catch |err| {
|
||||
std.log.err("Could not open {s}/{s}: {s}", .{subPath, entry.path, @errorName(err)});
|
||||
continue;
|
||||
};
|
||||
defer file.close();
|
||||
const string = file.readToEndAlloc(main.stackAllocator.allocator, std.math.maxInt(usize)) catch unreachable;
|
||||
defer main.stackAllocator.free(string);
|
||||
try output.put(id, JsonElement.parseFromString(externalAllocator, string));
|
||||
output.put(id, JsonElement.parseFromString(externalAllocator, string)) catch unreachable;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
/// Reads text files recursively from all subfolders.
|
||||
pub fn readAllFilesInAddons(externalAllocator: NeverFailingAllocator, addons: main.List(std.fs.Dir), subPath: []const u8, output: *main.List([]const u8)) !void {
|
||||
pub fn readAllFilesInAddons(externalAllocator: NeverFailingAllocator, addons: main.List(std.fs.Dir), subPath: []const u8, output: *main.List([]const u8)) void {
|
||||
for(addons.items) |addon| {
|
||||
var dir = addon.openDir(subPath, .{.iterate = true}) catch |err| {
|
||||
if(err == error.FileNotFound) continue;
|
||||
return err;
|
||||
if(err != error.FileNotFound) {
|
||||
std.log.err("Could not open addon directory {s}: {s}", .{subPath, @errorName(err)});
|
||||
}
|
||||
continue;
|
||||
};
|
||||
defer dir.close();
|
||||
|
||||
var walker = try dir.walk(main.globalAllocator.allocator);
|
||||
var walker = dir.walk(main.globalAllocator.allocator) catch unreachable;
|
||||
defer walker.deinit();
|
||||
|
||||
while(try walker.next()) |entry| {
|
||||
while(walker.next() catch |err| blk: {
|
||||
std.log.err("Got error while iterating addon directory {s}: {s}", .{subPath, @errorName(err)});
|
||||
break :blk null;
|
||||
}) |entry| {
|
||||
if(entry.kind == .file) {
|
||||
const file = try dir.openFile(entry.path, .{});
|
||||
const file = dir.openFile(entry.path, .{}) catch |err| {
|
||||
std.log.err("Could not open {s}/{s}: {s}", .{subPath, entry.path, @errorName(err)});
|
||||
continue;
|
||||
};
|
||||
defer file.close();
|
||||
const string = file.readToEndAlloc(externalAllocator.allocator, std.math.maxInt(usize)) catch unreachable;
|
||||
output.append(string);
|
||||
@ -73,19 +89,28 @@ pub fn readAllFilesInAddons(externalAllocator: NeverFailingAllocator, addons: ma
|
||||
}
|
||||
}
|
||||
|
||||
pub fn readAssets(externalAllocator: NeverFailingAllocator, assetPath: []const u8, blocks: *std.StringHashMap(JsonElement), items: *std.StringHashMap(JsonElement), biomes: *std.StringHashMap(JsonElement), recipes: *main.List([]const u8)) !void {
|
||||
pub fn readAssets(externalAllocator: NeverFailingAllocator, assetPath: []const u8, blocks: *std.StringHashMap(JsonElement), items: *std.StringHashMap(JsonElement), biomes: *std.StringHashMap(JsonElement), recipes: *main.List([]const u8)) void {
|
||||
var addons = main.List(std.fs.Dir).init(main.globalAllocator);
|
||||
defer addons.deinit();
|
||||
var addonNames = main.List([]const u8).init(main.globalAllocator);
|
||||
defer addonNames.deinit();
|
||||
|
||||
{ // Find all the sub-directories to the assets folder.
|
||||
var dir = try std.fs.cwd().openDir(assetPath, .{.iterate = true});
|
||||
var dir = std.fs.cwd().openDir(assetPath, .{.iterate = true}) catch |err| {
|
||||
std.log.err("Can't open asset path {s}: {s}", .{assetPath, @errorName(err)});
|
||||
return;
|
||||
};
|
||||
defer dir.close();
|
||||
var iterator = dir.iterate();
|
||||
while(try iterator.next()) |addon| {
|
||||
while(iterator.next() catch |err| blk: {
|
||||
std.log.err("Got error while iterating over asset path {s}: {s}", .{assetPath, @errorName(err)});
|
||||
break :blk null;
|
||||
}) |addon| {
|
||||
if(addon.kind == .directory) {
|
||||
addons.append(try dir.openDir(addon.name, .{}));
|
||||
addons.append(dir.openDir(addon.name, .{}) catch |err| {
|
||||
std.log.err("Got error while reading addon {s} from {s}: {s}", .{addon.name, assetPath, @errorName(err)});
|
||||
continue;
|
||||
});
|
||||
addonNames.append(main.globalAllocator.dupe(u8, addon.name));
|
||||
}
|
||||
}
|
||||
@ -95,13 +120,13 @@ pub fn readAssets(externalAllocator: NeverFailingAllocator, assetPath: []const u
|
||||
main.globalAllocator.free(addonName);
|
||||
};
|
||||
|
||||
try readAllJsonFilesInAddons(externalAllocator, addons, addonNames, "blocks", blocks);
|
||||
try readAllJsonFilesInAddons(externalAllocator, addons, addonNames, "items", items);
|
||||
try readAllJsonFilesInAddons(externalAllocator, addons, addonNames, "biomes", biomes);
|
||||
try readAllFilesInAddons(externalAllocator, addons, "recipes", recipes);
|
||||
readAllJsonFilesInAddons(externalAllocator, addons, addonNames, "blocks", blocks);
|
||||
readAllJsonFilesInAddons(externalAllocator, addons, addonNames, "items", items);
|
||||
readAllJsonFilesInAddons(externalAllocator, addons, addonNames, "biomes", biomes);
|
||||
readAllFilesInAddons(externalAllocator, addons, "recipes", recipes);
|
||||
}
|
||||
|
||||
pub fn init() !void {
|
||||
pub fn init() void {
|
||||
biomes_zig.init();
|
||||
blocks_zig.init();
|
||||
arena = main.utils.NeverFailingArenaAllocator.init(main.globalAllocator);
|
||||
@ -111,7 +136,7 @@ pub fn init() !void {
|
||||
commonBiomes = std.StringHashMap(JsonElement).init(arenaAllocator.allocator);
|
||||
commonRecipes = main.List([]const u8).init(arenaAllocator);
|
||||
|
||||
try readAssets(arenaAllocator, "assets/", &commonBlocks, &commonItems, &commonBiomes, &commonRecipes);
|
||||
readAssets(arenaAllocator, "assets/", &commonBlocks, &commonItems, &commonBiomes, &commonRecipes);
|
||||
}
|
||||
|
||||
fn registerItem(assetFolder: []const u8, id: []const u8, json: JsonElement) !*items_zig.BaseItem {
|
||||
@ -209,7 +234,7 @@ pub fn loadWorldAssets(assetFolder: []const u8, palette: *BlockPalette) !void {
|
||||
recipes.appendSlice(commonRecipes.items);
|
||||
defer recipes.clearAndFree();
|
||||
|
||||
try readAssets(arenaAllocator, assetFolder, &blocks, &items, &biomes, &recipes);
|
||||
readAssets(arenaAllocator, assetFolder, &blocks, &items, &biomes, &recipes);
|
||||
|
||||
// blocks:
|
||||
var block: u32 = 0;
|
||||
|
@ -1048,7 +1048,7 @@ const TextRendering = struct {
|
||||
}
|
||||
};
|
||||
|
||||
pub fn init() !void {
|
||||
pub fn init() void {
|
||||
draw.initCircle();
|
||||
draw.initDrawRect();
|
||||
draw.initImage();
|
||||
|
@ -124,7 +124,7 @@ pub const Callback = struct {
|
||||
}
|
||||
};
|
||||
|
||||
pub fn init() !void {
|
||||
pub fn init() void {
|
||||
GuiCommandQueue.init();
|
||||
windowList = List(*GuiWindow).init(main.globalAllocator);
|
||||
hudWindows = List(*GuiWindow).init(main.globalAllocator);
|
||||
|
51
src/main.zig
51
src/main.zig
@ -48,7 +48,7 @@ fn cacheStringImpl(comptime len: usize, comptime str: [len]u8) []const u8 {
|
||||
fn cacheString(comptime str: []const u8) []const u8 {
|
||||
return cacheStringImpl(str.len, str[0..].*);
|
||||
}
|
||||
var logFile: std.fs.File = undefined;
|
||||
var logFile: ?std.fs.File = undefined;
|
||||
var supportsANSIColors: bool = undefined;
|
||||
// overwrite the log function:
|
||||
pub const std_options = struct {
|
||||
@ -181,6 +181,26 @@ pub const std_options = struct {
|
||||
}
|
||||
};
|
||||
|
||||
fn initLogging() void {
|
||||
logFile = null;
|
||||
std.fs.cwd().makePath("logs") catch |err| {
|
||||
std.log.err("Couldn't create logs folder: {s}", .{@errorName(err)});
|
||||
return;
|
||||
};
|
||||
logFile = std.fs.cwd().createFile("logs/latest.log", .{}) catch |err| {
|
||||
std.log.err("Couldn't create logs/latest.log: {s}", .{@errorName(err)});
|
||||
return;
|
||||
};
|
||||
supportsANSIColors = std.io.getStdOut().supportsAnsiEscapeCodes();
|
||||
}
|
||||
|
||||
fn deinitLogging() void {
|
||||
if(logFile) |_logFile| {
|
||||
_logFile.close();
|
||||
logFile = null;
|
||||
}
|
||||
}
|
||||
|
||||
fn logToFile(comptime format: []const u8, args: anytype) void {
|
||||
var buf: [65536]u8 = undefined;
|
||||
var fba = std.heap.FixedBufferAllocator.init(&buf);
|
||||
@ -188,7 +208,7 @@ fn logToFile(comptime format: []const u8, args: anytype) void {
|
||||
|
||||
const string = std.fmt.allocPrint(allocator, format, args) catch format;
|
||||
defer allocator.free(string);
|
||||
logFile.writeAll(string) catch {};
|
||||
(logFile orelse return).writeAll(string) catch {};
|
||||
}
|
||||
|
||||
fn logToStdErr(comptime format: []const u8, args: anytype) void {
|
||||
@ -587,11 +607,11 @@ pub const Window = struct {
|
||||
c.glfwSetClipboardString(window, nullTerminatedString.ptr);
|
||||
}
|
||||
|
||||
fn init() !void {
|
||||
fn init() void {
|
||||
_ = c.glfwSetErrorCallback(GLFWCallbacks.errorCallback);
|
||||
|
||||
if(c.glfwInit() == 0) {
|
||||
return error.GLFWFailed;
|
||||
@panic("Failed to initialize GLFW");
|
||||
}
|
||||
|
||||
if(@import("builtin").mode == .Debug) {
|
||||
@ -600,7 +620,7 @@ pub const Window = struct {
|
||||
c.glfwWindowHint(c.GLFW_CONTEXT_VERSION_MAJOR, 4);
|
||||
c.glfwWindowHint(c.GLFW_CONTEXT_VERSION_MINOR, 6);
|
||||
|
||||
window = c.glfwCreateWindow(width, height, "Cubyz", null, null) orelse return error.GLFWFailed;
|
||||
window = c.glfwCreateWindow(width, height, "Cubyz", null, null) orelse @panic("Failed to create GLFW window");
|
||||
|
||||
_ = c.glfwSetKeyCallback(window, GLFWCallbacks.keyCallback);
|
||||
_ = c.glfwSetCharCallback(window, GLFWCallbacks.charCallback);
|
||||
@ -612,7 +632,7 @@ pub const Window = struct {
|
||||
c.glfwMakeContextCurrent(window);
|
||||
|
||||
if(c.gladLoadGL() == 0) {
|
||||
return error.GLADFailed;
|
||||
@panic("Failed to load OpenGL functions from GLAD");
|
||||
}
|
||||
reloadSettings();
|
||||
|
||||
@ -657,7 +677,7 @@ pub const Window = struct {
|
||||
|
||||
pub var lastFrameTime = std.atomic.Value(f64).init(0);
|
||||
|
||||
pub fn main() !void {
|
||||
pub fn main() void {
|
||||
seed = @bitCast(std.time.milliTimestamp());
|
||||
defer if(global_gpa.deinit() == .leak) {
|
||||
std.log.err("Memory leak", .{});
|
||||
@ -666,11 +686,8 @@ pub fn main() !void {
|
||||
defer sta.deinit();
|
||||
stackAllocator = sta.allocator();
|
||||
|
||||
// init logging.
|
||||
try std.fs.cwd().makePath("logs");
|
||||
logFile = try std.fs.cwd().createFile("logs/latest.log", .{});
|
||||
defer logFile.close();
|
||||
supportsANSIColors = std.io.getStdOut().supportsAnsiEscapeCodes();
|
||||
initLogging();
|
||||
defer deinitLogging();
|
||||
|
||||
threadPool = utils.ThreadPool.init(globalAllocator, 1 + ((std.Thread.getCpuCount() catch 4) -| 2));
|
||||
defer threadPool.deinit();
|
||||
@ -678,16 +695,16 @@ pub fn main() !void {
|
||||
settings.init();
|
||||
defer settings.deinit();
|
||||
|
||||
try Window.init();
|
||||
Window.init();
|
||||
defer Window.deinit();
|
||||
|
||||
try graphics.init();
|
||||
graphics.init();
|
||||
defer graphics.deinit();
|
||||
|
||||
audio.init() catch std.log.err("Failed to initialize audio. Continuing the game without sounds.", .{});
|
||||
defer audio.deinit();
|
||||
|
||||
try gui.init();
|
||||
gui.init();
|
||||
defer gui.deinit();
|
||||
|
||||
rotation.init();
|
||||
@ -702,7 +719,7 @@ pub fn main() !void {
|
||||
itemdrop.ItemDropRenderer.init();
|
||||
defer itemdrop.ItemDropRenderer.deinit();
|
||||
|
||||
try assets.init();
|
||||
assets.init();
|
||||
defer assets.deinit();
|
||||
|
||||
blocks.meshes.init();
|
||||
@ -711,7 +728,7 @@ pub fn main() !void {
|
||||
renderer.init();
|
||||
defer renderer.deinit();
|
||||
|
||||
try network.init();
|
||||
network.init();
|
||||
|
||||
entity.ClientEntityManager.init();
|
||||
defer entity.ClientEntityManager.deinit();
|
||||
|
@ -26,9 +26,12 @@ const Socket = struct {
|
||||
const os = std.os;
|
||||
socketID: os.socket_t,
|
||||
|
||||
fn startup() !void {
|
||||
fn startup() void {
|
||||
if(builtin.os.tag == .windows) {
|
||||
_ = try os.windows.WSAStartup(2, 2);
|
||||
_ = os.windows.WSAStartup(2, 2) catch |err| {
|
||||
std.log.err("Could not initialize the Windows Socket API: {s}", .{@errorName(err)});
|
||||
@panic("Could not init networking.");
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@ -100,8 +103,8 @@ const Socket = struct {
|
||||
}
|
||||
};
|
||||
|
||||
pub fn init() !void {
|
||||
try Socket.startup();
|
||||
pub fn init() void {
|
||||
Socket.startup();
|
||||
inline for(@typeInfo(Protocols).Struct.decls) |decl| {
|
||||
if(@TypeOf(@field(Protocols, decl.name)) == type) {
|
||||
const id = @field(Protocols, decl.name).id;
|
||||
@ -493,7 +496,7 @@ pub const ConnectionManager = struct {
|
||||
}
|
||||
}
|
||||
|
||||
fn onReceive(self: *ConnectionManager, data: []const u8, source: Address) !void {
|
||||
fn onReceive(self: *ConnectionManager, data: []const u8, source: Address) void {
|
||||
std.debug.assert(self.threadId == std.Thread.getCurrentId());
|
||||
self.mutex.lock();
|
||||
|
||||
@ -505,7 +508,7 @@ pub const ConnectionManager = struct {
|
||||
}
|
||||
if(conn.remoteAddress.port == source.port) {
|
||||
self.mutex.unlock();
|
||||
try conn.receive(data);
|
||||
conn.receive(data);
|
||||
return;
|
||||
}
|
||||
}
|
||||
@ -525,7 +528,7 @@ pub const ConnectionManager = struct {
|
||||
std.log.debug("Message: {any}", .{data});
|
||||
}
|
||||
|
||||
pub fn run(self: *ConnectionManager) !void {
|
||||
pub fn run(self: *ConnectionManager) void {
|
||||
self.threadId = std.Thread.getCurrentId();
|
||||
var sta = utils.StackAllocator.init(main.globalAllocator, 1 << 23);
|
||||
defer sta.deinit();
|
||||
@ -536,12 +539,13 @@ pub const ConnectionManager = struct {
|
||||
self.waitingToFinishReceive.broadcast();
|
||||
var source: Address = undefined;
|
||||
if(self.socket.receive(&self.receiveBuffer, 100, &source)) |data| {
|
||||
try self.onReceive(data, source);
|
||||
self.onReceive(data, source);
|
||||
} else |err| {
|
||||
if(err == error.Timeout) {
|
||||
// No message within the last ~100 ms.
|
||||
} else {
|
||||
return err; // TODO: Shutdown the game normally.
|
||||
std.log.err("Got error on receive: {s}", .{@errorName(err)});
|
||||
@panic("Network failed.");
|
||||
}
|
||||
}
|
||||
|
||||
@ -1635,7 +1639,14 @@ pub const Connection = struct {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn receive(self: *Connection, data: []const u8) !void {
|
||||
pub fn receive(self: *Connection, data: []const u8) void {
|
||||
self.flawedReceive(data) catch |err| {
|
||||
std.log.err("Got error while processing received network data: {s}", .{@errorName(err)});
|
||||
self.disconnect();
|
||||
};
|
||||
}
|
||||
|
||||
pub fn flawedReceive(self: *Connection, data: []const u8) !void {
|
||||
std.debug.assert(self.manager.threadId == std.Thread.getCurrentId());
|
||||
const protocol = data[0];
|
||||
if(self.handShakeState.load(.Monotonic) != Protocols.handShake.stepComplete and protocol != Protocols.handShake.id and protocol != Protocols.keepAlive and protocol != Protocols.important) {
|
||||
@ -1683,7 +1694,7 @@ pub const Connection = struct {
|
||||
if(Protocols.list[protocol]) |prot| {
|
||||
try prot(self, data[1..]);
|
||||
} else {
|
||||
std.log.warn("Received unknown protocol width id {}", .{protocol});
|
||||
std.log.warn("Received unknown protocol with id {}", .{protocol});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user