Compare commits

...

2 Commits

Author SHA1 Message Date
Pascal Abresch dc5397331b add avatar syncing 2022-07-03 20:00:30 +02:00
Pascal Abresch a195005f91 update readme 2022-07-03 19:59:52 +02:00
5 changed files with 78 additions and 29 deletions

View File

@ -2,7 +2,6 @@
This is the Poppy game\ This is the Poppy game\
A server is required to play the game, if you do not have one running then\ A server is required to play the game, if you do not have one running then\
run ```love .``` in the ```server/``` directory for a local one for now.\ run ```love .``` in the ```server/``` directory for a local one for now.\
(per default the client will connect to this server, it is currently a hardcoded constant in lua/networkThread.lua :/ )\
The performance is currently not so great on older computers,\ The performance is currently not so great on older computers,\
@ -15,7 +14,7 @@ I have not investigated this much yet. Safe to say it is not intended to run so
* Loading textures * Loading textures
* drawing on canvases * drawing on canvases
* physics calculation for collison and movement * physics calculation for collison and movement
* drawing physics collisions (on the physics layer) * drawing physics collisions (on the physics layer) (debug)
* Basic networking * Basic networking
* Get clientID * Get clientID
* Draw all players * Draw all players
@ -25,17 +24,28 @@ I have not investigated this much yet. Safe to say it is not intended to run so
* Send disconnect on client error * Send disconnect on client error
* Chat support * Chat support
* Retrieve initial game state (partial)
* Get users name
* Get users avatar
* Get world size
* Drawing * Drawing
* Draw with custom color * Draw with custom color
* Re-do base textures as gray scale to color in arbitrarily * Re-do base textures as gray scale to color in arbitrarily
* UI
* UI to connect to specific server
* Reconnect to server
* connect to other server during a session
## Not implemented (rough goals anyhow) ## Not implemented (rough goals anyhow)
* UI to connect to specific server * Remember visited servers (save the list)
* Reconnect to server * Add new servers to the list by user input
* connect to other server during a session * Add new servers at runtime via DNS-SD mDNS discovery
* Open second window? Open second instance instead? (does love2d allow that?)
* Saving the game (server stuff?) * Saving the map
* Loading the game/map (server stuff?) * Loading the map from disk (and send it to the server)
* Loading the map from server on connect
* confirmation before clearing canvas (that's quite destructive :D) * confirmation before clearing canvas (that's quite destructive :D)
* Make a way to add dialogs and stuff * Make a way to add dialogs and stuff
@ -72,7 +82,9 @@ I have not investigated this much yet. Safe to say it is not intended to run so
* Networking support * Networking support
* Figure out why and how physics is tied to framerate, why does jump height differ? * Figure out why and how physics is tied to framerate, why does jump height differ?
* Implement initial state sync (mainly server work) * Implement initial state sync
* Server remembers plays last position and tells you
* Server remembers drawn stuff and tells you
* Add ack que, resend lost packets (but only for stuff like drawing and such, movement may drop) * Add ack que, resend lost packets (but only for stuff like drawing and such, movement may drop)
* Tell the user if the server doesn't support the networking version requested * Tell the user if the server doesn't support the networking version requested

View File

