1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
|
local enet = require"enet"
local json = require"common.dkjson"
local Chunk = require"common.chunk".Chunk
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_chunk = Chunk.gen()
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
|