diff --git a/src/game.zig b/src/game.zig index 320c733..0a93ca6 100644 --- a/src/game.zig +++ b/src/game.zig @@ -213,21 +213,9 @@ pub fn start() !void { map = Map.init(&map_buf, level_size); - var stream = std.io.FixedBufferStream([]const u8){ - .pos = 0, - .buffer = world_data, - }; - const world_reader = stream.reader(); + var db = try world.Database.init(alloc); - var levels = try world.read(alloc, world_reader); - var level_data_offset = try stream.getPos(); - - try stream.seekTo(level_data_offset + levels[0].offset); - - level = try world.Level.read(world_reader); - - level_buf = try alloc.alloc(world.TileData, level.size); - try level.readTiles(world_reader, level_buf); + level = try db.levelLoad(alloc, 0); try extract.extractLevel(.{ .alloc = frame_alloc, @@ -241,9 +229,6 @@ pub fn start() !void { .switch_on = world.Tiles.SwitchesOn, }); - var entity_buf = try alloc.alloc(world.Entity, level.entity_count); - try level.readEntities(world_reader, entity_buf); - const spawnArr = level.getSpawn() orelse return error.NoPlayerSpawn; const spawn = Vec2{ spawnArr[0], spawnArr[1] }; diff --git a/src/world.zig b/src/world.zig index 4f04e61..9ae6f28 100644 --- a/src/world.zig +++ b/src/world.zig @@ -457,6 +457,54 @@ pub fn read(alloc: std.mem.Allocator, reader: anytype) ![]LevelHeader { return level_headers; } +const Cursor = std.io.FixedBufferStream([]const u8); +pub const Database = struct { + cursor: Cursor, + level_info: []LevelHeader, + level_data_begin: usize, + + const world_data = @embedFile(@import("world_data").path); + + pub fn init(alloc: std.mem.Allocator) !Database { + var cursor = Cursor{ + .pos = 0, + .buffer = world_data, + }; + + var reader = cursor.reader(); + + var levels = try read(alloc, reader); + var level_data_begin = @intCast(usize, try cursor.getPos()); + + return Database{ + .cursor = cursor, + .level_info = levels, + .level_data_begin = level_data_begin, + }; + } + + pub fn levelInfo(db: *Database, level: usize) !Level { + try db.cursor.seekTo(db.level_data_begin + db.level_info[level].offset); + const reader = db.cursor.reader(); + + return try Level.read(reader); + } + + pub fn levelLoad(db: *Database, alloc: std.mem.Allocator, level: usize) !Level { + var level_info = try db.levelInfo(level); + + const reader = db.cursor.reader(); + + var level_buf = try alloc.alloc(TileData, level_info.size); + try level_info.readTiles(reader, level_buf); + + var entity_buf = try alloc.alloc(Entity, level_info.entity_count); + try level_info.readEntities(reader, entity_buf); + + return level_info; + } +}; + // All levels in the game. If two rooms are next to each other, they // are assumed to be neighbors. Leaving the screen will load in the next // level in that direction. The player is placed at the same position