ExperimentalGear/scripts/multiplayerscreen.lua

934 lines
27 KiB
Lua

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 = "<FULL>"
else
Status = "<NOT FULL>"
end
if information.ingame then
Status = '<IN MATCH>'
end
if information.password then
Password = '<LOCKED>'
else
Password = ' <OPEN>'
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