stream updates

This commit is contained in:
Holly Stubbs 2022-08-26 12:52:00 +01:00
parent aa6a7338aa
commit da3dd4c715
Signed by: tgpholly
GPG key ID: B8583C4B7D18119E
17 changed files with 222 additions and 139 deletions

View file

@ -1,5 +1,6 @@
const osu = require("osu-packet"),
maths = require("./util/Maths.js"),
Streams = require("./Streams.js"),
OsuBattleRoyale = require("./MultiplayerExtras/OsuBattleRoyale.js");
module.exports = function(User, Message, Stream, IsCalledFromMultiplayer = false) {
@ -123,7 +124,7 @@ module.exports = function(User, Message, Stream, IsCalledFromMultiplayer = false
target: "#multiplayer",
senderId: global.botUser.id
});
global.StreamsHandler.sendToStream(Stream, local_osuPacketWriter.toBuffer, null);
Streams.sendToStream(Stream, local_osuPacketWriter.toBuffer, null);
} else if (countdown == 0) {
local_osuPacketWriter.SendMessage({
sendingClient: global.botUser.username,
@ -131,7 +132,7 @@ module.exports = function(User, Message, Stream, IsCalledFromMultiplayer = false
target: "#multiplayer",
senderId: global.botUser.id
});
global.StreamsHandler.sendToStream(Stream, local_osuPacketWriter.toBuffer, null);
Streams.sendToStream(Stream, local_osuPacketWriter.toBuffer, null);
User.currentMatch.matchStartCountdownActive = false;
setTimeout(() => User.currentMatch.startMatch(), 1000);
clearInterval(intervalRef);
@ -159,7 +160,7 @@ module.exports = function(User, Message, Stream, IsCalledFromMultiplayer = false
senderId: global.botUser.id
});
User.currentMatch.multiplayerExtras = null;
global.StreamsHandler.sendToStream(Stream, commandBanchoPacketWriter.toBuffer, null);
Streams.sendToStream(Stream, commandBanchoPacketWriter.toBuffer, null);
}
else enableOBR(User, Stream, commandBanchoPacketWriter);
}
@ -190,7 +191,7 @@ module.exports = function(User, Message, Stream, IsCalledFromMultiplayer = false
});
}
}
global.StreamsHandler.sendToStream(Stream, osuPacketWriter.toBuffer, null);
Streams.sendToStream(Stream, osuPacketWriter.toBuffer, null);
}
function enableOBR(User, Stream, commandBanchoPacketWriter) {
@ -208,5 +209,5 @@ function enableOBR(User, Stream, commandBanchoPacketWriter) {
target: "#multiplayer",
senderId: global.botUser.id
});
global.StreamsHandler.sendToStream(Stream, commandBanchoPacketWriter.toBuffer, null);
Streams.sendToStream(Stream, commandBanchoPacketWriter.toBuffer, null);
}

View file

