summaryrefslogtreecommitdiff
path: root/server
diff options
context:
space:
mode:
authorubq323 <ubq323@ubq323.website>2023-03-24 21:11:10 +0000
committerubq323 <ubq323@ubq323.website>2023-03-24 21:11:10 +0000
commite77609c5bc8b44aa22ef88063246fd05add5e705 (patch)
tree1829e2098e40f7fad82af8707bd8a359edd2be1d /server
parent0927f9297c06525a453b4aad44fa4c2916c75906 (diff)
use lmdb for world storage; plus other small things
support numpad 8456 for movement in addition to wasd refactor server and add player module update outdated documentation slightly
Diffstat (limited to 'server')
-rw-r--r--server/chunk.lua37
-rw-r--r--server/db.lua15
-rw-r--r--server/player.lua31
-rw-r--r--server/server.lua78
4 files changed, 107 insertions, 54 deletions
diff --git a/server/chunk.lua b/server/chunk.lua
index 8e71327..852f1fe 100644
--- a/server/chunk.lua
+++ b/server/chunk.lua
@@ -1,6 +1,7 @@
local class = require"common.class"
local Chunk = require"common.chunk".Chunk
local json = require"common.dkjson"
+local db = require'db'
local ChunkS = class.extend(Chunk)
function ChunkS.make(cls,...)
@@ -8,31 +9,41 @@ function ChunkS.make(cls,...)
self.dirty = false
return self
end
-function ChunkS.load_from_disk(cls,cp)
- -- returns nil if not there
- local filename = cp:filename()
- local f = io.open(filename,"r")
- if not f then return nil end
- local j = json.decode(f:read("a"))
- self = cls:from_packet_data(j)
+
+function ChunkS.apply_migrations(self)
+ -- if tile format has changed and format in db isn't up to date any more
+ -- then perform updates here
for i,t in ipairs(self.tiles) do
if t == false then self.tiles[i] = 0
elseif t == true then self.tiles[i] = 9 end
end
- f:close()
+end
+
+function ChunkS.load_from_disk(cls,cp)
+ -- tries to load from database. returns nil if not there.
+ local txn,dbi = db.get_db('chunks')
+ local d = dbi[tostring(cp)]
+ txn:commit()
+
+ if not d then return nil end
+ local j = json.decode(d)
+
+ local self = cls:from_packet_data(j)
+ self:apply_migrations()
+
return self
end
+
function ChunkS.save_if_dirty(self)
if self.dirty then
print("saving chunk",self.cp)
- local filename = self.cp:filename()
- local f = io.open(filename,"w")
- f:write(self:data_packet())
- f:flush()
- f:close()
+ local txn,dbi = db.get_db('chunks',true)
+ dbi[tostring(self.cp)] = self:data_packet()
+ txn:commit()
self.dirty = false
end
end
+
function ChunkS.set_at(self,...)
Chunk.set_at(self,...)
self.dirty = true
diff --git a/server/db.lua b/server/db.lua
new file mode 100644
index 0000000..4208aeb
--- /dev/null
+++ b/server/db.lua
@@ -0,0 +1,15 @@
+local lmdb = require'lmdb'
+local env = lmdb.open('data',{maxdbs=16})
+local function get_db(dbname, writeable)
+ -- shortcut
+ if writeable == nil then writeable = false end
+ local txn = assert(env:txn_begin(writeable),"couldn't begin txn")
+ local the_db = assert(txn:open(dbname), "couldn't open db")
+ return txn,the_db
+end
+
+
+return {
+ env=env,
+ get_db=get_db,
+}
diff --git a/server/player.lua b/server/player.lua
new file mode 100644
index 0000000..365eadc
--- /dev/null
+++ b/server/player.lua
@@ -0,0 +1,31 @@
+local class = require'common.class'
+local Pos = require'common.coords'.Pos
+
+local nextid = 1
+
+local function random_color()
+ return {math.random(),math.random(),math.random()}
+end
+
+local Player = class()
+function Player.make(cls,peer)
+ local self = {
+ pos = Pos:make(0,0),
+ color = random_color(),
+ peer = peer,
+ id = nextid,
+ }
+ nextid = nextid + 1
+ return setmetatable(self,cls)
+end
+function Player.info_part(self)
+ -- eh
+ return {
+ id=self.id,
+ x=self.pos.x,
+ y=self.pos.y,
+ color=self.color,
+ }
+end
+
+return {Player=Player}
diff --git a/server/server.lua b/server/server.lua
index 24b49ae..2da7988 100644
--- a/server/server.lua
+++ b/server/server.lua
@@ -6,6 +6,7 @@ local coords = require"common.coords"
local Pos = coords.Pos
local worldgen = require"worldgen"
local MapS = require"map".MapS
+local Player=require'player'.Player
local posix_time = require"posix.time"
local posix_signal = require"posix.signal"
@@ -16,7 +17,6 @@ print(host:get_socket_address())
-- sequential list of all players
local playerlist = {}
-local nextid = 1
-- this is maybe suboptimal
-- but it is simplest for now
@@ -33,28 +33,12 @@ local function player_by_peer(peer)
return nil
end
-local function random_color()
- return {math.random(),math.random(),math.random()}
-end
-local function make_player(peer)
- local p = {pos=Pos:make(0,0),color=random_color(),peer=peer,id=nextid}
- nextid = nextid + 1
- return p
-end
-local function player_info_part(player)
- return {
- id=player.id,
- x=player.pos.x,
- y=player.pos.y,
- color=player.color,
- }
-end
local function player_join_packet(player)
- return json.encode{t="join",pl=player_info_part(player)}
+ return json.encode{t="join",pl=player:info_part()}
end
local function player_you_packet(player)
- return json.encode{t="you",pl=player_info_part(player)}
+ return json.encode{t="you",pl=player:info_part()}
end
local function player_leave_packet(player)
return json.encode{t="leave",id=player.id}
@@ -68,32 +52,44 @@ end
local map = MapS:make()
+
+
+local function on_player_connect(ev)
+ local player = Player:make(ev.peer)
+ table.insert(playerlist, player)
+
+ player.peer:send(player_you_packet(player))
+
+ for i,otherplayer in ipairs(playerlist) do
+ if otherplayer ~= player then
+ player.peer:send(player_join_packet(otherplayer))
+ otherplayer.peer:send(player_join_packet(player))
+ end
+ end
+
+ print("connect",player.id,player.peer)
+end
+
+local function on_player_disconnect(ev)
+ local player,idx = player_by_peer(ev.peer)
+ if not player then error("sneeze"..ev.peer) end
+ table.remove(playerlist,idx)
+
+ for i,otherplayer in ipairs(playerlist) do
+ otherplayer.peer:send(player_leave_packet(player))
+ end
+
+ print("disconnect", player.id, player.peer)
+end
+
+
+
local function handle_ev(ev)
-- handle network event
if ev.type == "connect" then
- local player = make_player(ev.peer)
- table.insert(playerlist,player)
- print("connect",player.peer,player.id)
- player.peer:send(player_you_packet(player))
- local central_chunk = map:obtain(coords.ChunkPos:make(0,0))
- player.peer:send(central_chunk:data_packet())
-
- for i,otherplayer in ipairs(playerlist) do
- if otherplayer ~= player then
- -- tell new player about each other player
- player.peer:send(player_join_packet(otherplayer))
- -- tell each other player about new player
- otherplayer.peer:send(player_join_packet(player))
- end
- end
+ on_player_connect(ev)
elseif ev.type == "disconnect" then
- local player, idx = player_by_peer(ev.peer)
- if not player then error("sneeze "..ev.peer) end
- print("disconnect",player.peer,player.id)
- table.remove(playerlist,idx)
- for i,otherplayer in ipairs(playerlist) do
- otherplayer.peer:send(player_leave_packet(player))
- end
+ on_player_disconnect(ev)
elseif ev.type == "receive" then
local player = player_by_peer(ev.peer)
if not player then error("sneezey "..ev.peer) end