Compare commits

...

17 Commits

Author SHA1 Message Date
Pascal Abresch a861aab18a Protocol version 002 2022-06-19 11:29:10 +02:00
Pascal Abresch b785f96431 properly use love2d gameloop 2022-02-17 13:09:19 +01:00
Pascal Abresch 74bd5be5b3 minor fix 2022-01-09 16:36:39 +01:00
Pascal Abresch 98b3b98095 move some utils to server 2022-01-09 10:46:42 +01:00
Pascal Abresch 1993e403d1 add flying 2022-01-09 10:18:36 +01:00
Diego Esaa 1ba6352ef2 Fix broken server names
Prior to this commit, some of the player's names would have 'rqcid' prefixed
to them.
2022-01-08 21:46:53 +01:00
Diego Esaa dc24f21852 add backwards compatibility for unpack() 2022-01-08 21:46:24 +01:00
Pascal Abresch 0b64538d65 Add chat support 2022-01-08 20:57:18 +01:00
Pascal Abresch 9b55a97af7 add player name 2022-01-08 17:33:50 +01:00
Pascal Abresch 80ed7a8738 replace default port 2022-01-08 12:07:07 +01:00
Pascal Abresch 2841687bbe add texture delete command 2022-01-08 12:06:53 +01:00
Pascal Abresch d71a8b9138 add drawing support (kinda slow though) 2022-01-07 23:15:16 +01:00
Pascal Abresch 6cd8162cb4 add license 2022-01-04 20:11:40 +01:00
Pascal Abresch 0f3c555149 Tell other clients about leaving clients 2022-01-04 18:54:59 +01:00
Pascal Abresch 1cbe3a1c64 remove some logging 2022-01-04 18:54:39 +01:00
Pascal Abresch 1d4e5a49aa Readme added 2022-01-04 13:26:51 +01:00
Pascal Abresch 0a72496656 Add physics ping pong 2022-01-03 18:57:00 +01:00
11 changed files with 183 additions and 64 deletions

5
License Normal file
View File

@ -0,0 +1,5 @@
Copyright (C) 2022 by Pascal R. G. Abresch <nep@packageloss.eu>
Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.

14
Readme.md Normal file
View File