@ -1,7 +1,8 @@
const mysql = require("mysql2");
const consoleHelper = require("../consoleHelper.js");
module.exports = class {
constructor(databaseAddress, databasePort = 3306, databaseUsername, databasePassword, databaseName) {
constructor(databaseAddress, databasePort = 3306, databaseUsername, databasePassword, databaseName, connectedCallback) {
this.connectionPool = mysql.createPool({
connectionLimit: 128,
host: databaseAddress,
@ -10,6 +11,24 @@ module.exports = class {
password: databasePassword,
database: databaseName
});
const classCreationTime = Date.now();
this.dbActive = false;
if (connectedCallback == null) {
this.dbActive = true;
} else {
const connectionCheckInterval = setInterval(() => {
this.query("SELECT name FROM osu_info LIMIT 1")
.then(data => {
consoleHelper.printBancho(`Connected to database. Took ${Date.now() - classCreationTime}ms`);
this.dbActive = true;
clearInterval(connectionCheckInterval);
connectedCallback();
})
.catch(err => {});
}, 167); // Roughly 6 times per sec
}
}
query(query = "", data) {

View file

@ -1,6 +1,7 @@
const osu = require("osu-packet"),
MultiplayerMatch = require("../MultiplayerMatch.js"),
getUserById = require("../util/getUserById.js");
getUserById = require("../util/getUserById.js"),
Streams = require("../Streams.js");
function sameScoreCheck(playerScores = [{playerId:0,slotId:0,score:0,isCurrentlyFailed:false}], lowestScore = 0) {
for (let playerScore of playerScores) {
@ -27,8 +28,8 @@ function kickLowScorers(playerScores = [{playerId:0,slotId:0,score:0,isCurrently
slot.playerId = -1;
slot.status = 2;
// Remove the kicked player from the match's stream
global.StreamsHandler.removeUserFromStream(MultiplayerMatch.matchStreamName, kickedPlayer.uuid);
global.StreamsHandler.removeUserFromStream(MultiplayerMatch.matchChatStreamName, kickedPlayer.uuid);
Streams.removeUserFromStream(MultiplayerMatch.matchStreamName, kickedPlayer.uuid);
Streams.removeUserFromStream(MultiplayerMatch.matchChatStreamName, kickedPlayer.uuid);
// Remove the kicked player's referance this this match
kickedPlayer.currentMatch = null;
@ -52,7 +53,7 @@ function kickLowScorers(playerScores = [{playerId:0,slotId:0,score:0,isCurrently
senderId: global.botUser.id
});
global.StreamsHandler.sendToStream(MultiplayerMatch.matchChatStreamName, osuPacketWriter.toBuffer, null);
Streams.sendToStream(MultiplayerMatch.matchChatStreamName, osuPacketWriter.toBuffer, null);
}
}
}

View file

@ -3,6 +3,7 @@ const osu = require("osu-packet"),
UserPresence = require("./Packets/UserPresence.js"),
StatusUpdate = require("./Packets/StatusUpdate.js"),
MultiplayerMatch = require("./MultiplayerMatch.js"),
Streams = require("./Streams.js"),
User = require("./User.js");
module.exports = class {
@ -16,10 +17,10 @@ module.exports = class {
currentUser.currentMatch.leaveMatch(currentUser);
// Add user to the stream for the lobby
global.StreamsHandler.addUserToStream("multiplayer_lobby", currentUser.uuid);
Streams.addUserToStream("multiplayer_lobby", currentUser.uuid);
// Send user ids of all online users to all users in the lobby
global.StreamsHandler.sendToStream("multiplayer_lobby", UserPresenceBundle(currentUser, false), null);
Streams.sendToStream("multiplayer_lobby", UserPresenceBundle(currentUser, false), null);
// Loop through all matches
for (let i = 0; i < this.matches.length; i++) {
@ -30,8 +31,8 @@ module.exports = class {
if (slot.playerId == -1 || slot.status == 2) continue;
// Send information for this user to all users in the lobby
global.StreamsHandler.sendToStream("multiplayer_lobby", UserPresence(currentUser, slot.playerId, false), null);
global.StreamsHandler.sendToStream("multiplayer_lobby", StatusUpdate(currentUser, slot.playerId, false), null);
Streams.sendToStream("multiplayer_lobby", UserPresence(currentUser, slot.playerId, false), null);
Streams.sendToStream("multiplayer_lobby", StatusUpdate(currentUser, slot.playerId, false), null);
}
const osuPacketWriter = new osu.Bancho.Writer;
@ -40,11 +41,12 @@ module.exports = class {
currentUser.addActionToQueue(osuPacketWriter.toBuffer);
}
const osuPacketWriter = new osu.Bancho.Writer;
// Add the user to the #lobby channel
if (!global.StreamsHandler.isUserInStream("#lobby", currentUser.uuid)) {
global.StreamsHandler.addUserToStream("#lobby", currentUser.uuid);
if (!Streams.isUserInStream("#lobby", currentUser.uuid)) {
Streams.addUserToStream("#lobby", currentUser.uuid);
osuPacketWriter.ChannelJoinSuccess("#lobby");
}
@ -53,13 +55,13 @@ module.exports = class {
userLeaveLobby(currentUser) {
// Remove user from the stream for the multiplayer lobby if they are a part of it
if (global.StreamsHandler.isUserInStream("multiplayer_lobby", currentUser.uuid))
global.StreamsHandler.removeUserFromStream("multiplayer_lobby", currentUser.uuid);
if (Streams.isUserInStream("multiplayer_lobby", currentUser.uuid))
Streams.removeUserFromStream("multiplayer_lobby", currentUser.uuid);
}
updateMatchListing() {
// Send user ids of all online users to all users in the lobby
global.StreamsHandler.sendToStream("multiplayer_lobby", UserPresenceBundle(null, false), null);
Streams.sendToStream("multiplayer_lobby", UserPresenceBundle(null, false), null);
// List through all matches
for (let i = 0; i < this.matches.length; i++) {
@ -70,8 +72,8 @@ module.exports = class {
if (slot.playerId == -1 || slot.status == 2) continue;
// Send information for this user to all users in the lobby
global.StreamsHandler.sendToStream("multiplayer_lobby", UserPresence(null, slot.playerId, false), null);
global.StreamsHandler.sendToStream("multiplayer_lobby", StatusUpdate(null, slot.playerId, false), null);
Streams.sendToStream("multiplayer_lobby", UserPresence(null, slot.playerId, false), null);
Streams.sendToStream("multiplayer_lobby", StatusUpdate(null, slot.playerId, false), null);
}
const osuPacketWriter = new osu.Bancho.Writer;
@ -79,13 +81,13 @@ module.exports = class {
osuPacketWriter.MatchNew(this.matches[i].createOsuMatchJSON());
// Send this data back to every user in the lobby
global.StreamsHandler.sendToStream("multiplayer_lobby", osuPacketWriter.toBuffer, null);
Streams.sendToStream("multiplayer_lobby", osuPacketWriter.toBuffer, null);
}
}
createMultiplayerMatch(MatchHost, MatchData) {
async createMultiplayerMatch(MatchHost, MatchData) {
let matchClass = null;
this.matches.push(matchClass = new MultiplayerMatch(MatchHost, MatchData));
this.matches.push(matchClass = await MultiplayerMatch.createMatch(MatchHost, MatchData));
// Join the user to the newly created match
this.joinMultiplayerMatch(MatchHost, {
@ -139,11 +141,11 @@ module.exports = class {
JoiningUser.inMatch = true;
// Add user to the stream for the match
global.StreamsHandler.addUserToStream(streamName, JoiningUser.uuid);
global.StreamsHandler.addUserToStream(chatStreamName, JoiningUser.uuid);
Streams.addUserToStream(streamName, JoiningUser.uuid);
Streams.addUserToStream(chatStreamName, JoiningUser.uuid);
// Inform all users in the match that a new user has joined
global.StreamsHandler.sendToStream(streamName, osuPacketWriter1.toBuffer, null);
Streams.sendToStream(streamName, osuPacketWriter1.toBuffer, null);
osuPacketWriter.ChannelJoinSuccess("#multiplayer");
@ -165,7 +167,7 @@ module.exports = class {
}
}
leaveMultiplayerMatch(MatchUser = new User) {
async leaveMultiplayerMatch(MatchUser = new User) {
// Make sure the user is in a match
if (MatchUser.currentMatch == null) return;
@ -202,6 +204,9 @@ module.exports = class {
// Remove this match from the list of active matches
this.matches.splice(matchIndex, 1);
// Close the db match
global.DatabaseHelper.query("UPDATE mp_matches SET close_time = UNIX_TIMESTAMP() WHERE id = ?", [mpMatch.matchId]);
}
MatchUser.currentMatch = null;
@ -211,11 +216,6 @@ module.exports = class {
// Update the match listing to reflect this change (either removal or user leaving)
this.updateMatchListing();
// Delay a 2nd match listing update
setTimeout(() => {
this.updateMatchListing();
}, 1000);
}
getMatch(MatchID) {

View file

@ -1,13 +1,16 @@
const osu = require("osu-packet"),
getUserById = require("./util/getUserById.js"),
StatusUpdate = require("./Packets/StatusUpdate.js"),
Streams = require("./Streams.js"),
User = require("./User.js");
// TODO: Cache the player's slot position in their user class for a small optimisation
module.exports = class {
constructor(MatchHost = new User, MatchData = {matchId: -1,inProgress: false,matchType: 0,activeMods: 0,gameName: "",gamePassword: '',beatmapName: '',beatmapId: 1250198,beatmapChecksum: '',slots: [],host: 0,playMode: 0,matchScoringType: 0,matchTeamType: 0,specialModes: 0,seed: 0}) {
this.matchId = global.getAndAddToHistoricalMultiplayerMatches();
class MultiplayerMatch {
constructor(MatchData = {matchId: -1,inProgress: false,matchType: 0,activeMods: 0,gameName: "",gamePassword: '',beatmapName: '',beatmapId: 0,beatmapChecksum: '',slots: [],host: 0,playMode: 0,matchScoringType: 0,matchTeamType: 0,specialModes: 0,seed: 0}) {
this.matchId = MatchData.matchId;
this.roundId = 0;
this.inProgress = MatchData.inProgress;
this.matchStartCountdownActive = false;
@ -51,21 +54,43 @@ module.exports = class {
this.isTourneyMatch = false;
this.tourneyClientUsers = [];
}
const osuPacketWriter = new osu.Bancho.Writer;
static createMatch(MatchHost = new User, MatchData = {matchId: -1,inProgress: false,matchType: 0,activeMods: 0,gameName: "",gamePassword: '',beatmapName: '',beatmapId: 0,beatmapChecksum: '',slots: [],host: 0,playMode: 0,matchScoringType: 0,matchTeamType: 0,specialModes: 0,seed: 0}) {
return new Promise(async (resolve, reject) => {
MatchData.matchId = (await global.DatabaseHelper.query(
"INSERT INTO mp_matches (id, name, open_time, close_time, seed) VALUES (NULL, ?, UNIX_TIMESTAMP(), NULL, ?) RETURNING id;",
[MatchData.gameName, MatchData.seed]
))[0]["id"];
// Update the status of the current user
StatusUpdate(MatchHost, MatchHost.id);
osuPacketWriter.MatchNew(this.createOsuMatchJSON());
const matchInstance = new MultiplayerMatch(MatchData);
// Queue match creation for user
MatchHost.addActionToQueue(osuPacketWriter.toBuffer);
console.log(matchInstance.matchId);
global.StreamsHandler.addStream(this.matchStreamName, true, this.matchId);
global.StreamsHandler.addStream(this.matchChatStreamName, true, this.matchId);
// Update the status of the current user
StatusUpdate(MatchHost, MatchHost.id);
// Update the match listing for users in the multiplayer lobby
global.MultiplayerManager.updateMatchListing();
const osuPacketWriter = new osu.Bancho.Writer;
osuPacketWriter.MatchNew(matchInstance.createOsuMatchJSON());
MatchHost.addActionToQueue(osuPacketWriter.toBuffer);
Streams.addStream(matchInstance.matchStreamName, true, matchInstance.matchId);
Streams.addStream(matchInstance.matchChatStreamName, true, matchInstance.matchId);
// Update the match listing for users in the multiplayer lobby
global.MultiplayerManager.updateMatchListing();
resolve(matchInstance);
});
}
getSlotIdByPlayerId(playerId = 0) {
const player = getUserById(playerId);
if (player != null) return player.matchSlotId;
else return null;
}
createOsuMatchJSON() {
@ -101,8 +126,8 @@ module.exports = class {
slot.status = 1;
// Remove the leaving user from the match's stream
global.StreamsHandler.removeUserFromStream(this.matchStreamName, MatchUser.uuid);
global.StreamsHandler.removeUserFromStream(this.matchChatStreamName, MatchUser.uuid);
Streams.removeUserFromStream(this.matchStreamName, MatchUser.uuid);
Streams.removeUserFromStream(this.matchChatStreamName, MatchUser.uuid);
// Send this after removing the user from match streams to avoid a leave notification for self
this.sendMatchUpdate();
@ -115,7 +140,7 @@ module.exports = class {
MatchUser.addActionToQueue(osuPacketWriter.toBuffer);
}
updateMatch(MatchUser = new User, MatchData) {
async updateMatch(MatchUser = new User, MatchData) {
// Update match with new data
this.inProgress = MatchData.inProgress;
@ -123,7 +148,10 @@ module.exports = class {
this.activeMods = MatchData.activeMods;
this.gameName = MatchData.gameName;
if (this.gameName !== MatchData.gameName) {
this.gameName = MatchData.gameName;
await global.DatabaseHelper.query("UPDATE mp_matches SET name = ? WHERE id = ?", [this.gameName, this.matchId]);
}
if (MatchData.gamePassword == '') MatchData.gamePassword == null;
this.gamePassword = MatchData.gamePassword;
@ -139,7 +167,10 @@ module.exports = class {
this.matchTeamType = MatchData.matchTeamType;
this.specialModes = MatchData.specialModes;
this.seed = MatchData.seed;
if (this.seed !== MatchData.seed) {
this.seed = MatchData.seed;
await global.DatabaseHelper.query("UPDATE mp_matches SET seed = ? WHERE id = ?", [this.seed, this.matchId]);
}
this.sendMatchUpdate();
@ -153,7 +184,8 @@ module.exports = class {
osuPacketWriter.MatchUpdate(this.createOsuMatchJSON());
// Update all users in the match with new match information
global.StreamsHandler.sendToStream(this.matchStreamName, osuPacketWriter.toBuffer, null);
if (Streams.exists(this.matchStreamName))
Streams.sendToStream(this.matchStreamName, osuPacketWriter.toBuffer, null);
}
moveToSlot(MatchUser = new User, SlotToMoveTo) {
@ -234,7 +266,7 @@ module.exports = class {
if (cachedPlayerToken !== null && cachedPlayerToken !== "") {
// Remove the kicked user from the match stream
global.StreamsHandler.removeUserFromStream(this.matchStreamName, cachedPlayerToken);
Streams.removeUserFromStream(this.matchStreamName, cachedPlayerToken);
}
}
}
@ -288,7 +320,7 @@ module.exports = class {
osuPacketWriter.MatchPlayerSkipped(MatchUser.id);
osuPacketWriter.MatchSkip();
global.StreamsHandler.sendToStream(this.matchStreamName, osuPacketWriter.toBuffer, null);
Streams.sendToStream(this.matchStreamName, osuPacketWriter.toBuffer, null);
this.matchSkippedSlots = null;
} else {
@ -296,7 +328,7 @@ module.exports = class {
osuPacketWriter.MatchPlayerSkipped(MatchUser.id);
global.StreamsHandler.sendToStream(this.matchStreamName, osuPacketWriter.toBuffer, null);
Streams.sendToStream(this.matchStreamName, osuPacketWriter.toBuffer, null);
}
}
@ -356,7 +388,7 @@ module.exports = class {
osuPacketWriter.MatchStart(this.createOsuMatchJSON());
// Inform all users in the match that it has started
global.StreamsHandler.sendToStream(this.matchStreamName, osuPacketWriter.toBuffer, null);
Streams.sendToStream(this.matchStreamName, osuPacketWriter.toBuffer, null);
// Update all users in the match with new info
this.sendMatchUpdate();
@ -383,7 +415,7 @@ module.exports = class {
if (allLoaded) {
let osuPacketWriter = new osu.Bancho.Writer;
osuPacketWriter.MatchAllPlayersLoaded();
global.StreamsHandler.sendToStream(this.matchStreamName, osuPacketWriter.toBuffer, null);
Streams.sendToStream(this.matchStreamName, osuPacketWriter.toBuffer, null);
// Blank out user loading array
this.matchLoadSlots = null;
@ -432,25 +464,42 @@ module.exports = class {
if (allLoaded) this.finishMatch();
}
finishMatch() {
async finishMatch() {
if (!this.inProgress) return;
this.matchLoadSlots = null;
this.inProgress = false;
let osuPacketWriter = new osu.Bancho.Writer;
let queryData = [this.matchId, this.roundId++, this.playMode, this.matchType, this.matchScoringType, this.matchTeamType, this.activeMods, this.beatmapChecksum, (this.specialModes === 1) ? 1 : 0];
// Loop through all slots in the match
for (let slot of this.slots) {
// Make sure the slot has a user
if (slot.playerId === -1 || slot.status === 1 || slot.status === 2) continue;
if (slot.playerId === -1 || slot.status === 1 || slot.status === 2) {
queryData.push(null);
continue;
}
let score = null;
for (let _playerScore of this.playerScores) {
if (_playerScore.playerId === slot.playerId) {
score = _playerScore._raw;
break;
}
}
queryData.push(`${slot.playerId}|${score.totalScore}|${score.maxCombo}|${score.count300}|${score.count100}|${score.count50}|${score.countGeki}|${score.countKatu}|${score.countMiss}|${(score.currentHp == 254) ? 1 : 0}${(this.specialModes === 1) ? `|${slot.mods}` : ""}|${score.usingScoreV2 ? 1 : 0}${score.usingScoreV2 ? `|${score.comboPortion}|${score.bonusPortion}` : ""}`);
// Set the user's status back to normal from playing
slot.status = 4;
}
console.log(queryData);
osuPacketWriter.MatchComplete();
// Inform all users in the match that it is complete
global.StreamsHandler.sendToStream(this.matchStreamName, osuPacketWriter.toBuffer, null);
Streams.sendToStream(this.matchStreamName, osuPacketWriter.toBuffer, null);
// Update all users in the match with new info
this.sendMatchUpdate();
@ -460,6 +509,8 @@ module.exports = class {
if (this.multiplayerExtras != null) this.multiplayerExtras.onMatchFinished(JSON.parse(JSON.stringify(this.playerScores)));
await global.DatabaseHelper.query("INSERT INTO mp_match_rounds (id, match_id, round_id, round_mode, match_type, round_scoring_type, round_team_type, round_mods, beatmap_md5, freemod, player0, player1, player2, player3, player4, player5, player6, player7, player8, player9, player10, player11, player12, player13, player14, player15) VALUES (NULL, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)", queryData);
this.playerScores = null;
}
@ -477,6 +528,7 @@ module.exports = class {
if (playerScore.playerId == MatchPlayer.id) {
playerScore.score = MatchScoreData.totalScore;
playerScore.isCurrentlyFailed = MatchScoreData.currentHp == 254;
playerScore._raw = MatchScoreData;
break;
}
}
@ -484,7 +536,7 @@ module.exports = class {
osuPacketWriter.MatchScoreUpdate(MatchScoreData);
// Send the newly updated score to all users in the match
global.StreamsHandler.sendToStream(this.matchStreamName, osuPacketWriter.toBuffer, null);
Streams.sendToStream(this.matchStreamName, osuPacketWriter.toBuffer, null);
}
matchFailed(MatchUser = new User) {
@ -495,6 +547,8 @@ module.exports = class {
osuPacketWriter.MatchPlayerFailed(MatchUser.id);
global.StreamsHandler.sendToStream(this.matchStreamName, osuPacketWriter.toBuffer, null);
Streams.sendToStream(this.matchStreamName, osuPacketWriter.toBuffer, null);
}
}
}
module.exports = MultiplayerMatch;

View file

@ -1,10 +1,11 @@
const StatusUpdate = require("./StatusUpdate.js");
const StatusUpdate = require("./StatusUpdate.js"),
Streams = require("../Streams.js");
module.exports = function(currentUser, data) {
currentUser.updatePresence(data);
if (global.StreamsHandler.doesStreamExist(`sp_${currentUser.username}`)) {
if (Streams.exists(`sp_${currentUser.username}`)) {
const statusUpdate = StatusUpdate(currentUser, currentUser.id, false);
global.StreamsHandler.sendToStream(`sp_${currentUser.username}`, statusUpdate, null);
Streams.sendToStream(`sp_${currentUser.username}`, statusUpdate, null);
}
}

View file

@ -1,16 +1,17 @@
const osu = require("osu-packet"),
consoleHelper = require("../../consoleHelper.js");
consoleHelper = require("../../consoleHelper.js"),
Streams = require("../Streams.js");
module.exports = function(CurrentUser, channelName = "") {
// Make sure the user is not already in the channel
if (global.StreamsHandler.isUserInStream(channelName, CurrentUser.uuid))
if (Streams.isUserInStream(channelName, CurrentUser.uuid))
return consoleHelper.printBancho(`Did not add user to channel ${channelName} because they are already in it`);
const osuPacketWriter = new osu.Bancho.Writer;
osuPacketWriter.ChannelJoinSuccess(channelName);
if (!global.StreamsHandler.isUserInStream(channelName, CurrentUser.uuid))
global.StreamsHandler.addUserToStream(channelName, CurrentUser.uuid);
if (!Streams.isUserInStream(channelName, CurrentUser.uuid))
Streams.addUserToStream(channelName, CurrentUser.uuid);
CurrentUser.addActionToQueue(osuPacketWriter.toBuffer);
}

View file

@ -1,5 +1,7 @@
const Streams = require("../Streams.js");
module.exports = function(CurrentUser, data) {
if (data == "#multiplayer") return; // Ignore requests for multiplayer
global.StreamsHandler.removeUserFromStream(data, CurrentUser.uuid);
Streams.removeUserFromStream(data, CurrentUser.uuid);
}

View file

@ -1,21 +1,23 @@
const osu = require("osu-packet"),
consoleHelper = require("../../consoleHelper.js");
const consoleHelper = require("../../consoleHelper.js"),
Streams = require("../Streams.js");
module.exports = function(CurrentUser) {
if (CurrentUser.uuid === "bot") throw "Tried to log bot out, WTF???";
const logoutStartTime = Date.now();
const streamList = global.StreamsHandler.getStreams();
const streamList = Streams.getStreams();
for (let i = 0; i < streamList.length; i++) {
if (global.StreamsHandler.isUserInStream(streamList[i], CurrentUser.uuid)) {
global.StreamsHandler.removeUserFromStream(streamList[i], CurrentUser.uuid);
if (Streams.isUserInStream(streamList[i], CurrentUser.uuid)) {
Streams.removeUserFromStream(streamList[i], CurrentUser.uuid);
}
}
// Remove user from user list
global.users.remove(CurrentUser.uuid);
global.DatabaseHelper.query("UPDATE osu_info SET value = ? WHERE name = 'online_now'", [global.users.getLength() - 1]);
consoleHelper.printBancho(`User logged out, took ${Date.now() - logoutStartTime}ms. [User: ${CurrentUser.username}]`);
}

View file

@ -1,6 +1,7 @@
const osu = require("osu-packet"),
botCommandHandler = require("../BotCommandHandler.js"),
consoleHelper = require("../../consoleHelper.js");
consoleHelper = require("../../consoleHelper.js"),
Streams = require("../Streams.js");
module.exports = function(CurrentUser, CurrentPacket) {
let isSendingChannelLocked = false;
@ -39,16 +40,16 @@ module.exports = function(CurrentUser, CurrentPacket) {
});
if (CurrentPacket.target == "#multiplayer") {
global.StreamsHandler.sendToStream(CurrentUser.currentMatch.matchChatStreamName, osuPacketWriter.toBuffer, CurrentUser.uuid);
Streams.sendToStream(CurrentUser.currentMatch.matchChatStreamName, osuPacketWriter.toBuffer, CurrentUser.uuid);
botCommandHandler(CurrentUser, CurrentPacket.message, CurrentUser.currentMatch.matchChatStreamName, true);
return;
}
// Check the stream that we're sending to even exists
if (!global.StreamsHandler.doesStreamExist(CurrentPacket.target)) return;
if (!Streams.exists(CurrentPacket.target)) return;
// Write chat message to stream asociated with chat channel
global.StreamsHandler.sendToStream(CurrentPacket.target, osuPacketWriter.toBuffer, CurrentUser.uuid);
Streams.sendToStream(CurrentPacket.target, osuPacketWriter.toBuffer, CurrentUser.uuid);
if (CurrentPacket.target == "#osu")
global.addChatMessage(`${CurrentUser.username}: ${CurrentPacket.message.replaceAll("<", "&lt;").replaceAll(">", "&gt;")}`);

View file

@ -1,5 +1,6 @@
const osu = require("osu-packet"),
consoleHelper = require("./consoleHelper.js");
consoleHelper = require("./consoleHelper.js"),
Streams = require("../Streams.js");
module.exports = function(CurrentUser, MatchID) {
const match = global.MultiplayerManager.getMatch(MatchID);
@ -13,14 +14,14 @@ module.exports = function(CurrentUser, MatchID) {
}
}
if (global.StreamsHandler.isUserInStream(match.matchChatStreamName, CurrentUser.uuid))
if (Streams.isUserInStream(match.matchChatStreamName, CurrentUser.uuid))
return consoleHelper.printBancho(`Did not add user to channel ${match.matchChatStreamName} because they are already in it`);
const osuPacketWriter = new osu.Bancho.Writer;
osuPacketWriter.ChannelJoinSuccess("#multiplayer");
if (!global.StreamsHandler.isUserInStream(match.matchChatStreamName, CurrentUser.uuid))
global.StreamsHandler.addUserToStream(match.matchChatStreamName, CurrentUser.uuid);
if (!Streams.isUserInStream(match.matchChatStreamName, CurrentUser.uuid))
Streams.addUserToStream(match.matchChatStreamName, CurrentUser.uuid);
CurrentUser.addActionToQueue(osuPacketWriter.toBuffer);
}

View file

@ -1,5 +1,6 @@
const osu = require("osu-packet"),
consoleHelper = require("../../consoleHelper.js");
consoleHelper = require("../../consoleHelper.js"),
Streams = require("../Streams.js");
module.exports = function(CurrentUser, MatchID) {
const match = global.MultiplayerManager.getMatch(MatchID);
@ -9,14 +10,14 @@ module.exports = function(CurrentUser, MatchID) {
match.isTourneyMatch = false;
match.tourneyClientUsers = [];
if (global.StreamsHandler.isUserInStream(match.matchChatStreamName, CurrentUser.uuid))
if (Streams.isUserInStream(match.matchChatStreamName, CurrentUser.uuid))
return consoleHelper.printBancho(`Did not add user to channel ${match.matchChatStreamName} because they are already in it`);
const osuPacketWriter = new osu.Bancho.Writer;
osuPacketWriter.ChannelRevoked("#multiplayer");
if (!global.StreamsHandler.isUserInStream(match.matchChatStreamName, CurrentUser.uuid))
global.StreamsHandler.removeUserFromStream(match.matchChatStreamName, CurrentUser.uuid);
if (!Streams.isUserInStream(match.matchChatStreamName, CurrentUser.uuid))
Streams.removeUserFromStream(match.matchChatStreamName, CurrentUser.uuid);
CurrentUser.addActionToQueue(osuPacketWriter.toBuffer);
} else {

View file

@ -1,17 +1,18 @@
const osu = require("osu-packet"),
getUserById = require("./util/getUserById.js");
getUserById = require("./util/getUserById.js"),
Streams = require("./Streams.js");
module.exports = {
startSpectatingUser:function(currentUser, spectatedId) {
// Get the user this user is trying to spectate
const User = getUserById(spectatedId);
if (global.StreamsHandler.doesStreamExist(`sp_${User.id}`)) {
if (Streams.exists(`sp_${User.id}`)) {
// Just add user to stream since it already exists
global.StreamsHandler.addUserToStream(`sp_${User.id}`, currentUser.uuid);
Streams.addUserToStream(`sp_${User.id}`, currentUser.uuid);
} else {
// Stream doesn't exist, create it and add the spectator
global.StreamsHandler.addStream(`sp_${User.id}`, true, spectatedId);
global.StreamsHandler.addUserToStream(`sp_${User.id}`, currentUser.uuid);
Streams.addStream(`sp_${User.id}`, true, spectatedId);
Streams.addUserToStream(`sp_${User.id}`, currentUser.uuid);
}
// We want to do this stuff regardless
@ -34,7 +35,7 @@ module.exports = {
osuPacketWriter.FellowSpectatorJoined(currentUser.id);
// Send this packet to all the spectators
global.StreamsHandler.sendToStream(`sp_${User.id}`, osuPacketWriter.toBuffer);
Streams.sendToStream(`sp_${User.id}`, osuPacketWriter.toBuffer);
},
sendSpectatorFrames(currentUser, data) {
@ -45,7 +46,7 @@ module.exports = {
osuPacketWriter.SpectateFrames(data);
// Send the frames to all the spectators
global.StreamsHandler.sendToStream(`sp_${currentUser.id}`, osuPacketWriter.toBuffer, null);
Streams.sendToStream(`sp_${currentUser.id}`, osuPacketWriter.toBuffer, null);
},
stopSpectatingUser(currentUser) {
@ -61,7 +62,7 @@ module.exports = {
spectatedUser.addActionToQueue(osuPacketWriter.toBuffer);
// Remove this user from the spectator stream
global.StreamsHandler.removeUserFromStream(`sp_${spectatedUser.id}`, currentUser.uuid);
Streams.removeUserFromStream(`sp_${spectatedUser.id}`, currentUser.uuid);
// Make a new clear osu packet writer
osuPacketWriter = new osu.Bancho.Writer;
@ -70,6 +71,6 @@ module.exports = {
osuPacketWriter.FellowSpectatorLeft(currentUser.id);
// Send this packet to all spectators
global.StreamsHandler.sendToStream(`sp_${spectatedUser.id}`, osuPacketWriter.toBuffer);
Streams.sendToStream(`sp_${spectatedUser.id}`, osuPacketWriter.toBuffer);
}
}

View file

@ -2,42 +2,42 @@ const getUserByToken = require("./util/getUserByToken.js"),
consoleHelper = require("../consoleHelper.js");
module.exports = class {
constructor() {
this.avaliableStreams = {};
this.avaliableStreamKeys = [];
static init() {
global.avaliableStreams = {};
global.avaliableStreamKeys = [];
}
addStream(streamName = "", removeIfEmpty = false, spectatorHostId = null) {
static addStream(streamName = "", removeIfEmpty = false, spectatorHostId = null) {
// Make sure a stream with the same name doesn't exist already
if (this.avaliableStreamKeys.includes(streamName))
if (global.avaliableStreamKeys.includes(streamName))
return consoleHelper.printBancho(`Did not add stream [${streamName}] A stream with the same name already exists`);
// Add new stream to the list of streams
this.avaliableStreams[streamName] = {
global.avaliableStreams[streamName] = {
streamUsers: [], // An array containing a list of user tokens of the users in a given stream
streamSpectatorHost: spectatorHostId, // null unless stream is for spectating
removeIfEmpty: removeIfEmpty
}
this.avaliableStreamKeys = Object.keys(this.avaliableStreams);
global.avaliableStreamKeys = Object.keys(global.avaliableStreams);
consoleHelper.printBancho(`Added stream [${streamName}]`);
}
removeStream(streamName) {
static removeStream(streamName) {
try {
delete this.avaliableStreams[streamName];
this.avaliableStreamKeys = Object.keys(this.avaliableStreams);
delete global.avaliableStreams[streamName];
global.avaliableStreamKeys = Object.keys(global.avaliableStreams);
} catch (e) {
consoleHelper.printError(`Was not able to remove stream [${streamName}]`);
console.error(e);
}
}
addUserToStream(streamName, userToken) {
static addUserToStream(streamName, userToken) {
// Make sure the stream we are attempting to add this user to even exists
if (!this.doesStreamExist(streamName))
if (!this.exists(streamName))
return consoleHelper.printBancho(`Did not add user to stream [${streamName}] because it does not exist!`);
// Make sure the user isn't already in the stream
if (this.avaliableStreams[streamName].streamUsers.includes(userToken))
if (global.avaliableStreams[streamName].streamUsers.includes(userToken))
return consoleHelper.printBancho(`Did not add user to stream [${streamName}] because they are already in it!`);
// Make sure this isn't an invalid user (userId can't be lower than 1)
@ -45,16 +45,16 @@ module.exports = class {
return consoleHelper.printBancho(`Did not add user to stream [${streamName}] because their token is invalid!`);
// Add user's token to the stream's user list
this.avaliableStreams[streamName].streamUsers.push(userToken);
global.avaliableStreams[streamName].streamUsers.push(userToken);
consoleHelper.printBancho(`Added user [${userToken}] to stream ${streamName}`);
}
removeUserFromStream(streamName, userToken) {
static removeUserFromStream(streamName, userToken) {
// Make sure the stream we are attempting to add this user to even exists
if (!this.doesStreamExist(streamName))
if (!this.exists(streamName))
return consoleHelper.printBancho(`Did not remove user from stream [${streamName}] because it does not exist!`);
const stream = this.avaliableStreams[streamName];
const stream = global.avaliableStreams[streamName];
// Make sure the user isn't already in the stream
if (!stream.streamUsers.includes(userToken))
@ -82,18 +82,18 @@ module.exports = class {
}
if (stream.removeIfEmpty && stream.streamUsers.length == 0) {
this.removeStream(stream);
this.removeStream(streamName);
consoleHelper.printBancho(`Removed stream [${streamName}] There were no users in stream`);
}
}
sendToStream(streamName, streamData, initUser = null) {
static sendToStream(streamName, streamData, initUser = null) {
// Make sure the stream we are attempting to send to even exists
if (!this.doesStreamExist(streamName))
if (!this.exists(streamName))
return consoleHelper.printBancho(`Did not send to stream [${streamName}] because it does not exist!`);
// Get the stream to send the data to
const currentStream = this.avaliableStreams[streamName];
const currentStream = global.avaliableStreams[streamName];
// Loop through the users in this stream
for (let i = 0; i < currentStream.streamUsers.length; i++) {
@ -113,17 +113,17 @@ module.exports = class {
}
}
doesStreamExist(streamName) {
return this.avaliableStreamKeys.includes(streamName);
static exists(streamName) {
return global.avaliableStreamKeys.includes(streamName);
}
getStreams() {
static getStreams() {
// Return the names of all avaliable streams
return this.avaliableStreamKeys;
return global.avaliableStreamKeys;
}
isUserInStream(streamName, userToken) {
if (this.avaliableStreams[streamName].streamUsers.includes(userToken)) return true;
static isUserInStream(streamName, userToken) {
if (global.avaliableStreams[streamName].streamUsers.includes(userToken)) return true;
else return false;
}
}

View file

@ -9,6 +9,7 @@ const osu = require("osu-packet"),
countryHelper = require("./countryHelper.js"),
loginHelper = require("./loginHelper.js"),
Logout = require("./Packets/Logout.js"),
Streams = require("./Streams.js"),
UserPresenceBundle = require("./Packets/UserPresenceBundle.js"),
UserPresence = require("./Packets/UserPresence.js"),
StatusUpdate = require("./Packets/StatusUpdate.js");
@ -110,8 +111,8 @@ module.exports = async function(req, res, loginInfo) {
// Add user to #osu
osuPacketWriter.ChannelJoinSuccess("#osu");
if (!global.StreamsHandler.isUserInStream("#osu", NewUser.uuid))
global.StreamsHandler.addUserToStream("#osu", NewUser.uuid);
if (!Streams.isUserInStream("#osu", NewUser.uuid))
Streams.addUserToStream("#osu", NewUser.uuid);
// List all channels out to the client
for (let i = 0; i < global.channels.length; i++) {

View file

@ -22,7 +22,11 @@ global.botUser = global.users.add("bot", new User(3, "SillyBot", "bot"));
global.botUser.location[0] = 50;
global.botUser.location[1] = -32;
global.DatabaseHelper = new DatabaseHelperClass(config.database.address, config.database.port, config.database.username, config.database.password, config.database.name);
global.DatabaseHelper = new DatabaseHelperClass(config.database.address, config.database.port, config.database.username, config.database.password, config.database.name, async () => {
// Close any unclosed db matches on startup
global.DatabaseHelper.query("UPDATE mp_matches SET close_time = UNIX_TIMESTAMP() WHERE close_time IS NULL");
global.DatabaseHelper.query("UPDATE osu_info SET value = 0 WHERE name = 'online_now'");
});
async function subscribeToChannel(channelName = "", callback = function(message = "") {}) {
// Dup and connect new client for channel subscription (required)
@ -81,7 +85,8 @@ global.addChatMessage = function(msg) {
}
}
global.StreamsHandler = new Streams();
// Init stream class
Streams.init();
// An array containing all chat channels
global.channels = [
@ -94,19 +99,11 @@ global.channels = [
// Create a stream for each chat channel
for (let i = 0; i < global.channels.length; i++) {
global.StreamsHandler.addStream(global.channels[i].channelName, false);
Streams.addStream(global.channels[i].channelName, false);
}
// Add a stream for the multiplayer lobby
global.StreamsHandler.addStream("multiplayer_lobby", false);
if (!fs.existsSync("tHMM.ds")) fs.writeFileSync("tHMM.ds", "0");
global.totalHistoricalMultiplayerMatches = parseInt(fs.readFileSync("tHMM.ds").toString());
global.getAndAddToHistoricalMultiplayerMatches = function() {
global.totalHistoricalMultiplayerMatches++;
fs.writeFile("tHMM.ds", `${global.totalHistoricalMultiplayerMatches}`, () => {});
return global.totalHistoricalMultiplayerMatches;
}
Streams.addStream("multiplayer_lobby", false);
// Include packets
const ChangeAction = require("./Packets/ChangeAction.js"),

View file

@ -1,6 +1,6 @@
module.exports = function(username) {
for (let user of global.users.getIterableItems()) {
if (user.username == username)
if (user.username === username)
return user;
}
}