2021-01-26 12:24:13 +00:00
const osu = require ( "osu-packet" ) ,
2022-01-04 03:39:53 +00:00
getUserById = require ( "./util/getUserById.js" ) ,
2022-07-02 11:37:08 +01:00
StatusUpdate = require ( "./Packets/StatusUpdate.js" ) ,
2022-08-26 12:52:00 +01:00
Streams = require ( "./Streams.js" ) ,
2022-07-02 11:37:08 +01:00
User = require ( "./User.js" ) ;
2021-01-26 12:24:13 +00:00
// TODO: Cache the player's slot position in their user class for a small optimisation
2022-08-26 12:52:00 +01:00
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 ;
2022-01-04 03:39:53 +00:00
this . inProgress = MatchData . inProgress ;
this . matchStartCountdownActive = false ;
this . matchType = MatchData . matchType ;
this . activeMods = MatchData . activeMods ;
this . gameName = MatchData . gameName ;
if ( MatchData . gamePassword == '' ) MatchData . gamePassword == null ;
this . gamePassword = MatchData . gamePassword ;
this . beatmapName = MatchData . beatmapName ;
this . beatmapId = MatchData . beatmapId ;
this . beatmapChecksum = MatchData . beatmapChecksum ;
this . slots = MatchData . slots ;
for ( let i = 0 ; i < this . slots . length ; i ++ ) {
this . slots [ i ] . mods = 0 ;
}
this . host = MatchData . host ;
this . playMode = MatchData . playMode ;
this . matchScoringType = MatchData . matchScoringType ;
this . matchTeamType = MatchData . matchTeamType ;
this . specialModes = MatchData . specialModes ;
this . seed = MatchData . seed ;
this . matchStreamName = ` mp_ ${ this . matchId } ` ;
this . matchChatStreamName = ` mp_chat_ ${ this . matchId } ` ;
this . matchLoadSlots = null ;
this . matchSkippedSlots = null ;
this . playerScores = null ;
this . multiplayerExtras = null ;
this . isTourneyMatch = false ;
this . tourneyClientUsers = [ ] ;
2022-08-26 12:52:00 +01:00
}
2022-01-04 03:39:53 +00:00
2022-08-26 12:52:00 +01:00
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" ] ;
2022-01-04 03:39:53 +00:00
2022-08-26 12:52:00 +01:00
const matchInstance = new MultiplayerMatch ( MatchData ) ;
2022-01-04 03:39:53 +00:00
2022-08-26 12:52:00 +01:00
console . log ( matchInstance . matchId ) ;
2022-01-04 03:39:53 +00:00
2022-08-26 12:52:00 +01:00
// Update the status of the current user
StatusUpdate ( MatchHost , MatchHost . id ) ;
2022-01-04 03:39:53 +00:00
2022-08-26 12:52:00 +01:00
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 ;
2022-01-04 03:39:53 +00:00
}
createOsuMatchJSON ( ) {
return {
matchId : this . matchId ,
inProgress : this . inProgress ,
matchType : this . matchType ,
activeMods : this . activeMods ,
gameName : this . gameName ,
gamePassword : this . gamePassword ,
beatmapName : this . beatmapName ,
beatmapId : this . beatmapId ,
beatmapChecksum : this . beatmapChecksum ,
slots : this . slots ,
host : this . host ,
playMode : this . playMode ,
matchScoringType : this . matchScoringType ,
matchTeamType : this . matchTeamType ,
specialModes : this . specialModes ,
seed : this . seed
} ;
}
2022-07-02 11:37:08 +01:00
leaveMatch ( MatchUser = new User ) {
2022-07-05 08:13:45 +01:00
// Make sure this leave call is valid
if ( ! MatchUser . inMatch ) return ;
// Get the user's slot
const slot = this . slots [ MatchUser . matchSlotId ] ;
2022-01-04 03:39:53 +00:00
2022-07-05 08:13:45 +01:00
// Set the slot's status to avaliable
slot . playerId = - 1 ;
slot . status = 1 ;
2022-07-02 11:37:08 +01:00
2022-07-05 08:13:45 +01:00
// Remove the leaving user from the match's stream
2022-08-26 12:52:00 +01:00
Streams . removeUserFromStream ( this . matchStreamName , MatchUser . uuid ) ;
Streams . removeUserFromStream ( this . matchChatStreamName , MatchUser . uuid ) ;
2022-01-04 03:39:53 +00:00
2022-07-05 08:13:45 +01:00
// Send this after removing the user from match streams to avoid a leave notification for self
this . sendMatchUpdate ( ) ;
2022-01-04 03:39:53 +00:00
2022-07-05 08:13:45 +01:00
const osuPacketWriter = new osu . Bancho . Writer ;
2022-01-04 03:39:53 +00:00
2022-07-05 08:13:45 +01:00
// Remove user from the multiplayer channel for the match
osuPacketWriter . ChannelRevoked ( "#multiplayer" ) ;
2022-01-04 03:39:53 +00:00
2022-07-05 08:13:45 +01:00
MatchUser . addActionToQueue ( osuPacketWriter . toBuffer ) ;
2022-01-04 03:39:53 +00:00
}
2022-08-26 12:52:00 +01:00
async updateMatch ( MatchUser = new User , MatchData ) {
2022-01-04 03:39:53 +00:00
// Update match with new data
this . inProgress = MatchData . inProgress ;
this . matchType = MatchData . matchType ;
this . activeMods = MatchData . activeMods ;
2022-09-30 11:34:52 +01:00
const gameNameChanged = this . gameName !== MatchData . gameName ;
this . gameName = MatchData . gameName ;
2022-01-04 03:39:53 +00:00
if ( MatchData . gamePassword == '' ) MatchData . gamePassword == null ;
this . gamePassword = MatchData . gamePassword ;
this . beatmapName = MatchData . beatmapName ;
this . beatmapId = MatchData . beatmapId ;
this . beatmapChecksum = MatchData . beatmapChecksum ;
this . host = MatchData . host ;
this . playMode = MatchData . playMode ;
this . matchScoringType = MatchData . matchScoringType ;
this . matchTeamType = MatchData . matchTeamType ;
this . specialModes = MatchData . specialModes ;
2022-09-30 11:34:52 +01:00
const gameSeedChanged = this . seed !== MatchData . seed ;
this . seed = MatchData . seed ;
if ( gameNameChanged || gameSeedChanged ) {
const queryData = [ ] ;
if ( gameNameChanged ) {
queryData . push ( MatchData . gameName ) ;
}
if ( gameSeedChanged ) {
queryData . push ( MatchData . seed ) ;
}
queryData . push ( this . matchId ) ;
await global . DatabaseHelper . query ( ` UPDATE mp_matches SET ${ gameNameChanged ? ` name = ? ${ gameSeedChanged ? ", " : "" } ` : "" } ${ gameSeedChanged ? ` seed = ? ` : "" } WHERE id = ? ` , queryData ) ;
2022-08-26 12:52:00 +01:00
}
2022-01-04 03:39:53 +00:00
2022-07-02 11:37:08 +01:00
this . sendMatchUpdate ( ) ;
2022-01-04 03:39:53 +00:00
// Update the match listing in the lobby to reflect these changes
global . MultiplayerManager . updateMatchListing ( ) ;
}
sendMatchUpdate ( ) {
const osuPacketWriter = new osu . Bancho . Writer ;
osuPacketWriter . MatchUpdate ( this . createOsuMatchJSON ( ) ) ;
// Update all users in the match with new match information
2022-08-26 12:52:00 +01:00
if ( Streams . exists ( this . matchStreamName ) )
Streams . sendToStream ( this . matchStreamName , osuPacketWriter . toBuffer , null ) ;
2022-01-04 03:39:53 +00:00
}
2022-07-02 11:37:08 +01:00
moveToSlot ( MatchUser = new User , SlotToMoveTo ) {
2022-01-04 03:39:53 +00:00
const oldSlot = this . slots [ MatchUser . matchSlotId ] ;
// Set the new slot's data to the user's old slot data
this . slots [ SlotToMoveTo ] . playerId = MatchUser . id ;
MatchUser . matchSlotId = SlotToMoveTo ;
this . slots [ SlotToMoveTo ] . status = 4 ;
// Set the old slot's data to open
oldSlot . playerId = - 1 ;
oldSlot . status = 1 ;
2022-07-02 11:37:08 +01:00
this . sendMatchUpdate ( ) ;
2022-01-04 03:39:53 +00:00
// Update the match listing in the lobby to reflect this change
global . MultiplayerManager . updateMatchListing ( ) ;
}
2022-07-02 11:37:08 +01:00
changeTeam ( MatchUser = new User ) {
2022-01-04 03:39:53 +00:00
const slot = this . slots [ MatchUser . matchSlotId ] ;
slot . team = slot . team == 0 ? 1 : 0 ;
2021-02-01 03:01:37 +00:00
2022-07-02 11:37:08 +01:00
this . sendMatchUpdate ( ) ;
2022-01-04 03:39:53 +00:00
}
2021-02-01 03:01:37 +00:00
2022-07-02 11:37:08 +01:00
setStateReady ( MatchUser = new User ) {
2022-07-05 08:13:45 +01:00
if ( ! MatchUser . inMatch ) return ;
2022-07-02 11:37:08 +01:00
// Set the user's ready state to ready
this . slots [ MatchUser . matchSlotId ] . status = 8 ;
2021-09-24 01:39:46 +01:00
2022-07-02 11:37:08 +01:00
this . sendMatchUpdate ( ) ;
2022-01-04 03:39:53 +00:00
}
2021-09-24 01:39:46 +01:00
2022-07-02 11:37:08 +01:00
setStateNotReady ( MatchUser = new User ) {
2022-07-05 08:13:45 +01:00
if ( ! MatchUser . inMatch ) return ;
2022-07-02 11:37:08 +01:00
// Set the user's ready state to not ready
this . slots [ MatchUser . matchSlotId ] . status = 4 ;
2021-01-26 12:24:13 +00:00
2022-07-02 11:37:08 +01:00
this . sendMatchUpdate ( ) ;
2022-01-04 03:39:53 +00:00
}
2021-01-26 12:24:13 +00:00
2022-07-02 11:37:08 +01:00
lockMatchSlot ( MatchUser = new User , MatchUserToKick ) {
2022-01-04 03:39:53 +00:00
// Make sure the user attempting to kick / lock is the host of the match
if ( this . host != MatchUser . id ) return ;
2021-01-26 12:24:13 +00:00
2022-01-04 03:39:53 +00:00
// Make sure the user that is attempting to be kicked is not the host
if ( this . slots [ MatchUserToKick ] . playerId === this . host ) return ;
2021-01-26 12:24:13 +00:00
2022-01-04 03:39:53 +00:00
// Get the data of the slot at the index sent by the client
const slot = this . slots [ MatchUserToKick ] ;
2021-01-26 12:24:13 +00:00
2022-01-04 03:39:53 +00:00
let isSlotEmpty = true ;
2021-02-12 23:16:12 +00:00
2022-01-04 03:39:53 +00:00
// If the slot is empty lock/unlock instead of kicking
if ( slot . playerId === - 1 )
slot . status = slot . status === 1 ? 2 : 1 ;
// The slot isn't empty, kick the player
else {
const kickedPlayer = getUserById ( slot . playerId ) ;
kickedPlayer . matchSlotId = - 1 ;
slot . playerId = - 1 ;
slot . status = 1 ;
isSlotEmpty = false ;
}
2021-01-26 12:24:13 +00:00
2022-07-02 11:37:08 +01:00
this . sendMatchUpdate ( ) ;
2021-01-26 12:24:13 +00:00
2022-01-04 03:39:53 +00:00
// Update the match listing in the lobby listing to reflect this change
global . MultiplayerManager . updateMatchListing ( ) ;
2021-01-26 12:24:13 +00:00
2022-01-04 03:39:53 +00:00
if ( ! isSlotEmpty ) {
let cachedPlayerToken = getUserById ( slot . playerId ) . uuid ;
2021-02-12 23:16:12 +00:00
2022-01-04 03:39:53 +00:00
if ( cachedPlayerToken !== null && cachedPlayerToken !== "" ) {
// Remove the kicked user from the match stream
2022-08-26 12:52:00 +01:00
Streams . removeUserFromStream ( this . matchStreamName , cachedPlayerToken ) ;
2022-01-04 03:39:53 +00:00
}
}
}
2021-01-26 12:24:13 +00:00
2022-07-02 11:37:08 +01:00
missingBeatmap ( MatchUser = new User ) {
2022-01-04 03:39:53 +00:00
// User is missing the beatmap set the status to reflect it
this . slots [ MatchUser . matchSlotId ] . status = 16 ;
2022-07-02 11:37:08 +01:00
this . sendMatchUpdate ( ) ;
2022-01-04 03:39:53 +00:00
}
2022-07-02 11:37:08 +01:00
notMissingBeatmap ( MatchUser = new User ) {
2022-01-04 03:39:53 +00:00
// The user is not missing the beatmap, set the status to normal
this . slots [ MatchUser . matchSlotId ] . status = 4 ;
2022-07-02 11:37:08 +01:00
this . sendMatchUpdate ( ) ;
2022-01-04 03:39:53 +00:00
}
2022-07-02 11:37:08 +01:00
matchSkip ( MatchUser = new User ) {
2022-01-04 03:39:53 +00:00
if ( this . matchSkippedSlots == null ) {
this . matchSkippedSlots = [ ] ;
const skippedSlots = this . matchSkippedSlots ;
2022-07-02 11:37:08 +01:00
for ( let slot of this . slots ) {
2022-01-04 03:39:53 +00:00
// Make sure the slot has a user in it
if ( slot . playerId === - 1 || slot . status === 1 || slot . status === 2 ) continue ;
// Add the slot's user to the loaded checking array
skippedSlots . push ( { playerId : slot . playerId , skipped : false } ) ;
}
}
2022-07-02 11:37:08 +01:00
let allSkipped = true ;
for ( let skippedSlot of this . matchSkippedSlots ) {
2022-01-04 03:39:53 +00:00
// If loadslot belongs to this user then set loaded to true
2022-07-02 11:37:08 +01:00
if ( skippedSlot . playerId == MatchUser . id ) {
skippedSlot . skipped = true ;
2022-01-04 03:39:53 +00:00
}
2022-07-02 11:37:08 +01:00
if ( skippedSlot . skipped ) continue ;
2022-01-04 03:39:53 +00:00
2022-07-02 11:37:08 +01:00
// A user hasn't skipped
2022-01-04 03:39:53 +00:00
allSkipped = false ;
}
// All players have finished playing, finish the match
if ( allSkipped ) {
const osuPacketWriter = new osu . Bancho . Writer ;
osuPacketWriter . MatchPlayerSkipped ( MatchUser . id ) ;
osuPacketWriter . MatchSkip ( ) ;
2022-08-26 12:52:00 +01:00
Streams . sendToStream ( this . matchStreamName , osuPacketWriter . toBuffer , null ) ;
2022-01-04 03:39:53 +00:00
this . matchSkippedSlots = null ;
} else {
const osuPacketWriter = new osu . Bancho . Writer ;
osuPacketWriter . MatchPlayerSkipped ( MatchUser . id ) ;
2022-08-26 12:52:00 +01:00
Streams . sendToStream ( this . matchStreamName , osuPacketWriter . toBuffer , null ) ;
2022-01-04 03:39:53 +00:00
}
}
2022-07-02 11:37:08 +01:00
transferHost ( MatchUser = new User , SlotIDToTransferTo ) {
2022-01-04 03:39:53 +00:00
// Set the lobby's host to the new user
this . host = this . slots [ SlotIDToTransferTo ] . playerId ;
2022-07-02 11:37:08 +01:00
this . sendMatchUpdate ( ) ;
2022-01-04 03:39:53 +00:00
}
// TODO: Fix not being able to add DT when freemod is active
2022-07-02 11:37:08 +01:00
updateMods ( MatchUser = new User , MatchMods ) {
2022-01-04 03:39:53 +00:00
// Check if freemod is enabled
if ( this . specialModes === 1 ) {
this . slots [ MatchUser . matchSlotId ] . mods = MatchMods ;
2022-07-02 11:37:08 +01:00
this . sendMatchUpdate ( ) ;
2022-01-04 03:39:53 +00:00
} else {
// Make sure the person updating mods is the host of the match
if ( this . host !== MatchUser . id ) return ;
// Change the matches mods to these new mods
// TODO: Do this per user if freemod is enabled
this . activeMods = MatchMods ;
2022-07-02 11:37:08 +01:00
this . sendMatchUpdate ( ) ;
2022-01-04 03:39:53 +00:00
}
// Update match listing in the lobby to reflect this change
global . MultiplayerManager . updateMatchListing ( ) ;
}
startMatch ( ) {
// Make sure the match is not already in progress
// The client sometimes double fires the start packet
if ( this . inProgress ) return ;
this . inProgress = true ;
// Create array for monitoring users until they are ready to play
this . matchLoadSlots = [ ] ;
// Loop through all slots in the match
2022-07-02 11:37:08 +01:00
for ( let slot of this . slots ) {
2022-01-04 03:39:53 +00:00
// Make sure the slot has a user in it
if ( slot . playerId === - 1 || slot . status === 1 || slot . status === 2 ) continue ;
// Add the slot's user to the loaded checking array
2022-07-02 11:37:08 +01:00
this . matchLoadSlots . push ( {
2022-01-04 03:39:53 +00:00
playerId : slot . playerId ,
loaded : false
2022-07-02 11:37:08 +01:00
} ) ;
2022-01-04 03:39:53 +00:00
// Set the user's status to playing
slot . status = 32 ;
}
2022-07-02 11:37:08 +01:00
const osuPacketWriter = new osu . Bancho . Writer ;
2022-01-04 03:39:53 +00:00
osuPacketWriter . MatchStart ( this . createOsuMatchJSON ( ) ) ;
// Inform all users in the match that it has started
2022-08-26 12:52:00 +01:00
Streams . sendToStream ( this . matchStreamName , osuPacketWriter . toBuffer , null ) ;
2022-01-04 03:39:53 +00:00
// Update all users in the match with new info
this . sendMatchUpdate ( ) ;
// Update match listing in lobby to show the game is in progress
global . MultiplayerManager . updateMatchListing ( ) ;
}
2022-07-02 11:37:08 +01:00
matchPlayerLoaded ( MatchUser = new User ) {
// Loop through all user load check items and check if all users are loaded
let allLoaded = true ;
for ( let loadedSlot of this . matchLoadSlots ) {
2022-01-04 03:39:53 +00:00
// If loadslot belongs to this user then set loaded to true
2022-07-02 11:37:08 +01:00
if ( loadedSlot . playerId == MatchUser . id ) {
loadedSlot . loaded = true ;
2022-01-04 03:39:53 +00:00
}
2022-07-02 11:37:08 +01:00
if ( loadedSlot . loaded ) continue ;
2022-01-04 03:39:53 +00:00
allLoaded = false ;
}
// All players have loaded the beatmap, start playing.
if ( allLoaded ) {
let osuPacketWriter = new osu . Bancho . Writer ;
osuPacketWriter . MatchAllPlayersLoaded ( ) ;
2022-08-26 12:52:00 +01:00
Streams . sendToStream ( this . matchStreamName , osuPacketWriter . toBuffer , null ) ;
2022-01-04 03:39:53 +00:00
// Blank out user loading array
this . matchLoadSlots = null ;
this . playerScores = [ ] ;
2022-07-05 08:13:45 +01:00
for ( let i = 0 ; i < this . slots . length ; i ++ ) {
const slot = this . slots [ i ] ;
2022-01-04 03:39:53 +00:00
if ( slot . playerId === - 1 || slot . status === 1 || slot . status === 2 ) continue ;
this . playerScores . push ( { playerId : slot . playerId , slotId : i , score : 0 , isCurrentlyFailed : false } ) ;
}
}
}
2022-09-30 11:34:52 +01:00
async onPlayerFinishMatch ( MatchUser = new User ) {
2022-01-04 03:39:53 +00:00
if ( this . matchLoadSlots == null ) {
// Repopulate user loading slots again
2022-07-02 11:37:08 +01:00
this . matchLoadSlots = [ ] ;
for ( let slot of this . slots ) {
2022-01-04 03:39:53 +00:00
// Make sure the slot has a user
if ( slot . playerId === - 1 || slot . status === 1 || slot . status === 2 ) continue ;
// Populate user loading slots with this user's id and load status
2022-07-02 11:37:08 +01:00
this . matchLoadSlots . push ( {
2022-01-04 03:39:53 +00:00
playerId : slot . playerId ,
loaded : false
} ) ;
}
2022-07-02 11:37:08 +01:00
}
let allLoaded = true ;
2022-01-04 03:39:53 +00:00
// Loop through all loaded slots to make sure all users have finished playing
2022-07-02 11:37:08 +01:00
for ( let loadedSlot of this . matchLoadSlots ) {
if ( loadedSlot . playerId == MatchUser . id ) {
loadedSlot . loaded = true ;
2022-01-04 03:39:53 +00:00
}
2022-07-02 11:37:08 +01:00
if ( loadedSlot . loaded ) continue ;
2022-01-04 03:39:53 +00:00
// A user hasn't finished playing
allLoaded = false ;
}
// All players have finished playing, finish the match
2022-09-30 11:34:52 +01:00
if ( allLoaded ) await this . finishMatch ( ) ;
2022-01-04 03:39:53 +00:00
}
2022-08-26 12:52:00 +01:00
async finishMatch ( ) {
2022-01-04 03:39:53 +00:00
if ( ! this . inProgress ) return ;
this . matchLoadSlots = null ;
this . inProgress = false ;
let osuPacketWriter = new osu . Bancho . Writer ;
2022-08-26 12:52:00 +01:00
let queryData = [ this . matchId , this . roundId ++ , this . playMode , this . matchType , this . matchScoringType , this . matchTeamType , this . activeMods , this . beatmapChecksum , ( this . specialModes === 1 ) ? 1 : 0 ] ;
2022-01-04 03:39:53 +00:00
// Loop through all slots in the match
2022-07-02 11:37:08 +01:00
for ( let slot of this . slots ) {
2022-01-04 03:39:53 +00:00
// Make sure the slot has a user
2022-08-26 12:52:00 +01:00
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 } ` : "" } ` ) ;
2022-01-04 03:39:53 +00:00
// Set the user's status back to normal from playing
slot . status = 4 ;
}
2022-08-26 12:52:00 +01:00
console . log ( queryData ) ;
2022-01-04 03:39:53 +00:00
osuPacketWriter . MatchComplete ( ) ;
// Inform all users in the match that it is complete
2022-08-26 12:52:00 +01:00
Streams . sendToStream ( this . matchStreamName , osuPacketWriter . toBuffer , null ) ;
2022-01-04 03:39:53 +00:00
// Update all users in the match with new info
this . sendMatchUpdate ( ) ;
// Update match info in the lobby to reflect that the match has finished
global . MultiplayerManager . updateMatchListing ( ) ;
if ( this . multiplayerExtras != null ) this . multiplayerExtras . onMatchFinished ( JSON . parse ( JSON . stringify ( this . playerScores ) ) ) ;
2022-08-26 12:52:00 +01:00
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 ) ;
2022-01-04 03:39:53 +00:00
this . playerScores = null ;
}
2022-07-02 11:37:08 +01:00
updatePlayerScore ( MatchPlayer = new User , MatchScoreData ) {
2022-01-04 03:39:53 +00:00
const osuPacketWriter = new osu . Bancho . Writer ;
// Make sure the user's slot ID is not invalid
if ( this . matchSlotId == - 1 ) return ;
// Get the user's current slotID and append it to the givien data, just incase.
MatchScoreData . id = MatchPlayer . matchSlotId ;
// Update the playerScores array accordingly
2022-07-05 08:13:45 +01:00
for ( let playerScore of this . playerScores ) {
if ( playerScore . playerId == MatchPlayer . id ) {
playerScore . score = MatchScoreData . totalScore ;
playerScore . isCurrentlyFailed = MatchScoreData . currentHp == 254 ;
2022-08-26 12:52:00 +01:00
playerScore . _raw = MatchScoreData ;
2022-01-04 03:39:53 +00:00
break ;
}
}
osuPacketWriter . MatchScoreUpdate ( MatchScoreData ) ;
// Send the newly updated score to all users in the match
2022-08-26 12:52:00 +01:00
Streams . sendToStream ( this . matchStreamName , osuPacketWriter . toBuffer , null ) ;
2022-01-04 03:39:53 +00:00
}
2022-07-02 11:37:08 +01:00
matchFailed ( MatchUser = new User ) {
2022-01-04 03:39:53 +00:00
const osuPacketWriter = new osu . Bancho . Writer ;
// Make sure the user's slot ID is not invalid
if ( MatchUser . matchSlotId == - 1 ) return ;
osuPacketWriter . MatchPlayerFailed ( MatchUser . id ) ;
2022-08-26 12:52:00 +01:00
Streams . sendToStream ( this . matchStreamName , osuPacketWriter . toBuffer , null ) ;
2022-01-04 03:39:53 +00:00
}
2022-08-26 12:52:00 +01:00
}
module . exports = MultiplayerMatch ;