Compare commits

...

4 Commits

Author SHA1 Message Date
Pascal Abresch 39bce76863 add server running info label 2022-08-04 21:40:20 +02:00
Pascal Abresch 540b25379f improve main menu, add nicer button 2022-08-04 21:40:08 +02:00
Pascal Abresch 4de4a5eb9f minor fix 2022-08-04 21:14:56 +02:00
Pascal Abresch 2f2a098ca6 Change some stuff 2022-08-04 21:06:21 +02:00
24 changed files with 555 additions and 517 deletions

View File

@ -1,7 +1,7 @@
love.conf = function(conf) love.conf = function(conf)
conf.window.height = 480 conf.window.height = 1000
conf.window.minheight = 480 conf.window.minheight = 480
conf.window.width = 640 conf.window.width = 1000
conf.window.minwidth = 640 conf.window.minwidth = 640
conf.window.resizable = true conf.window.resizable = true
conf.window.vsync = -1 conf.window.vsync = -1

96
lua/commands.lua Normal file
View File

@ -0,0 +1,96 @@
local player = require("lua.player")
local utils = require("shared.utils")
local fonts = require("shared.fonts")
local commands = {}
local sharedCommands = require("lua.sharedCommands")
commands.commandsInit = sharedCommands.commandsInit
commands.init = function(clientID, args)
local nickname, args = utils.nextStringRecord(args)
local avatarEncoded, args = utils.nextStringRecord(args)
local worldID, args = utils.nextStringRecord(args)
local x, args = utils.nextIntRecord(args)
local y = tonumber(args)
local avatar = love.data.decode("string", "base64", avatarEncoded)
print("Connected as " .. clientID .. " with name " .. nickname)
print("New world is " .. worldID .. " Size is [" .. x .. "|" .. y .. "]")
players[clientID] = player.newPlayer({name = nickname, avatar = gameloop.avatars[avatar].image})
camera.target = clientID
_G.clientID = clientID
local world = { id = worldID, x = x, y = y }
gameloop.loadworld(world)
end
commands.ping = function(clientID)
gameloop.networkSend("pong")
end
commands.playerJoin = function(clientID, args)
local nickname, avatarEncoded = utils.nextStringRecord(args)
avatar = love.data.decode("string", "base64", avatarEncoded)
ui.addChatEntry("", nickname .. " Joined the game")
players[clientID] = player.newPlayer({name = nickname, avatar = gameloop.avatars[avatar].image})
players[clientID].label = love.graphics.newText(fonts.smallFont, nickname)
end
commands.playerLeave = function(clientID)
if players[clientID] then
local name = players[clientID].name
ui.addChatEntry("", name .. " Left the game")
players[clientID] = nil
end
end
commands.deletePhysics = function(clientID, args)
if clientID == camera.target then return end
if not players[clientID] then return end
physics.remove_solid(utils.getIntRecords(4, args))
end
commands.drawPhysics = function(clientID, args)
if clientID == camera.target then return end
if not players[clientID] then return end
physics.draw_solid(utils.getIntRecords(4, args))
end
commands.chatMessage = function(clientID, args)
local name
if clientID == "0" then
name = ""
else
name = players[clientID].name
end
ui.addChatEntry(players[clientID].name, args)
end
commands.deleteTexture = sharedCommands.deleteTexture
commands.drawTexture = sharedCommands.drawTexture
commands.moveUpdate = sharedCommands.moveUpdate
commands.moveFlying = sharedCommands.moveFlying
commands.clearCanvas = function(clientID)
drawing.clearAllCanvases()
end
commands.fillCanvas = function(clientID, args)
local layer, hash = utils.nextStringRecord(args)
hash = love.data.decode("string", "base64", hash)
drawing.fillCanvas(layer, hash)
end
return commands

View File

