summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorubq323 <ubq323@ubq323.website>2025-06-05 16:07:47 +0100
committerubq323 <ubq323@ubq323.website>2025-06-05 16:07:47 +0100
commit36df301ce86d7689de0b20735feffee969927e47 (patch)
treed61b6943ee5a9de497c0b6e9c713d2119fadf866
parentded2684211826c9585b1c6d9c1036e233b65fd86 (diff)
things
-rw-r--r--client/conf.lua1
l---------server/common.lua1
-rw-r--r--server/server.lua91
3 files changed, 64 insertions, 29 deletions
diff --git a/client/conf.lua b/client/conf.lua
new file mode 100644
index 0000000..faccea9
--- /dev/null
+++ b/client/conf.lua
@@ -0,0 +1 @@
+function love.conf(t) t.window.msaa=8 end
diff --git a/server/common.lua b/server/common.lua
new file mode 120000
index 0000000..a79312a
--- /dev/null
+++ b/server/common.lua
@@ -0,0 +1 @@
+../common.lua \ No newline at end of file
diff --git a/server/server.lua b/server/server.lua
index fa7f82f..d441989 100644
--- a/server/server.lua
+++ b/server/server.lua
@@ -4,52 +4,85 @@ local json = require'dkjson'
local Pos = require'r.pos'
local pairs_except = require'r.pairs_except'
local class = require'r.class'
+local rle = require'r.rle'
+local common = require 'common'
local host = enet.host_create('*:19683')
+local n = 0 local function next_name() n=n+1 return 'helen'..n end
-local n = 0
-local function next_name() n=n+1 return 'helen'..n end
+local chunks = common.ChunkMap()
+local Chunk = class()
+function Chunk.make(cls, cp, d) local self = setmetatable({cp=cp,d=d},cls)
+ chunks:add(cp,self) return self end
+function Chunk.generate(cls,cp)
+ print('\t','generating',cp)
+ local d={} for i=1,common.SIZE^2 do d[i] = 1 == math.random(3) end
+ return cls(cp,d) end
+function Chunk.packet(self)
+ return json.encode{ pos=self.cp, d=rle.encode(self.d), type='chunk' } end
+local function filename(cp) return 'chunk'..cp:key()..'.json' end
+function Chunk.load(cls, cp) local f = io.open(filename(cp),'r')
+ if not f then return nil end local j = json.decode(assert(f:read"a"))
+ f:close() return cls(cp,rle.decode(j.d)) end
+function Chunk.save(self) local f = io.open(filename(self.cp),'w')
+ assert(f:write(json.encode{d=rle.encode(self.d)})) f:close() end
+function Chunk.obtain(cls,cp)
+ if chunks:get(cp) then return chunks:get(cp) end
+ local ch = cls:load(cp) if ch then return ch end
+ return cls:generate(cp) end
local Player = class()
function Player.make(cls, obj) return setmetatable(obj,cls) end
-function Player.packet(self,packet_type) return json.encode {
- name=self.name, x=self.pos.x, y=self.pos.y, type=packet_type } end
-
-local size = 64
-local chunk = {}
-for i=1,size*size do chunk[i] = 1 == math.random(3) end
-function chunk.packet(self,packet_type)
- local r = {type=packet_type,d={}} for i,t in ipairs(self) do r.d[i]=t end
- return json.encode(r) end
-
+function Player.packet(self,packet_type)
+ return json.encode { name=self.name, pos=self.pos, type=packet_type } end
local players = {}
local function find_player(arg) local k,v = next(arg)
for pl in pairs(players) do if pl[k] == v then return pl end end end
local function other_players(player) return pairs_except(players, player) end
-
local function send_others(player,data)
data.from = player.name local packet = json.encode(data)
for player2 in other_players(player) do player2.peer:send(packet) end end
local function greet(player)
+ print('greeting',player.name,player.peer)
for player2 in other_players(player) do
player.peer:send(player2:packet'player')
- player2.peer:send(player:packet'player') end
- player.peer:send(chunk:packet'chunk') end
+ player2.peer:send(player:packet'player') end end
+
+local function doctor_chunks()
+ for player in pairs(players) do
+ local pcp = player.pos:divmod(common.SIZE)
+ for dx = -1,1 do for dy = -1,1 do local cp = pcp+Pos(dx,dy)
+ if not player.loaded[cp:key()] then
+ local chunk = Chunk:obtain(cp)
+ player.peer:send(chunk:packet())
+ player.loaded[cp:key()] = true end end end
+ for lcpk in pairs(player.loaded) do local lcp = Pos:unkey(lcpk)
+ if (lcp-pcp):linf() > 2 then
+ player.peer:send(json.encode{type='unchunk',pos=lcp})
+ player.loaded[lcp:key()] = nil end end end
+ for k,chunk in pairs(chunks.d) do local cp = Pos:unkey(k)
+ local used = false
+ for player in pairs(players) do if player.loaded[k] then used=true end end
+ if not used then print('unloading',cp) chunk:save() chunks:remove(cp) end end end
-while true do local ev = host:service(100) if ev then
- local peer = ev.peer local player = find_player{peer=peer}
- if ev.type=='connect' then
- print('connecting',peer)
- local player = Player{pos=Pos(0,0), peer=peer, name=next_name()}
- players[player] = true; greet(player)
- elseif ev.type=='disconnect' then
- print('disconnecting',peer)
- send_others(player, {type='unplayer'})
- players[player] = nil
- else local j = json.decode(ev.data)
- -- todo handle json error
- if j.type == 'move' then player.pos=Pos(j.x,j.y) send_others(player, j)
+while true do
+ local ev = host:service(100) if ev then
+ local peer = ev.peer local player = find_player{peer=peer}
+ if ev.type=='connect' then
+ print('connecting',peer)
+ local player = Player{pos=Pos(0,0), peer=peer, name=next_name(), loaded={}}
+ players[player] = true; greet(player)
+ elseif ev.type=='disconnect' then
+ print('disconnecting',peer)
+ send_others(player, {type='unplayer'})
+ players[player] = nil
+ elseif ev.type=='receive' then local j = json.decode(ev.data)
+ local pos if j.pos then pos = Pos(j.pos.x,j.pos.y) end
+ if j.type == 'move' then player.pos=pos send_others(player, j)
+ elseif j.type == 'tile' then print('tile',pos,j.tile) chunks:set_tile(pos,j.tile) send_others(player,j)
+ end
end
end
-end end
+ doctor_chunks()
+end