Binato/server/MultiplayerManager.js
2021-02-12 23:36:35 +00:00

220 lines
No EOL
8.5 KiB
JavaScript

const osu = require("osu-packet"),
UserPresenceBundle = require("./Packets/UserPresenceBundle.js"),
UserPresence = require("./Packets/UserPresence.js"),
StatusUpdate = require("./Packets/StatusUpdate.js"),
MultiplayerMatch = require("./MultiplayerMatch.js");
module.exports = class {
constructor() {
this.matches = [];
}
userEnterLobby(currentUser) {
// If the user is currently already in a match force them to leave
if (currentUser.currentMatch != null)
currentUser.currentMatch.leaveMatch(currentUser);
// Add user to the stream for the lobby
global.StreamsHandler.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);
// Loop through all matches
for (let i = 0; i < this.matches.length; i++) {
// Loop through all the users in this match
for (let i1 = 0; i1 < this.matches[i].slots.length; i1++) {
const slot = this.matches[i].slots[i1];
// Make sure there is a player / the slot is not locked
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);
}
const osuPacketWriter = new osu.Bancho.Writer;
// List the match on the client
osuPacketWriter.MatchNew(this.matches[i].createOsuMatchJSON());
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);
osuPacketWriter.ChannelJoinSuccess("#lobby");
}
currentUser.addActionToQueue(osuPacketWriter.toBuffer);
}
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);
}
updateMatchListing() {
// Send user ids of all online users to all users in the lobby
global.StreamsHandler.sendToStream("multiplayer_lobby", UserPresenceBundle(null, false), null);
// List through all matches
for (let i = 0; i < this.matches.length; i++) {
// List through all users in the match
for (let i1 = 0; i1 < this.matches[i].slots.length; i1++) {
const slot = this.matches[i].slots[i1];
// Make sure the slot has a user in it / isn't locked
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);
}
const osuPacketWriter = new osu.Bancho.Writer;
// List the match on the client
osuPacketWriter.MatchNew(this.matches[i].createOsuMatchJSON());
// Send this data back to every user in the lobby
global.StreamsHandler.sendToStream("multiplayer_lobby", osuPacketWriter.toBuffer, null);
}
}
createMultiplayerMatch(MatchHost, MatchData) {
let matchClass = null;
this.matches.push(matchClass = new MultiplayerMatch(MatchHost, MatchData));
// Join the user to the newly created match
this.joinMultiplayerMatch(MatchHost, {
matchId: matchClass.matchId,
gamePassword: matchClass.gamePassword
});
}
joinMultiplayerMatch(JoiningUser, JoinInfo) {
try {
let osuPacketWriter = new osu.Bancho.Writer;
const osuPacketWriter1 = new osu.Bancho.Writer;
let matchIndex = 0;
for (let i = 0; i < this.matches.length; i++) {
if (this.matches[i].matchId == JoinInfo.matchId) {
matchIndex = i;
break;
}
}
const streamName = this.matches[matchIndex].matchStreamName;
const chatStreamName = this.matches[matchIndex].matchChatStreamName;
const match = this.matches[matchIndex];
let full = true;
// Loop through all slots to find an empty one
for (let i = 0; i < match.slots.length; i++) {
const slot = match.slots[i];
// Make sure the slot doesn't have a player in it / the slot is locked
if (slot.playerId !== -1 || slot.status === 2) continue;
// Slot is empty and not locked, we can join the match!
full = false;
slot.playerId = JoiningUser.id;
JoiningUser.matchSlotId = i;
slot.status = 4;
break;
}
const matchJSON = match.createOsuMatchJSON();
osuPacketWriter1.MatchUpdate(matchJSON);
osuPacketWriter.MatchJoinSuccess(matchJSON);
if (full) {
throw "MatchFullException";
}
// Set the user's current match to this match
JoiningUser.currentMatch = match;
// Add user to the stream for the match
global.StreamsHandler.addUserToStream(streamName, JoiningUser.uuid);
global.StreamsHandler.addUserToStream(chatStreamName, JoiningUser.uuid);
// Inform all users in the match that a new user has joined
global.StreamsHandler.sendToStream(streamName, osuPacketWriter1.toBuffer, null);
osuPacketWriter.ChannelJoinSuccess("#multiplayer");
// Inform joining client they they have joined the match
JoiningUser.addActionToQueue(osuPacketWriter.toBuffer);
// Update the match listing for all users in the lobby since
// A user has joined a match
this.updateMatchListing();
} catch (e) {
// Inform the client that there was an issue joining the match
const osuPacketWriter = new osu.Bancho.Writer;
osuPacketWriter.MatchJoinFail();
JoiningUser.addActionToQueue(osuPacketWriter.toBuffer);
this.updateMatchListing();
}
}
leaveMultiplayerMatch(MatchUser) {
// Make sure the user is in a match
if (MatchUser.currentMatch == null) return;
const mpLobby = MatchUser.currentMatch.leaveMatch(MatchUser);
let empty = true;
// Check if the match is empty
for (let i = 0; i < mpLobby.slots.length; i++) {
const slot = mpLobby.slots[i];
// Check if the slot is avaliable
if (slot.playerId === -1) continue;
// There is a user in the match
empty = false;
break;
}
// The match is empty, proceed to remove it.
if (empty) {
let matchIndex;
// Loop through all matches
for (let i = 0; i < this.matches.length; i++) {
// If the match matches the match the user has left
if (this.matches[i].matchStreamName == MatchUser.currentMatch.matchStreamName) {
matchIndex = i;
break;
}
}
// Make sure we got a match index
if (matchIndex == null) return;
// Remove this match from the list of active matches
this.matches.splice(matchIndex, 1);
}
MatchUser.currentMatch = null;
// 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) {
for (let match in this.matches) {
if (match.matchId == MatchID) return match;
}
return null;
}
}