@ -0,0 +1,14 @@
This is the server for [Poppy](https://git.gryphno.de/nephele/poppy-client)
If you already cloned the client there is no need to clone the server, it is included as a submodule (and the client uses some server code aswell)
# Implementation status
* Basic sessions
* Physics sync
* Drawing sync
* Chat
# Not implemented
* Sync drawing, commision textures (store their hashes, store their imagedata for clients that need it)
* Timeout clients that haven't responded to a ping for quite some time

16
chat.lua Normal file
View File

@ -0,0 +1,16 @@
local constants = require("constants")
local util = require("utils")
local rpc = require("rpc")
return function(commands)
function commands.chatMessage(clientID, args)
assert(clients[clientID])
print("Chat " .. clients[clientID].name .. ": " .. args)
for i, player in pairs(clients) do
if i ~= clientiD then
local payload = util.unit("poppyV002", clientID, "chatMessage") .. constants.US .. args
server:sendto(payload, player.ip, player.port)
end
end
end
end

1
compat.lua Normal file
View File

@ -0,0 +1 @@
table.unpack = table.unpack or unpack

24
drawing.lua Normal file
View File

@ -0,0 +1,24 @@
local constants = require("constants")
local util = require("utils")
local rpc = require("rpc")
return function(commands)
function commands.drawTexture(clientID, args)
assert(clients[clientID])
for i, player in pairs(clients) do
if i ~= clientiD then
local payload = util.unit("poppyV001", clientID, "drawTexture") .. constants.US .. args
server:sendto(payload, player.ip, player.port)
end
end
end
function commands.deleteTexture(clientID, args)
assert(clients[clientID])
for i, player in pairs(clients) do
if i ~= clientiD then
local payload = util.unit("poppyV001", clientID, "deleteTexture") .. constants.US .. args
server:sendto(payload, player.ip, player.port)
end
end
end
end

View File

@ -9,6 +9,8 @@ local v1_message = {}
require("players")(v1_message)
require("physics")(v1_message)
require("world")(v1_message)
require("drawing")(v1_message)
require("chat")(v1_message)
server = assert(socket.udp())
local ip, port = nil, nil
@ -16,57 +18,58 @@ local ip, port = nil, nil
local clientCount = 0
clients = {}
server:settimeout(nil)
assert(server:setsockname("*", 42069))
server:settimeout(0)
assert(server:setsockname("*", 11150))
if not server or not socket then error("failed to listen on socket") end
while true do
::nw_next::
--print("iteration start")
local data
local world = {
x = 256,
y = 256,
id = "NYAAA"
}
function love.update(dt)
local data, ip, port
data, ip, port = server:receivefrom()
--print("received data from " .. ip)
if not data then
local err_code = ip
print(err_code)
goto nw_next
local errorCode = ip
if errorCode == "timeout" then
return
end
print(errorCode)
return
end
local result = rpc.validate(data)
if not result.errorMsg then
--print(util.resolve(result.record))
local response = rpc.execute(v1_message, clientID, result.record)
if result.clientID == "0" then
clientCount = clientCount + 1
response = "rq" .. constants.US .. "cid" .. constants.US .. clientCount
clients[clientCount ..""] = { ip = ip, port = port }
local nickname = string.sub(result.record, 5)
local c_response = util.unit("poppyV002", "0", "init", clientCount, nickname, id, x, y)
clients[clientCount ..""] = { ip = ip, port = port, name = nickname }
server:sendto(c_response, ip, port)
print("New client connected. Granting id: [" .. clientCount .. "] IP: " .. ip .. " Port:" .. port)
for i, client in pairs(clients) do
print("Iter : ".. i .. " client is " .. client.ip .. " : " .. client.port)
if i ~= clientCount .."" then
local payload = util.unit("poppyV001", clientCount, "player", "join")
print("Introducing client[" .. i .. "] and client[" .. clientCount.."]")
-- to Existing client
local payload = util.unit("poppyV002", clientCount, "playerJoin", nickname)
print("Payload1 : " ..payload)
server:sendto(payload, client.ip, client.port)
print("Telling client " .. i .. " about " .. clientCount)
print(payload)
local payload = util.unit("poppyV001", i, "player", "join")
-- to New client
local payload = util.unit("poppyV002", i, "playerJoin", client.name)
print("Payload2 : " ..payload)
server:sendto(payload, ip, port)
print("Telling client " .. clientCount .. " about " .. i)
print(payload)
end
end
result.clientID = clientCount
end
local response = rpc.execute(v2_message, clientID, result.record)
if response then
--print("Response was: ".. response)
local payload = "poppyV001" .. constants.US .. "0" .. constants.US .. response
--print("sending response to " .. ip .. ":" .. port .. " " .. payload)
local payload = "poppyV002" .. constants.US .. "0" .. constants.US .. response
assert(server:sendto(payload, ip, port))
end
end
--print("iteration over")
end
::nw_break::

View File

@ -1,12 +1,12 @@
local constants = require("constants")
local util = require("utils")
local rpc = require("rpc")
require("compat")
return function(commands)
commands.move = {}
function commands.move.update(clientID, args)
function commands.moveUpdate(clientID, args)
if not clients[clientID] then rpc.print("moveUpdate: invalid clientid [" .. clientID .. "]") return end
local x, y, speedx, speedy = table.unpack(util.resolve(args))
if not clients[clientID] then rpc.print("move.update: invalid clientid [" .. clientID .. "]") return end
clients[clientID].x = x
clients[clientID].y = y
clients[clientID].speedx = speedx
@ -14,10 +14,35 @@ return function(commands)
for i, player in pairs(clients) do
if i ~= clientID then
local payload = util.unit("poppyV001", clientID,
"move", "update", x, y, speedx, speedy)
local payload = util.unit("poppyV002", clientID, "moveUpdate", x, y, speedx, speedy)
server:sendto(payload, player.ip, player.port)
end
end
end
function commands.moveFlying(clientID, args)
if not clients[clientID] then rpc.print("moveFlying: invalid clientid [" .. clientID .. "]") return end
for i, player in pairs(clients) do
local payload = util.unit("poppyV002", clientID, "moveFlying", args)
server:sendto(payload, player.ip, player.port)
end
end
function commands.deletePhysics(clientID, args)
if not clients[clientID] then rpc.print("deletePhysics: invalid clientid [" .. clientID .. "]") return end
for i, player in pairs(clients) do
local payload = util.unit("poppyV002", clientID, "deletePhysics") .. constants.US .. args
server:sendto(payload, player.ip, player.port)
end
end
function commands.drawPhysics(clientID, args)
if not clients[clientID] then rpc.print("drawPhysics: invalid clientid [" .. clientID .. "]") return end
for i, player in pairs(clients) do
local payload = util.unit("poppyV002", clientID, "drawPhysics") .. constants.US .. args
server:sendto(payload, player.ip, player.port)
end
end
end

View File

@ -1,6 +1,12 @@
return function(commands)
commands.rq = commands.rq or {}
local util = require("utils")
function commands.rq.cid() return "granted" end
return function(commands)
function commands.playerLeave(clientID)
clients[clientID] = nil
for i, player in pairs(clients) do
local payload = util.unit("poppyV001", clientID,
"player", "leave")
server:sendto(payload, player.ip, player.port)
end
end
end

26
rpc.lua
View File

@ -1,5 +1,5 @@
local rpc = {
PROTOCOL_VERSION = "001"
PROTOCOL_VERSION = "002"
}
function rpc.clean(record)
@ -23,7 +23,7 @@ function rpc.validate(record)
record = nil
end
rpc.print("record is now ".. record)
clientID, count = record:match("^%d-\31")
clientID = rpc.clean(clientID)
if not clientID then
@ -53,24 +53,22 @@ function rpc.execute(commands, clientID, record)
local command = record:match("^.-\31")
if command then command = rpc.clean(command) end
record = record:gsub("^.-\31","")
--if not command then error("Failed to match a command?") end
if type(commands[command]) == "table" then
rpc.print(">" .. command)
return rpc.execute(commands[command], clientID, record)
else
if type(commands[command]) == "function" then
if not command then
command = record
record = nil
end
if type(commands[command]) == "function" then
if record then
rpc.print("executing " .. command .. " with " .. record)
return commands[command](clientID, record)
else
if type(commands[record] == "function") then
rpc.print("executing no arguments:" .. record)
return commands[record](clientID)
else
error("How did we get here? ... type is :" .. type(commands[command]))
end
rpc.print("executing no arguments:" .. command)
return commands[command](clientID)
end
end
end
return rpc

View File

@ -18,4 +18,42 @@ function tempTable.resolve(record)
return tTable
end
function tempTable.clean(record)
assert(type(record) == "string")
return record:gsub("\31", "")
end
function tempTable.pprint(record)
local cleaned, _ = record:gsub("\31","|")
print(cleaned)
end
function tempTable.nextIntRecord(record)
local nextR = tempTable.clean(record:match("^.-\31"))
record = record:gsub("^.-\31","")
return tonumber(nextR), record
end
function tempTable.nextStringRecord(record)
local nextR = tempTable.clean(record:match("^.-\31"))
record = record:gsub("^.-\31","")
return nextR, record
end
function tempTable.getIntRecords(number, record)
local tTable = {}
local nextR
for i = 1, number -1 do
nextR, record = tempTable.nextIntRecord(record)
table.insert(tTable, nextR)
end
local last = tempTable.clean(record:gsub("^.-\31",""))
print("Tonumbering " .. last)
table.insert(tTable, tonumber(last))
return unpack(tTable)
end
return tempTable

View File

@ -1,11 +0,0 @@
local world = {
x = 3000,
y = 3000,
id = "NYAAA"
}
return function(commands)
commands.rq = commands.rq or {}
function commands.rq.wid() return "12" end
end