local json = require("common.json") local Sound = require("common.sound") local Dim = require("common.dimensions") local Wallpaper = require("components.wallpaper") local Background = require('components.background'); local difbar = require('components.diff_rectangle'); local crew = game.GetSkinSetting("single_idol") require('common.gameconfig') -- inRoom components local Jacket = require("multiplayer.Room.jacket") local OwnInfo = require("multiplayer.Room.owninfo") local BasePanel = require("multiplayer.Room.base") local MainPanel = require("multiplayer.Room.main") local SongInfo = require("multiplayer.Room.songinfo") local BPM = require("multiplayer.Room.bpm") local InfoPanel = require("multiplayer.Room.infopanel") local PlayerPlate = require("multiplayer.Room.user") -- roomList components local SelectPanel = require("multiplayer.LobbySelect.panel") local RoomListImages = { panel = gfx.CreateSkinImage("nautica/room_panel.png", 1), price = gfx.CreateSkinImage("nautica/pw_or_price_panel.png", 1), jacket = gfx.CreateSkinImage("nautica/bg_jacket.png", 1), dot = gfx.CreateSkinImage("nautica/dot.png", 1), info = gfx.CreateSkinImage("nautica/panel_name.png", 1), placeholder = gfx.CreateSkinImage("song_select/loading.png", 0) } local MultiJacket = gfx.CreateSkinImage("multi/lobby/multi_jacket.png", 1); local panelW,panelH = gfx.ImageSize(RoomListImages.panel); local jacketW,jacketH = gfx.ImageSize(RoomListImages.jacket); local infoW,infoH = gfx.ImageSize(RoomListImages.info); local dotW,dotH = gfx.ImageSize(RoomListImages.dot); local Gradient = gfx.CreateSkinImage("multi/roomselect/lobby_select_gradiant.png", 1); local Plate = gfx.CreateSkinImage("multi/roomselect/lobby_select.png", 1); local station = gfx.CreateSkinImage("multi/roomselect/multi_station.png", 1); local no_dif = gfx.CreateSkinImage("nautica/no_dif.png", 1); local gradientW, gradientH = gfx.ImageSize(Gradient); local stationW, stationH = gfx.ImageSize(station); local headerMatchingImage = gfx.CreateSkinImage("titlescreen/entry.png", 1); local bg = gfx.CreateSkinImage("multi/lobby/bg.png", 1); local bg_graid1 = gfx.CreateSkinImage("multi/lobby/gradient_bottom.png", 1); local bg_graid2 = gfx.CreateSkinImage("multi/lobby/gradient_top.png", 1); local idle = "/idle" local idolAnimation = gfx.LoadSkinAnimation('crew/anim/' .. crew .. idle, 1 / 30, 0, true); local idolAnimTransitionScale = 0; local dancheck = require("components.danbadge"); local username = game.GetSkinSetting("username"); local msg = game.GetSkinSetting("MSG"); local vol = game.GetSkinSetting("_volforce"); local desw, desh = Dim.design.width, Dim.design.height local mposx = 0; local mposy = 0; local hovered = nil; local buttonWidth = desw * (3 / 4); local buttonHeight = 100; local buttonBorder = 2; local portrait local jacket_size; -- RoomList Values -- local verticalOffset = panelH local firstRoomY = (desh / 2)- (panelH/2) local numOfRoomsAround = 2 -- numbers of Rooms Showing local selectedIndex = 1 -- Users Value -- local userHeight = 100 --------------------- local BAR_ALPHA = 191; local HEADER_HEIGHT = 100 local scale; game.LoadSkinSample("click-02") game.LoadSkinSample("click-01") game.LoadSkinSample("menu_click") local loading = true; local rooms = {}; local lobby_users = {}; selected_room = nil; local user_id = nil; local all_ready; local user_ready; local go; local hard_mode = false; local rotate_host = false; local start_game_soon = false; local host = nil; local owner = nil; local missing_song = false; local did_exit = false; local irHeartbeatRequested = false; irText = '' local grades = { { ["max"] = 6900000, ["image"] = gfx.CreateSkinImage("common/grades/D.png", 0) }, { ["max"] = 7900000, ["image"] = gfx.CreateSkinImage("common/grades/C.png", 0) }, { ["max"] = 8600000, ["image"] = gfx.CreateSkinImage("common/grades/B.png", 0) }, { ["max"] = 8900000, ["image"] = gfx.CreateSkinImage("common/grades/A.png", 0) }, { ["max"] = 9200000, ["image"] = gfx.CreateSkinImage("common/grades/A+.png", 0) }, { ["max"] = 9400000, ["image"] = gfx.CreateSkinImage("common/grades/AA.png", 0) }, { ["max"] = 9600000, ["image"] = gfx.CreateSkinImage("common/grades/AA+.png", 0) }, { ["max"] = 9700000, ["image"] = gfx.CreateSkinImage("common/grades/AAA.png", 0) }, { ["max"] = 9800000, ["image"] = gfx.CreateSkinImage("common/grades/AAA+.png", 0) }, { ["max"] = 9900000, ["image"] = gfx.CreateSkinImage("common/grades/S.png", 0) } } local badges = { gfx.CreateSkinImage("song_select/medal/saved.png", 0), gfx.CreateSkinImage("song_select/medal/played.png", 0), gfx.CreateSkinImage("song_select/medal/clear.png", 0), gfx.CreateSkinImage("song_select/medal/hard-clear.png", 0), gfx.CreateSkinImage("song_select/medal/full-combo.png", 0), gfx.CreateSkinImage("song_select/medal/perfect.png", 0) } local SERVER = game.GetSkinSetting("multi.server") local drawIdol = function(deltaTime) local idolAnimTickRes = gfx.TickAnimation(idolAnimation, deltaTime); if idolAnimTickRes == 1 then gfx.GlobalAlpha(idolAnimTransitionScale); idolAnimTransitionScale = idolAnimTransitionScale + 1 / 60; if (idolAnimTransitionScale > 1) then idolAnimTransitionScale = 1; end gfx.ImageRect(0, 0, desw, desh, idolAnimation, 1, 0); gfx.GlobalAlpha(1); end end function getCorrectedIndex(from, offset) total = #rooms if (math.abs(offset) > total) then if (offset < 0) then offset = offset + total * math.floor(math.abs(offset) / total) else offset = offset - total * math.floor(math.abs(offset) / total) end end index = from + offset if index < 1 then index = total + (from + offset) -- this only happens if the offset is negative end if index > total then indexesUntilEnd = total - from index = offset - indexesUntilEnd -- this only happens if the offset is positive end return index end user_setup = function() split = desw user_y_off = 0 space = 0 local newlobby = {} buttonY = user_y_off +125+ userHeight/2 for i, user in ipairs(lobby_users) do if user.id ~= user_id then table.insert(newlobby,user) end end for i, newUser in ipairs(newlobby) do PlayerPlate.Draw(newUser,0,800,badges,grades,host) local side_button_off = 0 if owner == user_id and newUser.id ~= user_id then draw_button("K",split/2 + split*3/8+10+25, buttonY, 50, function() kick_user(newUser); end) side_button_off = 60; end if (owner == user_id or host == user_id) and newUser.id ~= host then draw_button("H",split/2 + split*3/8+10+25+side_button_off, buttonY, 50, function() change_host(newUser); end) end buttonY = buttonY + userHeight space = space +13 end gfx.FillColor(255, 255, 255) end function drawHeader() gfx.BeginPath() gfx.FillColor(0, 0, 0, BAR_ALPHA) gfx.Rect(0, 0, desw, HEADER_HEIGHT) gfx.Fill() gfx.ClosePath() gfx.ImageRect(desw / 2 - 200, HEADER_HEIGHT / 2 - 20, 400, 40, headerMatchingImage, 1, 0) end mouse_clipped = function(x, y, w, h) return mposx > x and mposy > y and mposx < x + w and mposy < y + h; end; custom_button = function(name, x, y, image, font, font_size, hoverindex) local jw, jh = gfx.ImageSize(image) gfx.BeginPath(); gfx.ImageRect(x, y, jw, jh, image, 1, 0); if mouse_clipped(x, y, jw, jh) then hovered = hoverindex; gfx.FillColor(255, 128, 0); else gfx.FillColor(255, 255, 255); end gfx.BeginPath(); gfx.TextAlign(gfx.TEXT_ALIGN_CENTER + gfx.TEXT_ALIGN_MIDDLE); gfx.LoadSkinFont(font) gfx.FontSize(font_size); gfx.Text(name, x + (jw / 2) + 5, y + (jh / 2.25)); end draw_button = function(name, x, y, buttonWidth, hoverindex) draw_button_color(name, x, y, buttonWidth, hoverindex, 40, 40, 40, 0, 128, 255) end draw_button_color = function(name, x, y, buttonWidth, hoverindex, r, g, b, olr, olg, olb) local rx = x - (buttonWidth / 2); local ty = y - (buttonHeight / 2); gfx.BeginPath(); gfx.FillColor(olr, olg, olb); if mouse_clipped(rx, ty, buttonWidth, buttonHeight) then hovered = hoverindex; gfx.FillColor(255, 128, 0); end gfx.Rect(rx - buttonBorder, ty - buttonBorder, buttonWidth + (buttonBorder * 2), buttonHeight + (buttonBorder * 2)); gfx.Fill(); gfx.BeginPath(); gfx.FillColor(r, g, b); gfx.Rect(rx, ty, buttonWidth, buttonHeight); gfx.Fill(); gfx.BeginPath(); gfx.FillColor(255, 255, 255); gfx.TextAlign(gfx.TEXT_ALIGN_CENTER + gfx.TEXT_ALIGN_MIDDLE); gfx.FontSize(40); gfx.Text(name, x, y); end; draw_checkbox = function(text, x, y, hoverindex, current, can_click) gfx.BeginPath(); if can_click then gfx.FillColor(255, 255, 255, 100); else gfx.FillColor(100, 100, 100, 100); end gfx.TextAlign(gfx.TEXT_ALIGN_CENTER + gfx.TEXT_ALIGN_MIDDLE); gfx.Text(text, x, y) local xmin, ymin, xmax, ymax = gfx.TextBounds(x, y, text); local sx = xmin - 40; local sy = y - 15; if can_click and mouse_clipped(xmin - 10, ymin, xmax - xmin, ymax - ymin) then hovered = hoverindex; end if current then -- Draw checkmark gfx.BeginPath(); gfx.FillColor(0, 236, 0, 100); gfx.Text(text, x, y) end end; function render_loading() if not loading then return end gfx.Save() gfx.ResetTransform() gfx.BeginPath() gfx.MoveTo(desw, desh) gfx.LineTo(desw - 350, desh) gfx.LineTo(desw - 300, desh - 50) gfx.LineTo(desw, desh - 50) gfx.ClosePath() gfx.FillColor(33, 33, 33) gfx.Fill() gfx.FillColor(255, 255, 255) gfx.TextAlign(gfx.TEXT_ALIGN_RIGHT, gfx.TEXT_ALIGN_BOTTOM) gfx.FontSize(70) gfx.Text("LOADING...", desw - 20, desh - 3) gfx.Restore() end function render_info() if searchStatus then gfx.BeginPath() gfx.FillColor(255, 255, 255) gfx.FontSize(20); gfx.TextAlign(gfx.TEXT_ALIGN_LEFT + gfx.TEXT_ALIGN_TOP) gfx.Text(searchStatus, 3, 3) end end draw_diff_icon = function(diff, x, y, w, h) difbar.render(deltaTime, x, y, 1, diff.difficulty + 1, diff.level); end local doffset = 0; local timer = 0; local possy = 1095; local possx = 150; draw_diffs = function(diffs, x, y, w, h, selectedDiff) local diffWidth = w / 2 local diffHeight = w / 2 local diffCount = #diffs gfx.Scissor(x + 84 + possx, y + possy, w / 2.451, h) for i = math.max(selectedDiff - 2, 1), math.max(selectedDiff - 1, 1) do local diff = diffs[i] local xpos = x + ((w / 2 - diffWidth / 2) + (selectedDiff - i + doffset) * (-0.8 * diffWidth)) if i ~= selectedDiff then draw_diff_icon(diff, xpos + possx, y + possy, diffWidth, diffHeight, false) end end --after selected for i = math.min(selectedDiff + 2, diffCount), selectedDiff + 1, -1 do local diff = diffs[i] local xpos = x + ((w / 2 - diffWidth / 2) + (selectedDiff - i + doffset) * (-0.8 * diffWidth)) if i ~= selectedDiff then draw_diff_icon(diff, xpos + possx, y + possy, diffWidth, diffHeight, false) end end local diff = diffs[selectedDiff] local xpos = x + ((w / 2 - diffWidth / 2) + (doffset) * (-0.8 * diffWidth)) draw_diff_icon(diff, xpos + possx, y + possy, diffWidth, diffHeight, true) gfx.ResetScissor() end set_diff = function(oldDiff, newDiff) game.PlaySample("click-02") doffset = doffset + oldDiff - newDiff end; local selected_room_index = 1; local ioffset = 0; local draw_room = function(information, x, y, selected, hoverindex) local PlayerAmount = information.current .. '/' .. information.max local Name = information.name local Status local Password gfx.BeginPath(); gfx.ImageRect(x/4.5,y, panelW/1.17, panelH/1.17, RoomListImages.panel,1,0); gfx.BeginPath(); gfx.ImageRect(x/4.5+3,y+5, jacketW/1.25, jacketH/1.17, RoomListImages.jacket,1,0); gfx.BeginPath(); gfx.ImageRect(x/4.5+10,y+22, jacketW/1.45,jacketH/1.45, RoomListImages.placeholder,1,0); gfx.BeginPath(); gfx.ImageRect(x/2-5,y+5, infoW/1.17, infoH/1.17, RoomListImages.info,1,0); gfx.BeginPath(); gfx.SetImageTint(0,128,255); if selected then gfx.SetImageTint(0,255,0); end if mouse_clipped(x/4.5,y, panelW/1.17, panelH/1.17) then hovered = hoverindex; gfx.SetImageTint(255,128,0); end gfx.BeginPath(); gfx.ImageRect(x/4.5,y, dotW/1.17, dotH/1.17, RoomListImages.dot,1,0); gfx.SetImageTint(255,255,255); gfx.FillColor(255,255,255); gfx.BeginPath(); gfx.TextAlign(gfx.TEXT_ALIGN_LEFT + gfx.TEXT_ALIGN_MIDDLE); gfx.FontSize(35); gfx.Text(Name, x-230,y+40); gfx.Text(PlayerAmount, x-230,y+40+40); gfx.FontSize(24); local jw,jh = gfx.ImageSize(RoomListImages.price); gfx.BeginPath(); gfx.ImageRect(x+230-5,y+40+29, jw/1.17, jh/1.17, RoomListImages.price,1,0); if information.current == information.max then Status = "" else Status = "" end if information.ingame then Status = '' end if information.password then Password = '' else Password = ' ' end gfx.Text(Status.." / "..Password, x+230+9,y+40+52.5); end function draw_rooms(y, h) while #rooms == 0 do gfx.FillColor(255, 255, 255); gfx.BeginPath() gfx.Text("No Rooms are available",y,h/2) return end if not rooms[selected_room_index] then selected_room_index = getCorrectedIndex(selectedIndex, 1) end local i = 1 if i <= numOfRoomsAround then local roomIndex = getCorrectedIndex(selected_room_index, -i) local room = rooms[roomIndex] local y = firstRoomY + (i - 1) * verticalOffset + verticalOffset draw_room(room, desw / 2, y, roomIndex == selected_room_index, function() join_room(room) end) i = i + 1 end local i = selected_room_index if i ~= nil then -- Draw the selected room local room = rooms[i] draw_room(room, desw / 2, firstRoomY, i == selected_room_index, function()join_room(room)end) end local i = 1 if i <= numOfRoomsAround then local roomIndex = getCorrectedIndex(selected_room_index, i) local room = rooms[roomIndex] local y = firstRoomY - (i - 1) * verticalOffset - verticalOffset draw_room(room, desw / 2, y, roomIndex == selected_room_index, function() join_room(room) end) i = i + 1 end end change_selected_room = function(off) local new_index = selected_room_index + off; --selected_room_index = 2; if new_index < 1 or new_index > #rooms then return; end local h = desh - 290; local num_rooms_visible = math.floor(h / (buttonHeight + 10)) local first_half_rooms = math.floor(num_rooms_visible / 2) local second_half_rooms = math.ceil(num_rooms_visible / 2) - 1 if off > 0 and (selected_room_index < first_half_rooms or selected_room_index >= #rooms - second_half_rooms - 1) then elseif off < 0 and (selected_room_index <= first_half_rooms or selected_room_index >= #rooms - second_half_rooms) then else ioffset = ioffset - new_index + selected_room_index; end game.PlaySample("menu_click") selected_room_index = new_index; end local IR_HeartbeatResponse = function(res) if res.statusCode == IRData.States.Success then irText = res.body.serverName .. ' ' .. res.body.irVersion; else game.Log("Can't connect to IR!", game.LOGGER_WARNING) end end local IR_Handle = function() if not irHeartbeatRequested then IR.Heartbeat(IR_HeartbeatResponse) irHeartbeatRequested = true; end end function render_lobby(deltaTime) gfx.BeginPath(); gfx.ImageRect(0, 0, desw, desh, bg, 1, 0); drawIdol(deltaTime) gfx.BeginPath(); gfx.ImageRect(0, 0, desw, desh, bg_graid1, 1, 0); gfx.ImageRect(0, 0, desw, desh, bg_graid2, 1, 0); gfx.BeginPath(); BasePanel.Draw() user_setup() InfoPanel.Draw(hard_mode,start_game_soon,owner,user_id,host) MainPanel.Draw() SongInfo.Draw() OwnInfo.Draw(deltaTime,lobby_users,user_id,badges,grades) BPM.Draw() Jacket.Draw() local jw , jh = gfx.ImageSize(MultiJacket); if mouse_clipped(333+12, 1284+19, jw/1.269,jh/1.35) and host == user_id then hovered = function() mpScreen.SelectSong() end end end function render_room_list(deltaTime) Background.draw(deltaTime) SelectPanel.Draw() -- the list draw_rooms(desw/2, desh - 290); -- gfx.BeginPath(); gfx.ImageRect(desw / desw, lobbypanelY, gradientW, gradientH, Gradient, 1, 0); gfx.BeginPath(); gfx.ImageRect(desw / desw, lobbypanelY, gradientW, gradientH, Plate, 1, 0); gfx.BeginPath(); gfx.ImageRect((desw / 2)-((stationW/0.8)/2), lobbypanelY+((stationH/0.8)/2)-5, stationW/0.8, stationH/0.8, station, 1, 0); end passwordErrorOffset = 0; function render_password_screen(deltaTime) gfx.FillColor(255, 255, 255) gfx.TextAlign(gfx.TEXT_ALIGN_CENTER, gfx.TEXT_ALIGN_BOTTOM) gfx.FontSize(70) gfx.Text("Joining " .. selected_room.name .. "...", desw / 2, desh / 4) gfx.FillColor(50, 50, 50) gfx.BeginPath() gfx.Rect(0, desh / 2 - 10, desw, 40) gfx.Fill(); gfx.FillColor(255, 255, 255) gfx.Text("Please enter room password:", desw / 2, desh / 2 - 40) gfx.Text(string.rep("*", #textInput.text), desw / 2, desh / 2 + 40) if passwordError then gfx.FillColor(255, 50, 50) gfx.FontSize(60 + math.floor(passwordErrorOffset * 20)) gfx.Text("Invalid password", desw / 2, desh / 2 + 80) end draw_button("Join", desw / 2, desh * 3 / 4, desw / 2, mpScreen.JoinWithPassword); end function render_new_room_password(deltaTime) gfx.FillColor(255, 255, 255) gfx.TextAlign(gfx.TEXT_ALIGN_CENTER, gfx.TEXT_ALIGN_BOTTOM) gfx.FontSize(70) gfx.Text("Create New Room", desw / 2, desh / 4) -- make something here gfx.FillColor(255, 255, 255) gfx.Text("Enter room password:", desw / 2, desh / 2 - 40) gfx.Text(string.rep("*", #textInput.text), desw / 2, desh / 2 + 40) draw_button("Create Room", desw / 2, desh * 3 / 4, desw / 2, mpScreen.NewRoomStep); end function render_new_room_name(deltaTime) gfx.BeginPath(); gfx.LoadSkinFont("segoeui.ttf") gfx.FillColor(255, 255, 255) gfx.TextAlign(gfx.TEXT_ALIGN_CENTER, gfx.TEXT_ALIGN_BOTTOM) gfx.FontSize(70) gfx.Text("Create New Room", desw / 2, desh / 4) gfx.Rect(0, desh / 2 - 10, desw / 2, 60) gfx.Text("Please enter room name:", desw / 2, desh / 2 - 40) gfx.Text(textInput.text, desw / 2, desh / 2 + 40) draw_button("Next", desw / 2, desh * 3 / 4, desw / 2, mpScreen.NewRoomStep); end function render_set_username(deltaTime) gfx.FillColor(255, 255, 255) gfx.TextAlign(gfx.TEXT_ALIGN_CENTER, gfx.TEXT_ALIGN_BOTTOM) gfx.FontSize(70) gfx.Text("First things first...", desw / 2, desh / 4) gfx.FillColor(50, 50, 50) gfx.BeginPath() gfx.Rect(0, desh / 2 - 10, desw, 60) gfx.Fill(); gfx.FillColor(255, 255, 255) gfx.Text("Enter a display name:", desw / 2, desh / 2 - 40) gfx.Text(textInput.text, desw / 2, desh / 2 + 40) draw_button("Join Multiplayer", desw / 2, desh * 3 / 4, desw / 2, function() loading = true; mpScreen.SaveUsername() end); end render = function(deltaTime) IR_Handle() Dim.updateResolution() Wallpaper.render() Dim.transformToScreenSpace() mposx, mposy = Dim.toViewSpace(game.GetMousePos()) Sound.stopMusic(); doffset = doffset * 0.9 ioffset = ioffset * 0.9 passwordErrorOffset = passwordErrorOffset * 0.9 timer = (timer + deltaTime) timer = timer % 2 hovered = nil; Background.draw(deltaTime) do_sounds(deltaTime); -- Room Listing View if screenState == "inRoom" then render_lobby(deltaTime); drawHeader() elseif screenState == "roomList" then render_room_list(deltaTime); drawHeader() elseif screenState == "passwordScreen" then render_password_screen(deltaTime); drawHeader() elseif screenState == "newRoomName" then render_new_room_name() drawHeader() elseif screenState == "newRoomPassword" then render_new_room_password() drawHeader() elseif screenState == "setUsername" then loading = false; render_set_username() drawHeader() end render_loading(); render_info(); end -- Ready up to play function ready_up() Tcp.SendLine(json.encode({ topic = "user.ready.toggle" })) end -- Toggle hard gauage function toggle_hard() Tcp.SendLine(json.encode({ topic = "user.hard.toggle" })) end -- Toggle hard gauage function toggle_mirror() Tcp.SendLine(json.encode({ topic = "user.mirror.toggle" })) end function new_room() host = user_id owner = user_id mpScreen.NewRoomStep() end -- Toggle host rotation function toggle_rotate() Tcp.SendLine(json.encode({ topic = "room.option.rotation.toggle" })) end -- Change lobby host function change_host(user) Tcp.SendLine(json.encode({ topic = "room.host.set", host = user.id })) end -- Kick user function kick_user(user) Tcp.SendLine(json.encode({ topic = "room.kick", id = user.id })) end -- Tell the server to start the game function start_game() selected_song.self_picked = false if (selected_song == nil) then return end if (start_game_soon) then return end Tcp.SendLine(json.encode({ topic = "room.game.start" })) end -- Join a given room function join_room(room) host = user_id selected_room = room; if room.password then mpScreen.JoinWithPassword(room.id) else mpScreen.JoinWithoutPassword(room.id) end end -- Handle button presses to advance the UI button_pressed = function(button) if button == game.BUTTON_STA then if start_game_soon then return end if screenState == "roomList" then if #rooms == 0 then new_room() else -- TODO navigate room selection join_room(rooms[selected_room_index]) end elseif screenState == "inRoom" then if host == user_id then if selected_song and selected_song.self_picked then if all_ready then start_game() else missing_song = false mpScreen.SelectSong() end else missing_song = false mpScreen.SelectSong() end else ready_up() end end end if button == game.BUTTON_BTA then toggle_hard(); end if button == game.BUTTON_BTB then toggle_mirror(); end if button == game.BUTTON_BTC then toggle_rotate(); end if button == game.BUTTON_BTD then ------------------------ end end -- Handle the escape key around the UI function key_pressed(key) if key == 27 then --escape pressed if screenState == "roomList" then did_exit = true; mpScreen.Exit(); return end -- Reset room data screenState = "roomList" -- have to update here selected_room = nil; rooms = {}; selected_song = nil selected_song_index = 1; jacket = 0; end end -- Handle mouse clicks in the UI mouse_pressed = function(button) if hovered then hovered() end return 0 end function init_tcp() Tcp.SetTopicHandler("server.info", function(data) loading = false user_id = data.userid end) -- Update the list of rooms as well as get user_id for the client Tcp.SetTopicHandler("server.rooms", function(data) rooms = {} for i, room in ipairs(data.rooms) do table.insert(rooms, room) end end) Tcp.SetTopicHandler("server.room.joined", function(data) selected_room = data.room --[[ local PlayerServerInfo = { name = username, msg = msg, nav = crew, volforce = vol, dan = "nothing" } local ServerPushTable = { topic = "user.extra.set", data = PlayerServerInfo, } Tcp.SendLine(json.encode(ServerPushTable)) ]] end) local sound_time = 0; local sound_clip = nil; local sounds_left = 0; local sound_interval = 0; function repeat_sound(clip, times, interval) sound_clip = clip; sound_time = 0; sounds_left = times - 1; sound_interval = interval; game.PlaySample(clip) end function do_sounds(deltaTime) if sound_clip == nil then return end sound_time = sound_time + deltaTime; if sound_time > sound_interval then sound_time = sound_time - sound_interval; game.PlaySample(sound_clip); sounds_left = sounds_left - 1 if sounds_left <= 0 then sound_clip = nil end end end local last_song = nil -- Update the current lobby Tcp.SetTopicHandler("room.update", function(data) -- Update the users in the lobby lobby_users = {} local prev_all_ready = all_ready; all_ready = true for i, user in ipairs(data.users) do table.insert(lobby_users, user) if user.id == user_id then user_ready = user.ready end if not user.ready then all_ready = false end end if user_id == host and #data.users > 1 and all_ready and not prev_all_ready then repeat_sound("click-02", 3, .1) end if data.host == user_id and host ~= user_id then repeat_sound("click-02", 3, .1) end if data.song ~= nil and last_song ~= data.song then game.PlaySample("menu_click") last_song = data.song end host = data.host if data.owner then owner = data.owner else owner = host end hard_mode = data.hard_mode mirror_mode = data.mirror_mode do_rotate = data.do_rotate if data.start_soon and not start_game_soon then repeat_sound("click-01", 5, 1) end start_game_soon = data.start_soon end) end