Compare commits
No commits in common. "a88ba01c6de557f819db0331090e576cb8edef7d" and "8b6f2e25883dea980d7825080fa4f433ff8c9629" have entirely different histories.
a88ba01c6d
...
8b6f2e2588
@ -1,62 +1,17 @@
|
|||||||
var express = require("express");
|
var express = require("express");
|
||||||
var qs = require("qs");
|
|
||||||
var {WebSocketServer} = require("ws");
|
var {WebSocketServer} = require("ws");
|
||||||
|
|
||||||
var app = express();
|
var app = express();
|
||||||
var server = app.listen(924);
|
var server = app.listen(924);
|
||||||
|
|
||||||
app.get('*', express.static("../frontend"));
|
app.get('*', express.static("../frontend"));
|
||||||
|
|
||||||
var wss = new WebSocketServer({
|
|
||||||
server,
|
|
||||||
clientTracking: true
|
|
||||||
});
|
|
||||||
|
|
||||||
wss.broadcast = function (msg) {
|
var wss = new WebSocketServer({server});
|
||||||
if (typeof msg == "object") msg = JSON.stringify(msg);
|
|
||||||
for (let ws of wss.clients) ws.send(msg);
|
|
||||||
}
|
|
||||||
wss.chatlog = [];
|
|
||||||
|
|
||||||
wss.on("connection", (ws, req) => {
|
wss.on("connection", (ws, req) => {
|
||||||
req.query = qs.parse(req.url.substr(req.url.indexOf('?')));
|
console.log(req);
|
||||||
|
ws.on("message", msg => {
|
||||||
ws.user = {
|
console.log(msg);
|
||||||
id: wss.clients.size,
|
|
||||||
uid: req.socket.remoteAddress,
|
|
||||||
nick: req.query.nick || "potato-chan",
|
|
||||||
color: [Math.floor(Math.random()*255),Math.floor(Math.random()*255),Math.floor(Math.random()*255)]
|
|
||||||
}
|
|
||||||
|
|
||||||
ws.send(JSON.stringify({
|
|
||||||
type: "load",
|
|
||||||
id: ws.user.id,
|
|
||||||
uid: ws.user.uid,
|
|
||||||
users: Array.from(wss.clients).map(x => x.user),
|
|
||||||
chatlog: []
|
|
||||||
}));
|
|
||||||
|
|
||||||
wss.broadcast({type: "chat", message: {type: "join", id: ws.user.id, uid: ws.user.uid, nick: ws.user.nick}});
|
|
||||||
ws.on("close", () => wss.broadcast({type: "chat", message: {type: "leave", id: ws.user.id, uid: ws.user.uid, nick: ws.user.nick}}));
|
|
||||||
|
|
||||||
ws.on("message", (msg, isBinary) => {
|
|
||||||
if (isBinary) {
|
|
||||||
wss.broadcast(Buffer.concat([msg, Buffer.from([ws.user.id])]));
|
|
||||||
} else {
|
|
||||||
msg = msg.toString();
|
|
||||||
try {
|
|
||||||
msg = JSON.parse(msg);
|
|
||||||
} catch (error) { return }
|
|
||||||
console.log(msg);
|
|
||||||
switch (msg.type) {
|
|
||||||
case "chat":
|
|
||||||
let message = {type: "message", content: msg.message, user: {uid: ws.user.uid, nick: ws.user.nick, color: ws.user.color}};
|
|
||||||
wss.broadcast({type: "chat", message});
|
|
||||||
wss.chatlog.push(message);
|
|
||||||
break;
|
|
||||||
case "nick":
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
|
});
|
||||||
});
|
|
||||||
|
@ -29,6 +29,15 @@
|
|||||||
<button id="user-kick">Kick</button>
|
<button id="user-kick">Kick</button>
|
||||||
</div>
|
</div>
|
||||||
<div id="dimmer"></div>
|
<div id="dimmer"></div>
|
||||||
|
<div id="rooms-menu">
|
||||||
|
<ul id="rooms"></ul>
|
||||||
|
</div>
|
||||||
|
<div id="room-settings-menu">
|
||||||
|
<label title="Change the name of this room">Room name <input id="room-name" type="text"></input></label>
|
||||||
|
<label title="Change how fast people can mash their piano">Note quota <input id="room-quota-note" type="number"> notes per <input id="room-quota-time" type="number"> milliseconds</label>
|
||||||
|
<label title="Change the default piano sound that everyone in the room hears">Piano sound <select id="room-sound"></select></label>
|
||||||
|
<button id="room-settings-save">Save</button>
|
||||||
|
</div>
|
||||||
<div id="midi-player-menu">
|
<div id="midi-player-menu">
|
||||||
<input id="midi-upload" type="file" accept="audio/midi">
|
<input id="midi-upload" type="file" accept="audio/midi">
|
||||||
<button id="midi-play">Play</button>
|
<button id="midi-play">Play</button>
|
||||||
@ -56,6 +65,7 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div id="footer">
|
<div id="footer">
|
||||||
|
<button id="rooms-button">Rooms</button>
|
||||||
<button id="room-settings-button">Room settings</button>
|
<button id="room-settings-button">Room settings</button>
|
||||||
<button id="midi-player-button">Midi player</button>
|
<button id="midi-player-button">Midi player</button>
|
||||||
|
|
||||||
|
149
frontend/main.js
149
frontend/main.js
@ -114,6 +114,28 @@ function loadMppBank(url, format) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class Bucket {
|
||||||
|
constructor(rate, time) {
|
||||||
|
this.lastCheck = Date.now();
|
||||||
|
this.allowance = rate;
|
||||||
|
this.rate = rate;
|
||||||
|
this.time = time;
|
||||||
|
}
|
||||||
|
|
||||||
|
spend(amount) {
|
||||||
|
this.allowance += (Date.now() - this.lastCheck) * (this.rate / this.time);
|
||||||
|
this.lastCheck = Date.now();
|
||||||
|
if (this.allowance > this.rate) {
|
||||||
|
this.allowance = this.rate;
|
||||||
|
}
|
||||||
|
if (this.allowance < amount) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
this.allowance -= amount;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
class Key {
|
class Key {
|
||||||
constructor(index) {
|
constructor(index) {
|
||||||
this.index = index;
|
this.index = index;
|
||||||
@ -158,6 +180,7 @@ class Piano {
|
|||||||
this.keys.push(new Key(i));
|
this.keys.push(new Key(i));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
this.bucket = new Bucket(Infinity, 0);
|
||||||
this.sustain = false;
|
this.sustain = false;
|
||||||
this.performanceMode = false;
|
this.performanceMode = false;
|
||||||
|
|
||||||
@ -296,6 +319,8 @@ class Piano {
|
|||||||
}
|
}
|
||||||
|
|
||||||
localKeyDown(key, velocity) {
|
localKeyDown(key, velocity) {
|
||||||
|
if (!this.bucket.spend(1)) return;
|
||||||
|
|
||||||
net.keyDown(key, velocity);
|
net.keyDown(key, velocity);
|
||||||
this.keyDown(key, velocity, net.id);
|
this.keyDown(key, velocity, net.id);
|
||||||
}
|
}
|
||||||
@ -510,6 +535,27 @@ function openModal(element, dimmer, callback) {
|
|||||||
document.addEventListener("click", clickListener, true);
|
document.addEventListener("click", clickListener, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
class Room {
|
||||||
|
constructor(room) {
|
||||||
|
this.name = room.name;
|
||||||
|
this.keyQuota = room.keyQuota;
|
||||||
|
this.sound = room.sound;
|
||||||
|
|
||||||
|
this.updateRoomSettings();
|
||||||
|
}
|
||||||
|
|
||||||
|
updateRoomSettings() {
|
||||||
|
piano.bucket = new Bucket(this.keyQuota.rate, this.keyQuota.per);
|
||||||
|
|
||||||
|
document.getElementById("room-name").value = this.name;
|
||||||
|
document.getElementById("room-quota-note").value = this.keyQuota.rate;
|
||||||
|
document.getElementById("room-quota-time").value = this.keyQuota.per;
|
||||||
|
document.getElementById("room-sound").value = this.sound;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
class User {
|
class User {
|
||||||
constructor(id, uid, nick, color) {
|
constructor(id, uid, nick, color) {
|
||||||
this.id = id;
|
this.id = id;
|
||||||
@ -592,8 +638,11 @@ class User {
|
|||||||
}
|
}
|
||||||
|
|
||||||
class Networker {
|
class Networker {
|
||||||
constructor(url = `ws://${location.host}`) {
|
constructor(url = `ws://${location.host}?`) {
|
||||||
if (localStorage.nick) url += "?nick=" + encodeURIComponent(localStorage.nick);
|
url += "room=" + encodeURIComponent(decodeURIComponent(location.pathname.slice(7)));
|
||||||
|
if (localStorage.nick) {
|
||||||
|
url += "&nick=" + encodeURIComponent(localStorage.nick);
|
||||||
|
}
|
||||||
|
|
||||||
this.ws = new WebSocket(url);
|
this.ws = new WebSocket(url);
|
||||||
this.ws.binaryType = "arraybuffer";
|
this.ws.binaryType = "arraybuffer";
|
||||||
@ -611,6 +660,7 @@ class Networker {
|
|||||||
});
|
});
|
||||||
|
|
||||||
this.users = {};
|
this.users = {};
|
||||||
|
this.rooms = [];
|
||||||
}
|
}
|
||||||
|
|
||||||
message(message) {
|
message(message) {
|
||||||
@ -621,8 +671,12 @@ class Networker {
|
|||||||
|
|
||||||
switch(message.type) {
|
switch(message.type) {
|
||||||
case "load":
|
case "load":
|
||||||
|
if (this.room == message.room) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
this.id = message.id;
|
this.id = message.id;
|
||||||
|
this.room = new Room(message.room);
|
||||||
|
|
||||||
this.users = {};
|
this.users = {};
|
||||||
for (let i=0; i<message.users.length; i++) {
|
for (let i=0; i<message.users.length; i++) {
|
||||||
@ -632,10 +686,52 @@ class Networker {
|
|||||||
|
|
||||||
chat.chatLog(message.chatlog);
|
chat.chatLog(message.chatlog);
|
||||||
|
|
||||||
|
this.rooms = message.rooms;
|
||||||
|
for (let i=0; i<this.rooms.length; i++) {
|
||||||
|
let element = document.createElement("li");
|
||||||
|
element.addEventListener("click", (function(room) {
|
||||||
|
return function() {
|
||||||
|
window.location.pathname = "/" + room;
|
||||||
|
};
|
||||||
|
})(this.rooms[i].name));
|
||||||
|
let roomName = document.createElement("span");
|
||||||
|
roomName.className = "name";
|
||||||
|
roomName.innerText = this.rooms[i].name;
|
||||||
|
element.appendChild(roomName);
|
||||||
|
|
||||||
|
let users = document.createElement("span");
|
||||||
|
users.className = "users";
|
||||||
|
users.innerText = this.rooms[i].users;
|
||||||
|
element.appendChild(users);
|
||||||
|
document.getElementById("rooms").appendChild(element);
|
||||||
|
}
|
||||||
|
|
||||||
if (localStorage.adminlogin) {
|
if (localStorage.adminlogin) {
|
||||||
net.chat("/adminlogin " + localStorage.adminlogin);
|
net.chat("/adminlogin " + localStorage.adminlogin);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
case "rooms":
|
||||||
|
this.rooms = message.rooms;
|
||||||
|
document.getElementById("rooms").innerHTML = "";
|
||||||
|
for (let i=0; i<this.rooms.length; i++) {
|
||||||
|
let element = document.createElement("li");
|
||||||
|
element.addEventListener("click", (function(room) {
|
||||||
|
return function() {
|
||||||
|
window.location.pathname = "/" + room;
|
||||||
|
};
|
||||||
|
})(this.rooms[i].name));
|
||||||
|
let roomName = document.createElement("span");
|
||||||
|
roomName.className = "name";
|
||||||
|
roomName.innerText = this.rooms[i].name;
|
||||||
|
element.appendChild(roomName);
|
||||||
|
|
||||||
|
let users = document.createElement("span");
|
||||||
|
users.className = "users";
|
||||||
|
users.innerText = this.rooms[i].users;
|
||||||
|
element.appendChild(users);
|
||||||
|
document.getElementById("rooms").appendChild(element);
|
||||||
|
}
|
||||||
|
break;
|
||||||
case "join":
|
case "join":
|
||||||
this.users[message.id] = new User(message.id, message.uid, message.nick, message.color);
|
this.users[message.id] = new User(message.id, message.uid, message.nick, message.color);
|
||||||
break;
|
break;
|
||||||
@ -667,6 +763,13 @@ class Networker {
|
|||||||
document.body.className = "admin";
|
document.body.className = "admin";
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
case "room-settings":
|
||||||
|
this.room.name = message.name;
|
||||||
|
this.room.keyQuota.rate = message.keyQuota.rate;
|
||||||
|
this.room.keyQuota.per = message.keyQuota.per;
|
||||||
|
this.room.sound = message.sound;
|
||||||
|
this.room.updateRoomSettings();
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
return;
|
return;
|
||||||
@ -726,6 +829,18 @@ class Networker {
|
|||||||
this.ws.send(buffer);
|
this.ws.send(buffer);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
roomSettings(data) {
|
||||||
|
this.ws.send(JSON.stringify({
|
||||||
|
type: "room-settings",
|
||||||
|
name: data.name,
|
||||||
|
keyQuota: {
|
||||||
|
rate: data.keyQuota.rate,
|
||||||
|
per: data.keyQuota.per
|
||||||
|
},
|
||||||
|
sound: data.sound
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
|
||||||
chat(message) {
|
chat(message) {
|
||||||
this.ws.send(JSON.stringify({
|
this.ws.send(JSON.stringify({
|
||||||
type: "chat",
|
type: "chat",
|
||||||
@ -856,6 +971,14 @@ class Chat {
|
|||||||
element.className = "nick";
|
element.className = "nick";
|
||||||
element.textContent = message.id + " changed nick to " + message.nick;
|
element.textContent = message.id + " changed nick to " + message.nick;
|
||||||
break;
|
break;
|
||||||
|
case "rank":
|
||||||
|
element.className = "rank";
|
||||||
|
if (message.rank === 1) {
|
||||||
|
element.textContent = "You're now the owner of this room.";
|
||||||
|
} else if (message.rank === 2) {
|
||||||
|
element.textContent = "You're now logged in as admin.";
|
||||||
|
}
|
||||||
|
break;
|
||||||
case "disconnected":
|
case "disconnected":
|
||||||
element.className = "disconnected";
|
element.className = "disconnected";
|
||||||
element.textContent = "You were disconnected from the server!";
|
element.textContent = "You were disconnected from the server!";
|
||||||
@ -930,6 +1053,14 @@ window.addEventListener("load", function() {
|
|||||||
});
|
});
|
||||||
|
|
||||||
// Footer menus
|
// Footer menus
|
||||||
|
document.getElementById("rooms-button").addEventListener("click", function(event) {
|
||||||
|
openModal(document.getElementById("rooms-menu"), true);
|
||||||
|
event.stopImmediatePropagation();
|
||||||
|
});
|
||||||
|
document.getElementById("room-settings-button").addEventListener("click", function(event) {
|
||||||
|
openModal(document.getElementById("room-settings-menu"), true);
|
||||||
|
event.stopImmediatePropagation();
|
||||||
|
});
|
||||||
document.getElementById("midi-player-button").addEventListener("click", function(event) {
|
document.getElementById("midi-player-button").addEventListener("click", function(event) {
|
||||||
openModal(document.getElementById("midi-player-menu"), false);
|
openModal(document.getElementById("midi-player-menu"), false);
|
||||||
event.stopImmediatePropagation();
|
event.stopImmediatePropagation();
|
||||||
@ -939,6 +1070,19 @@ window.addEventListener("load", function() {
|
|||||||
event.stopImmediatePropagation();
|
event.stopImmediatePropagation();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// Room settings
|
||||||
|
document.getElementById("room-settings-save").addEventListener("click", function() {
|
||||||
|
net.roomSettings({
|
||||||
|
name: document.getElementById("room-name").value,
|
||||||
|
keyQuota: {
|
||||||
|
rate: parseInt(document.getElementById("room-quota-note").value),
|
||||||
|
per: parseInt(document.getElementById("room-quota-time").value)
|
||||||
|
},
|
||||||
|
sound: document.getElementById("room-sound").value
|
||||||
|
});
|
||||||
|
document.getElementById("dimmer").click();
|
||||||
|
});
|
||||||
|
|
||||||
// Midi player
|
// Midi player
|
||||||
document.getElementById("midi-upload").addEventListener("change", function() {
|
document.getElementById("midi-upload").addEventListener("change", function() {
|
||||||
let reader = new FileReader();
|
let reader = new FileReader();
|
||||||
@ -1022,6 +1166,7 @@ window.addEventListener("load", function() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
document.getElementById("setting-sounds").appendChild(getOption());
|
document.getElementById("setting-sounds").appendChild(getOption());
|
||||||
|
document.getElementById("room-sound").appendChild(getOption());
|
||||||
});
|
});
|
||||||
document.getElementById("setting-sounds").addEventListener("input", function() {
|
document.getElementById("setting-sounds").addEventListener("input", function() {
|
||||||
let sound = this.value;
|
let sound = this.value;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user