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 local the_tiles = {} local ng = noise.NoiseAgg.make_perlin_octaves(4) for q = 1,chunk.SIZE-1 do for r = 1,chunk.SIZE-1 do local p = coords.Hex.make(q,r):to_pos() local nv = ng:at(p.x/20,p.y/20) assert(nv ~= 1,"oopsy") the_tiles[chunk.index(q,r)] = nv > 0 and 1+math.floor(math.sqrt(nv)*8) or false 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