@ -3,16 +3,17 @@ function alignToGrid(num, thing)
return num - (num % thing) return num - (num % thing)
end end
local utils = require("shared.utils")
function drawing.clearAllCanvases() function drawing.clearAllCanvases()
love.graphics.setCanvas(gameloop.buffer.pixel.fg) love.graphics.setCanvas(gameloop.Canvas.fg)
love.graphics.clear() love.graphics.clear()
love.graphics.setCanvas(gameloop.buffer.pixel.bg) love.graphics.setCanvas(gameloop.Canvas.bg)
love.graphics.clear() love.graphics.clear()
love.graphics.setCanvas(gameloop.buffer.pixel.dbg) love.graphics.setCanvas(gameloop.Canvas.dbg)
love.graphics.clear() love.graphics.clear()
love.graphics.setCanvas() love.graphics.setCanvas()
gameloop.buffer.physics = {} gameloop.Canvas.physics = {}
end end
@ -23,7 +24,7 @@ end
function drawing.fillCanvas(layer, hash) function drawing.fillCanvas(layer, hash)
love.graphics.setCanvas(gameloop.buffer.pixel[layer]) love.graphics.setCanvas(gameloop.Canvas[layer])
love.graphics.clear() love.graphics.clear()
for x = 0, gameloop.world.x -gameloop.textures[hash].image:getPixelWidth(), for x = 0, gameloop.world.x -gameloop.textures[hash].image:getPixelWidth(),
gameloop.textures[hash].image:getPixelWidth() do gameloop.textures[hash].image:getPixelWidth() do
@ -37,7 +38,7 @@ end
function drawing.fillCanvasNetwork(layer, hash) function drawing.fillCanvasNetwork(layer, hash)
gameloop.networkSend(unit("fillCanvas", layer, love.data.encode("string", "base64", hash))) gameloop.networkSend(utils.unit("fillCanvas", layer, love.data.encode("string", "base64", hash)))
drawing.fillCanvas(layer, hash) drawing.fillCanvas(layer, hash)
end end
@ -99,18 +100,17 @@ function drawing.input(dt)
if not (thisx == thisx) or not (thisy == thisy) then return end if not (thisx == thisx) or not (thisy == thisy) then return end
local ctrlDown = love.keyboard.isDown("lctrl") or love.keyboard.isDown("rctrl") local ctrlDown = love.keyboard.isDown("lctrl") or love.keyboard.isDown("rctrl")
love.graphics.setBlendMode("replace")
if ctrlDown then if ctrlDown then
love.graphics.setCanvas(gameloop.buffer.pixel.bg) love.graphics.setCanvas(gameloop.Canvas.bg)
else else
love.graphics.setCanvas(gameloop.buffer.pixel.fg) love.graphics.setCanvas(gameloop.Canvas.fg)
end end
if love.mouse.isDown(1) then -- only delete if love.mouse.isDown(1) then -- only delete
color_push() utils.color_push()
love.graphics.setColor(drawing.color) love.graphics.setColor(drawing.color)
love.graphics.draw(cursor.image, thisx, thisy) love.graphics.draw(cursor.image, thisx, thisy)
color_pop() utils.color_pop()
if ctrlDown then if ctrlDown then
drawing.draw_texture(drawing.cursorHash, thisx, thisy, "bg", drawing.color) drawing.draw_texture(drawing.cursorHash, thisx, thisy, "bg", drawing.color)
else else
@ -120,7 +120,8 @@ function drawing.input(dt)
cursor.image:getPixelHeight()) cursor.image:getPixelHeight())
end end
else else
color_push() love.graphics.setBlendMode("replace")
utils.color_push()
love.graphics.setColor(0,0,0,0) love.graphics.setColor(0,0,0,0)
love.graphics.rectangle("fill", thisx, thisy, love.graphics.rectangle("fill", thisx, thisy,
cursor.image:getPixelWidth(), cursor.image:getPixelWidth(),
@ -137,9 +138,9 @@ function drawing.input(dt)
cursor.image:getPixelWidth(), cursor.image:getPixelWidth(),
cursor.image:getPixelHeight()) cursor.image:getPixelHeight())
end end
color_pop() utils.color_pop()
love.graphics.setBlendMode("alpha")
end end
love.graphics.setBlendMode("alpha")
love.graphics.setCanvas() love.graphics.setCanvas()
end end
drawmouse.lastX = mousex drawmouse.lastX = mousex
@ -155,7 +156,7 @@ function drawing.draw_texture(hash, x, y, layer, color)
if not color[4] then color[4] = 1 end if not color[4] then color[4] = 1 end
local last = drawing.lastTexture local last = drawing.lastTexture
if hash ~= last.hash or x ~= last.x or y ~= last.y or layer ~= last.layer then if hash ~= last.hash or x ~= last.x or y ~= last.y or layer ~= last.layer then
gameloop.networkSend(unit("drawTexture", x, y, gameloop.networkSend(utils.unit("drawTexture", x, y,
layer, love.data.encode("string", "base64", hash), color[1], color[2], color[3], color[4])) layer, love.data.encode("string", "base64", hash), color[1], color[2], color[3], color[4]))
end end
last.hash, last.x, last.y, last.layer = hash, x, y, layer last.hash, last.x, last.y, last.layer = hash, x, y, layer
@ -168,7 +169,7 @@ function drawing.del_texture(x, y, width, height, layer)
local last = drawing.lastTextureDel local last = drawing.lastTextureDel
if x ~= last.x or y ~= last.y or width ~= last.width if x ~= last.x or y ~= last.y or width ~= last.width
or height ~= last.height or layer ~= last.layer then or height ~= last.height or layer ~= last.layer then
gameloop.networkSend(unit("deleteTexture", x, y, width, height, layer)) gameloop.networkSend(utils.unit("deleteTexture", x, y, width, height, layer))
last.x, last.y, last.width, last.height, last.layer = x, y, width, height, layer last.x, last.y, last.width, last.height, last.layer = x, y, width, height, layer
end end
end end
@ -177,7 +178,7 @@ end
local lastDWP = { x = 0, y = 0, width = 0, height = 0} local lastDWP = { x = 0, y = 0, width = 0, height = 0}
function drawing.draw_solid(x, y, width, height) function drawing.draw_solid(x, y, width, height)
if x ~= lastDWP.x or y ~= lastDWP.y or width ~= lastDWP.width or height ~= lastDWP.height then if x ~= lastDWP.x or y ~= lastDWP.y or width ~= lastDWP.width or height ~= lastDWP.height then
gameloop.networkSend(unit("drawPhysics", x, y, width, height)) gameloop.networkSend(utils.unit("drawPhysics", x, y, width, height))
physics.draw_solid(x, y, width, height) physics.draw_solid(x, y, width, height)
lastDWP.x, lastDWP.y, lastDWP.width, lastDWP.height = x, y, width, height lastDWP.x, lastDWP.y, lastDWP.width, lastDWP.height = x, y, width, height
end end
@ -187,12 +188,13 @@ end
local lastRMP = { x = 0, y = 0, width = 0, height = 0} local lastRMP = { x = 0, y = 0, width = 0, height = 0}
function drawing.remove_solid(x, y, width, height) function drawing.remove_solid(x, y, width, height)
if x ~= lastRMP.x or y ~= lastRMP.y or width ~= lastRMP.width or height ~= lastRMP.height then if x ~= lastRMP.x or y ~= lastRMP.y or width ~= lastRMP.width or height ~= lastRMP.height then
gameloop.networkSend(unit("deletePhysics", x, y, width, height)) gameloop.networkSend(utils.unit("deletePhysics", x, y, width, height))
physics.remove_solid(x, y, width, height) physics.remove_solid(x, y, width, height)
lastRMP.x, lastRMP.y, lastRMP.width, lastRMP.height = x, y, width, height lastRMP.x, lastRMP.y, lastRMP.width, lastRMP.height = x, y, width, height
end end
end end
function drawing.init() function drawing.init()
local path = "textures/blocks/krock/Glass/03.png" local path = "textures/blocks/krock/Glass/03.png"
local texture = {data = love.image.newImageData(path), local texture = {data = love.image.newImageData(path),
@ -203,7 +205,6 @@ function drawing.init()
drawing.cursor = textures[drawing.cursorHash] drawing.cursor = textures[drawing.cursorHash]
texture, path = nil, nil texture, path = nil, nil
local clientChannel = love.thread.getChannel ( "clientChannel" );
mouse.lastpos = {} mouse.lastpos = {}
mouse.lastpos.x = 0 mouse.lastpos.x = 0

View File

@ -2,23 +2,30 @@ gameloop = {}
gameloop.world = nil gameloop.world = nil
gameloop.textures = {} gameloop.textures = {}
gameloop.avatars = {} gameloop.avatars = {}
local rpc = require("server.rpc") commands = require("lua.commands")
local v2_message = require("lua.network")
local socket = require "socket" local socket = require "socket"
local util = require("server.utils")
local utils = require("shared.utils")
local fonts = require("shared.fonts")
local rpc = require("server.rpc")
local constants = require("server.constants")
gameloop.nwChecklist = {}
gameloop.Canvas = {}
local count = 1
local function normalDraw() local function normalDraw()
if count == 1 then print("use canvas!") count = 2 end
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)
-- Draw background -- Draw background
if drawBackground then if drawBackground then
color_push() utils.color_push()
love.graphics.setColor(0.05, 0.05, 0.05) love.graphics.setColor(0.05, 0.05, 0.05)
love.graphics.rectangle("fill", math.floor(view.x) * scale, math.floor(view.y) * scale, gameloop.world.x * scale, gameloop.world.y * scale) love.graphics.rectangle("fill", math.floor(view.x) * scale, math.floor(view.y) * scale, gameloop.world.x * scale, gameloop.world.y * scale)
love.graphics.setColor(1, 1, 1, 1) love.graphics.setColor(1, 1, 1, 1)
love.graphics.draw(gameloop.buffer.pixel.bg, layerTransform) love.graphics.draw(gameloop.Canvas.bg, layerTransform)
color_pop() utils.color_pop()
end end
-- draw player -- draw player
@ -31,7 +38,7 @@ local function normalDraw()
love.graphics.draw(player.avatar, playerTransform) love.graphics.draw(player.avatar, playerTransform)
if player.name then if player.name then
if not player.label then if not player.label then
player.label = love.graphics.newText(ui.smallFont, player.name) player.label = love.graphics.newText(fonts.smallFont, player.name)
end end
local labelTransform = love.math.newTransform( local labelTransform = love.math.newTransform(
math.floor(player.x - (player.label:getWidth() / 2) + math.floor(player.x - (player.label:getWidth() / 2) +
@ -43,7 +50,7 @@ local function normalDraw()
end end
-- Draw foreground -- Draw foreground
love.graphics.draw(gameloop.buffer.pixel.fg, layerTransform) love.graphics.draw(gameloop.Canvas.fg, layerTransform)
-- Draw UI -- Draw UI
love.graphics.draw(ui.buffer) love.graphics.draw(ui.buffer)
@ -54,10 +61,10 @@ local function debugDraw()
normalDraw() 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)
love.graphics.draw(gameloop.buffer.pixel.dbg, layerTransform) love.graphics.draw(gameloop.Canvas.dbg, layerTransform)
love.graphics.draw(gameloop.buffer.pixel.dbg2, layerTransform) love.graphics.draw(gameloop.Canvas.dbg2, layerTransform)
love.graphics.setCanvas(gameloop.buffer.pixel.dbg2) love.graphics.setCanvas(gameloop.Canvas.dbg2)
love.graphics.clear() love.graphics.clear()
love.graphics.setCanvas() love.graphics.setCanvas()
end end
@ -65,15 +72,15 @@ 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 = "poppyV003" ..US.. clientID ..US.. args local request = constants.protocolVersion ..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 = "poppyV003" ..US.. clientID ..US.. args local request = constants.protocolVersion ..constants.US.. clientID ..constants.US.. args
print("=> " .. util.pprint(request)) print("=> " .. utils.pprint(request))
gameloop.client:send(request) gameloop.client:send(request)
end end
@ -89,7 +96,7 @@ function normalNetworkSync()
end end
local response = rpc.validate(message) local response = rpc.validate(message)
if not response.errorMsg then if not response.errorMsg then
rpc.execute(v2_message, response.clientID, response.record) rpc.execute(commands, response.clientID, response.record)
message = nil message = nil
else else
error(errorMsg) error(errorMsg)
@ -102,7 +109,7 @@ function debugNetworkSync()
local message, errorString = nil, false local message, errorString = nil, false
while not errorString do while not errorString do
local message, errorString = gameloop.client:receive() local message, errorString = gameloop.client:receive()
if message then print("<= " .. util.pprint(message)) end if message then print("<= " .. utils.pprint(message)) end
if not message then if not message then
if errorString == "timeout" then return else if errorString == "timeout" then return else
menu.init() menu.init()
@ -111,7 +118,7 @@ function debugNetworkSync()
end end
local response = rpc.validate(message) local response = rpc.validate(message)
if not response.errorMsg then if not response.errorMsg then
rpc.execute(v2_message, response.clientID, response.record) rpc.execute(commands, response.clientID, response.record)
message = nil message = nil
else else
error(errorMsg) error(errorMsg)
@ -196,28 +203,29 @@ end
function gameloop.init(server, nickname, avatarHash) function gameloop.init(server, nickname, avatarHash)
love.errorhandler = errorhandler local US = constants.US
--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?") assert(avatarHash, "Gameloop called without avatar?")
gameloop.server = server gameloop.server = server
scale = 1 scale = 1
love.graphics.setDefaultFilter("nearest", "nearest", 0) love.graphics.setDefaultFilter("nearest", "nearest", 0)
layer = true layer = true
grid = 16 grid = 16
color = {} color = {}
mouse = {} mouse = {}
window = {} window = {}
window.x, window.y = love.graphics.getDimensions() window.x, window.y = love.graphics.getDimensions()
players = {} players = {}
textures = {} textures = {}
view = {} view = {}
view.x = 0 view.x = 0
view.y = 0 view.y = 0
@ -226,7 +234,8 @@ function gameloop.init(server, nickname, avatarHash)
-- Must be done now because it has to be ready before "init" returns from the server -- Must be done now because it has to be ready before "init" returns from the server
-- which is /before/ the game world is loaded -- which is /before/ the game world is loaded
gameloop.loadAvatars() gameloop.loadAvatars()
commands.commandsInit()
gameloop.client = socket.udp() gameloop.client = socket.udp()
gameloop.client:setpeername(server.adress, server.port) gameloop.client:setpeername(server.adress, server.port)
gameloop.client:settimeout(0) gameloop.client:settimeout(0)
@ -234,9 +243,9 @@ function gameloop.init(server, nickname, avatarHash)
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 = "poppyV003" ..US.. "0" ..US.. unit("init", nickname, love.data.encode("string", "base64", avatarHash)) local request = constants.protocolVersion ..US.. "0" ..US.. utils.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("=> " .. utils.pprint(request)) end
if not NETWORK_DEBUG then if not NETWORK_DEBUG then
gameloop.networkSend = normalNetworkSend gameloop.networkSend = normalNetworkSend
@ -250,9 +259,20 @@ function gameloop.init(server, nickname, avatarHash)
gameloop.networkSync(dt) gameloop.networkSync(dt)
love.timer.sleep((1/60) -dt) love.timer.sleep((1/60) -dt)
end end
local infoFont
if love.filesystem.getInfo("fonts/font.ttf") then
infoFont = love.graphics.newFont("fonts/font.ttf", 45)
else
infoFont = love.graphics.newFont(45)
end
local message = love.graphics.newText(infoFont, "Connecting...")
love.graphics.draw(message, 40, 40, 0, 1, 1)
love.draw = function(dt) love.draw = function(dt)
love.graphics.present() love.graphics.setColor(0.05, 0.05, 0.05)
love.graphics.rectangle("fill", 0, 0, window.x, window.y)
love.graphics.setColor(1, 1, 1)
love.graphics.draw(message, 40, 40, 0, 1, 1)
end end
end end
@ -293,17 +313,15 @@ end
function gameloop.loadworld(world) function gameloop.loadworld(world)
-- Game connected! -- Game connected!
love.errorhandler = errorhandlerNetwork --love.errorhandler = errorhandlerNetwork
local buffer = {} print("make canvas!")
buffer.pixel = {} gameloop.Canvas.fg = love.graphics.newCanvas(world.x, world.y)
buffer.pixel.fg = love.graphics.newCanvas(world.x, world.y) gameloop.Canvas.bg = love.graphics.newCanvas(world.x, world.y)
buffer.pixel.bg = love.graphics.newCanvas(world.x, world.y)
if PHYSICS_DEBUG then if PHYSICS_DEBUG then
buffer.pixel.dbg = love.graphics.newCanvas(world.x, world.y) gameloop.Canvas.dbg = love.graphics.newCanvas(world.x, world.y)
buffer.pixel.dbg2 = love.graphics.newCanvas(world.x, world.y) gameloop.Canvas.dbg2 = love.graphics.newCanvas(world.x, world.y)
end end
buffer.physics = {} gameloop.Canvas.physics = {}
gameloop.buffer = buffer
ui.init() ui.init()
drawing.init() drawing.init()
@ -331,12 +349,13 @@ function gameloop.loadworld(world)
love.resize = function() love.resize = function()
normalDraw()
ui.resize() ui.resize()
camera.resize() camera.resize()
end end
love.quit = function() love.quit = function()
gameloop.networkSend(unit("playerLeave")) gameloop.networkSend(utils.unit("playerLeave"))
end end
gameloop.world = world gameloop.world = world

View File

@ -1,18 +0,0 @@
setmetatable(_G, {
__index = function(self, idx)
if rawget(self, idx) == nil then
error("attempted to read implicit global:" .. idx)
end
end
})
PHYSICS_DEBUG = true
NETWORK_DEBUG = true
constants = require("server.constants")
US = string.char(31)
local menu = require("lua.menuloop")
function love.load()
menu.init()
end

View File

@ -1,25 +1,32 @@
layout = {} local layout = {}
uiState = {} layout.uiState = {}
local debugPrint = function(string) local fonts = require("shared.fonts")
local utils = require("shared.utils")
local asserts = require("shared.asserts")
function layout.debugPrint(string)
--print(string) --print(string)
end end
function layout.canvasAndColor(container, x, y, simulate) function layout.canvasAndColor(container, x, y, simulate)
asserts.number("layout.canvasAndColor", 2, x, y)
if simulate then return layout.handle(container[1], x, y, simulate) end if simulate then return layout.handle(container[1], x, y, simulate) end
color_push() utils.color_push()
love.graphics.setCanvas(container.canvas) love.graphics.setCanvas(container.canvas)
x, y = layout.handle(container[1], x, y, simulate) x, y = layout.handle(container[1], x, y, simulate)
love.graphics.setCanvas() love.graphics.setCanvas()
color_pop() utils.color_pop()
return x, y return x, y
end end
function layout.rotate(container, x, y, simulate) function layout.rotate(container, x, y, simulate)
assert_num("layout.rotate", 2, x, y) asserts.number("layout.rotate", 2, x, y)
assert_num("layout.rotate (container)", container.rotation) asserts.number("layout.rotate (container)", container.rotation)
local transform = love.math.newTransform(0, 0, container.rotation) local transform = love.math.newTransform(0, 0, container.rotation)
local noTransform = love.math.newTransform(0, 0, 0) local noTransform = love.math.newTransform(0, 0, 0)
love.graphics.replaceTransform(transform) love.graphics.replaceTransform(transform)
@ -30,7 +37,8 @@ end
function layout.frame(container, x, y, simulate) function layout.frame(container, x, y, simulate)
assert_num("layout.frame", 2, x, y) asserts.number("layout.frame", 2, x, y)
x2, y2 = layout.handle(container[1], x +1, y +1, simulate) x2, y2 = layout.handle(container[1], x +1, y +1, simulate)
if not simulate then if not simulate then
love.graphics.rectangle("line", x, y, x2 -x, y2 -y) love.graphics.rectangle("line", x, y, x2 -x, y2 -y)
@ -42,7 +50,7 @@ end
function layout.cursorSelect(container, x, y, simulate) function layout.cursorSelect(container, x, y, simulate)
x2, y2 = layout.handle(container[1], x, y, simulate) x2, y2 = layout.handle(container[1], x, y, simulate)
if not simulate then if not simulate then
table.insert(uiState, { identifier = container.identifier, kind=container.kind, table.insert(layout.uiState, { identifier = container.identifier, kind=container.kind,
x=x, x2=x2, y=y, y2=y2 }) x=x, x2=x2, y=y, y2=y2 })
end end
return x2, y2 return x2, y2
@ -50,8 +58,10 @@ end
function layout.linewidth(container, x, y, simulate) function layout.linewidth(container, x, y, simulate)
if simulate then return layout.handle(container[1], x, y, simulate) end
assert(container.width, "layout.linewidth (container) no container.width provided!") assert(container.width, "layout.linewidth (container) no container.width provided!")
if simulate then return layout.handle(container[1], x, y, simulate) end
local oldWidth = love.graphics.getLineWidth() local oldWidth = love.graphics.getLineWidth()
love.graphics.setLineWidth(container.width) love.graphics.setLineWidth(container.width)
x, y = layout.handle(container[1], x, y, simulate) x, y = layout.handle(container[1], x, y, simulate)
@ -66,6 +76,7 @@ function layout.spacer(container, x, y, simulate)
"Argument container.width to layout.spacer must not be NaN!") "Argument container.width to layout.spacer must not be NaN!")
assert(container.height == container.height, assert(container.height == container.height,
"Argument container.height to layout.spacer must not be NaN!") "Argument container.height to layout.spacer must not be NaN!")
local width = container.width or 0 local width = container.width or 0
local height = container.height or 0 local height = container.height or 0
if container[1] then if container[1] then
@ -100,7 +111,8 @@ end
function layout.bwColorPicker(container, x, y, simulate) function layout.bwColorPicker(container, x, y, simulate)
assert(x and y) asserts.number("layout.bwColorPicker", 2, x, y)
local startx, starty = x, y local startx, starty = x, y
granularity = container.granularity or 0.04 granularity = container.granularity or 0.04
local points = {} local points = {}
@ -109,7 +121,7 @@ function layout.bwColorPicker(container, x, y, simulate)
local pointSize = container.pointSize or 8 local pointSize = container.pointSize or 8
if not simulate then if not simulate then
color_push() utils.color_push()
love.graphics.setPointSize(pointSize) love.graphics.setPointSize(pointSize)
for c=0, 1.0, granularity do for c=0, 1.0, granularity do
@ -117,7 +129,7 @@ function layout.bwColorPicker(container, x, y, simulate)
love.graphics.points(myx+(pointSize/2), y +(pointSize/2)) love.graphics.points(myx+(pointSize/2), y +(pointSize/2))
myx = myx + pointSize myx = myx + pointSize
end end
color_pop() utils.color_pop()
local iterationCount = (1.0 / granularity) local iterationCount = (1.0 / granularity)
maxx = x + pointSize * iterationCount maxx = x + pointSize * iterationCount
@ -135,7 +147,8 @@ end
function layout.colorPicker(container, x, y, simulate) function layout.colorPicker(container, x, y, simulate)
assert(x and y) asserts.number("layout.colorPicker", 2, x, y)
local startx, starty = x, y local startx, starty = x, y
granularity = container.granularity or 0.2 granularity = container.granularity or 0.2
local points = {} local points = {}
@ -144,7 +157,7 @@ function layout.colorPicker(container, x, y, simulate)
local pointSize = container.pointSize or 8 local pointSize = container.pointSize or 8
if not simulate then if not simulate then
color_push() utils.color_push()
love.graphics.setPointSize(pointSize) love.graphics.setPointSize(pointSize)
for r=0, 1.0, granularity do for r=0, 1.0, granularity do
@ -159,7 +172,7 @@ function layout.colorPicker(container, x, y, simulate)
if myx > endx then endx = myx end if myx > endx then endx = myx end
myx = x myx = x
end end
color_pop() utils.color_pop()
local iterationCount = (1.0 / granularity) + 1 local iterationCount = (1.0 / granularity) + 1
maxx = x + pointSize * iterationCount * iterationCount maxx = x + pointSize * iterationCount * iterationCount
@ -178,34 +191,39 @@ end
function layout.color(container, x, y, simulate) function layout.color(container, x, y, simulate)
if simulate then return layout.handle(container[1], x, y, simulate) end if simulate then return layout.handle(container[1], x, y, simulate) end
assert(container.color, "layout.color Color!")
assert(#container.color == 3 or #container.color == 4) assert(#container.color == 3 or #container.color == 4)
color_push() utils.color_push()
love.graphics.setColor(container.color) love.graphics.setColor(container.color)
x, y = layout.handle(container[1], x, y, simulate) x, y = layout.handle(container[1], x, y, simulate)
color_pop() utils.color_pop()
return x, y return x, y
end end
function layout.rect(container, x, y, simulate) function layout.rect(container, x, y, simulate)
assert_num("layout.rect", 2, x, y) asserts.number("layout.rect", 2, x, y)
assert_num("layout.rect (container)", 2, container.width, container.height) asserts.number("layout.rect (container)", 2, container.width, container.height)
if not simulate then
if container.color then if simulate then return x + container.width, y + container.height end
color_push()
love.graphics.setColor(container.color.r, container.color.g, container.color.b, container.color.a or 1) if container.color then
utils.color_push()
love.graphics.setColor(container.color.r, container.color.g, container.color.b, container.color.a or 1)
love.graphics.rectangle(container.fill or "fill", x, y, container.width, container.height)
utils.color_pop()
else
love.graphics.rectangle(container.fill or "fill", x, y, container.width, container.height) love.graphics.rectangle(container.fill or "fill", x, y, container.width, container.height)
color_pop()
else
love.graphics.rectangle(container.fill or "fill", x, y, container.width, container.height)
end
end end
return x + container.width, y + container.height return x + container.width, y + container.height
end end
function layout.overlayRect(container, x, y, simulate) function layout.overlayRect(container, x, y, simulate)
assert_num("layout.overlayRect", 2, x, y) asserts.number("layout.overlayRect", 2, x, y)
winx, winy = layout.handle(container[1], x, y, simulate) winx, winy = layout.handle(container[1], x, y, simulate)
width = winx -x width = winx -x
height = winy -y height = winy -y
@ -218,7 +236,7 @@ end
function layout.label(container, x, y, simulate) function layout.label(container, x, y, simulate)
if not container.font then container.font = ui.font end if not container.font then container.font = fonts.normalFont end
local text = love.graphics.newText( container.font, container.text ) local text = love.graphics.newText( container.font, container.text )
if not text then text = "Unset text!!" end if not text then text = "Unset text!!" end
if not simulate then if not simulate then
@ -269,11 +287,11 @@ function layout.naiveGrid(container, startX, startY, simulate)
else else
if not container[1] then return startX, startY end if not container[1] then return startX, startY end
end end
for i, v in ipairs(container) do for i, v in ipairs(container) do
retX, retY = layout.handle(v, workX, workY, simulate) retX, retY = layout.handle(v, workX, workY, simulate)
if retY > maxY then maxY = retY end if retY > maxY then maxY = retY end
if retX > startX + width then if retX > startX + width then
workY = maxY workY = maxY
workX = startX workX = startX
@ -282,7 +300,7 @@ function layout.naiveGrid(container, startX, startY, simulate)
workX = retX workX = retX
end end
end end
return maxX, maxY return maxX, maxY
end end
@ -298,7 +316,7 @@ function layout.copySize(container, x, y, simulate)
return bigx, bigy return bigx, bigy
end end
function layout.vertical(container, x, y, simulate) function layout.vertical(container, x, y, simulate)
local bigx = x local bigx = x
if not simulate then if not simulate then
@ -318,11 +336,14 @@ end
local depth = -1 local depth = -1
function layout.handle(container, x, y, simulate) function layout.handle(container, x, y, simulate)
assert_num("layout.handle", 2, x, y)
asserts.number("layout.handle", 2, x, y)
assert(container, "layout.handle called without container") assert(container, "layout.handle called without container")
local name = container["name"] local name = container["name"]
assert(name, "layout.handle container without name") assert(name, "layout.handle container without name")
assert(layout[name], "Unknown layout function " .. name .. " called") assert(layout[name], "Unknown layout function " .. name .. " called")
depth = depth +1 depth = depth +1
local depthCursor = "" local depthCursor = ""
for i=0, depth do for i=0, depth do
@ -330,22 +351,24 @@ function layout.handle(container, x, y, simulate)
end end
if depth == 0 then if depth == 0 then
if simulate then if simulate then
debugPrint("Starting simulation") layout.debugPrint("Starting simulation")
else else
debugPrint("Starting rendering") layout.debugPrint("Starting rendering")
end end
end end
debugPrint(depthCursor.. ">" .. container.name) layout.debugPrint(depthCursor.. ">" .. container.name)
x, y = layout[name](container, x, y, simulate) x, y = layout[name](container, x, y, simulate)
assert_num("layout.handle" .. container.name .. " is not returning properly!", 2, x, y) asserts.number("layout.handle" .. container.name .. " is not returning properly!", 2, x, y)
debugPrint(depthCursor.."<" .. container.name) layout.debugPrint(depthCursor.."<" .. container.name)
depth = depth -1 depth = depth -1
if depth == -1 then if depth == -1 then
if simulate then if simulate then
debugPrint("simulation ended\n") layout.debugPrint("simulation ended\n")
else else
debugPrint("rendering ended\n") layout.debugPrint("rendering ended\n")
end end
end end
return x, y return x, y
end end
return layout

View File

@ -4,6 +4,11 @@ menu.serverlist = {
{description = "A localhost server [ipv6]", host = "::1", port = "11150"} {description = "A localhost server [ipv6]", host = "::1", port = "11150"}
} }
local utils = require("shared.utils")
local fonts = require("shared.fonts")
local layout = require("lua.layout")
local altPressed, enterPressed = false, false local altPressed, enterPressed = false, false
function menu.keyreleased(key, _) function menu.keyreleased(key, _)
if key == "lalt" then if key == "lalt" then
@ -39,14 +44,45 @@ function menu.resize()
love.graphics.setCanvas() love.graphics.setCanvas()
end end
local firstClient = true
function menu.mousepressed(mousex, mousey) function menu.mousepressed(mousex, mousey)
local textures = gameloop.textures for i, v in ipairs(layout.uiState) do
for i, v in ipairs(uiState) do
if mousex >= v.x and mousex <= v.x2 then if mousex >= v.x and mousex <= v.x2 then
if mousey >= v.y and mousey <= v.y2 then if mousey >= v.y and mousey <= v.y2 then
if v.kind == "localServer" then
love.graphics.reset()
love.graphics.origin()
love.graphics.clear(.6, 0, .6)
love.graphics.setColor(1, 1, 1)
love.graphics.present()
print("Starting server!")
local serverloop = require("server.main")
serverloop.init()
end
if v.kind == "server" then if v.kind == "server" then
local names = { "Herbert", "Thorben", "Martin", "Heinrich", "Dietrich", "Markus", "Florian", "Helmut", "Willhelm", "Fritz", "Gustav", "Konrad", "Berta", "Charlotte", "Hildegard", "Lieselotte", "Gudrun", "Giesela", "Margarete", "Antonia", "Friederike", "Clotilde", "Marlies", "Hedwig" } if firstClient then
print("Starting client!")
dofile "lua/gameloop.lua"
dofile "lua/layout.lua"
dofile "lua/ui.lua"
dofile "lua/camera.lua"
dofile "lua/physics.lua"
dofile "lua/drawing.lua"
setmetatable(_G, {
__index = function(self, idx)
if rawget(self, idx) == nil then
error("attempted to read implicit global:" .. idx)
end
end
})
PHYSICS_DEBUG = false
NETWORK_DEBUG = true
firstclient = false
end
local textures = gameloop.textures
local names = { "Herbert", "Thorben", "Martin", "Heinrich", "Dietrich", "Markus", "Florian", "Helmut", "Willhelm", "Fritz", "Gustav", "Konrad", "Berta", "Charlotte", "Hildegard", "Lieselotte", "Gudrun", "Giesela", "Margarete", "Antonia", "Friederike", "Clotilde", "Marlies", "Hedwig", "Agathe" }
local lastNames = { "Müller", "Schmidt", "Meier", "Bauer", "Werner", "Schumacher", "Bergmann", "Eisenhauer", "Heisenberg" } local lastNames = { "Müller", "Schmidt", "Meier", "Bauer", "Werner", "Schumacher", "Bergmann", "Eisenhauer", "Heisenberg" }
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
@ -54,7 +90,7 @@ function menu.mousepressed(mousex, mousey)
local avatar = love.image.newImageData("textures/player/nephele/dog.png") local avatar = love.image.newImageData("textures/player/nephele/dog.png")
local avatarHash = love.data.hash("sha512", avatar:getString()) local avatarHash = love.data.hash("sha512", avatar:getString())
gameloop.init({ adress = serverEntry.host, port = serverEntry.port }, fullName, avatarHash) gameloop.init({ adress = serverEntry.host, port = serverEntry.port }, fullName, avatarHash)
uiState = {} layout.uiState = {}
end end
end end
end end
@ -63,16 +99,19 @@ end
menu.serverentry = function(id, description, host, port) menu.serverentry = function(id, description, host, port)
return {name = "horizontal", return {name = "cursorSelect", kind = "server", identifier = id,
{name = "label", text = description }, {name = "horizontal",
{name = "spacer", width = 20 }, {name = "drawTexture", texture = love.graphics.newImage("textures/menu/serverPlay.png")},
{name = "label", text = "[".. host .."]"}, {name = "spacer", width = 10 },
{name = "label", text = ":".. port }, {name = "label", text = description },
{name = "spacer", width = 25 }, {name = "spacer", width = 20 },
{name = "cursorSelect", kind = "server", identifier = id, {name = "label", text = "[".. host .."]", font = fonts.smallFont},
{name = "drawTexture", texture = love.graphics.newImage("textures/menu/serverPlay.png")}}} {name = "label", text = ":".. port, font = fonts.smallFont },
}
}
end end
menu.layoutServerList = function() menu.layoutServerList = function()
local list = {name = "vertical"} local list = {name = "vertical"}
for i, v in ipairs(menu.serverlist) do for i, v in ipairs(menu.serverlist) do
@ -87,28 +126,41 @@ menu.layout = {name ="vertical",
{name = "horizontal", {name = "horizontal",
{name = "spacer", width = 20}, {name = "spacer", width = 20},
{name = "drawTexture", texture = love.graphics.newImage("ressources/Poppy.png")}, {name = "drawTexture", texture = love.graphics.newImage("ressources/Poppy.png")},
{name = "label", text = "Welcome to poppy!"}, {name = "label", font = fonts.bigFont, text = "Welcome to poppy!"},
}, },
{name = "horizontal", {name = "horizontal",
{name = "spacer", width = 60}, {name = "spacer", width = 60},
{name = "vertical", {name = "vertical",
{name = "spacer", height = 60}, {name = "spacer", height = 60},
{name = "label", text = "Pick a server to join!"}, {name = "cursorSelect", kind = "localServer", identifier = "::1",
{name = "spacer", height = 20}, {name = "horizontal",
menu.layoutServerList() {name = "drawTexture",
texture = love.graphics.newImage("textures/menu/serverPlay.png")
},
{name = "spacer", width = 10},
{name = "label", text = "Spin up a local server"},
}
},
{name = "spacer", width = 60},
{name = "vertical",
{name = "spacer", height = 60},
{name = "label", text = "Or pick a server to join!", font = fonts.headerFont},
{name = "spacer", height = 20},
menu.layoutServerList()
}
} }
} }
} }
function drawMenu() function drawMenu()
color_push() utils.color_push()
love.graphics.setCanvas(menu.Canvas) love.graphics.setCanvas(menu.Canvas)
uiState = {} uiState = {}
love.graphics.clear( ) love.graphics.clear( )
layout.handle(menu.layout, 0, 0) layout.handle(menu.layout, 0, 0)
love.graphics.setCanvas() love.graphics.setCanvas()
color_pop() utils.color_pop()
end end
@ -118,6 +170,7 @@ end
function menu.init() function menu.init()
print("init menu")
menu.width, menu.height = love.window.getMode() menu.width, menu.height = love.window.getMode()
menu.Canvas = love.graphics.newCanvas(menu.width, menu.height) menu.Canvas = love.graphics.newCanvas(menu.width, menu.height)
drawMenu() drawMenu()
@ -125,6 +178,7 @@ function menu.init()
love.keyreleased = menu.keyreleased love.keyreleased = menu.keyreleased
love.keypressed = menu.keypressed love.keypressed = menu.keypressed
love.mousepressed = menu.mousepressed love.mousepressed = menu.mousepressed
print("inited menu")
end end
return menu return menu

View File

@ -1,159 +0,0 @@
local player = require("lua.player")
local util = require("server.utils")
local v2_message = {}
v2_message.init = function(clientID, args)
local nickname, args = util.nextStringRecord(args)
local avatarEncoded, args = util.nextStringRecord(args)
local worldID, args = util.nextStringRecord(args)
local x, args = util.nextIntRecord(args)
local y = tonumber(args)
local avatar = love.data.decode("string", "base64", avatarEncoded)
print("Connected as " .. clientID .. " with name " .. nickname)
print("New world is " .. worldID .. " Size is [" .. x .. "|" .. y .. "]")
players[clientID] = player.newPlayer({name = nickname, avatar = gameloop.avatars[avatar].image})
camera.target = clientID
_G.clientID = clientID
local world = { id = worldID, x = x, y = y }
gameloop.loadworld(world)
end
v2_message.ping = function(clientID)
gameloop.networkSend("pong")
end
v2_message.playerJoin = function(clientID, args)
local nickname, avatarEncoded = util.nextStringRecord(args)
avatar = love.data.decode("string", "base64", avatarEncoded)
ui.addChatEntry("", nickname .. " Joined the game")
players[clientID] = player.newPlayer({name = nickname, avatar = gameloop.avatars[avatar].image})
players[clientID].label = love.graphics.newText(ui.smallFont, nickname)
end
v2_message.playerLeave = function(clientID)
if players[clientID] then
local name = players[clientID].name
ui.addChatEntry("", name .. " Left the game")
players[clientID] = nil
end
end
v2_message.moveUpdate = function(clientID, args)
if not players[clientID] then return end
local x, args = util.nextIntRecord(args)
local y, args = util.nextIntRecord(args)
local speedx, args = util.nextIntRecord(args)
local speedy = util.clean(args:gsub("^.-\31",""))
players[clientID].x = x
players[clientID].y = y
players[clientID].speed.x = speedx
players[clientID].speed.y = speedy
end
v2_message.moveFlying = function(clientID, args)
if not players[clientID] then return end
players[clientID].flying = (args == "true")
end
v2_message.deletePhysics = function(clientID, args)
if clientID == camera.target then return end
if not players[clientID] then return end
physics.remove_solid(util.getIntRecords(4, args))
end
v2_message.drawPhysics = function(clientID, args)
if clientID == camera.target then return end
if not players[clientID] then return end
physics.draw_solid(util.getIntRecords(4, args))
end
v2_message.drawTexture = function(clientID, args)
if clientID == camera.target then return end
local x, args = util.nextIntRecord(args)
local y, args = util.nextIntRecord(args)
local layer, args = util.nextStringRecord(args)
local hash, args = util.nextStringRecord(args)
hash = love.data.decode("string", "base64", hash)
local r, args = util.nextIntRecord(args)
local g, args = util.nextIntRecord(args)
local b, a = util.nextIntRecord(args)
a = tonumber(a)
if not r or not g or not b then
r, g, b = 1, 1, 1
end
if not a then
a = 1
end
if not gameloop.textures[hash] then print("Failed to find hash!") return end
love.graphics.setBlendMode("replace")
if layer == "fg" then
love.graphics.setCanvas(gameloop.buffer.pixel.fg)
elseif layer == "bg" then
love.graphics.setCanvas(gameloop.buffer.pixel.bg)
end
if not gameloop.textures[hash].image then love.graphics.newImage(gameloop.textures[hash].data) end
color_push()
love.graphics.setColor(r, g, b ,a)
love.graphics.draw(gameloop.textures[hash].image, x, y)
color_pop()
love.graphics.setBlendMode("alpha")
love.graphics.setCanvas()
end
v2_message.deleteTexture = function(clientID, args)
if clientID == camera.target then return end
local x, args = util.nextIntRecord(args)
local y, args = util.nextIntRecord(args)
local width, args = util.nextIntRecord(args)
local height, layer = util.nextIntRecord(args)
if layer == "fg" then
love.graphics.setCanvas(gameloop.buffer.pixel.fg)
elseif layer == "bg" then
love.graphics.setCanvas(gameloop.buffer.pixel.bg)
end
love.graphics.setBlendMode("replace")
color_push()
love.graphics.setColor(0,0,0,0)
love.graphics.rectangle("fill", x, y, width, height)
color_pop()
love.graphics.setBlendMode("alpha")
love.graphics.setCanvas()
end
v2_message.chatMessage = function(clientID, args)
local name
if clientID == "0" then
name = ""
else
name = players[clientID].name
end
ui.addChatEntry(players[clientID].name, args)
end
v2_message.clearCanvas = function(clientID)
drawing.clearAllCanvases()
end
v2_message.fillCanvas = function(clientID, args)
local layer, hash = util.nextStringRecord(args)
hash = love.data.decode("string", "base64", hash)
drawing.fillCanvas(layer, hash)
end
return v2_message

View File

@ -1,5 +1,8 @@
physics = {} physics = {}
local asserts = require("shared.asserts")
local utils = require("shared.utils")
function physics.keyreleased_debug(key, _) function physics.keyreleased_debug(key, _)
if key == "kp4" then if key == "kp4" then
player.x = player.x -1 player.x = player.x -1
@ -17,30 +20,30 @@ end
function physics.remove_solid(x, y, sizex, sizey) function physics.remove_solid(x, y, sizex, sizey)
assert_num("physics.remove_solid", 4, x, y, sizex, sizey) asserts.number("physics.remove_solid", 4, x, y, sizex, sizey)
for coord_x=x, x + sizex-1 do for coord_x=x, x + sizex-1 do
for coord_y=y, y + sizey-1 do for coord_y=y, y + sizey-1 do
gameloop.buffer.physics[coord_x*gameloop.world.x+coord_y] = nil gameloop.Canvas.physics[coord_x*gameloop.world.x+coord_y] = nil
end end
end end
end end
function physics.draw_solid(x, y, sizex, sizey) function physics.draw_solid(x, y, sizex, sizey)
assert_num("physics.draw_solid", 4, x, y, sizex, sizey) asserts.number("physics.draw_solid", 4, x, y, sizex, sizey)
for coord_x=x, x + sizex-1 do for coord_x=x, x + sizex-1 do
for coord_y=y, y + sizey-1 do for coord_y=y, y + sizey-1 do
gameloop.buffer.physics[coord_x*gameloop.world.x+coord_y] = {0, 0, 0, true } gameloop.Canvas.physics[coord_x*gameloop.world.x+coord_y] = {0, 0, 0, true }
end end
end end
end end
function draw_colision(x, y, x2, y2, pixelx, pixely) function draw_colision(x, y, x2, y2, pixelx, pixely)
color_push() utils.color_push()
love.graphics.setLineWidth(1) love.graphics.setLineWidth(1)
love.graphics.setDefaultFilter("nearest", "nearest", 0) love.graphics.setDefaultFilter("nearest", "nearest", 0)
love.graphics.setCanvas(gameloop.buffer.pixel.dbg2) love.graphics.setCanvas(gameloop.Canvas.dbg2)
if pixelx then if pixelx then
love.graphics.setColor(.6, 0, .6, 1) love.graphics.setColor(.6, 0, .6, 1)
love.graphics.rectangle("fill", x, y, x2, y2) love.graphics.rectangle("fill", x, y, x2, y2)
@ -51,15 +54,15 @@ function draw_colision(x, y, x2, y2, pixelx, pixely)
love.graphics.rectangle("fill", x, y, x2, y2) love.graphics.rectangle("fill", x, y, x2, y2)
end end
love.graphics.setCanvas() love.graphics.setCanvas()
color_pop() utils.color_pop()
end end
function physics.is_blocked_x(x, y, sizex) function physics.is_blocked_x(x, y, sizex)
x, y = math.floor(x), math.floor(y) x, y = math.floor(x), math.floor(y)
assert_num("physics.is_blocked_x", 3, x, y, sizex) asserts.number("physics.is_blocked_x", 3, x, y, sizex)
for coord_x=x ,x + sizex -1 do for coord_x=x ,x + sizex -1 do
if gameloop.buffer.physics[coord_x * gameloop.world.x+y] and gameloop.buffer.physics[coord_x*gameloop.world.x+y][4] then if gameloop.Canvas.physics[coord_x * gameloop.world.x+y] and gameloop.Canvas.physics[coord_x*gameloop.world.x+y][4] then
if PHYSICS_DEBUG then draw_colision(x, y, sizex, 1, coord_x, y) end if PHYSICS_DEBUG then draw_colision(x, y, sizex, 1, coord_x, y) end
return true return true
end end
@ -71,9 +74,9 @@ end
function physics.is_blocked_y(x, y, sizey) function physics.is_blocked_y(x, y, sizey)
x, y = math.floor(x), math.floor(y) x, y = math.floor(x), math.floor(y)
assert_num("physics.is_blocked_y", 3, x, y, sizey) asserts.number("physics.is_blocked_y", 3, x, y, sizey)
for coord_y=y, y + sizey -1 do for coord_y=y, y + sizey -1 do
if gameloop.buffer.physics[x*gameloop.world.x+coord_y] and gameloop.buffer.physics[x*gameloop.world.x+coord_y][4] then if gameloop.Canvas.physics[x*gameloop.world.x+coord_y] and gameloop.Canvas.physics[x*gameloop.world.x+coord_y][4] then
if PHYSICS_DEBUG then draw_colision(x, y, 1, sizey, x, coord_y) end if PHYSICS_DEBUG then draw_colision(x, y, 1, sizey, x, coord_y) end
return true return true
end end
@ -85,16 +88,16 @@ end
function physics.keypressed( key, code, isrepeat) function physics.keypressed( key, code, isrepeat)
if isrepeat then return end if isrepeat then return end
if camera.target == 0 then return end if camera.target == 0 then return end
player = players[camera.target] player = players[camera.target]
if key == "p" then if key == "p" then
player.flying = not player.flying player.flying = not player.flying
if player.flying then if player.flying then
player.speed.y = 0 player.speed.y = 0
gameloop.networkSend(unit("moveFlying", "true")) gameloop.networkSend(utils.unit("moveFlying", "true"))
else else
gameloop.networkSend(unit("moveFlying", "false")) gameloop.networkSend(utils.unit("moveFlying", "false"))
end end
end end
end end
@ -282,7 +285,7 @@ last.packet, last.x, last.y, last.speedx, last.speedy = 0, 0, 0, 0, 0
function physics.send_update(player, dt) function physics.send_update(player, dt)
if last.packet > 0.03 then if last.packet > 0.03 then
if last.x ~= player.x or last.y ~= player.y then if last.x ~= player.x or last.y ~= player.y then
gameloop.networkSend(unit("moveUpdate", player.x, player.y, player.speed.x, player.speed.y)) gameloop.networkSend(utils.unit("moveUpdate", player.x, player.y, player.speed.x, player.speed.y))
last.packet = 0 last.packet = 0
last.x, last.y = player.x, player.y last.x, last.y = player.x, player.y
last.speedx, last.speedy = player.speedx, player.speedy last.speedx, last.speedy = player.speedx, player.speedy

86
lua/sharedCommands.lua Normal file
View File

@ -0,0 +1,86 @@
local player = require("lua.player")
local utils = require("shared.utils")
local commands = {}
local canvas = {}
local players
local textures
function commands.commandsInit()
if gameloop then -- client
canvas.fg = gameloop.Canvas.fg
canvas.bg = gameloop.Canvas.bg
players = _G.players
textures = gameloop.textures
else
canvas.fg = serverloop.Canvas.fg
canvas.bg = serverloop.Canvas.bg
players = _G.clients
textures = serverloop.textures
end
end
commands.moveUpdate = function(clientID, args)
if not players[clientID] then return end
local x, args = utils.nextIntRecord(args)
local y, args = utils.nextIntRecord(args)
local speedx, args = utils.nextIntRecord(args)
local speedy = utils.clean(args:gsub("^.-\31",""))
players[clientID].x = x
players[clientID].y = y
players[clientID].speed.x = speedx
players[clientID].speed.y = speedy
end
commands.moveFlying = function(clientID, args)
if not players[clientID] then return end
players[clientID].flying = (args == "true")
end
commands.drawTexture = function(clientID, args)
if clientID == camera.target then return end
local x, args = utils.nextIntRecord(args)
local y, args = utils.nextIntRecord(args)
local layer, args = utils.nextStringRecord(args)
local hash, args = utils.nextStringRecord(args)
hash = love.data.decode("string", "base64", hash)
local r, args = utils.nextIntRecord(args)
local g, args = utils.nextIntRecord(args)
local b, a = utils.nextIntRecord(args)
a = tonumber(a)
if not gameloop.textures[hash] then print("Failed to find hash!") return end
love.graphics.setBlendMode("replace")
love.graphics.setCanvas(canvas[layer])
love.graphics.setCanvas(canvas.bg)
if not textures[hash].image then love.graphics.newImage(textures[hash].data) end
utils.color_push()
love.graphics.setColor(r, g, b ,a)
love.graphics.draw(textures[hash].image, x, y)
utils.color_pop()
love.graphics.setBlendMode("alpha")
love.graphics.setCanvas()
end
commands.deleteTexture = function(clientID, args)
if clientID == camera.target then return end
local x, args = utils.nextIntRecord(args)
local y, args = utils.nextIntRecord(args)
local width, args = utils.nextIntRecord(args)
local height, layer = utils.nextIntRecord(args)
love.graphics.setCanvas(canvas[layer])
love.graphics.setBlendMode("replace")
utils.color_push()
love.graphics.setColor(0,0,0,0)
love.graphics.rectangle("fill", x, y, width, height)
utils.color_pop()
love.graphics.setBlendMode("alpha")
love.graphics.setCanvas()
end
return commands

View File

@ -1,14 +1,9 @@
ui = {} ui = {}
ui.textureTree = nil ui.textureTree = nil
if love.filesystem.getInfo("fonts/font.ttf") then
ui.smallFont = love.graphics.newFont("fonts/font.ttf", 14) local layout = require("lua.layout")
ui.font = love.graphics.newFont("fonts/font.ttf", 20)
ui.bigFont = love.graphics.newFont("fonts/font.ttf", 45) local utils = require("shared.utils")
else
ui.smallFont = love.graphics.newFont(14)
ui.font = love.graphics.newFont(20)
ui.bigFont = love.graphics.newFont(45)
end
ui.sidebarScale = 1 ui.sidebarScale = 1
ui.sidebarWidth = 13 * 16 ui.sidebarWidth = 13 * 16
@ -62,7 +57,7 @@ function ui.keyreleased(key, _)
if key == "return" and not love.keyboard.isDown("lalt") then if key == "return" and not love.keyboard.isDown("lalt") then
textEnabled = false textEnabled = false
if textEntry ~= "" then if textEntry ~= "" then
gameloop.networkSend(unit("chatMessage", textEntry)) gameloop.networkSend(utils.unit("chatMessage", textEntry))
textEntry = "" textEntry = ""
end end
ui.draw(window.x, window.y) ui.draw(window.x, window.y)
@ -98,11 +93,11 @@ function ui.chatEntry()
fill = "fill", fill = "fill",
color = { r = .1, g = .1, b = .1, .7 } color = { r = .1, g = .1, b = .1, .7 }
}, },
{name = "frame", {name = "frame",
{name = "label", {name = "label",
text = passedEntry text = passedEntry
}
} }
}
} }
return chatEntry return chatEntry
end end
@ -126,22 +121,22 @@ function ui.addChatEntry(user, message)
end end
local entry = {name = "rotate", local entry = {name = "rotate",
rotation = 0, -- OKAY DIEGO >:( rotation = 0, -- OKAY DIEGO >:(
{name = "copySize", {name = "copySize",
{name = "rect", {name = "rect",
fill = "fill", fill = "fill",
color = { r = .1, g = .1, b = .1, a = .6 } color = { r = .1, g = .1, b = .1, a = .6 }
},
{name = "vertical",
{name = "label",
text = chatText,
font = ui.smallFont
}, },
{name = "vertical", {name = "spacer",
{name = "label", height = 2
text = chatText,
font = ui.smallFont
},
{name = "spacer",
height = 2
}
} }
} }
} }
}
table.insert(chatentries, entry) table.insert(chatentries, entry)
ui.draw(window.x, window.y) ui.draw(window.x, window.y)
end end
@ -180,7 +175,7 @@ function textureEntry(hash)
local width = texture.image:getWidth() local width = texture.image:getWidth()
local height = texture.image:getHeight() local height = texture.image:getHeight()
if drawing and drawing.cursorHash and hash == drawing.cursorHash then if drawing and drawing.cursorHash and hash == drawing.cursorHash then
return{name = "overlayRect", return {name = "overlayRect",
fill = "line", fill = "line",
{name = "drawHash", {name = "drawHash",
hash = hash, hash = hash,
@ -188,7 +183,7 @@ function textureEntry(hash)
} }
} }
else else
return{name = "cursorSelect", return {name = "cursorSelect",
identifier = hash, identifier = hash,
kind = "picker", kind = "picker",
{name = "drawHash", {name = "drawHash",
@ -204,7 +199,7 @@ function textureRun(entryTable, width)
local textures = gameloop.textures local textures = gameloop.textures
local entries = {name = "naiveGrid", width = width - 20} local entries = {name = "naiveGrid", width = width - 20}
local entryTableSorted = {} local entryTableSorted = {}
-- Sort the entries alphapetically (or well, probably more... "byte compared") :) -- Sort the entries alphapetically (or well, probably more... "byte compared") :)
-- This implies that in <author>/<packname>/<fileName> the fileName controls where -- This implies that in <author>/<packname>/<fileName> the fileName controls where
-- the texture lands in the block drawer, smaller lands further left. -- the texture lands in the block drawer, smaller lands further left.
@ -212,7 +207,7 @@ function textureRun(entryTable, width)
table.insert(entryTableSorted, {name = iter, entry = entry}) table.insert(entryTableSorted, {name = iter, entry = entry})
end end
table.sort(entryTableSorted, function(k1, k2) return k1.name < k2.name end) table.sort(entryTableSorted, function(k1, k2) return k1.name < k2.name end)
for iter, entry in pairs(entryTableSorted) do for iter, entry in pairs(entryTableSorted) do
if not textures[entry.entry].image then if not textures[entry.entry].image then
textures[entry.entry].image = love.graphics.newImage(textures[entry.entry].data) textures[entry.entry].image = love.graphics.newImage(textures[entry.entry].data)
@ -245,7 +240,10 @@ function ui.blockDrawer(textureTree, w, h, container)
table.insert(container, {name = "label", text = pack}) table.insert(container, {name = "label", text = pack})
table.insert(container, table.insert(container,
{name = "color", {name = "color",
color = drawing.color, color = drawing.color or {1, 1, 1},
--[[ HACK! remove the 1, 1, 1.
drawing.color should be set!
]]--
textureRun(subTree, w) textureRun(subTree, w)
}) })
end end
@ -267,7 +265,7 @@ function ui.testDrawer(w, h)
end end
local selectedTab = "help" local selectedTab = "blocks"
function ui.tabDrawer(textureTree, w, h) function ui.tabDrawer(textureTree, w, h)
local labels local labels
local helpTab = {name = "label", local helpTab = {name = "label",
@ -296,7 +294,7 @@ function ui.tabDrawer(textureTree, w, h)
}, },
{name = "spacer", {name = "spacer",
width = 5 width = 5
}, },
{name = "cursorSelect", {name = "cursorSelect",
identifier = "disconnect", identifier = "disconnect",
kind = "button", kind = "button",
@ -361,7 +359,7 @@ end
function ui.draw(w, h) function ui.draw(w, h)
window.x, window.y = w, h window.x, window.y = w, h
color_push() utils.color_push()
love.graphics.setCanvas(ui.buffer) love.graphics.setCanvas(ui.buffer)
uiState = {} uiState = {}
love.graphics.clear( ) love.graphics.clear( )
@ -374,14 +372,14 @@ function ui.draw(w, h)
layout.handle(chatLayout, 0, window.y - sizey) layout.handle(chatLayout, 0, window.y - sizey)
end end
layout.handle(ui.chatlog(), 25, 90) layout.handle(ui.chatlog(), 25, 90)
color_pop() utils.color_pop()
love.graphics.setCanvas() love.graphics.setCanvas()
end end
function ui.mousepressed(mousex, mousey) function ui.mousepressed(mousex, mousey)
local textures = gameloop.textures local textures = gameloop.textures
for i, v in ipairs(uiState) do for i, v in ipairs(layout.uiState) do
if mousex >= v.x and mousex <= v.x2 then if mousex >= v.x and mousex <= v.x2 then
if mousey >= v.y and mousey <= v.y2 then if mousey >= v.y and mousey <= v.y2 then
if v.kind == "picker" then if v.kind == "picker" then
@ -411,7 +409,7 @@ function ui.mousepressed(mousex, mousey)
return return
elseif v.kind == "button" then elseif v.kind == "button" then
if v.identifier == "disconnect" then if v.identifier == "disconnect" then
gameloop.networkSend(unit("playerLeave")) gameloop.networkSend(utils.unit("playerLeave"))
menu.init() menu.init()
return return
elseif v.identifier == "increaseUISize" then elseif v.identifier == "increaseUISize" then

View File

@ -1,60 +0,0 @@
local colorstack = {}
function color_push()
local depth = #colorstack +1
colorstack[depth] = {}
colorstack[depth].r, colorstack[depth].g, colorstack[depth].b,
colorstack[depth].a = love.graphics.getColor()
end
function color_pop()
love.graphics.setColor(colorstack[#colorstack].r, colorstack[#colorstack].g,
colorstack[#colorstack].b, colorstack[#colorstack].a)
table.remove(colorstack, #colorstack)
end
function assert_num(name, count, ...)
local args = { ... }
for i = 1, count do
assert(args[i] ~= nil, "Argument " .. i .. " to " .. name .. " may not be nil and must be an int!")
assert(type(args[i]) == "number", "Argument " .. i .. " to " .. name .. " must be an int!")
assert(args[i] == args[i], "Argument " .. i .. " to " .. name .. " must not be NaN!")
end
end
function assert_num_or_nil(name, count, ...)
local args = { ... }
for i = 1, count do
if (args[i] ~= nil) then
assert(type(args[i]) == "number", "Argument " .. i .. " to " .. name .. " can only be of type int!")
assert(args[i] == args[i], "Argument " .. i .. " to " .. name .. " may not be NaN!")
end
end
end
local recordSeperator = string.char(30)
local unitSeperator = string.char(31)
function unit(...)
local args = { ... }
local string = args[1]
for i=2, #args do
string = string .. unitSeperator .. args[i]
end
return string
end
function record(...)
local args = { ... }
local string = args[1]
for i=2, #args do
string = string .. recordSeperator .. args[i]
end
return string
end

View File

@ -2,11 +2,16 @@ function dofile(fileString)
local chunk = love.filesystem.load(fileString) local chunk = love.filesystem.load(fileString)
chunk() chunk()
end end
dofile "lua/gameloop.lua"
dofile "lua/utils.lua"
dofile "lua/layout.lua" function love.load(args)
dofile "lua/init.lua" if args[1] == "--server" then
dofile "lua/ui.lua" print("Starting server!")
dofile "lua/camera.lua" local serverloop = require("server.main")
dofile "lua/physics.lua" serverloop.init()
dofile "lua/drawing.lua" else
constants = require("server.constants")
local menu = require("lua.menuloop")
menu.init()
end
end

BIN
ressources/Icons/PlayButton Normal file

Binary file not shown.

View File

@ -1,11 +1,12 @@
local constants = require("constants") local utils = require("shared.utils")
local util = require("utils")
local rpc = require("rpc") local constants = require("server.constants")
local rpc = require("server.rpc")
return function(commands) return function(commands)
function commands.chatMessage(clientID, args) function commands.chatMessage(clientID, args)
assert(clients[clientID]) assert(clients[clientID])
print("Chat " .. clients[clientID].name .. ": " .. args) print("Chat " .. clients[clientID].name .. ": " .. args)
broadcast(clientID, util.unit("chatMessage", args)) broadcast(clientID, utils.unit("chatMessage", args))
end end
end end

View File

@ -1,6 +1,7 @@
local constants = require("constants") local util = require("shared.utils")
local util = require("utils")
local rpc = require("rpc") local constants = require("server.constants")
local rpc = require("server.rpc")
return function(commands) return function(commands)
function commands.drawTexture(clientID, args) function commands.drawTexture(clientID, args)

View File

@ -1,7 +1,7 @@
local constants = require("constants") local constants = require("server.constants")
local util = require("utils") local util = require("shared.utils")
local rpc = require("rpc") local rpc = require("server.rpc")
require("compat") require("server.compat")
return function(commands) return function(commands)
function commands.moveUpdate(clientID, args) function commands.moveUpdate(clientID, args)

View File

@ -1,4 +1,4 @@
local util = require("utils") local util = require("shared.utils")
return function(commands) return function(commands)
function commands.playerLeave(clientID) function commands.playerLeave(clientID)

View File

@ -3,4 +3,9 @@ return {
US = string.char(31), US = string.char(31),
protocolVersion = "poppyV003", protocolVersion = "poppyV003",
world = {
x = 3000,
y = 3000,
id = "NYAAA"
}
} }

View File

@ -1,30 +1,36 @@
print("Startup!")
local constants = require("constants")
protocolVersion = constants.protocolVersion
local rpc = require("rpc")
local socket = require("socket") local socket = require("socket")
local util = require("utils")
local fonts = require("shared.fonts")
local constants = require("server.constants")
local rpc = require("server.rpc")
local util = require("shared.utils")
protocolVersion = constants.protocolVersion
local commands = {} local commands = {}
require("commands/players")(commands) require("server.commands.players")(commands)
require("commands/physics")(commands) require("server.commands.physics")(commands)
require("commands/drawing")(commands) require("server.commands.drawing")(commands)
require("commands/chat")(commands) require("server.commands.chat")(commands)
local unpriviligedCommands = {} local unpriviligedCommands = {}
require("unpriviliged_commands/init")(unpriviligedCommands) require("server.unpriviliged_commands.init")(unpriviligedCommands)
server = assert(socket.udp()) server = assert(socket.udp())
local ip, port = nil, nil local ip, port = nil, nil
clients = {} clients = {}
serverloop = {}
serverloop.textures = {}
server:settimeout(0) server:settimeout(0)
assert(server:setsockname("*", 11150)) assert(server:setsockname("*", 11150))
print(server:getsockname()) local socketString = server:getsockname()
print(socketString)
if not server or not socket then error("failed to listen on socket") end if not server or not socket then error("failed to listen on socket") end
print("Server startup.")
function broadcast(clientID, message) function broadcast(clientID, message)
local payload = util.unit(protocolVersion, clientID, message) local payload = util.unit(protocolVersion, clientID, message)
@ -37,7 +43,30 @@ function broadcast(clientID, message)
end end
function love.update(dt) function loadTextures(directory, container)
if not container then container = {} end
local entries = love.filesystem.getDirectoryItems(directory)
if #entries == 0 then return container end
for i, file in pairs(entries) do
local path = directory .."/".. file
local entry = love.filesystem.getInfo(path)
if entry.type == "directory" and file ~= ".git" then
container[file] = {}
container[file] = loadTextures(path, container[file])
elseif entry.type == "file" or entry.type == "symlink" then
local status, imageData = pcall(love.image.newImageData, path);
if status then
local hash = love.data.hash("sha512", imageData:getString())
serverloop.textures[hash] = {data = imageData}
container[file] = hash
end
end
end
return container
end
function mainloop(dt)
local data, ip, port local data, ip, port
data, ip, port = server:receivefrom() data, ip, port = server:receivefrom()
if not data then if not data then
@ -68,3 +97,23 @@ function love.update(dt)
end end
end end
end end
function serverloop.init()
loadTextures("textures/blocks", serverloop.textures)
serverloop.Canvas = {}
serverloop.Canvas.fg = love.graphics.newCanvas(constants.world.x, constants.world.y)
serverloop.Canvas.bg = love.graphics.newCanvas(constants.world.x, constants.world.y)
print("Startup!")
love.update = mainloop
love.draw = function()
love.graphics.clear(.2, 0, .2)
love.graphics.print("Poppy server is running.", fonts.normalFont, 20, 20)
love.graphics.print("listening on " .. socketString, fonts.normalFont, 20, 50)
return end
love.keyreleased = function() return end
love.keypressed = function() return end
love.mousepressed = function() return end
end
return serverloop

View File

@ -1,38 +1,31 @@
local constants = require("constants") local utils = require("shared.utils")
local util = require("utils")
local rpc = require("rpc") local constants = require("server.constants")
local rpc = require("server.rpc")
local clientCount = 0 local clientCount = 0
local world = {
x = 3000,
y = 3000,
id = "NYAAA"
}
return function(commands) return function(commands)
function commands.init(args, ip, port) function commands.init(args, ip, port)
clientCount = clientCount +1 clientCount = clientCount +1
local nickname, avatar = util.nextStringRecord(args) local nickname, avatar = utils.nextStringRecord(args)
clients[clientCount] = { ip = ip, port = port, name = nickname, avatar = avatar } clients[clientCount] = { ip = ip, port = port, name = nickname, avatar = avatar }
print("New client connected. Granting id: [" .. clientCount .. "] IP: " .. ip .. " Port:" .. port) print("New client connected. Granting id: [" .. clientCount .. "] IP: " .. ip .. " Port:" .. port)
for i, client in pairs(clients) do for i, client in pairs(clients) do
if i ~= clientCount then if i ~= clientCount then
print("Introducing client[" .. i .. "] and client[" .. clientCount .. "]")
-- to Existing client -- to Existing client
local payload = util.unit(protocolVersion, clientCount, "playerJoin", nickname, avatar) local payload = utils.unit(protocolVersion, clientCount, "playerJoin", nickname, avatar)
print("<= " .. util.pprint(payload))
server:sendto(payload, client.ip, client.port) server:sendto(payload, client.ip, client.port)
-- to New client -- to New client
local payload = util.unit(protocolVersion, i, "playerJoin", client.name, client.avatar) local payload = utils.unit(protocolVersion, i, "playerJoin", client.name, client.avatar)
print("<= " .. util.pprint(payload))
server:sendto(payload, ip, port) server:sendto(payload, ip, port)
end end
end end
-- Client response -- Client response
local response = util.unit(protocolVersion, clientCount, "init", nickname, avatar, world.id, world.x, world.y) local response = utils.unit(protocolVersion, clientCount, "init", nickname, avatar, constants.world.id, constants.world.x, constants.world.y)
server:sendto(response, ip, port) server:sendto(response, ip, port)
end end
end end

View File

@ -1,59 +0,0 @@
local tempTable = {}
function tempTable.unit(...)
local args = { ... }
local string = args[1]
assert(string, "No args to unit!")
for i=2, #args do
--print(type(string) .. "with" .. type(args[i]))
string = string .. string.char(31) .. args[i]
end
return string
end
function tempTable.resolve(record)
local tTable = {}
for entry in record:gmatch("[^\31]+") do
table.insert(tTable, entry)
end
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","|")
return 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",""))
table.insert(tTable, tonumber(last))
return unpack(tTable)
end
return tempTable

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.1 KiB

After

Width:  |  Height:  |  Size: 939 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.8 KiB