Multiplayer fixes
This commit is contained in:
parent
aff53f1ab9
commit
469cbb9bc9
1 changed files with 57 additions and 48 deletions
|
@ -46,7 +46,7 @@ export default class Match {
|
||||||
public countdownTime:number = 0;
|
public countdownTime:number = 0;
|
||||||
public countdownTimer?:NodeJS.Timeout;
|
public countdownTimer?:NodeJS.Timeout;
|
||||||
|
|
||||||
private cachedMatchJSON:MatchData;
|
private serialisedMatchJSON:MatchData;
|
||||||
private readonly shared:Shared;
|
private readonly shared:Shared;
|
||||||
|
|
||||||
private constructor(matchData:MatchData, shared:Shared) {
|
private constructor(matchData:MatchData, shared:Shared) {
|
||||||
|
@ -95,7 +95,7 @@ export default class Match {
|
||||||
this.matchStream = shared.streams.CreateStream(`multiplayer:match_${this.matchId}`, false);
|
this.matchStream = shared.streams.CreateStream(`multiplayer:match_${this.matchId}`, false);
|
||||||
this.matchChatChannel = shared.chatManager.AddSpecialChatChannel("multiplayer", `mp_${this.matchId}`);
|
this.matchChatChannel = shared.chatManager.AddSpecialChatChannel("multiplayer", `mp_${this.matchId}`);
|
||||||
|
|
||||||
this.cachedMatchJSON = matchData;
|
this.serialisedMatchJSON = matchData;
|
||||||
|
|
||||||
//this.multiplayerExtras = null;
|
//this.multiplayerExtras = null;
|
||||||
|
|
||||||
|
@ -118,7 +118,7 @@ export default class Match {
|
||||||
|
|
||||||
const osuPacketWriter = osu.Bancho.Writer();
|
const osuPacketWriter = osu.Bancho.Writer();
|
||||||
|
|
||||||
osuPacketWriter.MatchNew(matchInstance.generateMatchJSON());
|
osuPacketWriter.MatchNew(matchInstance.serialiseMatch());
|
||||||
|
|
||||||
matchHost.addActionToQueue(osuPacketWriter.toBuffer);
|
matchHost.addActionToQueue(osuPacketWriter.toBuffer);
|
||||||
|
|
||||||
|
@ -132,10 +132,27 @@ export default class Match {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Convert class data back to a format that osu-packet can understand
|
// Convert class data back to a format that osu-packet can understand
|
||||||
public generateMatchJSON() : MatchData {
|
public serialiseMatch() : MatchData {
|
||||||
|
const matchDataRef = this.serialisedMatchJSON;
|
||||||
|
matchDataRef.matchId = this.matchId;
|
||||||
|
matchDataRef.matchType = this.matchType;
|
||||||
|
matchDataRef.activeMods = this.activeMods;
|
||||||
|
matchDataRef.gameName = this.gameName;
|
||||||
|
matchDataRef.gamePassword = this.gamePassword ?? "";
|
||||||
|
matchDataRef.inProgress = this.inProgress;
|
||||||
|
matchDataRef.beatmapName = this.beatmapName;
|
||||||
|
matchDataRef.beatmapId = this.beatmapId;
|
||||||
|
matchDataRef.beatmapChecksum = this.beatmapChecksum;
|
||||||
|
matchDataRef.host = this.host.id;
|
||||||
|
matchDataRef.playMode = this.playMode;
|
||||||
|
matchDataRef.matchScoringType = this.matchScoringType;
|
||||||
|
matchDataRef.matchTeamType = this.matchTeamType;
|
||||||
|
matchDataRef.specialModes = this.specialModes;
|
||||||
|
matchDataRef.seed = this.seed;
|
||||||
|
|
||||||
for (let i = 0; i < this.slots.length; i++) {
|
for (let i = 0; i < this.slots.length; i++) {
|
||||||
const slot = this.slots[i];
|
const slot = this.slots[i];
|
||||||
const osuSlot = this.cachedMatchJSON.slots[i];
|
const osuSlot = this.serialisedMatchJSON.slots[i];
|
||||||
|
|
||||||
osuSlot.status = slot.status;
|
osuSlot.status = slot.status;
|
||||||
osuSlot.team = slot.team;
|
osuSlot.team = slot.team;
|
||||||
|
@ -147,7 +164,7 @@ export default class Match {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return this.cachedMatchJSON;
|
return this.serialisedMatchJSON;
|
||||||
}
|
}
|
||||||
|
|
||||||
public leaveMatch(user:User) {
|
public leaveMatch(user:User) {
|
||||||
|
@ -184,12 +201,12 @@ export default class Match {
|
||||||
if (matchData.gamePassword === "") {
|
if (matchData.gamePassword === "") {
|
||||||
this.gamePassword = undefined;
|
this.gamePassword = undefined;
|
||||||
} else {
|
} else {
|
||||||
this.gamePassword = this.cachedMatchJSON.gamePassword = matchData.gamePassword;
|
this.gamePassword = matchData.gamePassword;
|
||||||
}
|
}
|
||||||
|
|
||||||
this.beatmapName = this.cachedMatchJSON.beatmapName = matchData.beatmapName;
|
this.beatmapName = matchData.beatmapName;
|
||||||
this.beatmapId = this.cachedMatchJSON.beatmapId = matchData.beatmapId;
|
this.beatmapId = matchData.beatmapId;
|
||||||
this.beatmapChecksum = this.cachedMatchJSON.beatmapChecksum = matchData.beatmapChecksum;
|
this.beatmapChecksum = matchData.beatmapChecksum;
|
||||||
|
|
||||||
if (matchData.host !== this.host.id) {
|
if (matchData.host !== this.host.id) {
|
||||||
const hostUser = this.shared.users.getById(matchData.host);
|
const hostUser = this.shared.users.getById(matchData.host);
|
||||||
|
@ -198,17 +215,16 @@ export default class Match {
|
||||||
throw "Host User of match was undefined";
|
throw "Host User of match was undefined";
|
||||||
}
|
}
|
||||||
this.host = hostUser;
|
this.host = hostUser;
|
||||||
this.cachedMatchJSON.host = this.host.id;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
this.playMode = this.cachedMatchJSON.playMode = matchData.playMode;
|
this.playMode = matchData.playMode;
|
||||||
|
|
||||||
this.matchScoringType = this.cachedMatchJSON.matchScoringType = matchData.matchScoringType;
|
this.matchScoringType = matchData.matchScoringType;
|
||||||
this.matchTeamType = this.cachedMatchJSON.matchTeamType = matchData.matchTeamType;
|
this.matchTeamType = matchData.matchTeamType;
|
||||||
this.specialModes = this.cachedMatchJSON.specialModes = matchData.specialModes;
|
this.specialModes = matchData.specialModes;
|
||||||
|
|
||||||
const gameSeedChanged = this.seed !== matchData.seed;
|
const gameSeedChanged = this.seed !== matchData.seed;
|
||||||
this.seed = this.cachedMatchJSON.seed = matchData.seed;
|
this.seed = matchData.seed;
|
||||||
|
|
||||||
if (gameNameChanged || gameSeedChanged) {
|
if (gameNameChanged || gameSeedChanged) {
|
||||||
const queryData = [];
|
const queryData = [];
|
||||||
|
@ -220,7 +236,10 @@ export default class Match {
|
||||||
}
|
}
|
||||||
queryData.push(this.matchId);
|
queryData.push(this.matchId);
|
||||||
|
|
||||||
await this.shared.database.query(`UPDATE mp_matches SET ${gameNameChanged ? `name = ?${gameSeedChanged ? ", " : ""}` : ""}${gameSeedChanged ? `seed = ?` : ""} WHERE id = ?`, queryData);
|
await this.shared.database.query(
|
||||||
|
`UPDATE mp_matches SET ${gameNameChanged ? `name = ?${gameSeedChanged ? ", " : ""}` : ""}${gameSeedChanged ? `seed = ?` : ""} WHERE id = ?`,
|
||||||
|
queryData
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
this.sendMatchUpdate();
|
this.sendMatchUpdate();
|
||||||
|
@ -232,7 +251,7 @@ export default class Match {
|
||||||
public sendMatchUpdate() {
|
public sendMatchUpdate() {
|
||||||
const osuPacketWriter = osu.Bancho.Writer();
|
const osuPacketWriter = osu.Bancho.Writer();
|
||||||
|
|
||||||
osuPacketWriter.MatchUpdate(this.generateMatchJSON());
|
osuPacketWriter.MatchUpdate(this.serialiseMatch());
|
||||||
|
|
||||||
// Update all users in the match with new match information
|
// Update all users in the match with new match information
|
||||||
this.matchStream.Send(osuPacketWriter.toBuffer);
|
this.matchStream.Send(osuPacketWriter.toBuffer);
|
||||||
|
@ -291,17 +310,12 @@ export default class Match {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Make sure the user attempting to kick / lock is the host of the match
|
// Make sure the user attempting to kick / lock is the host of the match
|
||||||
if (User.Equals(user, this.host)) {
|
if (!User.Equals(user, this.host)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const slot = this.slots[slotToActionOn];
|
const slot = this.slots[slotToActionOn];
|
||||||
if (slot.player instanceof Slot) {
|
if (slot.player instanceof User) { // Kick
|
||||||
// Kick
|
|
||||||
if (User.Equals(user, slot.player)) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const kickedPlayer = slot.player;
|
const kickedPlayer = slot.player;
|
||||||
|
|
||||||
// Remove player's refs to the match & slot
|
// Remove player's refs to the match & slot
|
||||||
|
@ -311,15 +325,11 @@ export default class Match {
|
||||||
// Nuke all slot properties
|
// Nuke all slot properties
|
||||||
slot.reset();
|
slot.reset();
|
||||||
|
|
||||||
// Send update before removing the user from the stream so they know
|
// Kick player
|
||||||
// they got kicked
|
this.shared.multiplayerManager.LeaveMatch(kickedPlayer);
|
||||||
this.sendMatchUpdate();
|
|
||||||
|
|
||||||
// Remove player from stream and chat
|
this.sendMatchUpdate();
|
||||||
this.matchStream.RemoveUser(kickedPlayer);
|
} else { // Lock / Unlock
|
||||||
this.matchChatChannel.Leave(kickedPlayer);
|
|
||||||
} else {
|
|
||||||
// Lock / Unlock
|
|
||||||
slot.status = slot.status === SlotStatus.Empty ? SlotStatus.Locked : SlotStatus.Empty;
|
slot.status = slot.status === SlotStatus.Empty ? SlotStatus.Locked : SlotStatus.Empty;
|
||||||
|
|
||||||
this.sendMatchUpdate();
|
this.sendMatchUpdate();
|
||||||
|
@ -354,7 +364,7 @@ export default class Match {
|
||||||
if (this.matchSkippedSlots === undefined) {
|
if (this.matchSkippedSlots === undefined) {
|
||||||
this.matchSkippedSlots = new Array<MatchStartSkipData>();
|
this.matchSkippedSlots = new Array<MatchStartSkipData>();
|
||||||
|
|
||||||
for (let slot of this.slots) {
|
for (const slot of this.slots) {
|
||||||
// Make sure the slot has a user in it
|
// Make sure the slot has a user in it
|
||||||
if (slot.player === undefined || slot.status === SlotStatus.Empty || slot.status === SlotStatus.Locked) {
|
if (slot.player === undefined || slot.status === SlotStatus.Empty || slot.status === SlotStatus.Locked) {
|
||||||
continue;
|
continue;
|
||||||
|
@ -369,7 +379,7 @@ export default class Match {
|
||||||
}
|
}
|
||||||
|
|
||||||
let allSkipped = true;
|
let allSkipped = true;
|
||||||
for (let skippedSlot of this.matchSkippedSlots) {
|
for (const skippedSlot of this.matchSkippedSlots) {
|
||||||
// If loadslot belongs to this user then set loaded to true
|
// If loadslot belongs to this user then set loaded to true
|
||||||
if (skippedSlot.playerId === user.id) {
|
if (skippedSlot.playerId === user.id) {
|
||||||
skippedSlot.flag = true;
|
skippedSlot.flag = true;
|
||||||
|
@ -403,9 +413,8 @@ export default class Match {
|
||||||
public transferHost(user:User, slotIDToTransferTo:number) {
|
public transferHost(user:User, slotIDToTransferTo:number) {
|
||||||
// Set the lobby's host to the new user
|
// Set the lobby's host to the new user
|
||||||
const newHost = this.slots[slotIDToTransferTo].player;
|
const newHost = this.slots[slotIDToTransferTo].player;
|
||||||
if (newHost instanceof Slot) {
|
if (newHost instanceof User) {
|
||||||
this.host = newHost;
|
this.host = newHost;
|
||||||
this.cachedMatchJSON.host = this.host.id;
|
|
||||||
|
|
||||||
this.sendMatchUpdate();
|
this.sendMatchUpdate();
|
||||||
}
|
}
|
||||||
|
@ -446,7 +455,7 @@ export default class Match {
|
||||||
|
|
||||||
this.matchLoadSlots = new Array<MatchStartSkipData>();
|
this.matchLoadSlots = new Array<MatchStartSkipData>();
|
||||||
// Loop through all slots in the match
|
// Loop through all slots in the match
|
||||||
for (let slot of this.slots) {
|
for (const slot of this.slots) {
|
||||||
// Make sure the slot has a user in it
|
// Make sure the slot has a user in it
|
||||||
if (slot.player === undefined || slot.status === SlotStatus.Empty || slot.status === SlotStatus.Locked) {
|
if (slot.player === undefined || slot.status === SlotStatus.Empty || slot.status === SlotStatus.Locked) {
|
||||||
continue;
|
continue;
|
||||||
|
@ -464,7 +473,7 @@ export default class Match {
|
||||||
|
|
||||||
const osuPacketWriter = osu.Bancho.Writer();
|
const osuPacketWriter = osu.Bancho.Writer();
|
||||||
|
|
||||||
osuPacketWriter.MatchStart(this.generateMatchJSON());
|
osuPacketWriter.MatchStart(this.serialiseMatch());
|
||||||
|
|
||||||
// Inform all users in the match that it has started
|
// Inform all users in the match that it has started
|
||||||
this.matchStream.Send(osuPacketWriter.toBuffer);
|
this.matchStream.Send(osuPacketWriter.toBuffer);
|
||||||
|
@ -482,7 +491,7 @@ export default class Match {
|
||||||
}
|
}
|
||||||
|
|
||||||
let allLoaded = true;
|
let allLoaded = true;
|
||||||
for (let loadedSlot of this.matchLoadSlots) {
|
for (const loadedSlot of this.matchLoadSlots) {
|
||||||
if (loadedSlot.playerId === user.id) {
|
if (loadedSlot.playerId === user.id) {
|
||||||
loadedSlot.flag = true;
|
loadedSlot.flag = true;
|
||||||
}
|
}
|
||||||
|
@ -502,7 +511,7 @@ export default class Match {
|
||||||
this.matchLoadSlots = undefined;
|
this.matchLoadSlots = undefined;
|
||||||
|
|
||||||
this.playerScores = new Array<PlayerScore>();
|
this.playerScores = new Array<PlayerScore>();
|
||||||
for (let slot of this.slots) {
|
for (const slot of this.slots) {
|
||||||
if (slot.player === undefined || slot.status === SlotStatus.Empty || slot.status === SlotStatus.Locked) {
|
if (slot.player === undefined || slot.status === SlotStatus.Empty || slot.status === SlotStatus.Locked) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
@ -523,7 +532,7 @@ export default class Match {
|
||||||
if (this.matchLoadSlots === undefined) {
|
if (this.matchLoadSlots === undefined) {
|
||||||
// Repopulate user loading slots again
|
// Repopulate user loading slots again
|
||||||
this.matchLoadSlots = [];
|
this.matchLoadSlots = [];
|
||||||
for (let slot of this.slots) {
|
for (const slot of this.slots) {
|
||||||
// Make sure the slot has a user
|
// Make sure the slot has a user
|
||||||
if (slot.player === undefined || slot.status === SlotStatus.Empty || slot.status === SlotStatus.Locked) {
|
if (slot.player === undefined || slot.status === SlotStatus.Empty || slot.status === SlotStatus.Locked) {
|
||||||
continue;
|
continue;
|
||||||
|
@ -538,7 +547,7 @@ export default class Match {
|
||||||
}
|
}
|
||||||
|
|
||||||
let allLoaded = true;
|
let allLoaded = true;
|
||||||
for (let loadedSlot of this.matchLoadSlots) {
|
for (const loadedSlot of this.matchLoadSlots) {
|
||||||
if (loadedSlot.playerId == user.id) {
|
if (loadedSlot.playerId == user.id) {
|
||||||
loadedSlot.flag = true;
|
loadedSlot.flag = true;
|
||||||
}
|
}
|
||||||
|
@ -581,14 +590,14 @@ export default class Match {
|
||||||
throw "playerScores was null in a place it really shouldn't have been!";
|
throw "playerScores was null in a place it really shouldn't have been!";
|
||||||
}
|
}
|
||||||
|
|
||||||
for (let slot of this.slots) {
|
for (const slot of this.slots) {
|
||||||
// For every empty / locked slot push a null to the data array
|
// For every empty / locked slot push a null to the data array
|
||||||
if (slot.player === undefined || slot.status === SlotStatus.Empty || slot.status === SlotStatus.Locked) {
|
if (slot.player === undefined || slot.status === SlotStatus.Empty || slot.status === SlotStatus.Locked) {
|
||||||
queryData.push(null);
|
queryData.push(null);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (let _playerScore of this.playerScores) {
|
for (const _playerScore of this.playerScores) {
|
||||||
if (_playerScore.player?.id === slot.player?.id && _playerScore._raw !== undefined) {
|
if (_playerScore.player?.id === slot.player?.id && _playerScore._raw !== undefined) {
|
||||||
const score = _playerScore._raw;
|
const score = _playerScore._raw;
|
||||||
queryData.push(`${slot.player?.id}|${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}` : ""}`);
|
queryData.push(`${slot.player?.id}|${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}` : ""}`);
|
||||||
|
@ -623,11 +632,11 @@ export default class Match {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
matchScoreData.id = user.matchSlot.player.id;
|
matchScoreData.id = user.id;
|
||||||
|
|
||||||
// Update playerScores
|
// Update playerScores
|
||||||
for (let playerScore of this.playerScores) {
|
for (const playerScore of this.playerScores) {
|
||||||
if (playerScore.player?.id == user.id) {
|
if (playerScore.player?.id === user.id) {
|
||||||
playerScore.score = matchScoreData.totalScore;
|
playerScore.score = matchScoreData.totalScore;
|
||||||
const isCurrentlyFailed = matchScoreData.currentHp == 254;
|
const isCurrentlyFailed = matchScoreData.currentHp == 254;
|
||||||
playerScore.isCurrentlyFailed = isCurrentlyFailed;
|
playerScore.isCurrentlyFailed = isCurrentlyFailed;
|
||||||
|
|
Loading…
Reference in a new issue