diff options
| -rw-r--r-- | .gitignore | 1 | ||||
| -rw-r--r-- | client/camera.lua | 2 | ||||
| -rw-r--r-- | client/main.lua | 149 | ||||
| -rw-r--r-- | client/msgbox.lua | 53 | ||||
| -rw-r--r-- | client/util.lua | 2 | ||||
| -rw-r--r-- | net.txt | 5 | ||||
| -rw-r--r-- | server/server.lua | 10 | 
7 files changed, 196 insertions, 26 deletions
@@ -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) @@ -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  | 
