local enet = require"enet" local json = require"common.dkjson" local chunk = require"common.chunk" local Chunk = require"common.chunk".Chunk local noise = require"noise" local unpack = unpack or table.unpack local coords = require"common.coords" math.randomseed(os.time()) local host = enet.host_create("*:8473") 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 local function player_by_id(id) for i,pl in ipairs(playerlist) do if pl.id == id then return pl, i end end return nil end local function player_by_peer(peer) for i,pl in ipairs(playerlist) do if pl.peer == peer then return pl, i end end return nil end 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} nextid = nextid + 1 return p end local function player_info_part(player) return { id=player.id, x=player.pos[1], y=player.pos[2], color=player.color, } end local function player_join_packet(player) return json.encode{t="join",pl=player_info_part(player)} end local function player_you_packet(player) return json.encode{t="you",pl=player_info_part(player)} end local function player_leave_packet(player) return json.encode{t="leave",id=player.id} end local function player_move_packet(player,x,y) return json.encode{t="move",id=player.id,x=x,y=y} end -- worldgen local the_tiles = {} 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 ng2 = noise.NoiseAgg:make{p(1,20),p(0.5,15)} for q = 0,chunk.SIZE-1 do for r = 0,chunk.SIZE-1 do local p = coords.Hex:make(q,r):to_pos() local ix = chunk.index(q,r) local nv = ng:at(p.x,p.y) if nv <= 0 then the_tiles[ix] = false else local nv2 = ng2:at(p.x,p.y) nv2 = math.max(-0.9999999,math.min(0.9999999,nv2*2.5)) nv2 = (nv2+1)/2 print(nv2) local tv = 1+math.floor(nv2*8) assert(1<=tv and tv<=8,"oopsy woopsy") the_tiles[ix] = tv end end end local the_chunk = Chunk:make(the_tiles) print"generated chunk" while true do local ev = host:service(100) if ev then 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)) player.peer:send(the_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 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 elseif ev.type == "receive" then local player = player_by_peer(ev.peer) if not player then error("sneezey "..ev.peer) end local j = json.decode(ev.data) local op = j.t if op == "ppos" then local x,y = j.x,j.y player.pos[1] = x player.pos[2] = y -- print(player.id,"-->",player.pos[1],player.pos[2]) for i,otherplayer in ipairs(playerlist) do if otherplayer ~= player then otherplayer.peer:send(player_move_packet(player,x,y)) end end elseif op == "settile" then local h = coords.Hex:make(j.q,j.r) the_chunk:set_at(h,j.tile) -- print(player.id,"settile",h,j.tile) for i,otherplayer in ipairs(playerlist) do if otherplayer ~= player then -- same packet structure s2c as c2s -- when multiple chunks exist and players only get info -- about stuff near to them, that won't be the case any more otherplayer.peer:send(ev.data) end end end end -- for k,v in pairs(ev) do io.write(tostring(k),":",tostring(v)," ") end -- print() end end