diff --git a/data/css/main.css b/data/css/main.css index 5f4ddb9..be96401 100644 --- a/data/css/main.css +++ b/data/css/main.css @@ -1229,3 +1229,49 @@ .ejs_virtualGamepad_open svg { fill: currentColor; } + +.ejs_netplay_name_input { + margin-top: .5rem; + margin-bottom: .5rem; + line-height: 1.5; + color: rgba(0,0,0,.8); + text-align: left; +} +.ejs_netplay_name_input input { + font-size: 1rem; + padding: .4rem; + max-width: 100%; + color: #000!important; + background-color: #fff!important; + margin: 0; + height: 2rem; + display: block; + font-family: Arial; +} +.ejs_netplay_name_heading { + margin-top: 0!important; + margin-bottom: 0!important; + font-weight: 600!important; + font-size: 1.25rem; + line-height: 1.25!important; + color: rgba(var(--ejs-primary-color),1)!important; + display: flex; + justify-content: space-between; + align-items: center; +} +.ejs_netplay_table { + font-family: Avenir,"Avenir Next","Helvetica Neue","Segoe UI",Helvetica,Arial,sans-serif; + font-size: 0.8rem; + padding: 0 10px; +} +.ejs_netplay_join_button { + float: none; + padding: .1rem .5rem; + background-color: rgba(var(--ejs-primary-color),1); + color: #fff!important; + border-radius: .25rem; + cursor: pointer; +} +.ejs_netplay_table_row:hover { + background-color: #2d2d2d; +} diff --git a/data/emulator.js b/data/emulator.js index f2ad54f..ee5d143 100644 --- a/data/emulator.js +++ b/data/emulator.js @@ -882,6 +882,7 @@ class EmulatorJS { this.createBottomMenuBar(); this.createControlSettingMenu(); this.createCheatsMenu() + this.createNetplayMenu(); this.setVirtualGamepad(); this.addEventListener(this.elements.parent, "keydown keyup", this.keyChange.bind(this)); this.addEventListener(this.elements.parent, "mousedown touchstart", (e) => { @@ -1082,7 +1083,7 @@ class EmulatorJS { }) } isPopupOpen() { - return this.cheatMenu.style.display !== "none" || this.controlMenu.style.display !== "none" || this.currentPopup !== null; + return this.cheatMenu.style.display !== "none" || this.netplayMenu.style.display !== "none" || this.controlMenu.style.display !== "none" || this.currentPopup !== null; } isChild(first, second) { if (!first || !second) return false; @@ -1295,6 +1296,9 @@ class EmulatorJS { FS.writeFile(path, sav); this.gameManager.loadSaveFiles(); }); + const netplay = addButton("Netplay", '', async () => { + this.openNetplayMenu(); + }); const spacer = this.createElement("span"); spacer.classList.add("ejs_menu_bar_spacer"); @@ -2796,6 +2800,140 @@ class EmulatorJS { popup.appendChild(popupMsg); return [popup, popupMsg]; } + createNetplayMenu() { + const body = this.createPopup("Netplay", { + "Create a Room": () => { + console.log("aaaaaaaaaaaa"); + }, + "Close": () => { + this.netplayMenu.style.display = "none"; + this.netplay.updateList.stop(); + } + }, true); + this.netplayMenu = body.parentElement; + const rooms = this.createElement("div"); + const title = this.createElement("strong"); + title.innerText = "Rooms"; + const table = this.createElement("table"); + table.classList.add("ejs_netplay_table"); + table.style.width = "100%"; + table.setAttribute("cellspacing", "0"); + const thead = this.createElement("thead"); + const row = this.createElement("tr"); + const addToHeader = (text) => { + const item = this.createElement("td"); + item.innerText = text; + item.style["text-align"] = "center"; + row.appendChild(item); + return item; + } + thead.appendChild(row); + addToHeader("Room Name").style["text-align"] = "left"; + addToHeader("Players").style.width = "80px"; + addToHeader("").style.width = "80px"; //"join" button + table.appendChild(thead); + const tbody = this.createElement("tbody"); + + table.appendChild(tbody); + rooms.appendChild(title); + rooms.appendChild(table); + body.appendChild(rooms); + + this.openNetplayMenu = () => { + this.netplayMenu.style.display = ""; + if (!this.netplay) { + this.netplay = {}; + this.netplay.table = tbody; + this.defineNetplayFunctions(); + const popups = this.createSubPopup(); + this.netplayMenu.appendChild(popups[0]); + popups[1].classList.add("ejs_cheat_parent"); //Hehe + const popup = popups[1]; + + const header = this.createElement("div"); + const title = this.createElement("h2"); + title.innerText = this.localization("Set Player Name"); + title.classList.add("ejs_netplay_name_heading"); + header.appendChild(title); + popup.appendChild(header); + + const main = this.createElement("div"); + main.classList.add("ejs_netplay_name_input"); + const head = this.createElement("strong"); + head.innerText = "Player Name"; + const input = this.createElement("input"); + input.type = "text"; + input.setAttribute("maxlength", 20); + + main.appendChild(head); + main.appendChild(this.createElement("br")); + main.appendChild(input); + popup.appendChild(main); + + popup.appendChild(this.createElement("br")); + const submit = this.createElement("button"); + submit.classList.add("ejs_button_button"); + submit.classList.add("ejs_popup_submit"); + submit.style["background-color"] = "rgba(var(--ejs-primary-color),1)"; + submit.innerText = "Submit"; + popup.appendChild(submit); + this.addEventListener(submit, "click", (e) => { + if (!input.value.trim()) return; + this.netplay.name = input.value.trim(); + popups[0].remove(); + }) + } + this.netplay.updateList.start(); + } + } + defineNetplayFunctions() { + this.netplay.getOpenRooms = async () => { + //async because it will need to pull from server. This is for testing + return [{name:"Room 1", players:1, max:2},{name:"Room 2", players:2, max:2}]; + } + this.netplay.updateTableList = async () => { + const addToTable = (name, current, max) => { + const row = this.createElement("tr"); + row.classList.add("ejs_netplay_table_row"); + const addToHeader = (text) => { + const item = this.createElement("td"); + item.innerText = text; + item.style.padding = "10px 0"; + item.style["text-align"] = "center"; + row.appendChild(item); + return item; + } + addToHeader(name).style["text-align"] = "left"; + addToHeader(current + "/" + max).style.width = "80px"; + + const parent = addToHeader(""); + parent.style.width = "80px"; + if (current < max) { + const join = this.createElement("button"); + join.classList.add("ejs_netplay_join_button"); + join.classList.add("ejs_button_button"); + join.style["background-color"] = "rgba(var(--ejs-primary-color),1)"; + join.innerText = "Join"; + parent.appendChild(join); + } + this.netplay.table.appendChild(row); + } + this.netplay.table.innerHTML = ""; + const open = await this.netplay.getOpenRooms(); + for (let i=0; i { + this.netplay.updateList.interval = setInterval(this.netplay.updateTableList.bind(this), 1000); + }, + stop: () => { + clearInterval(this.netplay.updateList.interval); + } + } + } createCheatsMenu() { const body = this.createPopup("Cheats", { "Add Cheat": () => {