From 9f0b255f32dfa81bffe75f89335a78a659b4ce6a Mon Sep 17 00:00:00 2001 From: TrueKuehli Date: Tue, 27 Nov 2018 12:16:33 +0100 Subject: Reworked the code, but currently unable to test, so bugs are bound to be in there Will test it sometime later. There also might still be stuff, that has yet to be reworked. --- .../src/js/src_old/modules/playModule.js | 46 ++++++ .../src/js/src_old/modules/server-client.js | 93 +++++++++++ .../src/js/src_old/modules/ui/login-modal.js | 181 +++++++++++++++++++++ .../src/js/src_old/modules/ui/modal.js | 67 ++++++++ .../src/js/src_old/modules/ui/server-listing.js | 67 ++++++++ 5 files changed, 454 insertions(+) create mode 100644 WebInterface/NodeJSServer/src/js/src_old/modules/playModule.js create mode 100644 WebInterface/NodeJSServer/src/js/src_old/modules/server-client.js create mode 100644 WebInterface/NodeJSServer/src/js/src_old/modules/ui/login-modal.js create mode 100644 WebInterface/NodeJSServer/src/js/src_old/modules/ui/modal.js create mode 100644 WebInterface/NodeJSServer/src/js/src_old/modules/ui/server-listing.js (limited to 'WebInterface/NodeJSServer/src/js/src_old') diff --git a/WebInterface/NodeJSServer/src/js/src_old/modules/playModule.js b/WebInterface/NodeJSServer/src/js/src_old/modules/playModule.js new file mode 100644 index 0000000..931f598 --- /dev/null +++ b/WebInterface/NodeJSServer/src/js/src_old/modules/playModule.js @@ -0,0 +1,46 @@ +// TODO: Handle disconnect + +/** + * Handles ingame networking; + */ +export default class GameClient { + /** + * Defines basic attributes + * @param {string} user The username of the player + * @param {HubConnection} connection Already established connection to the + * server + */ + constructor(user, connection) { + this.user = user; + this.connection = connection; + } + + /** + * Registers chat html component + * @param {string} chatId Id of chat component + */ + registerChat(chatId) { + this.chat = document.getElementById(chatId); + this.messageList = this.chat.querySelector('#message-list'); + this.messageInput = this.chat.querySelector('#input-message'); + this.messageSend = this.chat.querySelector('#send-message'); + + this.connection.on('ReceiveMessage', (user, message) => { + let msg = message.replace(/&/g, '&') + .replace(//g, '>'); + let encodedMsg = user + ' sagt: ' + msg; + + let messageP = document.createElement('p'); + messageP.class = 'message'; + messageP.textContent = encodedMsg; + + this.messageList.appendChild(messageP); + }); + + this.messageSend.addEventListener('click', () => { + let message = this.messageInput.value; + this.connection.invoke('SendMessage', this.user, message); + }); + } +} diff --git a/WebInterface/NodeJSServer/src/js/src_old/modules/server-client.js b/WebInterface/NodeJSServer/src/js/src_old/modules/server-client.js new file mode 100644 index 0000000..2f712b5 --- /dev/null +++ b/WebInterface/NodeJSServer/src/js/src_old/modules/server-client.js @@ -0,0 +1,93 @@ +import * as signalR from '@aspnet/signalr'; +import ServerListing from './ui/server-listing.js'; + +/** + * Class for communication to server + */ +export default class ServerClient { + /** + * Creates new connection + * @param {string} url URL of server running signalR + * @param {string} serverListingId HTML ID of server-listing element, + * to populate with available games + * @param {BannerController} notifications Notification Manager + * @param {array} ui UI Elements to reload on login + * @param {boolean} [debug=false] Enable debug output? + */ + constructor(url, serverListingId, notifications, ui, debug = false) { + this.ui = ui; + const connectionBuilder = new signalR.HubConnectionBuilder() + .withUrl(url); + + if (debug) { + connectionBuilder.configureLogging(signalR.LogLevel.Debug); + } else { + connectionBuilder.configureLogging(signalR.LogLevel.Error); + } + + this.connection = connectionBuilder.build(); + this.connection.start() + .then(() => this.loadServers()) // Load games list, once connected + .catch((err) => console.error(err.toString())); + + // Initialize refreshing (blocks new refreshes if true) + this.refreshing = false; + + this.serverListing = new ServerListing(serverListingId, notifications); + } + + /** + * Requests list of avalable games on the server + */ + loadServers() { + if (this.refreshing) return; // If already refreshing, no new request + + this.connection.on('ListGroups', (groups) => { + // Populate server listing + this.serverListing.flushElements(); + this.serverListing.addElements(groups, this, this.ui); + this.connection.off('ListGroups'); + + this.refreshing = false; + }); + + this.connection.invoke('GetGroups') + .catch((err) => { + this.refreshing = false; + console.error(err.toString()); + }); + this.refreshing = true; + } + + /** + * Sends a game creating request to the server + * @param {string} name Name of the new game + * @param {string} password Password + */ + createServer(name, password) { + // TODO: Create + } + + /** + * Sends a login request + * @param {string} group Group name to join + * @param {string} password Password to send as SHA-256 Base64 String + * @param {string} username Display name to use + * @param {ServerClient~loginCallback} callback Callback function to use + */ + sendLogin(group, password, username, callback) { + this.connection.on('LoginResponse', (result) => { + callback(result, this.connection); + this.connection.off('LoginResponse'); + }); + this.connection.invoke('Login', group, username, password); + } +} + +/** + * Callback to call with response to login request + * @callback ServerClient~loginCallback + * @param {number} result 0: Success, 1: PasswordError, 2:UsernameTaken, + * 3:Unknown Error + * @param {ConnectionHub} connection Connection to the server + */ diff --git a/WebInterface/NodeJSServer/src/js/src_old/modules/ui/login-modal.js b/WebInterface/NodeJSServer/src/js/src_old/modules/ui/login-modal.js new file mode 100644 index 0000000..13de78e --- /dev/null +++ b/WebInterface/NodeJSServer/src/js/src_old/modules/ui/login-modal.js @@ -0,0 +1,181 @@ +import Modal from './modal.js'; +import '../hash.js'; + +/** + * Class to implement a login modal from the parent modal class + */ +export default class LoginModal extends Modal { + /** + * Creates necessary elements for login modal + * @param {string} serverName Name of the server, used for login and displayed + * in title + * @param {ServerClient} serverClient Server client object used to send the + * login + * @param {BannerController} notificationManager Object controlling the main + * notification banners + * @param {array} ui UI elements to call refresh method on after login + */ + constructor(serverName, serverClient, notificationManager, ui) { + super(serverName); + this.serverName = serverName; + this.serverClient = serverClient; + this.notificationManager = notificationManager; + this.pageUI = ui; + + let passBox = document.createElement('div'); + let nameBox = document.createElement('div'); + let sendBox = document.createElement('div'); + + let passwordLabel = document.createElement('label'); + let passwordInput = document.createElement('input'); + let passwordInvalid = document.createElement('span'); + passwordLabel.setAttribute('for', 'password-input'); + passwordLabel.textContent = 'Passwort:'; + passwordLabel.title = 'Das Passwort des Spiels'; + passwordInput.id = 'password-input'; + passwordInput.type = 'password'; + passwordInput.placeholder = 'Passwort'; + passwordInput.title = 'Das Passwort des Spiels'; + passwordInvalid.className = 'invalid hidden'; + passwordInvalid.textContent = 'Das eingegebene Passwort ist falsch.'; + + let nameLabel = document.createElement('label'); + let nameInput = document.createElement('input'); + let nameInvalid = document.createElement('span'); + nameLabel.setAttribute('for', 'name-input'); + nameLabel.textContent = 'Benutzername:'; + nameLabel.title = 'Dein Anzeigename'; + nameInput.id = 'name-input'; + nameInput.type = 'text'; + nameInput.autocomplete = 'on'; + nameInput.placeholder = 'Name'; + nameInput.title = 'Dein Anzeigename'; + nameInvalid.className = 'invalid hidden'; + nameInvalid.textContent = + 'Der eingegebene Nutzername ist bereits vergeben.'; + + let sendButton = document.createElement('button'); + sendButton.className = 'btn'; + sendButton.textContent = 'Login'; + sendButton.id = 'login-button'; + + passBox.appendChild(passwordLabel); + passBox.appendChild(passwordInput); + passBox.appendChild(passwordInvalid); + nameBox.appendChild(nameLabel); + nameBox.appendChild(nameInput); + nameBox.appendChild(nameInvalid); + sendBox.appendChild(sendButton); + + this.body.appendChild(passBox); + this.body.appendChild(nameBox); + this.body.appendChild(sendBox); + + this.nameInput = nameInput; + this.passwordInput = passwordInput; + this.loginButton = sendButton; + + this.passwordInvalid = passwordInvalid; + this.nameInvalid = nameInvalid; + + this.registerLoginBtn(); + } + + /** + * Registers event to send login, on button press + */ + registerLoginBtn() { + let eventListener; + let loginCallBack = (result, connection) => { + console.log(result); + if (result == 0) { + this.redirectToPlay(connection); + this.close(); + } else if (result == 1) { + this.invalid('Name'); + this.loginButton.addEventListener('click', eventListener); + } else if (result == 2) { + this.invalid('Pass'); + this.loginButton.addEventListener('click', eventListener); + } else { + this.notificationManager.show('unknownLoginErr', + 'Ein unbekannter Fehler ist aufgetreten'); + this.close(); + } + }; + + eventListener = () => { + this.invalid(); // Remove 'invalid' messages + this.loginButton.removeEventListener('click', eventListener); + this.userName = this.nameInput.value; + this.passwordInput.value.getHash() + .then((result) => { + this.serverClient.sendLogin(this.serverName, result, + this.userName, loginCallBack); + }); + }; + this.loginButton.addEventListener('click', eventListener); + } + + /** + * Displays text under invalid password / username + * @param {string} inv Which field to display under (Pass / Name) + * Blank inv will hide both + */ + invalid(inv) { + this.body.classList.remove('frst-warning'); + this.body.classList.remove('scnd-warning'); + + this.passwordInvalid.classList.add('hidden'); + this.nameInvalid.classList.add('hidden'); + + this.passwordInput.style.borderColor = 'none'; + this.nameInput.style.borderColor = 'none'; + + if (inv == 'Pass') { + this.body.classList.add('frst-warning'); + this.passwordInvalid.classList.remove('hidden'); + this.passwordInput.style.borderColor = '#ef5350'; + } else if (inv == 'Name') { + this.body.classList.add('scnd-warning'); + this.nameInvalid.classList.remove('hidden'); + this.nameInput.style.borderColor = '#ef5350'; + } + } + + /** + * Loads play site + * @param {HubConnection} connection Connection to the server + */ + redirectToPlay(connection) { + window.history.pushState('object or string', 'Game Page', + 'play#game=' + this.serverName); + fetch('play').then((response) => { + response.text().then((htmlString) => { + // Replace all references, since we're starting one level farther up + htmlString = htmlString.replace(/\.\.\//g, './'); + htmlString = /((.)|(\n))*<\/body>/g.exec(htmlString)[0]; + htmlString = htmlString.replace(/