@ -1,11 +1,13 @@
gameloop = {} gameloop = {}
gameloop.world = nil gameloop.world = nil
gameloop.textures = {} gameloop.textures = {}
gameloop.avatars = {}
local rpc = require("server.rpc") local rpc = require("server.rpc")
local v2_message = require("lua.network") local v2_message = require("lua.network")
local socket = require "socket" local socket = require "socket"
local util = require("server.utils") local util = require("server.utils")
local function normalDraw() local function normalDraw()
local layerTransform = love.math.newTransform(math.floor(view.x) * scale, math.floor(view.y) * scale, 0, scale, scale) local layerTransform = love.math.newTransform(math.floor(view.x) * scale, math.floor(view.y) * scale, 0, scale, scale)
@ -63,14 +65,14 @@ end
local function normalNetworkSend(args) local function normalNetworkSend(args)
if clientID == "0" then print("Invalid clientID?") end if clientID == "0" then print("Invalid clientID?") end
local request = "poppyV002" ..US.. clientID ..US.. args local request = "poppyV003" ..US.. clientID ..US.. args
gameloop.client:send(request) gameloop.client:send(request)
end end
local function debugNetworkSend(args) local function debugNetworkSend(args)
assert(clientID ~= 0) assert(clientID ~= 0)
local request = "poppyV002" ..US.. clientID ..US.. args local request = "poppyV003" ..US.. clientID ..US.. args
print("=> " .. util.pprint(request)) print("=> " .. util.pprint(request))
gameloop.client:send(request) gameloop.client:send(request)
end end
@ -129,7 +131,7 @@ function errorhandler(msg)
if love.filesystem.getInfo("fonts/font.ttf") then if love.filesystem.getInfo("fonts/font.ttf") then
errorfont = love.graphics.newFont("fonts/font.ttf", 45) errorfont = love.graphics.newFont("fonts/font.ttf", 45)
else else
errorfont = love.graphics.getFont(45) errorfont = love.graphics.newFont(45)
end end
love.graphics.reset() love.graphics.reset()
love.graphics.origin() love.graphics.origin()
@ -139,14 +141,16 @@ function errorhandler(msg)
local message2 = love.graphics.newText(errorfont, "Press q to exit") local message2 = love.graphics.newText(errorfont, "Press q to exit")
local message3 = love.graphics.newText(errorfont, msg) local message3 = love.graphics.newText(errorfont, msg)
love.graphics.draw(message, 40, 40, 0, 1, 1) love.graphics.draw(message, 40, 40, 0, 1, 1)
love.graphics.draw(message2, 40, 95, 0, 1, 1) love.graphics.draw(message2, 40, 90, 0, 1, 1)
love.graphics.draw(message3, 40, 145, 0, 1, 1) love.graphics.draw(message3, 40, 140, 0, 1, 1)
print(msg)
local indent = 0 local indent = 0
local messageline local messageline
for line in debug.traceback():gmatch("([^\n]*)\n?") do for line in debug.traceback():gmatch("([^\n]*)\n?") do
print(line)
messageline = love.graphics.newText(errorfont, line) messageline = love.graphics.newText(errorfont, line)
love.graphics.draw(messageline, 40, 255 + indent, 0, 1, 1) love.graphics.draw(messageline, 40, 250 + indent, 0, 1, 1)
indent = indent + 55 indent = indent + 50
end end
love.graphics.present() love.graphics.present()
return function() return function()
@ -169,10 +173,33 @@ function gameloop.mousepressed(mousex, mousey)
end end
function gameloop.init(server, nickname) function gameloop.loadAvatars()
local container = {}
local entries = love.filesystem.getDirectoryItems("textures/player")
if #entries == 0 then return error("no avatars found") end
for i, file in pairs(entries) do
local path = "textures/player" .."/".. file
local entry = love.filesystem.getInfo(path)
if entry.type == "directory" then
local textures = love.filesystem.getDirectoryItems(path)
for i, texture in pairs(textures) do
print(path)
local imageData = love.image.newImageData(path .. "/" .. texture)
local image = love.graphics.newImage(path .. "/" .. texture)
local imageHash = love.data.hash("sha512", imageData:getString())
container[imageHash] = {data = imageData, image = image}
end
end
end
gameloop.avatars = container
end
function gameloop.init(server, nickname, avatarHash)
love.errorhandler = errorhandler love.errorhandler = errorhandler
assert(server, "Gameloop called without server to connect to?") assert(server, "Gameloop called without server to connect to?")
assert(nickname, "Gameloop called without nickname?") assert(nickname, "Gameloop called without nickname?")
assert(avatarHash, "Gameloop called without avatar?")
gameloop.server = server gameloop.server = server
scale = 1 scale = 1
@ -196,6 +223,9 @@ function gameloop.init(server, nickname)
view.y = 0 view.y = 0
clientID = "0" clientID = "0"
-- Must be done now because it has to be ready before "init" returns from the server
-- which is /before/ the game world is loaded
gameloop.loadAvatars()
gameloop.client = socket.udp() gameloop.client = socket.udp()
gameloop.client:setpeername(server.adress, server.port) gameloop.client:setpeername(server.adress, server.port)
@ -204,7 +234,7 @@ function gameloop.init(server, nickname)
print("Socketnname: " .. gameloop.client:getsockname()) print("Socketnname: " .. gameloop.client:getsockname())
print("Connecting to [" .. server.adress .."]:" .. server.port) print("Connecting to [" .. server.adress .."]:" .. server.port)
local request = "poppyV002" ..US.. "0" ..US.. unit("init", nickname) local request = "poppyV003" ..US.. "0" ..US.. unit("init", nickname, love.data.encode("string", "base64", avatarHash))
gameloop.client:send(request) gameloop.client:send(request)
if NETWORK_DEBUG then print("=> " .. util.pprint(request)) end if NETWORK_DEBUG then print("=> " .. util.pprint(request)) end

