1
0
dodge-bolt/src/systems/multiplayer.lua

152 lines
3.7 KiB
Lua

local Multiplayer = {}
local binser = require("lib.binser")
local pprint = require("lib.pprint")
local uid = require("helpers.uid")
local RATE_LIMIT = 20
local CMD = {
SPAWN_PLAYER = 1,
MOVE_PLAYER = 2,
AIM_PLAYER = 3,
PLAYER_SHOT = 4,
}
local function removeValue(t, v)
for i, vv in ipairs(t) do
if v == vv then
table.remove(t, i)
end
end
end
function Multiplayer:init()
self.connected_peers = {}
local host_socket = self.pool.data.host_socket
for i=1, host_socket:peer_count() do
local peer = host_socket:get_peer(i)
if peer:state() == "connected" then
self:onPeerConnect(peer)
end
end
end
function Multiplayer:onPeerConnect(peer)
table.insert(self.connected_peers, peer:index())
end
function Multiplayer:onPeerDisconnect(peer)
local peer_index = peer:index()
removeValue(self.connected_peers, peer_index)
for _, player in ipairs(self.pool.groups.player.entities) do
if player.peer_index == peer_index then
self.pool:removeEntity(player)
end
end
end
function Multiplayer:disconnectPeers()
local host_socket = self.pool.data.host_socket
for _, index in ipairs(self.connected_peers) do
local peer = host_socket:get_peer(index)
peer:disconnect_now()
self:onPeerDisconnect(peer)
end
host_socket:flush()
end
function Multiplayer:sendToPeer(peer, ...)
peer:send(binser.serialize(...), nil, "unreliable")
end
function Multiplayer:sendToAllPeers(...)
local payload = binser.serialize(...)
local host_socket = self.pool.data.host_socket
for _, index in ipairs(self.connected_peers) do
local peer = host_socket:get_peer(index)
peer:send(payload, nil, "unreliable")
end
end
function Multiplayer:update()
local host_socket = self.pool.data.host_socket
local event = host_socket:service()
if event then
if event.type == "connect" then
self:onPeerConnect(event.peer)
elseif event.type == "disconnect" then
self:onPeerDisconnect(event.peer)
elseif event.type == "receive" then
local parameters = binser.deserialize(event.data)
self:handlePeerMessage(event.peer, unpack(parameters))
end
end
end
function Multiplayer:getPlayerEntityById(id)
for _, player in ipairs(self.pool.groups.player.entities) do
if player.id == id then
return player
end
end
end
function Multiplayer:handlePeerMessage(peer, cmd, ...)
if cmd == CMD.SPAWN_PLAYER then
local id = ...
local PlayerSystem = self.pool:getSystem(require("systems.player"))
local player = PlayerSystem:spawnPlayer()
player.id = id
player.peer_index = peer:index()
elseif cmd == CMD.MOVE_PLAYER then
local id, move_dir, pos = ...
local player = self:getPlayerEntityById(id)
if player and player.peer_index == peer:index() then
player.move_dir = move_dir
player.pos = pos
end
elseif cmd == CMD.AIM_PLAYER then
local id, aim_dir = ...
local player = self:getPlayerEntityById(id)
if player and player.peer_index == peer:index() then
player.aim_dir = aim_dir
end
elseif cmd == CMD.PLAYER_SHOT then
local id = ...
local player = self:getPlayerEntityById(id)
if player and player.peer_index == peer:index() then
self.pool:emit("tryShootingBolt", player)
end
else
print("DEBUG INFORMATION:")
print("Message:")
pprint{cmd, ...}
error("Unhandled message from peer")
end
end
function Multiplayer:addToGroup(group, player)
if group == "player" and not player.peer_index then
player.id = uid()
self:sendToAllPeers(CMD.SPAWN_PLAYER, player.id)
self.pool:queue(player)
end
end
function Multiplayer:playerMoved(player)
self:sendToAllPeers(CMD.MOVE_PLAYER, player.id, player.move_dir, player.pos)
end
function Multiplayer:playerAimed(player)
self:sendToAllPeers(CMD.AIM_PLAYER, player.id, player.aim_dir)
end
function Multiplayer:playerShot(player)
self:sendToAllPeers(CMD.PLAYER_SHOT, player.id)
end
return Multiplayer