feat(dungeon): add seed-derived cached floors
This commit is contained in:
1 parent
7e205a548f
commit
05541457e3
1 file changed
+60
@@ -0,0 +1,60 @@
|
|||||||
|
-- Owns every floor. Each level's layout is derived from the world seed and its
|
||||||
|
-- depth alone, through a private rng that never touches the world rng stream, so
|
||||||
|
-- a floor generates identically no matter when it is first entered. Generated
|
||||||
|
-- floors are cached, which is what makes revisiting one restore its exact state.
|
||||||
|
|
||||||
|
local Rng = require("rng")
|
||||||
|
local Builder = require("builder")
|
||||||
|
local Level = require("level")
|
||||||
|
|
||||||
|
local Dungeon = {}
|
||||||
|
Dungeon.__index = Dungeon
|
||||||
|
|
||||||
|
local SALT = 0x9E3779B97F4A7C15
|
||||||
|
|
||||||
|
function Dungeon.new(worldSeed, options)
|
||||||
|
return setmetatable({
|
||||||
|
worldSeed = worldSeed,
|
||||||
|
options = options or {},
|
||||||
|
levels = {},
|
||||||
|
}, Dungeon)
|
||||||
|
end
|
||||||
|
|
||||||
|
function Dungeon:levelSeed(depth)
|
||||||
|
return math.tointeger(self.worldSeed ~ (depth * SALT)) or 0
|
||||||
|
end
|
||||||
|
|
||||||
|
function Dungeon:get(depth)
|
||||||
|
if not self.levels[depth] then
|
||||||
|
local rng = Rng.new(self:levelSeed(depth))
|
||||||
|
self.levels[depth] = Builder.build(depth, rng, self.options)
|
||||||
|
end
|
||||||
|
return self.levels[depth]
|
||||||
|
end
|
||||||
|
|
||||||
|
function Dungeon:isGenerated(depth)
|
||||||
|
return self.levels[depth] ~= nil
|
||||||
|
end
|
||||||
|
|
||||||
|
function Dungeon:toData()
|
||||||
|
local depths = {}
|
||||||
|
for depth in pairs(self.levels) do
|
||||||
|
depths[#depths + 1] = depth
|
||||||
|
end
|
||||||
|
table.sort(depths)
|
||||||
|
local stored = {}
|
||||||
|
for _, depth in ipairs(depths) do
|
||||||
|
stored[#stored + 1] = { depth = depth, level = self.levels[depth]:toData() }
|
||||||
|
end
|
||||||
|
return { worldSeed = self.worldSeed, options = self.options, levels = stored }
|
||||||
|
end
|
||||||
|
|
||||||
|
function Dungeon.fromData(snapshot)
|
||||||
|
local dungeon = Dungeon.new(snapshot.worldSeed, snapshot.options)
|
||||||
|
for _, entry in ipairs(snapshot.levels) do
|
||||||
|
dungeon.levels[entry.depth] = Level.fromData(entry.level)
|
||||||
|
end
|
||||||
|
return dungeon
|
||||||
|
end
|
||||||
|
|
||||||
|
return Dungeon
|
||||||
Reference in new issue
Block a user