View File

@ -51,7 +51,9 @@ function menu.mousepressed(mousex, mousey)
local fullName = names[love.math.random(1, #names)] .. " " .. lastNames[love.math.random(1, #lastNames)] local fullName = names[love.math.random(1, #names)] .. " " .. lastNames[love.math.random(1, #lastNames)]
local serverID = v.identifier local serverID = v.identifier
local serverEntry = menu.serverlist[serverID] local serverEntry = menu.serverlist[serverID]
gameloop.init({ adress = serverEntry.host, port = serverEntry.port }, fullName) local avatar = love.image.newImageData("textures/player/nephele/dog.png")
local avatarHash = love.data.hash("sha512", avatar:getString())
gameloop.init({ adress = serverEntry.host, port = serverEntry.port }, fullName, avatarHash)
uiState = {} uiState = {}
end end
end end

View File

@ -2,19 +2,20 @@ local player = require("lua.player")
local util = require("server.utils") local util = require("server.utils")
local v2_message = {} local v2_message = {}
v2_message.init = function(clientID, args) v2_message.init = function(clientID, args)
local nickname, args = util.nextStringRecord(args) local nickname, args = util.nextStringRecord(args)
local avatarEncoded, args = util.nextStringRecord(args)
local worldID, args = util.nextStringRecord(args) local worldID, args = util.nextStringRecord(args)
local x, args = util.nextIntRecord(args) local x, args = util.nextIntRecord(args)
local y = tonumber(args) local y = tonumber(args)
local avatar = love.data.decode("string", "base64", avatarEncoded)
print("Connected as " .. clientID .. " with name " .. nickname) print("Connected as " .. clientID .. " with name " .. nickname)
print("New world is " .. worldID .. " Size is [" .. x .. "|" .. y .. "]") print("New world is " .. worldID .. " Size is [" .. x .. "|" .. y .. "]")
players[clientID] = player.newPlayer() players[clientID] = player.newPlayer({name = nickname, avatar = gameloop.avatars[avatar].image})
camera.target = clientID camera.target = clientID
_G.clientID = clientID _G.clientID = clientID
players[clientID].name = nickname
local world = { id = worldID, x = x, y = y } local world = { id = worldID, x = x, y = y }
gameloop.loadworld(world) gameloop.loadworld(world)
end end
@ -25,11 +26,12 @@ v2_message.ping = function(clientID)
end end
v2_message.playerJoin = function(clientID, name) v2_message.playerJoin = function(clientID, args)
ui.addChatEntry("", name .. " Joined the game") local nickname, avatarEncoded = util.nextStringRecord(args)
players[clientID] = player.newPlayer() avatar = love.data.decode("string", "base64", avatarEncoded)
players[clientID].label = love.graphics.newText(ui.smallFont, name) ui.addChatEntry("", nickname .. " Joined the game")
players[clientID].name = name players[clientID] = player.newPlayer({name = nickname, avatar = gameloop.avatars[avatar].image})
players[clientID].label = love.graphics.newText(ui.smallFont, nickname)
end end

View File

@ -1,7 +1,10 @@
local playerfuncs = {} local playerfuncs = {}
playerfuncs.newPlayer = function(arg) playerfuncs.newPlayer = function(arg)
assert(arg.avatar)
assert(arg.name)
local playerTable = {} local playerTable = {}
playerTable.avatar = love.graphics.newImage("textures/player/andysphinx/personb.png") playerTable.avatar = arg.avatar
playerTable.name = arg.name
playerTable.speed = {} playerTable.speed = {}
playerTable.speed.x = 0 playerTable.speed.x = 0
playerTable.speed.y = 0 playerTable.speed.y = 0