diff options
| author | ubq323 <ubq323@ubq323.website> | 2025-06-08 13:21:15 +0100 | 
|---|---|---|
| committer | ubq323 <ubq323@ubq323.website> | 2025-06-08 13:21:15 +0100 | 
| commit | 22d767b3e10959cd1545b5b1986bfbc44ff41491 (patch) | |
| tree | 1978cb31315917dbf85b96a9dad4e90eb9dba8fa | |
| parent | 36df301ce86d7689de0b20735feffee969927e47 (diff) | |
lots of various things
| -rw-r--r-- | .gitignore | 2 | ||||
| l--------- | client/common.lua | 2 | ||||
| -rw-r--r-- | client/main.lua | 46 | ||||
| -rw-r--r-- | common.lua | 17 | ||||
| -rw-r--r-- | server/server.lua | 19 | 
5 files changed, 63 insertions, 23 deletions
diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..55a4677 --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +chunk*.json +.env diff --git a/client/common.lua b/client/common.lua index 1b8b461..a79312a 120000 --- a/client/common.lua +++ b/client/common.lua @@ -1 +1 @@ -common.lua
\ No newline at end of file +../common.lua
\ No newline at end of file diff --git a/client/main.lua b/client/main.lua index 089bc08..2a30aa2 100644 --- a/client/main.lua +++ b/client/main.lua @@ -6,6 +6,7 @@ local class = require'r.class'  local enet = require'enet'  local pprint = require'pprint'  local json = require'dkjson' +local rle = require'r.rle'  local SPEED = 8 -- tiles per second  local colors = {[true]={141/255,128/255,22/255}, [false]={71/255,50/255,122/255}} @@ -16,32 +17,39 @@ local conn = host:connect('localhost:19683')  local players = {}  local chunks = common.ChunkMap()  local lp = { pos=Pos(0,0), movetimer=0, dir=nil } -- local player +local cam = Camera(nil, 20)  local directions = {w=Pos(0,-1),a=Pos(-1,0),s=Pos(0,1),d=Pos(1,0)} -function love.keypressed(k,s,r) if directions[s] then lp.dir=s end end +function love.keypressed(k,s,r) +	if directions[s] then +		if not love.keyboard.isScancodeDown('lshift') then lp.dir = s +		else local tgt = lp.pos + directions[s] +			local val = not chunks:tile(tgt); chunks:set_tile(tgt,val) +			conn:send(json.encode{type='tile',pos=tgt,tile=val}) end +	elseif s=='space' then cam.zoom = cam.zoom == 10 and 20 or 10 end end  function love.keyreleased(k,s)  if s==lp.dir then lp.dir=nil end end  function lp.update(dt)  	lp.movetimer = lp.movetimer - dt  	if lp.movetimer <= 0 and lp.dir then  		local d = directions[lp.dir] local newpos = lp.pos+d  		if chunks:tile(newpos) == false then -			lp.pos = newpos -			conn:send(json.encode{type='move',x=newpos.x,y=newpos.y}) -			lp.movetimer = 1 / SPEED  end end end +			conn:send(json.encode{type='move',pos=newpos}) +			lp.pos = newpos  lp.movetimer = 1 / SPEED  end end end  local function draw_player(p, c) G.setColor(c) G.circle('fill',p.x,p.y,0.3) end  function lp.draw() draw_player(lp.pos, {0,1,0}) end -local cam = Camera(nil, 64)  function love.update(dt)  	lp.update(dt)  	local ev = host:service()  while ev do  		-- pprint(ev)  		if ev.type == 'receive' then local j = json.decode(ev.data) -				if j.type == 'player' 	then players[j.name] = {name=j.name,pos=Pos(j.x,j.y)} +			local pos  if j.pos then pos = Pos(j.pos.x,j.pos.y) end +				if j.type == 'player' 	then players[j.name] = {name=j.name,pos=pos}  			elseif j.type == 'unplayer' then players[j.from] = nil -			elseif j.type == 'move' 	then players[j.from].pos = Pos(j.x,j.y) -			elseif j.type == 'chunk'	then chunks:add(Pos(j.x,j.y),j.d) -			elseif j.type == 'unchunk'	then chunks:remove(Pos(j.x,j.y)) +			elseif j.type == 'move' 	then players[j.from].pos = pos +			elseif j.type == 'chunk'	then chunks:add(pos,{d=rle.decode(j.d)}) +			elseif j.type == 'unchunk'	then chunks:remove(pos) +			elseif j.type == 'tile'		then chunks:set_tile(pos,j.tile)  			end  		end  		ev = host:service() @@ -50,8 +58,24 @@ end  function love.draw()  	G.clear(1,1,1); G.origin()  	cam.pos = lp.pos; cam:apply_trans() -	-- if chunk then for x=0,63 do for y=0,63 do -	-- 	G.setColor(colors[chunk[1+x*64+y]]) G.rectangle('fill',x-0.5,y-0.5,1,1) end end end + +	local tl,br = cam:extents() +	tl = tl:floor()  br = br:ceil() +	for x=tl.x,br.x do for y=tl.y,br.y do +		local t = chunks:tile(Pos(x,y)) +		if t ~= nil then G.setColor(colors[t~=(x<0)]) G.rectangle('fill',x-0.5,y-0.5,1,1) end end end  	lp.draw()  	for _,player in pairs(players) do draw_player(player.pos,{0,1,1}) end +	G.origin() G.setColor(1,0,0) +	G.print(tostring(lp.pos),100,100) +	G.setColor(0,0,0,0.8) +	G.rectangle('fill',0,0,100,100) +	G.setColor(1,1,1) +	for cx=-7,7 do for cy=-7,7 do local p=Pos(cx,cy) if chunks:get(p) then +		p = (p + Pos(7,7))*10 +		G.setColor(1,1,1) G.rectangle('fill',p.x,p.y,10,10) +		G.setColor(0,0,1) G.rectangle('line',p.x,p.y,10,10) +		end end end +	local p = (lp.pos/common.SIZE+Pos(7,7))*10 +	G.setColor(1,0,0) G.rectangle('fill',p.x-1,p.y-1,2,2)  end @@ -1,17 +1,22 @@  local class = require 'r.class' +local pprint = require 'pprint' +local Pos = require 'r.pos'  local SIZE = 64  local ChunkMap = class()  function ChunkMap.make(cls) return setmetatable({d={}},cls) end -local function key(pos) return pos.x .. ':' .. pos.y end -function ChunkMap.add(self,pos,val) self.d[key(pos)] = val end -function ChunkMap.remove(self,pos) self:add(pos,nil) end -function ChunkMap.get(self,pos) return self.d[key(pos)] end +function ChunkMap.add(self,pos,val) self.d[pos:key()] = val end +function ChunkMap.remove(self,pos) self.d[pos:key()] = nil end +function ChunkMap.get(self,pos) return self.d[pos:key()] end  local function idx(pos) return 1+pos.x*SIZE+pos.y end  function ChunkMap.tile(self,pos) -	local cp = (pos/SIZE):floor() local ix = idx(pos-cp*SIZE) -	return self:get(cp)[ix] end +	local cp,mod = pos:divmod(SIZE) local ch = self:get(cp) +	return ch and ch.d[idx(mod)] end +function ChunkMap.set_tile(self,pos,val) +	local cp,mod = pos:divmod(SIZE) local ch = self:get(cp) +	if ch then ch.d[idx(mod)] = val end end  return {  	ChunkMap = ChunkMap, +	SIZE = SIZE,  } diff --git a/server/server.lua b/server/server.lua index d441989..a53d9a1 100644 --- a/server/server.lua +++ b/server/server.lua @@ -5,18 +5,26 @@ local Pos = require'r.pos'  local pairs_except = require'r.pairs_except'  local class = require'r.class'  local rle = require'r.rle' +local noise = require'r.noise'  local common = require 'common' +local SIZE = common.SIZE  local host = enet.host_create('*:19683')  local n = 0 local function next_name() n=n+1  return 'helen'..n end +local function P(amp,scale,seed) +	return {scale=scale,amp=amp,gen=noise.PerlinNoise(seed)} end +local noise_gen = noise.NoiseAgg{ P(0.5,17,3), P(1,10,1), P(0.4,6,2) } +  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 +	local d={} for x=0,SIZE-1 do for y=0,SIZE-1 do +		local nv = noise_gen:at(x,y) local fill = nv>0.06 +		if math.random(3) == 2 then fill = not fill end +		d[1+x*SIZE+y] = (cp.x<0) ~= fill end end  	return cls(cp,d) end  function Chunk.packet(self)  	return json.encode{ pos=self.cp, d=rle.encode(self.d), type='chunk' } end @@ -25,6 +33,7 @@ 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') +	print('saving',self.cp)  	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 @@ -51,7 +60,7 @@ local function greet(player)  local function doctor_chunks()  	for player in pairs(players) do -		local pcp = player.pos:divmod(common.SIZE) +		local pcp = player.pos:divmod(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) @@ -64,7 +73,7 @@ local function doctor_chunks()  	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 +		if not used then chunk:save() chunks:remove(cp) end end end  while true do  	local ev = host:service(100)  if ev then @@ -80,7 +89,7 @@ while true do  		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) +			elseif j.type == 'tile' then chunks:set_tile(pos,j.tile) send_others(player,j)  			end  		end  	end  | 
