From a3af144dec34adf9e8ac047dd368bb102de40821 Mon Sep 17 00:00:00 2001 From: ubq323 Date: Mon, 20 Feb 2023 03:55:51 +0000 Subject: chat system, some controls changes --- .gitignore | 1 + client/camera.lua | 2 +- client/main.lua | 149 +++++++++++++++++++++++++++++++++++++++++++++--------- client/msgbox.lua | 53 +++++++++++++++++++ client/util.lua | 2 +- net.txt | 5 ++ server/server.lua | 10 +++- 7 files changed, 196 insertions(+), 26 deletions(-) create mode 100644 client/msgbox.lua diff --git a/.gitignore b/.gitignore index e4c3052..448f390 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,4 @@ +*.love server/enet.so server/world/* flamegraph.pl diff --git a/client/camera.lua b/client/camera.lua index 528b45b..bb1d8a6 100644 --- a/client/camera.lua +++ b/client/camera.lua @@ -12,7 +12,7 @@ function Camera.make(cls,pos,zoom) return setmetatable({pos=pos,zoom=zoom},cls) end function Camera.apply_trans(self) - love.graphics.origin() + -- love.graphics.origin() -- centre (0,0) in the middle of the screen love.graphics.translate(screen_width/2,screen_height/2) -- apply camera transformations diff --git a/client/main.lua b/client/main.lua index 27b93f9..9de4290 100644 --- a/client/main.lua +++ b/client/main.lua @@ -1,5 +1,6 @@ local enet = require"enet" local json = require"common.dkjson" +local utf8 = require"utf8" local SERVER_HOSTNAME = "ubq323.website" @@ -16,6 +17,7 @@ local Chunk = require"common.chunk".Chunk local util = require"util" local Map = require"common.map".Map local movement = require"movement" +local msgbox = require"msgbox" -- local pprint=require"common.pprint" -- pprint.setup{show_all=true} @@ -23,11 +25,21 @@ local movement = require"movement" local help_text = [[ controls: -wasd: move left mouse: place -q,e: zoom in/out right mouse: destroy +wasd: move shift: sprint -F3: toggle debug -F1: show/hide this help]] + +left mouse: place +right mouse: destroy +mousewheel: zoom in/out + +F1: show/hide this help +F3: show/hide debug +F11: toggle "big mode" (bad) + +enter: toggle chat]] + + + math.randomseed(os.time()) @@ -35,13 +47,62 @@ local map = Map:make() local host,peer + +local selected_tile = 9 + +-- normal: regular gameplay +-- chat: chat box is open +-- more modes may come +local ui_mode = "normal" + _G.debugmode = false -local show_controls = true +local show_controls = false + +local this_chatmsg = "" +local chatmsg_text = love.graphics.newText(love.graphics.getFont()) + +local big_mode = false +local orig_w,orig_h = love.graphics.getDimensions() function love.keypressed(key,scancode,isrepeat) - if scancode == "f3" then _G.debugmode = not _G.debugmode end - if scancode == "f1" then show_controls = not show_controls end + if key == "f11" then + big_mode = not big_mode + if big_mode then + love.window.setMode(orig_w*2,orig_h*2) + else + love.window.setMode(orig_w,orig_h) + end + end + if ui_mode == "normal" then + if key == "f3" then _G.debugmode = not _G.debugmode end + if key == "f1" then show_controls = not show_controls end + for i = 1,9 do if key == tostring(i) then selected_tile = i end end + if key == "return" then + ui_mode = "chat" + this_chatmsg = "" + end + elseif ui_mode == "chat" then + if key == "return" then + ui_mode = "normal" + peer:send(json.encode{t="chat",msg=this_chatmsg}) + -- msgbox.add("[me] "..this_chatmsg) + elseif key == "escape" then + ui_mode = "normal" + elseif key == "backspace" then + local boffs = utf8.offset(this_chatmsg,-1) + if boffs then + this_chatmsg = this_chatmsg:sub(1,boffs-1) + end + + end + end +end + +function love.textinput(text) + if ui_mode == "chat" then + this_chatmsg = this_chatmsg..text + end end local function draw_player(pl,islocal) @@ -61,7 +122,7 @@ local remote_players = {} local function update_local_player(pl,dt) local SPEED = 8*math.sqrt(3) -- 8 hexagonheights per second - if love.keyboard.isScancodeDown("lshift") then SPEED = SPEED*2 end + if love.keyboard.isDown("lshift") then SPEED = SPEED*2.5 end local function kd(code) if love.keyboard.isScancodeDown(code) then return 1 else return 0 end end @@ -96,25 +157,35 @@ local function send_settile(hpos,tile) peer:send(json.encode{t="settile",q=hpos.q,r=hpos.r,tile=tile}) end +function love.wheelmoved(dx,dy) + camera.zoom = camera.zoom * (1.15 ^ dy) + camera.zoom = math.max(2.5,math.min(50,camera.zoom)) +end function love.update(dt) - if local_player then - update_local_player(local_player,dt) - if love.keyboard.isScancodeDown"q" then camera.zoom = camera.zoom*1.05 end - if love.keyboard.isScancodeDown"e" then camera.zoom = camera.zoom/1.05 end - camera.zoom = math.max(2.5,math.min(50,camera.zoom)) - sync_local_player(local_player) - end + msgbox.update(dt) + if ui_mode == "normal" then + + -- movement and zoom in/out (keyboard input) + if local_player then + update_local_player(local_player,dt) + sync_local_player(local_player) + end - local mh = camera:screen_to_world(Pos:make(love.mouse.getPosition())):to_hex():round() - if map:at(mh) == 0 and love.mouse.isDown(1) then - map:set_at(mh,9) - send_settile(mh,9) - elseif map:at(mh) ~= 0 and love.mouse.isDown(2) then - map:set_at(mh,0) - send_settile(mh,0) + -- mouse input + local msx,msy = love.mouse.getPosition() + if big_mode then msx,msy = msx/2,msy/2 end + local mh = camera:screen_to_world(Pos:make(msx,msy)):to_hex():round() + if map:at(mh) == 0 and love.mouse.isDown(1) then + map:set_at(mh,selected_tile) + send_settile(mh,selected_tile) + elseif map:at(mh) ~= 0 and love.mouse.isDown(2) then + map:set_at(mh,0) + send_settile(mh,0) + end end + -- load and unload chunks if local_player then local player_cp = local_player.pos:to_hex():containing_chunk() -- load chunks near to player (within 3x3 square) @@ -140,6 +211,7 @@ function love.update(dt) end + -- handle network packets repeat local ev = host:service() if ev and ev.type == "receive" then @@ -149,9 +221,11 @@ function love.update(dt) if op == "join" then local pl = j.pl remote_players[pl.id] = {pos=coords.Pos:make(pl.x,pl.y),color=pl.color,id=pl.id} + msgbox.add(pl.id.." joined") elseif op == "leave" then local id = j.id remote_players[id]=nil + msgbox.add(id.." left") elseif op == "move" then local id,x,y = j.id,j.x,j.y assert(remote_players[id],"wheeze "..id) @@ -166,6 +240,9 @@ function love.update(dt) elseif op == "settile" then local h = coords.Hex:make(j.q,j.r) map:set_at(h,j.tile) + elseif op == "chat" then + local msg,from = j.msg,j.from + msgbox.add("["..tostring(from).."] "..msg) end end until not ev @@ -174,6 +251,7 @@ end function love.draw() love.graphics.clear(1,1,1) love.graphics.origin() + if big_mode then love.graphics.scale(2) end if local_player then camera.pos = local_player.pos end @@ -196,6 +274,8 @@ function love.draw() local hm = wm:to_hex() love.graphics.origin() + if big_mode then love.graphics.scale(2) end + util.print_good(tostring(selected_tile), 400,10) if _G.debugmode and local_player then util.print_good({ "ms "..tostring(sm), @@ -208,19 +288,42 @@ function love.draw() "voob "..tostring(camera.zoom), "-", "fps "..tostring(love.timer.getFPS()), - "ping "..tostring(peer:round_trip_time()) + "ping "..tostring(peer:round_trip_time()), },10,10) end if show_controls then util.print_good(help_text,300,200) end + + msgbox.draw() + + if ui_mode ~= "normal" then + util.print_good(ui_mode, 700,10) + end + + if ui_mode == "chat" then + local W,H = love.graphics.getDimensions() + chatmsg_text:set("- "..this_chatmsg) + local tw,th = chatmsg_text:getDimensions() + local y = H-th-30 + love.graphics.setColor(0,0,0,0.8) + love.graphics.rectangle("fill",0,y,W,th) + love.graphics.setColor(1,1,1) + love.graphics.draw(chatmsg_text,0,y) + love.graphics.setColor(0.8,0.8,0.8) + love.graphics.line(tw,y,tw,y+th) + end + end function love.load() + love.keyboard.setKeyRepeat(true) -- require"profile".start(10,io.open("./trace","w")) host = enet.host_create() peer = host:connect(SERVER_HOSTNAME..":8473") + msgbox.add("connected to "..SERVER_HOSTNAME..":8473") + msgbox.add("press F1 for controls help") end function love.quit() diff --git a/client/msgbox.lua b/client/msgbox.lua new file mode 100644 index 0000000..720bfab --- /dev/null +++ b/client/msgbox.lua @@ -0,0 +1,53 @@ +local font = love.graphics.getFont() + + +local msgs = {} + +local function add(str) + table.insert(msgs, 1, {text=love.graphics.newText(font,str),time=10}) +end + +local margin_bottom = 70 + +local function draw() + if #msgs == 0 then return end + + local W,H = love.graphics.getDimensions() + local maxw = 0 + local sumh = 0 + for _,msg in ipairs(msgs) do + local text = msg.text + maxw = math.max(maxw,text:getWidth()) + sumh = sumh + text:getHeight() + end + love.graphics.setColor(0,0,0,0.8) + love.graphics.rectangle("fill",0,H-sumh-margin_bottom,maxw,sumh) + + love.graphics.setColor(1,1,1) + local cury = H + for _,msg in ipairs(msgs) do + local text = msg.text + local h = text:getHeight() + love.graphics.draw(text,0,cury-h-margin_bottom) + cury = cury - h + end +end + +local function update(dt) + for ix = #msgs,1,-1 do + local m = msgs[ix] + m.time = m.time - dt + if m.time <= 0 then + msgs[ix] = nil + end + end +end + + + + +return { + draw=draw, + update=update, + add=add, +} diff --git a/client/util.lua b/client/util.lua index f9ec088..8a18b96 100644 --- a/client/util.lua +++ b/client/util.lua @@ -6,7 +6,7 @@ local function print_good(lines,x,y) for _,line in ipairs(lines) do text:set(line) local w,h = text:getDimensions() - love.graphics.setColor(0,0,0,0.6) + love.graphics.setColor(0,0,0,0.8) love.graphics.rectangle("fill",x,y,w,h) love.graphics.setColor(1,1,1) love.graphics.draw(text,x,y) diff --git a/net.txt b/net.txt index ced98ee..4a81d7d 100644 --- a/net.txt +++ b/net.txt @@ -8,6 +8,9 @@ settile {q,r,tile} reqchunk {u,v} request chunk data for chunk at chunkpos u,v +chat {msg} + send chat message msg + s2c: playerinfopart:: {id,x,y,color:[r,g,b]} @@ -29,3 +32,5 @@ chunk {tiles=[array of 128*128 booleans],u,v} settile {q,r,tile} tile at H(q,r) was set to tile (currently boolean) +chat {msg,from} + recieve chat message msg from player with name from. diff --git a/server/server.lua b/server/server.lua index 85112c9..f78bdd0 100644 --- a/server/server.lua +++ b/server/server.lua @@ -60,6 +60,9 @@ end local function player_move_packet(player,x,y) return json.encode{t="move",id=player.id,x=x,y=y} end +local function chat_packet(fromplayer,msg) + return json.encode{t="chat",from=fromplayer.id,msg=msg} +end local map = MapS:make() @@ -121,6 +124,11 @@ local function handle_ev(ev) local cp = coords.ChunkPos:make(j.u,j.v) local ch = map:obtain(cp) player.peer:send(ch:data_packet()) + elseif op == "chat" then + print("chat ["..player.id.."] "..j.msg) + for i,otherplayer in ipairs(playerlist) do + otherplayer.peer:send(chat_packet(player,j.msg)) + end end end end @@ -160,7 +168,7 @@ local ntick = 0 local function player_near_chunk(cp) -- true: chunk at cp should stay loaded (because of a nearby player), -- false: no players nearby, can be unloaded - -- this is kind of inefficient at the moment + -- this is maybe not as efficient as it possibly could be for _,player in ipairs(playerlist) do local pcp = player.pos:to_hex():containing_chunk() for _,neighb in ipairs(pcp:neighborhood()) do -- cgit v1.2.3