diff --git a/client/main.lua b/client/main.lua index 8848125..a30d03b 100644 --- a/client/main.lua +++ b/client/main.lua @@ -25,52 +25,40 @@ function love.load(args) local username = args[3] local socket = loex.socket.connect(address) - assert(socket) + assert(socket) local font = love.graphics.newFont(23) love.graphics.setFont(font) - game = {} - game.gravity = 42 -- TODO + game = {} + game.gravity = 42 -- TODO - game.socket = socket - game.username = username + game.socket = socket + game.username = username - game.ondraw = loex.signal.new() - game.onupdate = loex.signal.new() - game.onmousemoved = loex.signal.new() - game.onmousepressed = loex.signal.new() - game.onkeypressed = loex.signal.new() - game.onresize = loex.signal.new() - game.onquit = loex.signal.new() + game.ondraw = loex.signal.new() + game.onupdate = loex.signal.new() + game.onmousemoved = loex.signal.new() + game.onmousepressed = loex.signal.new() + game.onkeypressed = loex.signal.new() + game.onresize = loex.signal.new() + game.onquit = loex.signal.new() - require("screens.joinscreen").init(game) + require("screens.joinscreen").init(game) end -function love.update(dt) - game.onupdate:emit(game, dt) -end +function love.update(dt) game.onupdate:emit(game, dt) end -function love.draw() - game.ondraw:emit(game) -end +function love.draw() game.ondraw:emit(game) end -function love.mousepressed(x,y,button,istouch,presses) - game.onmousepressed:emit(game,x,y,button,istouch,presses) +function love.mousepressed(x, y, button, istouch, presses) + game.onmousepressed:emit(game, x, y, button, istouch, presses) end -function love.mousemoved(x, y, dx, dy,istouch) - game.onmousemoved:emit(game,x,y,dx,dy,istouch) -end +function love.mousemoved(x, y, dx, dy, istouch) game.onmousemoved:emit(game, x, y, dx, dy, istouch) end -function love.keypressed(k,scancode,isrepeat) - game.onkeypressed:emit(game, k, scancode, isrepeat) -end +function love.keypressed(k, scancode, isrepeat) game.onkeypressed:emit(game, k, scancode, isrepeat) end -function love.resize(w, h) - game.onresize:emit(game,w,h) -end +function love.resize(w, h) game.onresize:emit(game, w, h) end -function love.quit() - game.onquit:emit(game) -end +function love.quit() game.onquit:emit(game) end diff --git a/client/packets.lua b/client/packets.lua index 84c81df..52c6c6d 100644 --- a/client/packets.lua +++ b/client/packets.lua @@ -1,20 +1,12 @@ local packets = {} local encode = loex.socket.encode -function packets.place(x, y, z, t) - return encode {type="place",x=x,y=y,z=z,t=t} -end +function packets.place(x, y, z, t) return encode { type = "place", x = x, y = y, z = z, t = t } end -function packets.breaktile(x, y, z) - return encode {type="breaktile",x=x,y=y,z=z} -end +function packets.breaktile(x, y, z) return encode { type = "breaktile", x = x, y = y, z = z } end -function packets.join(username) - return encode {type="join", username=username} -end +function packets.join(username) return encode { type = "join", username = username } end -function packets.move(x, y, z) - return encode {type="move", x=x,y=y,z=z} -end +function packets.move(x, y, z) return encode { type = "move", x = x, y = y, z = z } end return packets diff --git a/client/quad.lua b/client/quad.lua index 92cf7b1..0579383 100644 --- a/client/quad.lua +++ b/client/quad.lua @@ -1,13 +1,13 @@ local a = -1.0 local b = 1.0 -return function (texture) - return g3d.newModel ({ - {0, a, a, 1, 1}, - {0, b, b, 0, 0}, - {0, b, a, 0, 1}, +return function(texture) + return g3d.newModel({ + { 0, a, a, 1, 1 }, + { 0, b, b, 0, 0 }, + { 0, b, a, 0, 1 }, - {0, a, a, 1, 1}, - {0, a, b, 1, 0}, - {0, b, b, 0, 0}, -}, texture) + { 0, a, a, 1, 1 }, + { 0, a, b, 1, 0 }, + { 0, b, b, 0, 0 }, + }, texture) end diff --git a/client/screens/chunkremesh.lua b/client/screens/chunkremesh.lua index f3922a9..eb32159 100644 --- a/client/screens/chunkremesh.lua +++ b/client/screens/chunkremesh.lua @@ -2,9 +2,7 @@ require("love.math") require("love.data") local ffi = require("ffi") -local channel, cx, cy, cz, blockdata, size, tids, -n1, n2, n3, n4, n5, n6, -c0, c1, c2, c3, c4, c5, c6 = ... +local channel, cx, cy, cz, blockdata, size, tids, n1, n2, n3, n4, n5, n6, c0, c1, c2, c3, c4, c5, c6 = ... local blockdatapointer = ffi.cast("uint8_t *", blockdata:getFFIPointer()) local n1p = n1 and ffi.cast("uint8_t *", n1:getFFIPointer()) @@ -23,7 +21,7 @@ local c5p = c5 and ffi.cast("uint8_t *", c5:getFFIPointer()) local c6p = c6 and ffi.cast("uint8_t *", c6:getFFIPointer()) local function getc(pointer, x, y, z) - if true then return 255 end + if true then return 255 end local i = x + size * y + size * size * z -- if this block is outside of the chunk, check the neighboring chunks if they exist @@ -92,7 +90,7 @@ if count > 0 then for i = start, stop, step do local primary = i % 2 == 1 local secondary = i > 2 and i < 6 - local c = getc(c0p, x,y,z) / 255 + local c = getc(c0p, x, y, z) / 255 datapointer[dataindex].x = x + (mx == 1 and primary and 1 or 0) + (mx == 2 and secondary and 1 or 0) datapointer[dataindex].y = y + (my == 1 and primary and 1 or 0) + (my == 2 and secondary and 1 or 0) datapointer[dataindex].z = z + (mz == 1 and primary and 1 or 0) + (mz == 2 and secondary and 1 or 0) diff --git a/client/screens/cursormodel.lua b/client/screens/cursormodel.lua index 0dd56bd..4d0bc28 100644 --- a/client/screens/cursormodel.lua +++ b/client/screens/cursormodel.lua @@ -1,43 +1,42 @@ local a = -0.005 local b = 1.005 return g3d.newModel { - { a, a, a }, - { b, a, a }, - { b, a, a }, - { a, a, a }, - { a, a, b }, - { a, a, b }, - { b, a, b }, - { a, a, b }, - { a, a, b }, - { b, a, b }, - { b, a, a }, - { b, a, a }, + { a, a, a }, + { b, a, a }, + { b, a, a }, + { a, a, a }, + { a, a, b }, + { a, a, b }, + { b, a, b }, + { a, a, b }, + { a, a, b }, + { b, a, b }, + { b, a, a }, + { b, a, a }, - { a, b, a }, - { b, b, a }, - { b, b, a }, - { a, b, a }, - { a, b, b }, - { a, b, b }, - { b, b, b }, - { a, b, b }, - { a, b, b }, - { b, b, b }, - { b, b, a }, - { b, b, a }, + { a, b, a }, + { b, b, a }, + { b, b, a }, + { a, b, a }, + { a, b, b }, + { a, b, b }, + { b, b, b }, + { a, b, b }, + { a, b, b }, + { b, b, b }, + { b, b, a }, + { b, b, a }, - { a, a, a }, - { a, b, a }, - { a, b, a }, - { b, a, a }, - { b, b, a }, - { b, b, a }, - { a, a, b }, - { a, b, b }, - { a, b, b }, - { b, a, b }, - { b, b, b }, - { b, b, b }, + { a, a, a }, + { a, b, a }, + { a, b, a }, + { b, a, a }, + { b, b, a }, + { b, b, a }, + { a, a, b }, + { a, b, b }, + { a, b, b }, + { b, a, b }, + { b, b, b }, + { b, b, b }, } - diff --git a/client/screens/errorscreen.lua b/client/screens/errorscreen.lua index 2b3c9aa..d5e9c1f 100644 --- a/client/screens/errorscreen.lua +++ b/client/screens/errorscreen.lua @@ -1,17 +1,17 @@ local errorscreen = {} local lg = love.graphics -function errorscreen.init(g, cause) - g.errorscreen = {} - g.errorscreen.cause = cause - g.ondraw:catch(errorscreen.draw) +function errorscreen.init(g, cause) + g.errorscreen = {} + g.errorscreen.cause = cause + g.ondraw:catch(errorscreen.draw) end function errorscreen.draw(g) lg.clear(1, 0, 0) local w, h = lg.getWidth(), lg.getHeight() - local cause = g.errorscreen.cause + local cause = g.errorscreen.cause w = w - lg.getFont():getWidth(cause) h = h - lg.getFont():getHeight() diff --git a/client/screens/gamescreen.lua b/client/screens/gamescreen.lua index a4c3b2f..79aef75 100644 --- a/client/screens/gamescreen.lua +++ b/client/screens/gamescreen.lua @@ -14,87 +14,82 @@ local CEILING = 10 local gamescreen = {} function gamescreen.init(g, player) - g.gamescreen = { - cursor = {}, - cursormodel = require("screens.cursormodel"), - texturepack = lg.newImage("assets/texturepack.png"), - threadpool = {}, - threadusage = 0, - mouse = {}, - placequeue = {}, - breakqueue = {}, - remeshqueue = {}, - remeshchannel = love.thread.newChannel(), - frameremeshes = 0, - synctimer = 0, - player=player, - } - - player.box = { - x = 0, - y = 0, - z = 0, - w = 0.3, - d = 0.3, - h = 0.9, - } - - -- load up some threads so that chunk meshing won't block the main thread - for i = 1, 8 do - g.gamescreen.threadpool[i] = love.thread.newThread("screens/chunkremesh.lua") - end - - g.gamescreen.player_model = quad(lg.newImage("assets/saul.png")) - g.gamescreen.snowball_model = quad(lg.newImage("assets/snowball.png")) - g.gamescreen.place_sound = love.sound.newSoundData("assets/audio/place.wav") - g.gamescreen.footstep_sounds = { - love.sound.newSoundData("assets/audio/footsteps/footstep-01.wav"), - love.sound.newSoundData("assets/audio/footsteps/footstep-02.wav"), - love.sound.newSoundData("assets/audio/footsteps/footstep-03.wav"), - love.sound.newSoundData("assets/audio/footsteps/footstep-04.wav"), - love.sound.newSoundData("assets/audio/footsteps/footstep-05.wav"), - love.sound.newSoundData("assets/audio/footsteps/footstep-06.wav"), - love.sound.newSoundData("assets/audio/footsteps/footstep-07.wav"), - love.sound.newSoundData("assets/audio/footsteps/footstep-08.wav"), - love.sound.newSoundData("assets/audio/footsteps/footstep-09.wav"), - } - - g.gamescreen.gravity = 42 + g.gamescreen = { + cursor = {}, + cursormodel = require("screens.cursormodel"), + texturepack = lg.newImage("assets/texturepack.png"), + threadpool = {}, + threadusage = 0, + mouse = {}, + placequeue = {}, + breakqueue = {}, + remeshqueue = {}, + remeshchannel = love.thread.newChannel(), + frameremeshes = 0, + synctimer = 0, + player = player, + } + + player.box = { + x = 0, + y = 0, + z = 0, + w = 0.3, + d = 0.3, + h = 0.9, + } + + -- load up some threads so that chunk meshing won't block the main thread + for i = 1, 8 do + g.gamescreen.threadpool[i] = love.thread.newThread("screens/chunkremesh.lua") + end + + g.gamescreen.player_model = quad(lg.newImage("assets/saul.png")) + g.gamescreen.snowball_model = quad(lg.newImage("assets/snowball.png")) + g.gamescreen.place_sound = love.sound.newSoundData("assets/audio/place.wav") + g.gamescreen.footstep_sounds = { + love.sound.newSoundData("assets/audio/footsteps/footstep-01.wav"), + love.sound.newSoundData("assets/audio/footsteps/footstep-02.wav"), + love.sound.newSoundData("assets/audio/footsteps/footstep-03.wav"), + love.sound.newSoundData("assets/audio/footsteps/footstep-04.wav"), + love.sound.newSoundData("assets/audio/footsteps/footstep-05.wav"), + love.sound.newSoundData("assets/audio/footsteps/footstep-06.wav"), + love.sound.newSoundData("assets/audio/footsteps/footstep-07.wav"), + love.sound.newSoundData("assets/audio/footsteps/footstep-08.wav"), + love.sound.newSoundData("assets/audio/footsteps/footstep-09.wav"), + } + + g.gamescreen.gravity = 42 lg.setMeshCullMode("back") - love.audio.setDistanceModel("inverseclamped") + love.audio.setDistanceModel("inverseclamped") - g.ondraw:catch(gamescreen.draw) - g.onupdate:catch(gamescreen.update) - g.onmousemoved:catch(gamescreen.onmousemoved) - --g.onmousepressed:catch(gamescreen.onmousepressed) - g.onkeypressed:catch(gamescreen.onkeypressed) + g.ondraw:catch(gamescreen.draw) + g.onupdate:catch(gamescreen.update) + g.onmousemoved:catch(gamescreen.onmousemoved) + --g.onmousepressed:catch(gamescreen.onmousepressed) + g.onkeypressed:catch(gamescreen.onkeypressed) g.world.ontilemodified:catch(gamescreen.ontilemodified, g) g.world.onentityinserted:catch(gamescreen.onentityinserted, g) g.world.onentityremoved:catch(gamescreen.onentityremoved, g) g.world.onchunkinserted:catch(gamescreen.onchunkinserted, g) g.world.onchunkremoved:catch(gamescreen.onchunkremoved, g) - require("services.nethandler").init(g) - require("services.player").init(g) - require("common.services.snowball").init(g) + require("services.nethandler").init(g) + require("services.player").init(g) + require("common.services.snowball").init(g) end - function gamescreen.onchunkinserted(g, chunk) local x, y, z = chunk.x, chunk.y, chunk.z - gamescreen.requestremesh(g,chunk) + gamescreen.requestremesh(g, chunk) end -function gamescreen.onchunkremoved(g,chunk) end +function gamescreen.onchunkremoved(g, chunk) end -function gamescreen.onentityinserted(g,entity) - print(entity.id .. " added") -end +function gamescreen.onentityinserted(g, entity) print(entity.id .. " added") end -function gamescreen.onentityremoved(g,entity) - print(entity.id .. " removed") -end +function gamescreen.onentityremoved(g, entity) print(entity.id .. " removed") end function gamescreen.onresize(g, w, h) g3d.camera.aspectRatio = w / h @@ -102,9 +97,9 @@ function gamescreen.onresize(g, w, h) end function gamescreen.update(g, dt) - local self = g.gamescreen - local mouse = self.mouse - local threadpool = self.threadpool + local self = g.gamescreen + local mouse = self.mouse + local threadpool = self.threadpool -- collect mouse inputs mouse.wasleft, mouse.wasright = mouse.left, mouse.right @@ -163,16 +158,37 @@ function gamescreen.update(g, dt) -- send over the neighboring chunks to the thread -- so that voxels on the edges can face themselves properly local n1, n2, n3, n4, n5, n6 = g.world:neighbourhood(c.x, c.y, c.z) - if not (n1 and n2 and n3 and n4 and n5 and n6) - or not g.world:chunk(loex.hash.spatial(c.x,c.y,CEILING-1)) then + if + not (n1 and n2 and n3 and n4 and n5 and n6) or not g.world:chunk(loex.hash.spatial(c.x, c.y, CEILING - 1)) + then offi = offi + 1 break end - c1, c2, c3, c4, c5, c6 = n1.cdata, n2.cdata, n3.cdata, n4.cdata, n5.cdata, n6.cdata n1, n2, n3, n4, n5, n6 = n1.data, n2.data, n3.data, n4.data, n5.data, n6.data - thread:start(self.remeshchannel, c.x, c.y, c.z, c.data, size, loex.tiles.id, n1, n2, n3, n4, n5, n6, c.cdata, c1,c2,c3,c4,c5,c6) + thread:start( + self.remeshchannel, + c.x, + c.y, + c.z, + c.data, + size, + loex.tiles.id, + n1, + n2, + n3, + n4, + n5, + n6, + c.cdata, + c1, + c2, + c3, + c4, + c5, + c6 + ) table.remove(self.remeshqueue, 1 + offi) self.threadusage = self.threadusage + 1 -- use up thread break @@ -180,7 +196,7 @@ function gamescreen.update(g, dt) end end - -- player movement + -- player movement local keyboard = love.keyboard local speed, jumpforce = 5, 12 local dirx, diry, dirz = g3d.camera.getLookVector() @@ -190,7 +206,7 @@ function gamescreen.update(g, dt) if keyboard.isDown("w") then move.x = move.x + dirx move.y = move.y + diry - end + end if keyboard.isDown("s") then move.x = move.x - dirx move.y = move.y - diry @@ -199,7 +215,7 @@ function gamescreen.update(g, dt) if keyboard.isDown("a") then move.x = move.x - diry move.y = move.y + dirx - end + end if keyboard.isDown("d") then move.x = move.x + diry move.y = move.y - dirx @@ -209,27 +225,27 @@ function gamescreen.update(g, dt) p.vz = p.vz - self.gravity * dt local onground = physics.moveandcollide(g.world, p, p.box, dt) - if onground and (move.x ~= 0 or move.y ~= 0) then - if not p.ssfootsteps:isPlaying() then - p.ssfootsteps:queue(self.footstep_sounds[math.random(1, #self.footstep_sounds)]) - assert(p.ssfootsteps:play()) - end - end + if onground and (move.x ~= 0 or move.y ~= 0) then + if not p.ssfootsteps:isPlaying() then + p.ssfootsteps:queue(self.footstep_sounds[math.random(1, #self.footstep_sounds)]) + assert(p.ssfootsteps:play()) + end + end g3d.camera.position[1] = p.x g3d.camera.position[2] = p.y g3d.camera.position[3] = p.z + 0.7 g3d.camera.lookInDirection() - -- player jump + -- player jump if onground and keyboard.isDown("space") then p.vz = jumpforce end - do + do local dx, dy, dz = g3d.camera.getLookVector() local x, y, z = g3d.camera.position[1], g3d.camera.position[2], g3d.camera.position[3] - love.audio.setPosition(x,y,z) - love.audio.setOrientation(dx,dy,dz, 0,0,1) - end + love.audio.setPosition(x, y, z) + love.audio.setOrientation(dx, dy, dz, 0, 0, 1) + end local syncinterval = 1 / 20 self.synctimer = self.synctimer + dt @@ -280,7 +296,8 @@ function gamescreen.update(g, dt) if tile == -1 then break end if tile > 0 then self.cursor = {} - self.cursor.placex, self.cursor.placey, self.cursor.placez = floor(x - dx * step), floor(y - dy * step), floor(z - dz * step) + self.cursor.placex, self.cursor.placey, self.cursor.placez = + floor(x - dx * step), floor(y - dy * step), floor(z - dz * step) self.cursor.x, self.cursor.y, self.cursor.z = tx, ty, tz break end @@ -289,7 +306,7 @@ function gamescreen.update(g, dt) local placetile = loex.tiles.slime.id - -- left click to break block + -- left click to break block if mouse.leftclick and self.cursor then local x, y, z = self.cursor.x, self.cursor.y, self.cursor.z self.breakqueue[("%d/%d/%d"):format(x, y, z)] = { @@ -321,22 +338,22 @@ function gamescreen.update(g, dt) } g.master:send(packets.place(x, y, z, placetile), CHANNEL_EVENTS, "reliable") g.world:tile(x, y, z, placetile) - gamescreen.play_place_sound(g,x, y, z) + gamescreen.play_place_sound(g, x, y, z) end end end -function gamescreen.play_place_sound(g,x,y,z) - local self = g.gamescreen - local source = love.audio.newSource(self.place_sound) - source:setPosition(x, y, z) - source:setAttenuationDistances(0.5,2000000) - source:setRolloff(0.3) - source:play() +function gamescreen.play_place_sound(g, x, y, z) + local self = g.gamescreen + local source = love.audio.newSource(self.place_sound) + source:setPosition(x, y, z) + source:setAttenuationDistances(0.5, 2000000) + source:setRolloff(0.3) + source:play() end function gamescreen.draw(g) - local self = g.gamescreen + local self = g.gamescreen lg.clear(lume.color("#4488ff")) lg.setColor(1, 1, 1) @@ -354,33 +371,35 @@ function gamescreen.draw(g) end lg.setMeshCullMode("back") - -- draw crosshair - local cross = 4 - lg.setColor(1,1,1) - lg.rectangle("fill", (lg.getWidth()-cross)/2, (lg.getHeight()-cross)/2, cross, cross) + -- draw crosshair + local cross = 4 + lg.setColor(1, 1, 1) + lg.rectangle("fill", (lg.getWidth() - cross) / 2, (lg.getHeight() - cross) / 2, cross, cross) end function gamescreen.throw_snowball(g) local x, y, z = g3d.camera.position[1], g3d.camera.position[2], g3d.camera.position[3] local dx, dy, dz = g3d.camera.getLookVector() - local force = 30 - g.master:send(socket.encode { - type="snowball_throw", - x=x,y=y,z=z, - vx=dx*force,vy=dy*force,vz=dz*force - }) - g.gamescreen.player.sssnowball_throw:play() + local force = 30 + g.master:send(socket.encode { + type = "snowball_throw", + x = x, + y = y, + z = z, + vx = dx * force, + vy = dy * force, + vz = dz * force, + }) + g.gamescreen.player.sssnowball_throw:play() end -function gamescreen.onmousemoved(g, x, y, dx, dy, istouch) - g3d.camera.firstPersonLook(dx, dy) -end +function gamescreen.onmousemoved(g, x, y, dx, dy, istouch) g3d.camera.firstPersonLook(dx, dy) end -function gamescreen.onkeypressed(g, k) - if k == "q" then - print("thrown snowball") - gamescreen.throw_snowball(g) - end +function gamescreen.onkeypressed(g, k) + if k == "q" then + print("thrown snowball") + gamescreen.throw_snowball(g) + end end function gamescreen.ontilemodified(g, x, y, z, _) @@ -403,11 +422,11 @@ function gamescreen.ontilemodified(g, x, y, z, _) end function gamescreen.requestremesh(g, c, priority) - local self = g.gamescreen + local self = g.gamescreen -- don't add a nil chunk or a chunk that's already in the queue local world = g.world if not c or c.inremesh or not c.data then return end - if not c.cdata then c.cdata = love.data.newByteData(size^3) end + if not c.cdata then c.cdata = love.data.newByteData(size ^ 3) end c.inremesh = true if priority then diff --git a/client/screens/joinscreen.lua b/client/screens/joinscreen.lua index 1c513f1..f8d28a8 100644 --- a/client/screens/joinscreen.lua +++ b/client/screens/joinscreen.lua @@ -7,96 +7,94 @@ local lg = love.graphics local joinscreen = {} function joinscreen.init(g) - local signals = { - g.ondraw:catch(joinscreen.draw), - g.socket.onconnect:catch(joinscreen.socket_onconnect, g), - g.socket.onreceive:catch(joinscreen.socket_onreceive, g), - g.socket.ondisconnect:catch(joinscreen.socket_ondisconnect, g), - } - g.joinscreen = {signals=signals} - - -- base functions - g.onupdate:catch(function(g) g.socket:service() end) - g.onquit:catch(function(g) g.socket:disconnect() end) + local signals = { + g.ondraw:catch(joinscreen.draw), + g.socket.onconnect:catch(joinscreen.socket_onconnect, g), + g.socket.onreceive:catch(joinscreen.socket_onreceive, g), + g.socket.ondisconnect:catch(joinscreen.socket_ondisconnect, g), + } + g.joinscreen = { signals = signals } + + -- base functions + g.onupdate:catch(function(g) g.socket:service() end) + g.onquit:catch(function(g) g.socket:disconnect() end) end function joinscreen.cleanup(g) - for _, signal in ipairs(g.joinscreen.signals) do signal:destroy() end - g.joinscreen = nil + for _, signal in ipairs(g.joinscreen.signals) do + signal:destroy() + end + g.joinscreen = nil end function joinscreen.error(g, cause) - joinscreen.cleanup(g) - errorscreen.init(g, cause) + joinscreen.cleanup(g) + errorscreen.init(g, cause) end function joinscreen.socket_onreceive(g, peer, d) - print("received " .. d.type) - if d.type == "joinsuccess" then - local spawnx, spawny, spawnz = d.x, d.y, d.z - assert(d.id) - - g.world = loex.world.new() - - local player = {id=d.id} - player.x, player.y, player.z = spawnx, spawny, spawnz - player.vx, player.vy, player.vz = 0,0,0 - player.username = g.username - - player.ssfootsteps = love.audio.newQueueableSource(48000, 16, 1) - player.ssfootsteps:setAttenuationDistances(1, 1) - player.sssnowball_throw = love.audio.newSource("assets/audio/snowball_throw.wav", "static") - - g.world:insert(player) - g.world:tag(player, "player") - - print( - ("Joined under username " .. player.username .. " (ID: " .. player.id .. ") at spawn point %d, %d, %d"):format( - spawnx, - spawny, - spawnz - ) - ) - joinscreen.cleanup(g) - gamescreen.init(g, player) - elseif d.type == "joinfailure" then - joinscreen.error(g, d.cause) - else - joinscreen.error(g,"unexpected packet type " .. d.typed) - end + print("received " .. d.type) + if d.type == "joinsuccess" then + local spawnx, spawny, spawnz = d.x, d.y, d.z + assert(d.id) + + g.world = loex.world.new() + + local player = { id = d.id } + player.x, player.y, player.z = spawnx, spawny, spawnz + player.vx, player.vy, player.vz = 0, 0, 0 + player.username = g.username + + player.ssfootsteps = love.audio.newQueueableSource(48000, 16, 1) + player.ssfootsteps:setAttenuationDistances(1, 1) + player.sssnowball_throw = love.audio.newSource("assets/audio/snowball_throw.wav", "static") + + g.world:insert(player) + g.world:tag(player, "player") + + print( + ("Joined under username " .. player.username .. " (ID: " .. player.id .. ") at spawn point %d, %d, %d"):format( + spawnx, + spawny, + spawnz + ) + ) + joinscreen.cleanup(g) + gamescreen.init(g, player) + elseif d.type == "joinfailure" then + joinscreen.error(g, d.cause) + else + joinscreen.error(g, "unexpected packet type " .. d.typed) + end end function joinscreen.socket_onconnect(g, peer) - print("connected!") + print("connected!") - -- set master peer - g.master = peer + -- set master peer + g.master = peer - -- send join - local join_packet = packets.join(g.username) - g.master:send(join_packet) + -- send join + local join_packet = packets.join(g.username) + g.master:send(join_packet) end -function joinscreen.socket_ondisconnect(g) - joinscreen.error(g,"connection closed") -end +function joinscreen.socket_ondisconnect(g) joinscreen.error(g, "connection closed") end -function joinscreen.update(g) - g.socket:service() -end +function joinscreen.update(g) g.socket:service() end function joinscreen.draw() local w, h = lg.getWidth(), lg.getHeight() - local l = 3 - local s = "" - local k = math.floor(love.timer.getTime()) % l - for i = 0, l-1 do - if i == k then - s = s .. "O" - else - s = s .. "o" - end + local l = 3 + local s = "" + local k = math.floor(love.timer.getTime()) % l + for i = 0, l - 1 do + if i == k then + s = s .. "O" + else + s = s .. "o" + end end w = w - lg.getFont():getWidth(s) diff --git a/client/services/nethandler.lua b/client/services/nethandler.lua index 0c028cc..b87c3df 100644 --- a/client/services/nethandler.lua +++ b/client/services/nethandler.lua @@ -1,14 +1,12 @@ local nethandler = {} -function nethandler.init(g) - g.socket.onreceive:catch(nethandler.onreceive, g) -end +function nethandler.init(g) g.socket.onreceive:catch(nethandler.onreceive, g) end function nethandler.onreceive(g, peer, d) - if d.type == "joinsuccess" then return end -- FIXME + if d.type == "joinsuccess" then return end -- FIXME - print("received " .. d.type) - nethandler[d.type](g, d) + print("received " .. d.type) + nethandler[d.type](g, d) end function nethandler.broken(g, d) @@ -19,13 +17,13 @@ function nethandler.broken(g, d) end function nethandler.placed(g, d) - local gamescreen = require("screens.gamescreen") + local gamescreen = require("screens.gamescreen") local x, y, z, t = tonumber(d.x), tonumber(d.y), tonumber(d.z), tonumber(d.t) local hash = ("%d/%d/%d"):format(x, y, z) - if not g.gamescreen.placequeue[hash] or g.gamescreen.placequeue[hash].t ~= t then - g.world:tile(x, y, z, t) - gamescreen.play_place_sound(g, x, y, z) - end + if not g.gamescreen.placequeue[hash] or g.gamescreen.placequeue[hash].t ~= t then + g.world:tile(x, y, z, t) + gamescreen.play_place_sound(g, x, y, z) + end g.gamescreen.placequeue[hash] = nil end @@ -39,20 +37,17 @@ function nethandler.entitymove(g, d) entity.z = z end -function nethandler.entityadd(g, d) -end +function nethandler.entityadd(g, d) end -function nethandler.entityremove(g, d) - g.world:remove(g.world:entity(d.id)) -end +function nethandler.entityremove(g, d) g.world:remove(g.world:entity(d.id)) end function nethandler.entityremoteset(g, d) local entity = g.world:entity(d.id) - for k, v in pairs(d.properties) do - if not (entity.id == g.gamescreen.player.id and k:match("[xyz]")) then -- TODO: position correction - entity[k] = v - end - end + for k, v in pairs(d.properties) do + if not (entity.id == g.gamescreen.player.id and k:match("[xyz]")) then -- TODO: position correction + entity[k] = v + end + end end function nethandler.chunkadd(g, d) diff --git a/client/services/player.lua b/client/services/player.lua index 8b831a5..159f388 100644 --- a/client/services/player.lua +++ b/client/services/player.lua @@ -2,36 +2,35 @@ local player = {} local lg = love.graphics function player.init(g) - g.socket.onreceive:catch(player.onreceive, g) + g.socket.onreceive:catch(player.onreceive, g) - g.onupdate:catch(player.onupdate) - g.ondraw:catch(player.ondraw) + g.onupdate:catch(player.onupdate) + g.ondraw:catch(player.ondraw) end function player.onreceive(g, _, packet) - if packet.type == "entityadd" and packet.entity_type == "player" then - local e = { id=packet.id,x=packet.x,y=packet.y,z=packet.z, username=packet.username } - g.world:insert(e) - g.world:tag(e, "player") - end + if packet.type == "entityadd" and packet.entity_type == "player" then + local e = { id = packet.id, x = packet.x, y = packet.y, z = packet.z, username = packet.username } + g.world:insert(e) + g.world:tag(e, "player") + end end -function player.onupdate(g) -end +function player.onupdate(g) end function player.ondraw(g) - local player_model = g.gamescreen.player_model - local camera = g3d.camera.position + local player_model = g.gamescreen.player_model + local camera = g3d.camera.position lg.setMeshCullMode("none") lg.setColor(1, 1, 1) for _, e in pairs(g.world:query("player")) do if e ~= g.gamescreen.player then - player_model:setTranslation(e.x, e.y, e.z) - player_model:setRotation(0, 0, math.atan2(e.y - camera[2], e.x - camera[1])) - player_model:setScale(1, 0.6, 0.9) - player_model:draw() + player_model:setTranslation(e.x, e.y, e.z) + player_model:setRotation(0, 0, math.atan2(e.y - camera[2], e.x - camera[1])) + player_model:setScale(1, 0.6, 0.9) + player_model:draw() end end end diff --git a/common/physics.lua b/common/physics.lua index 5170b7c..b60424d 100644 --- a/common/physics.lua +++ b/common/physics.lua @@ -1,19 +1,19 @@ local physics = {} -local tiles = loex.tiles +local tiles = loex.tiles local cube = { w = 0.5, h = 0.5, d = 0.5, x = 0, y = 0, z = 0 } local epsilonx, epsilony, epsilonz = 0.0045, 0.002, 0.005 local utils = loex.utils local floor, min, max = math.floor, math.min, math.max local expandb, iterb, intersectbb = utils.expandb, utils.iterb, utils.intersectbb -function physics.intersect_point_world(world, x, y, z) - local i,j,k = floor(x), floor(y), floor(z) - return world:tile(i, j, k) > 0 +function physics.intersect_point_world(world, x, y, z) + local i, j, k = floor(x), floor(y), floor(z) + return world:tile(i, j, k) > 0 end function physics.moveandcollide(world, e, box, dt) - local bounce = 0 + local bounce = 0 local dx, dy, dz = e.vx * dt, e.vy * dt, e.vz * dt local x, y, z = e.x, e.y, e.z @@ -21,8 +21,8 @@ function physics.moveandcollide(world, e, box, dt) local onground = false - -- Z MOVEMENT - local collidedz = false + -- Z MOVEMENT + local collidedz = false local boxz = expandb(lume.clone(box), 0, 0, dz) boxz.x = boxz.x + x boxz.y = boxz.y + y @@ -37,19 +37,17 @@ function physics.moveandcollide(world, e, box, dt) if dz < 0 then dz = min(max(dz, (k + 1 + epsilonz) - (z - h)), 0) onground = true - bounce = (bounce + (tiles.id[t].bounce or 0)) * 0.5 + bounce = (bounce + (tiles.id[t].bounce or 0)) * 0.5 else dz = max(min(dz, (k - epsilonz) - (z + h)), 0) - end - collidedz = true + end + collidedz = true end end end - if collidedz then - e.vz = -e.vz * bounce - end + if collidedz then e.vz = -e.vz * bounce end - -- X MOVEMENT + -- X MOVEMENT local boxx = expandb(lume.clone(box), dx, 0, dz) boxx.x = boxx.x + x boxx.y = boxx.y + y @@ -71,7 +69,7 @@ function physics.moveandcollide(world, e, box, dt) end end - -- Y MOVEMENT + -- Y MOVEMENT local boxy = expandb(lume.clone(box), dx, dy, dz) boxy.x = boxy.x + x boxy.y = boxy.y + y diff --git a/common/services/snowball.lua b/common/services/snowball.lua index e9a766b..3ef501d 100644 --- a/common/services/snowball.lua +++ b/common/services/snowball.lua @@ -4,59 +4,61 @@ local lg = love.graphics local snowball = {} function snowball.init(g) - g.onupdate:catch(snowball.onupdate) -- client side prediction also - if g.master then - g.socket.onreceive:catch(snowball.onreceive_client, g) - g.ondraw:catch(snowball.ondraw) - end + g.onupdate:catch(snowball.onupdate) -- client side prediction also + if g.master then + g.socket.onreceive:catch(snowball.onreceive_client, g) + g.ondraw:catch(snowball.ondraw) + end end function snowball.onreceive_client(g, peer, packet) - if packet.type == "entityadd" and packet.entity_type == "snowball" then - print("SNOWBALL ADDED") - snowball.entity(g, packet.id, packet.x, packet.y, packet.z, packet.vx, packet.vy, packet.vz) - end + if packet.type == "entityadd" and packet.entity_type == "snowball" then + print("SNOWBALL ADDED") + snowball.entity(g, packet.id, packet.x, packet.y, packet.z, packet.vx, packet.vy, packet.vz) + end end function snowball.ondraw(g) - local snowball_model = g.gamescreen.snowball_model - local camera = g3d.camera.position + local snowball_model = g.gamescreen.snowball_model + local camera = g3d.camera.position lg.setMeshCullMode("none") lg.setColor(1, 1, 1) for _, e in pairs(g.world:query("snowball")) do if e ~= g.gamescreen.player then - local dx,dy,dz = e.x-camera[1], e.y-camera[2], e.z-camera[3] - snowball_model:setTranslation(e.x, e.y, e.z) - snowball_model:setRotation(0, -math.atan2(dz, math.sqrt(dx*dx+dy*dy)), math.atan2(e.y - camera[2], e.x - camera[1])) - snowball_model:setScale(0.4, 0.4, 0.4) - snowball_model:draw() + local dx, dy, dz = e.x - camera[1], e.y - camera[2], e.z - camera[3] + snowball_model:setTranslation(e.x, e.y, e.z) + snowball_model:setRotation( + 0, + -math.atan2(dz, math.sqrt(dx * dx + dy * dy)), + math.atan2(e.y - camera[2], e.x - camera[1]) + ) + snowball_model:setScale(0.4, 0.4, 0.4) + snowball_model:draw() end end end function snowball.onupdate(g, dt) - for _, e in pairs(g.world:query("snowball")) do - e.vz = e.vz - g.gravity * dt - e.x = e.x + e.vx * dt - e.y = e.y + e.vy * dt - e.z = e.z + e.vz * dt - - if g.master == nil and physics.intersect_point_world(g.world, e.x, e.y, e.z) then - g.world:tag(e, "destroyed") - end - end + for _, e in pairs(g.world:query("snowball")) do + e.vz = e.vz - g.gravity * dt + e.x = e.x + e.vx * dt + e.y = e.y + e.vy * dt + e.z = e.z + e.vz * dt + + if g.master == nil and physics.intersect_point_world(g.world, e.x, e.y, e.z) then g.world:tag(e, "destroyed") end + end end function snowball.entity(g, id, x, y, z, vx, vy, vz) - local e = {id=id} - e.x, e.y, e.z = x, y, z - e.vx, e.vy, e.vz = vx, vy, vz + local e = { id = id } + e.x, e.y, e.z = x, y, z + e.vx, e.vy, e.vz = vx, vy, vz - g.world:insert(e) - g.world:tag(e, "snowball") - return e + g.world:insert(e) + g.world:tag(e, "snowball") + return e end return snowball diff --git a/common/signal.lua b/common/signal.lua index a48f5a1..5aa6320 100644 --- a/common/signal.lua +++ b/common/signal.lua @@ -4,36 +4,33 @@ signal.__index = signal local signal_handle = {} signal_handle.__index = signal_handle -function signal_handle:destroy() - self.signal.subs[self.id] = nil -end +function signal_handle:destroy() self.signal.subs[self.id] = nil end function signal.new() local new = {} new.subs = {} - new.idc = 0 + new.idc = 0 setmetatable(new, signal) return new end -function signal:catch(f, ...) - assert(f) - local handle = {signal=self, id=self.idc} - setmetatable(handle, signal_handle) - self.idc = self.idc + 1 +function signal:catch(f, ...) + assert(f) + local handle = { signal = self, id = self.idc } + setmetatable(handle, signal_handle) + self.idc = self.idc + 1 - self.subs[handle.id] = { f = f, opt = { ... } } - return handle + self.subs[handle.id] = { f = f, opt = { ... } } + return handle end function signal:emit(...) for id, sub in pairs(self.subs) do if #sub.opt ~= 0 then - - local args = { ... } - for n=#sub.opt,1,-1 do - table.insert(args, 1, sub.opt[n]) - end + local args = { ... } + for n = #sub.opt, 1, -1 do + table.insert(args, 1, sub.opt[n]) + end sub.f(unpack(args)) else diff --git a/common/socket.lua b/common/socket.lua index d11e17d..c366aa6 100644 --- a/common/socket.lua +++ b/common/socket.lua @@ -36,16 +36,16 @@ function socket.connect(address) end function socket.encode(t) - local p - if t.bin then - local bin = t.bin - t.bin = nil - p = json.encode(t) - p = p .. bin - else - p = json.encode(t) - end - return p + local p + if t.bin then + local bin = t.bin + t.bin = nil + p = json.encode(t) + p = p .. bin + else + p = json.encode(t) + end + return p end -- function socket:broadcast(data, channel, mode, dest) @@ -88,11 +88,9 @@ end --end -- function socket.decode(p) - local t, idx = json.decode(p) - if idx <= #p then - t.bin = string.sub(p,idx,#p) - end - return t + local t, idx = json.decode(p) + if idx <= #p then t.bin = string.sub(p, idx, #p) end + return t end function socket:peerdata(peer) return self.peerdatas[peer:index()] end diff --git a/common/tiles.lua b/common/tiles.lua index af7d037..88c5bbf 100644 --- a/common/tiles.lua +++ b/common/tiles.lua @@ -9,7 +9,7 @@ tiles.tiles = { bricks = { id = 5, tex = 3 }, leaves = { id = 6, tex = 16 }, log = { id = 7, tex = { 22, 22, 21, 21, 21, 21 } }, - slime = { id = 8, tex = 5, bounce=0.8 }, + slime = { id = 8, tex = 5, bounce = 0.8 }, } local id = {} diff --git a/common/world.lua b/common/world.lua index bc5067f..ea30126 100644 --- a/common/world.lua +++ b/common/world.lua @@ -11,7 +11,7 @@ function world.new() new.chunks = {} new.entities = {} - new.tagtables = {} + new.tagtables = {} new.ontilemodified = loex.signal.new() new.onentityinserted = loex.signal.new() @@ -31,61 +31,55 @@ function world:insert(e) end function world:tag(e, tag) - local tagtable = self.tagtables[tag] - if not tagtable then - tagtable = {} - self.tagtables[tag] = tagtable - end - tagtable[e.id] = e - - return tags + local tagtable = self.tagtables[tag] + if not tagtable then + tagtable = {} + self.tagtables[tag] = tagtable + end + tagtable[e.id] = e + + return tags end function world:untag(e, tag) - local tagtable = self.tagtables[tag] - if tagtable then - tagtable[e.id] = nil - end + local tagtable = self.tagtables[tag] + if tagtable then tagtable[e.id] = nil end end function world:tagged(e, tag) - local tagtable = self.tagtables[tag] - return tagtable and tagtable[e.id] + local tagtable = self.tagtables[tag] + return tagtable and tagtable[e.id] end function world:remove(e) assert(self.entities[e.id], "entity does not exist") - local e = self.entities[e.id] + local e = self.entities[e.id] self.entities[e.id] = nil - for _, tagtable in pairs(self.tagtables) do - tagtable[e.id] = nil - end + for _, tagtable in pairs(self.tagtables) do + tagtable[e.id] = nil + end self.onentityremoved:emit(e) end local function intersect(a, b) - local t = {} - if a == nil or b == nil then - return t - end - - for k, _ in pairs(a) do - if b[k] ~= nil then - t[k]=true - end - end - return t + local t = {} + if a == nil or b == nil then return t end + + for k, _ in pairs(a) do + if b[k] ~= nil then t[k] = true end + end + return t end function world:query(...) local tags = { ... } - if #tags == 0 then return self.entities end + if #tags == 0 then return self.entities end local query = self.tagtables[tags[1]] - for i=2,#tags do - query = intersect(query, self.tagtables[tags[i]]) + for i = 2, #tags do + query = intersect(query, self.tagtables[tags[i]]) end return query or {} end diff --git a/server/game.lua b/server/game.lua index ea91685..6be4523 100644 --- a/server/game.lua +++ b/server/game.lua @@ -8,13 +8,13 @@ local size = loex.chunk.size local game = {} function game.new() - local new = {} - setmetatable(new, { __index = game }) - return new + local new = {} + setmetatable(new, { __index = game }) + return new end function game:init(socket) - self.socket = socket + self.socket = socket self.world = loex.world.new() self.world.onentityinserted:catch(self.world_onentityinserted, self) @@ -22,35 +22,31 @@ function game:init(socket) self.genstate = gen.state.new(overworld.layers, 43242) - self.gravity = 42 + self.gravity = 42 - self.onupdate = loex.signal.new() - self.onshutdown = loex.signal.new() + self.onupdate = loex.signal.new() + self.onshutdown = loex.signal.new() - require("services.connection_manager").init(self) - require("services.player").init(self) - require("services.sync").init(self) - require("common.services.snowball").init(self) + require("services.connection_manager").init(self) + require("services.player").init(self) + require("services.sync").init(self) + require("common.services.snowball").init(self) end function game:update(dt) self.socket:service() - self.onupdate:emit(self, dt) + self.onupdate:emit(self, dt) end -function game:world_onentityinserted(e) - print(e.id .. " added") -end +function game:world_onentityinserted(e) print(e.id .. " added") end -function game:world_onentityremoved(e) - print(e.id .. " removed") -end +function game:world_onentityremoved(e) print(e.id .. " removed") end function game:shutdown() - print("shutting down...") - self.socket:disconnect() - self.onshutdown:emit(self) + print("shutting down...") + self.socket:disconnect() + self.onshutdown:emit(self) end return game diff --git a/server/main.lua b/server/main.lua index a8ff219..3a8514b 100644 --- a/server/main.lua +++ b/server/main.lua @@ -9,7 +9,7 @@ CHANNEL_CHUNKS = 1 CHANNEL_EVENTS = 3 CHANNEL_UPDATES = 4 -local game +local game function love.load(args) if #args < 1 then @@ -21,16 +21,10 @@ function love.load(args) print("starting server on port " .. tostring(port) .. "...") local socket = loex.socket.host(port, 64) - game = require("game").new() - game:init(socket) + game = require("game").new() + game:init(socket) end +function love.update(dt) game:update(dt) end -function love.update(dt) - game:update(dt) -end - -function love.quit() - game:shutdown() -end - +function love.quit() game:shutdown() end diff --git a/server/packets.lua b/server/packets.lua index ec9da83..4fc299f 100644 --- a/server/packets.lua +++ b/server/packets.lua @@ -1,45 +1,35 @@ local packets = {} local encode = loex.socket.encode -function packets.joinsuccess(id, x, y, z) - return encode { - type="joinsuccess", - x=x, - y=y, - z=z, - id=id - } +function packets.joinsuccess(id, x, y, z) + return encode { + type = "joinsuccess", + x = x, + y = y, + z = z, + id = id, + } end -function packets.joinfailure(cause) - return encode { - type="joinfailure", - cause=cause - } +function packets.joinfailure(cause) + return encode { + type = "joinfailure", + cause = cause, + } end -function packets.chunkadd(tiles, cx, cy, cz) - return encode { type="chunkadd", cx=cx, cy=cy, cz=cz, bin=tiles } -end +function packets.chunkadd(tiles, cx, cy, cz) return encode { type = "chunkadd", cx = cx, cy = cy, cz = cz, bin = tiles } end -function packets.chunkremove(cx, cy, cz) - return encode { type="chunkremove", cx=cx,cy=cy,cz=cz } -end +function packets.chunkremove(cx, cy, cz) return encode { type = "chunkremove", cx = cx, cy = cy, cz = cz } end -function packets.placed(x, y, z, t) - return encode { type="placed",x=x,y=y,z=z,t=t } -end +function packets.placed(x, y, z, t) return encode { type = "placed", x = x, y = y, z = z, t = t } end -function packets.broken(x, y, z) - return encode { type="broken", x=x,y=y,z=z} -end +function packets.broken(x, y, z) return encode { type = "broken", x = x, y = y, z = z } end -function packets.entityadd(id) - return encode {type="entityadd", id=id } -end +function packets.entityadd(id) return encode { type = "entityadd", id = id } end function packets.entityremove(id) -- TODO: get rid of this packet - return encode {type="entityremove", id=id} + return encode { type = "entityremove", id = id } end -- function packets.entitymove(id, x, y, z) @@ -47,11 +37,11 @@ end -- end function packets.entityremoteset(id, properties) - return encode { - type="entityremoteset", - id=id, - properties=properties, - } + return encode { + type = "entityremoteset", + id = id, + properties = properties, + } end return packets diff --git a/server/services/connection_manager.lua b/server/services/connection_manager.lua index 3039dd4..7382019 100644 --- a/server/services/connection_manager.lua +++ b/server/services/connection_manager.lua @@ -1,4 +1,4 @@ -local player = require("services.player") +local player = require("services.player") local packets = require("packets") local connection_manager = {} @@ -17,26 +17,24 @@ function connection_manager.verify_username(g, username) if g.taken_usernames[username] then return "Username already taken. Try again :)" end end -function connection_manager.init(g) - g.banlist = {} -- TODO: load from list - g.taken_usernames = {} +function connection_manager.init(g) + g.banlist = {} -- TODO: load from list + g.taken_usernames = {} - g.socket.onconnect:catch(connection_manager.socket_onconnect, g) - g.socket.ondisconnect:catch(connection_manager.socket_ondisconnect, g) - g.socket.onreceive:catch(connection_manager.socket_onreceive, g) + g.socket.onconnect:catch(connection_manager.socket_onconnect, g) + g.socket.ondisconnect:catch(connection_manager.socket_ondisconnect, g) + g.socket.onreceive:catch(connection_manager.socket_onreceive, g) end -function connection_manager.socket_onconnect(g, peer) - print("new connection!") -end +function connection_manager.socket_onconnect(g, peer) print("new connection!") end function connection_manager.socket_ondisconnect(g, peer) - local socket = g.socket + local socket = g.socket local peerdata = socket:peerdata(peer) if peerdata.playerentity then print(peerdata.playerentity.username .. " left the game :<") - g.world:tag(peerdata.playerentity, "destroyed") + g.world:tag(peerdata.playerentity, "destroyed") g.taken_usernames[peerdata.playerentity.username] = nil end end @@ -44,8 +42,8 @@ end function connection_manager.socket_onreceive(g, peer, packet) print("received " .. packet.type) - local socket = g.socket - local world = g.world + local socket = g.socket + local world = g.world local peerdata = socket:peerdata(peer) @@ -58,7 +56,7 @@ function connection_manager.socket_onreceive(g, peer, packet) return end - -- spawn player + -- spawn player local p = player.entity(g, world, lume.uuid(), 0, 0, 180, packet.username, peer) peer:send(packets.joinsuccess(p.id, p.x, p.y, p.z), CHANNEL_ONE) diff --git a/server/services/player.lua b/server/services/player.lua index 454e276..73d0bcf 100644 --- a/server/services/player.lua +++ b/server/services/player.lua @@ -10,60 +10,60 @@ local floor = math.floor local player = {} function player.init(g) - assert(g.master == nil) - g.onupdate:catch(player.update) - g.socket.onreceive:catch(player.socket_onreceive, g) + assert(g.master == nil) + g.onupdate:catch(player.update) + g.socket.onreceive:catch(player.socket_onreceive, g) g.world.ontilemodified:catch(player.world_ontilemodified, g) g.world.onentityremoved:catch(player.world_onentityremoved, g) end -function player.view_onchunkinserted(g, p, c) - p.master:send(packets.chunkadd(c:dump(), c.x, c.y, c.z)) -end - -function player.view_onchunkremoved(g, p, c) - p.master:send(packets.chunkremove(c.x, c.y, c.z)) -end - -function player.view_onentityinserted(g, p, e) - -- TODO: need abstraction for this - if g.world:tagged(e, "player") then - p.master:send(socket.encode { - type="entityadd", - id=e.id, - x=e.x,y=e.y,z=e.z, - username=e.username, - entity_type="player" - }) - elseif g.world:tagged(e, "snowball") then - p.master:send(socket.encode { - type="entityadd", - id=e.id, - x=e.x,y=e.y,z=e.z, - vx=e.vx,vy=e.vy,vz=e.vz, - entity_type="snowball", - }) - end +function player.view_onchunkinserted(g, p, c) p.master:send(packets.chunkadd(c:dump(), c.x, c.y, c.z)) end + +function player.view_onchunkremoved(g, p, c) p.master:send(packets.chunkremove(c.x, c.y, c.z)) end + +function player.view_onentityinserted(g, p, e) + -- TODO: need abstraction for this + if g.world:tagged(e, "player") then + p.master:send(socket.encode { + type = "entityadd", + id = e.id, + x = e.x, + y = e.y, + z = e.z, + username = e.username, + entity_type = "player", + }) + elseif g.world:tagged(e, "snowball") then + p.master:send(socket.encode { + type = "entityadd", + id = e.id, + x = e.x, + y = e.y, + z = e.z, + vx = e.vx, + vy = e.vy, + vz = e.vz, + entity_type = "snowball", + }) + end end -function player.view_onentityremoved(g, p, e) - p.master:send(packets.entityremove(e.id)) -end +function player.view_onentityremoved(g, p, e) p.master:send(packets.entityremove(e.id)) end function player.entity(g, w, id, x, y, z, username, master) - local e = {id=id} - - e.last_throw = os.time() - e.x, e.y, e.z = x, y, z - e.vx, e.vy, e.vz = 0, 0, 0 - e.box = { - x = 0, - y = 0, - z = 0, - w = 0.3, - d = 0.3, - h = 0.9, - } + local e = { id = id } + + e.last_throw = os.time() + e.x, e.y, e.z = x, y, z + e.vx, e.vy, e.vz = 0, 0, 0 + e.box = { + x = 0, + y = 0, + z = 0, + w = 0.3, + d = 0.3, + h = 0.9, + } e.username = username e.master = master @@ -73,10 +73,10 @@ function player.entity(g, w, id, x, y, z, username, master) e.view.onentityinserted:catch(player.view_onentityinserted, g, e) e.view.onentityremoved:catch(player.view_onentityremoved, g, e) - e.remote = {} + e.remote = {} - w:insert(e) - w:tag(e, "box") + w:insert(e) + w:tag(e, "box") w:tag(e, "player") return e @@ -90,11 +90,11 @@ function player.inview(e, x, y, z) end function player.socket_onreceive(g, peer, d) - if d.type == "join" then return end -- FIXME - local p = g.socket:peerdata(peer).playerentity - if not p then return end + if d.type == "join" then return end -- FIXME + local p = g.socket:peerdata(peer).playerentity + if not p then return end - local world = g.world + local world = g.world local handles = { ["move"] = function(p, d) @@ -111,29 +111,29 @@ function player.socket_onreceive(g, peer, d) local x, y, z = tonumber(d.x), tonumber(d.y), tonumber(d.z) world:tile(x, y, z, loex.tiles.air.id) end, - ["snowball_throw"] = function(p, d) - -- throw snowballs - --if os.time() - p.last_throw > 0.05 then - print("thrown snowball") - p.last_throw = os.time() - - local e = snowball.entity(g, lume.uuid(), d.x, d.y, d.z, d.vx, d.vy, d.vz) - e.remote = {} - --end - end + ["snowball_throw"] = function(p, d) + -- throw snowballs + --if os.time() - p.last_throw > 0.05 then + print("thrown snowball") + p.last_throw = os.time() + + local e = snowball.entity(g, lume.uuid(), d.x, d.y, d.z, d.vx, d.vy, d.vz) + e.remote = {} + --end + end, } handles[d.type](p, d) end function player.world_onentityremoved(g, e) - local world = g.world + local world = g.world for _, p in pairs(world:query("player")) do if p.view:entity(e) then p.view:remove(e) end end end function player.world_ontilemodified(g, x, y, z, t) - local world = g.world + local world = g.world local packet if t == loex.tiles.air.id then packet = packets.broken(x, y, z) @@ -142,66 +142,64 @@ function player.world_ontilemodified(g, x, y, z, t) end for _, p in pairs(world:query("player")) do - if p.view:tile(x, y, z) >= 0 then - p.master:send(packet) - end + if p.view:tile(x, y, z) >= 0 then p.master:send(packet) end end end function player.update(g, dt) - local world = g.world - local genstate = g.genstate + local world = g.world + local genstate = g.genstate local gendistance = 5 - for _, p in pairs(g.world:query("player")) do - - -- generate world - for i = -gendistance + floor(p.x / size), gendistance + floor(p.x / size) do - for j = -gendistance + floor(p.y / size), gendistance + floor(p.y / size) do - for k = 0, overworld.columnheight - 1 do - if not world:chunk(loex.hash.spatial(i, j, k)) then - local c = overworld:generate(genstate, i, j, k) - world:insertchunk(c) - end - end - end - end - - - -- compute chunks in player view - for _, c in pairs(world.chunks) do - if not player.inview(p, c.x * size, c.y * size, c.z * size) then - if p.view.chunks[c.hash] then p.view:removechunk(c.hash) end - else - if not p.view.chunks[c.hash] then p.view:insertchunk(c) end - end - end - - -- compute entities in player view - for _, e in pairs(world.entities) do - if e ~= p then - if not player.inview(p, e.x, e.y, e.z) then - if p.view:entity(e.id) then p.view:remove(e) end - else - if not p.view:entity(e.id) then - p.view:insert(e) - else - -- TODO: this is bad, really bad - if not (e.remote.x == e.x and e.remote.y == e.y and e.remote.z == e.z) then - p.master:send(socket.encode { - type="entityremoteset", - id=e.id, - properties={x=e.x,y=e.y,z=e.z}, - }) - end - end - end - end - end - end - for _, e in pairs(world.entities) do - if e.remote then e.remote.x, e.remote.y, e.remote.z = e.x, e.y, e.z end - end + for _, p in pairs(g.world:query("player")) do + -- generate world + for i = -gendistance + floor(p.x / size), gendistance + floor(p.x / size) do + for j = -gendistance + floor(p.y / size), gendistance + floor(p.y / size) do + for k = 0, overworld.columnheight - 1 do + if not world:chunk(loex.hash.spatial(i, j, k)) then + local c = overworld:generate(genstate, i, j, k) + world:insertchunk(c) + end + end + end + end + + -- compute chunks in player view + for _, c in pairs(world.chunks) do + if not player.inview(p, c.x * size, c.y * size, c.z * size) then + if p.view.chunks[c.hash] then p.view:removechunk(c.hash) end + else + if not p.view.chunks[c.hash] then p.view:insertchunk(c) end + end + end + + -- compute entities in player view + for _, e in pairs(world.entities) do + if e ~= p then + if not player.inview(p, e.x, e.y, e.z) then + if p.view:entity(e.id) then p.view:remove(e) end + else + if not p.view:entity(e.id) then + p.view:insert(e) + else + -- TODO: this is bad, really bad + if not (e.remote.x == e.x and e.remote.y == e.y and e.remote.z == e.z) then + p.master:send(socket.encode { + type = "entityremoteset", + id = e.id, + properties = { x = e.x, y = e.y, z = e.z }, + }) + end + end + end + end + end + end + for _, e in pairs(world.entities) do + if e.remote then + e.remote.x, e.remote.y, e.remote.z = e.x, e.y, e.z + end + end end return player diff --git a/server/services/sync.lua b/server/services/sync.lua index 2d3dec7..fa09986 100644 --- a/server/services/sync.lua +++ b/server/services/sync.lua @@ -1,46 +1,41 @@ local sync = {} -local packets = require "packets" +local packets = require("packets") -function sync.init(g) - g.onupdate:catch(sync.update) -end +function sync.init(g) g.onupdate:catch(sync.update) end function sync.update(g, dt) - local world = g.world - local socket = g.socket + local world = g.world + local socket = g.socket - local genstate = g.genstate + local genstate = g.genstate for _, e in pairs(world.entities) do - --- -- sync edits --- local p_edits, p_edits_count = e:property_edits() --- local t_edits, t_edits_count = e:tag_edits() --- --- if p_edits_count > 0 or t_edits_count > 0 then --- local packet = packets.entityremoteset(e.id, p_edits, t_edits) --- e:clear_tag_edits() --- e:clear_property_edits() --- --- for _, p in ipairs(world:query("player")) do --- if p.view:entity(e.id) then p.master:send(packet) end --- end --- end - - -- sync destroys - if g.world:tagged(e, "destroyed") then - for _, p in pairs(world:query("player")) do - if p.view:entity(e.id) then - p.view:remove(e) - end - end - end + -- -- sync edits + -- local p_edits, p_edits_count = e:property_edits() + -- local t_edits, t_edits_count = e:tag_edits() + -- + -- if p_edits_count > 0 or t_edits_count > 0 then + -- local packet = packets.entityremoteset(e.id, p_edits, t_edits) + -- e:clear_tag_edits() + -- e:clear_property_edits() + -- + -- for _, p in ipairs(world:query("player")) do + -- if p.view:entity(e.id) then p.master:send(packet) end + -- end + -- end + + -- sync destroys + if g.world:tagged(e, "destroyed") then + for _, p in pairs(world:query("player")) do + if p.view:entity(e.id) then p.view:remove(e) end + end + end end - -- remove destroyed entities - for _, e in pairs(world:query("destroyed")) do - world:remove(e) - end + -- remove destroyed entities + for _, e in pairs(world:query("destroyed")) do + world:remove(e) + end end return sync