summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorubq323 <ubq323@ubq323.website>2023-02-11 15:33:13 +0000
committerubq323 <ubq323@ubq323.website>2023-02-11 15:33:13 +0000
commitb4c189ab1b6233c7e7e260446e80b789f375b5d6 (patch)
treea051262e11172ccd65015fc89f4b92adf0de2ae7
parent81ee73e37348eaae6b1e4a23378d13d129133904 (diff)
change from random worldgen to be based on a hash of position; implement serverside chunk unloading
-rw-r--r--client/main.lua2
-rw-r--r--server/chunk.lua3
-rw-r--r--server/map.lua5
-rw-r--r--server/noise.lua24
-rw-r--r--server/server.lua31
-rw-r--r--server/worldgen.lua18
6 files changed, 58 insertions, 25 deletions
diff --git a/client/main.lua b/client/main.lua
index a544250..03df16a 100644
--- a/client/main.lua
+++ b/client/main.lua
@@ -89,7 +89,7 @@ function love.update(dt)
update_local_player(local_player,dt)
if love.keyboard.isScancodeDown"q" then camera.zoom = camera.zoom*1.05 end
if love.keyboard.isScancodeDown"e" then camera.zoom = camera.zoom/1.05 end
- camera.zoom = math.max(2.25,math.min(50,camera.zoom))
+ camera.zoom = math.max(1,math.min(50,camera.zoom))
sync_local_player(local_player)
end
diff --git a/server/chunk.lua b/server/chunk.lua
index 4fb2960..1e2e135 100644
--- a/server/chunk.lua
+++ b/server/chunk.lua
@@ -5,7 +5,7 @@ local json = require"common.dkjson"
local ChunkS = class.extend(Chunk)
function ChunkS.make(cls,...)
local self = Chunk.make(cls,...)
- self.dirty = true
+ self.dirty = false
return self
end
function ChunkS.load_from_disk(cls,cp)
@@ -26,6 +26,7 @@ function ChunkS.save_if_dirty(self)
f:write(self:data_packet())
f:flush()
f:close()
+ self.dirty = false
end
end
function ChunkS.set_at(self,...)
diff --git a/server/map.lua b/server/map.lua
index 9627de9..3d7f377 100644
--- a/server/map.lua
+++ b/server/map.lua
@@ -29,15 +29,12 @@ function MapS.obtain(self,cp)
end
function MapS.save_chunk(self,cp)
+ -- will only actually save anything if anything needs saving.
-- any attempt to save not-loaded chunks is silently ignored
local ch = self:chunk(cp)
if not ch then return end
ch:save_if_dirty()
end
-function MapS.save_and_unload(self,cp)
- self:save_chunk(cp)
- self:remove_chunk(cp)
-end
return {MapS=MapS}
diff --git a/server/noise.lua b/server/noise.lua
index fe254ac..bf7ac2e 100644
--- a/server/noise.lua
+++ b/server/noise.lua
@@ -1,13 +1,29 @@
local Pos = require"common.coords".Pos
local class = require"common.class"
+local bit = require"bit"
local tau = 2*math.pi
math.randomseed(os.time())
-local function random_unit_vec()
+
+local function hash_list(t)
+ local h = #t
+ for _,x in ipairs(t) do
+ x = bit.bxor(bit.rshift(x,16),x) * 0x45d9f3b
+ x = bit.bxor(bit.rshift(x,16),x) * 0x45d9f3b
+ x = bit.bxor(bit.rshift(x,16),x)
+ h = bit.bxor(h,x + 0x9e3779b9 + bit.lshift(h,6) + bit.rshift(h,2))
+ end
+ return h
+end
+
+local function hash_to_unit_vec(t)
+ local h = hash_list(t)
+ math.randomseed(h)
local theta = math.random()*tau
return Pos:make(math.cos(theta),math.sin(theta))
end
+
local function lerp(a,b,t) return (1-t)*a + t*b end
local function smoothstep(x)
if x<0 then return 0 end
@@ -17,15 +33,15 @@ end
local function slerp(a,b,t) return lerp(a,b,smoothstep(t)) end
local PerlinNoise = class()
-function PerlinNoise.make(cls)
+function PerlinNoise.make(cls,ind_seed)
local grid = {}
setmetatable(grid,{__index=function(t,k) t[k] = {} return t[k] end})
- return setmetatable({grid=grid},cls)
+ return setmetatable({grid=grid,ind_seed=ind_seed},cls)
end
function PerlinNoise.vertex(self,ix,iy)
local v = self.grid[ix][iy]
if v then return v end
- local vv = random_unit_vec()
+ local vv = hash_to_unit_vec{ix,iy,self.ind_seed}
self.grid[ix][iy] = vv
return vv
end
diff --git a/server/server.lua b/server/server.lua
index cc9903e..88f4efe 100644
--- a/server/server.lua
+++ b/server/server.lua
@@ -3,6 +3,7 @@ local json = require"common.dkjson"
local chunk = require"common.chunk"
local noise = require"noise"
local coords = require"common.coords"
+local Pos = coords.Pos
local worldgen = require"worldgen"
local MapS = require"map".MapS
local posix_time = require"posix.time"
@@ -34,7 +35,7 @@ local function random_color()
return {math.random(),math.random(),math.random()}
end
local function make_player(peer)
- local p = {pos={0,0},color=random_color(),peer=peer,id=nextid}
+ local p = {pos=Pos:make(0,0),color=random_color(),peer=peer,id=nextid}
nextid = nextid + 1
return p
end
@@ -42,8 +43,8 @@ end
local function player_info_part(player)
return {
id=player.id,
- x=player.pos[1],
- y=player.pos[2],
+ x=player.pos.x,
+ y=player.pos.y,
color=player.color,
}
end
@@ -95,8 +96,7 @@ local function handle_ev(ev)
local op = j.t
if op == "ppos" then
local x,y = j.x,j.y
- player.pos[1] = x
- player.pos[2] = y
+ player.pos = coords.Pos:make(x,y)
-- print(player.id,"-->",player.pos[1],player.pos[2])
for i,otherplayer in ipairs(playerlist) do
if otherplayer ~= player then
@@ -157,11 +157,30 @@ local ndts = 100
local ntick = 0
+local function player_near_chunk(cp)
+ -- true: chunk at cp should stay loaded (because of a nearby player),
+ -- false: no players nearby, can be unloaded
+ -- this is kind of inefficient at the moment
+ for _,player in ipairs(playerlist) do
+ local pcp = player.pos:to_hex():containing_chunk()
+ for _,neighb in ipairs(pcp:neighborhood()) do
+ if neighb == cp then
+ return true
+ end
+ end
+ end
+ return false
+end
+
local function tick(ntick)
if ntick % 30 == 0 then
- print("saving things...")
+ print("saving things")
for cp,ch in map:iter_chunks() do
map:save_chunk(cp)
+ if not player_near_chunk(cp) then
+ print("unloading chunk",cp)
+ map:remove_chunk(cp)
+ end
end
end
end
diff --git a/server/worldgen.lua b/server/worldgen.lua
index 2ef1ac0..0a8485b 100644
--- a/server/worldgen.lua
+++ b/server/worldgen.lua
@@ -4,18 +4,18 @@ local chunk = require"common.chunk"
local ChunkS = require"chunk".ChunkS
local CHUNK_SIZE = require"common.constants".CHUNK_SIZE
-local function p(amp,scale) return {scale=scale,amp=amp,gen=noise.PerlinNoise:make()} end
--- local ng = noise.NoiseAgg:make{
--- p(1,20),
--- -- p(0.7,2),
--- p(0.5,15),
--- --p(2,200),
--- }
+local function p(amp,scale,seed)
+ return {
+ scale=scale,
+ amp=amp,
+ gen=noise.PerlinNoise:make(seed)
+ }
+end
-- whether there is a tile there or not
-local surface_ng = noise.NoiseAgg:make{p(1,20),p(0.5,15)}
+local surface_ng = noise.NoiseAgg:make{p(1,20,1),p(0.7,5,2)}
-- if there is a tile there, what color should it be
-local color_ng = noise.NoiseAgg:make{p(1,20),p(0.5,15)}
+local color_ng = noise.NoiseAgg:make{p(1,20,3),p(0.5,15,4)}
local function gen_chunk(chpos)