Binato/server/Multiplayer.js
2020-09-02 10:15:41 +01:00

557 lines
No EOL
20 KiB
JavaScript

const osu = require("osu-packet"),
getUserById = require("./util/getUserById.js"),
DatabaseHelper = require("./DatabaseHelper.js"),
StatusUpdate = require("./Packets/StatusUpdate.js");
module.exports = {
userEnterLobby:function(currentUser) {
if (currentUser.currentMatch != null) {
this.leaveMatch(currentUser);
currentUser.currentMatch = null;
}
global.StreamsHandler.addUserToStream("multiplayer_lobby", currentUser.id);
const osuPacketWriter1 = new osu.Bancho.Writer;
let userIds = [];
for (let i = 0; i < global.users.length; i++) {
userIds.push(global.users[i].id);
}
osuPacketWriter1.UserPresenceBundle(userIds);
global.StreamsHandler.sendToStream("multiplayer_lobby", osuPacketWriter1.toBuffer, null);
for (let i = 0; i < global.matches.length; i++) {
for (let i1 = 0; i1 < global.matches[i][1].slots.length; i1++) {
const slot = global.matches[i][1].slots[i1];
if (slot.playerId == -1 || slot.status == 2) continue;
const osuPacketWriter = new osu.Bancho.Writer;
const User = getUserById(slot.playerId);
// Get user score info from the database
const userScoreDB = DatabaseHelper.getFromDB(`SELECT * FROM users_modes_info WHERE user_id = ${User.id} AND mode_id = ${User.playMode} LIMIT 1`);
let UserStatusObject = {
userId: User.id,
status: User.actionID,
statusText: User.actionText,
beatmapChecksum: User.beatmapChecksum,
currentMods: User.currentMods,
playMode: User.playMode,
beatmapId: User.beatmapID,
rankedScore: userScoreDB.ranked_score,
accuracy: userScoreDB.avg_accuracy / 100, // Scale of 0 to 1
playCount: userScoreDB.playcount,
totalScore: userScoreDB.total_score,
rank: 1,
performance: userScoreDB.pp_raw
};
osuPacketWriter.HandleOsuUpdate(UserStatusObject);
global.StreamsHandler.sendToStream("multiplayer_lobby", osuPacketWriter.toBuffer, null);
}
const osuPacketWriter = new osu.Bancho.Writer;
osuPacketWriter.MatchNew(global.matches[i][1]);
currentUser.addActionToQueue(osuPacketWriter.toBuffer);
}
const osuPacketWriter = new osu.Bancho.Writer;
osuPacketWriter.ChannelJoinSuccess("#lobby");
if (!global.StreamsHandler.isUserInStream("#lobby", currentUser.id))
global.StreamsHandler.addUserToStream("#lobby", currentUser.id);
currentUser.addActionToQueue(osuPacketWriter.toBuffer);
},
updateMatchListing:function() {
const osuPacketWriter1 = new osu.Bancho.Writer;
let userIds = [];
for (let i = 0; i < global.users.length; i++) {
userIds.push(global.users[i].id);
}
osuPacketWriter1.UserPresenceBundle(userIds);
global.StreamsHandler.sendToStream("multiplayer_lobby", osuPacketWriter1.toBuffer, null);
for (let i = 0; i < global.matches.length; i++) {
for (let i1 = 0; i1 < global.matches[i][1].slots.length; i1++) {
const slot = global.matches[i][1].slots[i1];
if (slot.playerId == -1 || slot.status == 2) continue;
const osuPacketWriter = new osu.Bancho.Writer;
const User = getUserById(slot.playerId);
// Get user score info from the database
const userScoreDB = DatabaseHelper.getFromDB(`SELECT * FROM users_modes_info WHERE user_id = ${User.id} AND mode_id = ${User.playMode} LIMIT 1`);
let UserStatusObject = {
userId: User.id,
status: User.actionID,
statusText: User.actionText,
beatmapChecksum: User.beatmapChecksum,
currentMods: User.currentMods,
playMode: User.playMode,
beatmapId: User.beatmapID,
rankedScore: userScoreDB.ranked_score,
accuracy: userScoreDB.avg_accuracy / 100, // Scale of 0 to 1
playCount: userScoreDB.playcount,
totalScore: userScoreDB.total_score,
rank: 1,
performance: userScoreDB.pp_raw
};
osuPacketWriter.HandleOsuUpdate(UserStatusObject);
global.StreamsHandler.sendToStream("multiplayer_lobby", osuPacketWriter.toBuffer, null);
}
const osuPacketWriter = new osu.Bancho.Writer;
osuPacketWriter.MatchNew(global.matches[i][1]);
global.StreamsHandler.sendToStream("multiplayer_lobby", osuPacketWriter.toBuffer, null);
}
},
createMultiplayerMatch:function(currentUser, data) {
const osuPacketWriter = new osu.Bancho.Writer;
if (data.gamePassword == '') data.gamePassword == null;
let NewMatchObject = {
matchId: global.matches.length,
inProgress: false,
matchType: 0,
activeMods: 0,
gameName: data.gameName,
gamePassword: data.gamePassword,
beatmapName: data.beatmapName,
beatmapId: data.beatmapId,
beatmapChecksum: data.beatmapChecksum,
slots: data.slots,
host: currentUser.id,
playMode: 0,
matchScoringType: 0,
matchTeamType: 0,
specialModes: 0,
hidden: false,
seed: data.seed
}
for (let i = 0; i < NewMatchObject.slots.length; i++) {
let s = NewMatchObject.slots[i];
s.mods = 0;
}
StatusUpdate(currentUser, currentUser.id);
osuPacketWriter.MatchNew(NewMatchObject);
// Queue match creation for user
currentUser.addActionToQueue(osuPacketWriter.toBuffer);
global.StreamsHandler.addStream(`mp_${data.gameName.split(" ").join("-")}`, true, NewMatchObject.matchId);
global.matches.push([`mp_${data.gameName.split(" ").join("-")}`, NewMatchObject]);
this.updateMatchListing();
this.joinMultiplayerMatch(currentUser, {
matchId: NewMatchObject.matchId,
gamePassword: NewMatchObject.gamePassword
});
},
joinMultiplayerMatch:function(currentUser, data) {
try {
let osuPacketWriter = new osu.Bancho.Writer;
const osuPacketWriter1 = new osu.Bancho.Writer;
const streamName = global.matches[data.matchId][0];
const mpLobby = global.matches[data.matchId][1];
let full = true;
for (let i = 0; i < mpLobby.slots.length; i++) {
const slot = mpLobby.slots[i];
if (slot.playerId !== -1 || slot.status === 2) continue;
full = false;
slot.playerId = currentUser.id;
currentUser.matchSlotId = i;
slot.status = 4;
break;
}
osuPacketWriter1.MatchUpdate(mpLobby);
osuPacketWriter.MatchJoinSuccess(mpLobby);
if (full) {
osuPacketWriter = new osu.Bancho.Writer;
osuPacketWriter.MatchJoinFail();
} else {
global.StreamsHandler.removeUserFromStream("multiplayer_lobby", currentUser.id);
}
currentUser.currentMatch = data.matchId;
global.StreamsHandler.addUserToStream(streamName, currentUser.id);
global.StreamsHandler.sendToStream(streamName, osuPacketWriter1.toBuffer, null);
osuPacketWriter.ChannelJoinSuccess("#multiplayer");
currentUser.addActionToQueue(osuPacketWriter.toBuffer);
this.updateMatchListing();
} catch (e) {
const osuPacketWriter = new osu.Bancho.Writer;
osuPacketWriter.MatchJoinFail();
currentUser.addActionToQueue(osuPacketWriter.toBuffer);
this.updateMatchListing();
}
},
setReadyState:function(currentUser, state) {
const mpLobby = global.matches[currentUser.currentMatch][1];
const osuPacketWriter = new osu.Bancho.Writer;
for (let i = 0; i < mpLobby.slots.length; i++) {
const slot = mpLobby.slots[i];
if (slot.playerId == currentUser.id) {
if (state) slot.status = 8;
else slot.status = 4;
console.log("e");
break;
}
}
osuPacketWriter.MatchUpdate(mpLobby);
global.StreamsHandler.sendToStream(global.matches[currentUser.currentMatch][0], osuPacketWriter.toBuffer, null);
},
sendMatchUpdate:function(currentUser) {
const mpLobby = global.matches[currentUser.currentMatch][1];
const osuPacketWriter = new osu.Bancho.Writer;
osuPacketWriter.MatchUpdate(mpLobby);
global.StreamsHandler.sendToStream(global.matches[currentUser.currentMatch][0], osuPacketWriter.toBuffer, null);
},
updateMatch:function(currentUser, data) {
global.matches[currentUser.currentMatch][1] = data;
const osuPacketWriter = new osu.Bancho.Writer;
osuPacketWriter.MatchUpdate(global.matches[currentUser.currentMatch][1]);
global.StreamsHandler.sendToStream(global.matches[currentUser.currentMatch][0], osuPacketWriter.toBuffer, null);
this.updateMatchListing();
},
moveToSlot:function(currentUser, data) {
const mpLobby = global.matches[currentUser.currentMatch][1];
const osuPacketWriter = new osu.Bancho.Writer;
let currentUserData, slotIndex;
for (let i = 0; i < mpLobby.slots.length; i++) {
const slot = mpLobby.slots[i];
if (slot.playerId != currentUser.id) continue;
currentUserData = slot;
slotIndex = i;
break;
}
mpLobby.slots[data].playerId = currentUserData.playerId;
currentUser.matchSlotId = data;
mpLobby.slots[data].status = currentUserData.status;
mpLobby.slots[slotIndex].playerId = -1;
mpLobby.slots[slotIndex].status = 1;
osuPacketWriter.MatchUpdate(mpLobby);
global.StreamsHandler.sendToStream(global.matches[currentUser.currentMatch][0], osuPacketWriter.toBuffer, null);
this.updateMatchListing();
},
kickPlayer:function(currentUser, data) {
const mpLobby = global.matches[currentUser.currentMatch][1];
const osuPacketWriter = new osu.Bancho.Writer;
if (mpLobby.host != currentUser.id) return;
const slot = mpLobby.slots[data];
let cachedPlayerId = slot.playerId;
if (slot.playerId === -1) { // Slot is empty, lock it
if (slot.status === 1) slot.status = 2;
else slot.status = 1;
} else { // Slot isn't empty kick player
const kickedPlayer = getUserById(slot.playerId);
kickedPlayer.matchSlotId = -1;
slot.playerId = -1;
slot.status = 1;
}
osuPacketWriter.MatchUpdate(mpLobby);
global.StreamsHandler.sendToStream(global.matches[currentUser.currentMatch][0], osuPacketWriter.toBuffer, null);
this.updateMatchListing();
if (cachedPlayerId !== null || cachedPlayerId !== -1) {
global.StreamsHandler.removeUserFromStream(global.matches[currentUser.currentMatch][0], cachedPlayerId);
}
},
missingBeatmap:function(currentUser, state) {
const mpLobby = global.matches[currentUser.currentMatch][1];
const osuPacketWriter = new osu.Bancho.Writer;
for (let i = 0; i < mpLobby.slots.length; i++) {
const slot = mpLobby.slots[i];
if (slot.playerId != currentUser.id) continue;
if (state) {
slot.status = 16;
} else {
slot.status = 4;
}
break;
}
osuPacketWriter.MatchUpdate(mpLobby);
global.StreamsHandler.sendToStream(global.matches[currentUser.currentMatch][0], osuPacketWriter.toBuffer, null);
},
transferHost:function(currentUser, data) {
const mpLobby = global.matches[currentUser.currentMatch][1];
const osuPacketWriter = new osu.Bancho.Writer;
const newUser = getUserById(mpLobby.slots[data].playerId);
mpLobby.host = newUser.id;
osuPacketWriter.MatchUpdate(mpLobby);
global.StreamsHandler.sendToStream(global.matches[currentUser.currentMatch][0], osuPacketWriter.toBuffer, null);
},
updateMods(currentUser, data) { // TODO: Allow freemod to work
if (global.matches[currentUser.currentMatch][1].host !== currentUser.id) return;
const osuPacketWriter = new osu.Bancho.Writer;
global.matches[currentUser.currentMatch][1].activeMods = data;
osuPacketWriter.MatchUpdate(global.matches[currentUser.currentMatch][1]);
global.StreamsHandler.sendToStream(global.matches[currentUser.currentMatch][0], osuPacketWriter.toBuffer, null);
this.updateMatchListing();
},
startMatch(currentUser) {
const mpLobby = global.matches[currentUser.currentMatch][1];
if (mpLobby.inProgress) return;
mpLobby.inProgress = true;
global.matches[currentUser.currentMatch][2] = [];
const loadedSlots = global.matches[currentUser.currentMatch][2];
for (let i = 0; i < mpLobby.slots.length; i++) {
const slot = mpLobby.slots[i];
if (slot.playerId === -1 || slot.status === 1 || slot.status === 2) continue;
loadedSlots.push({playerId: slot.playerId, loaded: false});
}
const osuPacketWriter = new osu.Bancho.Writer;
for (let i = 0; i < mpLobby.slots.length; i++) {
const slot = mpLobby.slots[i];
if (slot.playerId === -1 || slot.status === 1 || slot.status === 2) continue;
slot.status = 32;
}
osuPacketWriter.MatchStart(mpLobby);
global.StreamsHandler.sendToStream(global.matches[currentUser.currentMatch][0], osuPacketWriter.toBuffer, null);
this.sendMatchUpdate(currentUser);
this.updateMatchListing();
},
setPlayerLoaded:function(currentUser) {
const loadedSlots = global.matches[currentUser.currentMatch][2];
for (let i = 0; i < loadedSlots.length; i++) {
if (loadedSlots[i].playerId == currentUser.id) {
loadedSlots[i].loaded = true;
}
}
let allLoaded = true;
for (let i = 0; i < loadedSlots.length; i++) {
if (loadedSlots[i].loaded) continue;
allLoaded = false;
}
if (allLoaded) {
let osuPacketWriter = new osu.Bancho.Writer;
osuPacketWriter.MatchAllPlayersLoaded();
global.StreamsHandler.sendToStream(global.matches[currentUser.currentMatch][0], osuPacketWriter.toBuffer, null);
global.matches[currentUser.currentMatch][2] = null;
}
},
onPlayerFinishMatch:function(currentUser) {
const mpLobby = global.matches[currentUser.currentMatch][1];
if (global.matches[currentUser.currentMatch][2] == null) {
global.matches[currentUser.currentMatch][2] = [];
const loadedSlots = global.matches[currentUser.currentMatch][2];
for (let i = 0; i < mpLobby.slots.length; i++) {
const slot = mpLobby.slots[i];
if (slot.playerId === -1 || slot.status === 1 || slot.status === 2) continue;
loadedSlots.push({playerId: slot.playerId, loaded: false});
}
}
const loadedSlots = global.matches[currentUser.currentMatch][2];
for (let i = 0; i < loadedSlots.length; i++) {
if (loadedSlots[i].playerId == currentUser.id) {
loadedSlots[i].loaded = true;
}
}
let allLoaded = true;
for (let i = 0; i < loadedSlots.length; i++) {
if (loadedSlots[i].loaded) continue;
allLoaded = false;
}
if (allLoaded) this.finishMatch(currentUser);
},
finishMatch:function(currentUser) {
const mpLobby = global.matches[currentUser.currentMatch][1];
if (!mpLobby.inProgress) return;
global.matches[currentUser.currentMatch][2] = [];
mpLobby.inProgress = false;
let osuPacketWriter = new osu.Bancho.Writer;
for (let i = 0; i < mpLobby.slots.length; i++) {
const slot = mpLobby.slots[i];
if (slot.playerId === -1 || slot.status === 1 || slot.status === 2) continue;
slot.status = 4;
}
osuPacketWriter.MatchComplete();
global.StreamsHandler.sendToStream(global.matches[currentUser.currentMatch][0], osuPacketWriter.toBuffer, null);
this.sendMatchUpdate(currentUser);
this.updateMatchListing();
},
updatePlayerScore:function(currentUser, data) {
const osuPacketWriter = new osu.Bancho.Writer;
if (currentUser.matchSlotId == -1) return console.log("it did the big fuck");
data.id = currentUser.matchSlotId;
osuPacketWriter.MatchScoreUpdate(data);
global.StreamsHandler.sendToStream(global.matches[currentUser.currentMatch][0], osuPacketWriter.toBuffer, null);
},
leaveMatch:function(currentUser) {
try {
const mpLobby = global.matches[currentUser.currentMatch][1];
let containsUser = false;
for (let i = 0; i < mpLobby.slots.length; i++) {
const slot = mpLobby.slots[i];
if (slot.playerId == currentUser.id) {
containsUser = true;
break;
}
}
// Make sure we don't run more than once
if (!containsUser) return;
let osuPacketWriter = new osu.Bancho.Writer;
for (let i = 0; i < mpLobby.slots.length; i++) {
const slot = mpLobby.slots[i];
if (slot.playerId != currentUser.id) continue;
slot.playerId = -1;
slot.status = 1;
break;
}
osuPacketWriter.MatchUpdate(mpLobby);
global.StreamsHandler.removeUserFromStream(global.matches[currentUser.currentMatch][0], currentUser.id);
global.StreamsHandler.sendToStream(global.matches[currentUser.currentMatch][0], osuPacketWriter.toBuffer, null);
osuPacketWriter = new osu.Bancho.Writer;
osuPacketWriter.ChannelRevoked("#multiplayer");
currentUser.addActionToQueue(osuPacketWriter.toBuffer);
let empty = true;
for (let i = 0; i < mpLobby.slots.length; i++) {
const slot = mpLobby.slots[i];
if (slot.playerId === -1) continue;
empty = false;
break;
}
if (empty) {
let matchIndex;
for (let i = 0; i < global.matches.length; i++) {
if (global.matches[i][0] == global.matches[currentUser.currentMatch][0]) {
matchIndex = i;
break;
}
}
// Make sure we got a match index
if (matchIndex == null) return;
// Remove this match from the list of active matches
global.matches.splice(matchIndex, 1);
}
} catch (e) { }
this.updateMatchListing();
// Delay a 2nd match listing update
setTimeout(() => {
this.updateMatchListing();
}, 1000);
}
}