Minigames
packets22 packets
Minigames, as game.MinigameXtCommManager sends and handles them. Messages to the server go through gMainFrame.server.setXtObject_Str(cmd, [args], true, subRoom) on extension o: the fourth argument picks the room id, the in-room game's sub room when it is set and the player's room otherwise (SFClient.getCurrentRoomId).
What each game says while it is played (mm) is its own protocol, written by the game's movie; those arguments are kept as they came. Gem awards (mg), pet mastery (ma) and scores (msv) are sent as sums folded with a serial number the server hands out for each award and the player's id (MinigameManager.sendGemAward, sendMasteryPoints, sendScore), so the server can tell a forged award from a real one. Their packets carry the sums as they go over the wire; foldMinigameAward, unfoldMinigameAward, foldMinigameScore and unfoldMinigameScore do the client's arithmetic both ways, given the serial.
Hearing and sending packets
What the game sends is heard on phantom.packets.client, and what the server sends on phantom.packets.server. watch hears a packet after it has gone through; on hears it first and may change or drop it; send sends one to that end. See Packets.
Overview
| Packet | Command | Way | What it is |
|---|---|---|---|
MinigameInfoRequest | mi | game → server | The client asks the server to describe minigames. |
MinigameJoin | mj | game → server | The player asks to play a minigame. |
MinigameStartRequest | ms | game → server | The player starts a waiting minigame now. |
MinigameLeave | ml | game → server | The player leaves an in-room minigame. |
MinigameSend | mm | game → server | A minigame sends its own message to the server. |
MinigamePvp | mp | game → server | The player challenges, accepts, or turns down a two player game. |
MinigameCustomPvpJoin | mcp | game → server | The player joins a two player game another player set up. |
MinigameLeaderboardRequest | mlb | game → server | The client asks for a minigame’s leaderboard. |
MinigameInfoResult | mi | server → game | The server describes minigames. |
MinigameJoinResult | mj | server → game | The server seats the player in a minigame, or says why not. |
MinigameStarted | ms | server → game | The minigame starts, with its players. |
MinigameMessage | mm | server → game | A minigame’s own message from the server. |
MinigameLeft | ml | server → game | A player left the minigame. |
MinigameEnded | me | server → game | The minigame ended. |
MinigameRoomRemoved | mr | server → game | The minigame’s room was removed. |
MinigamePvpInvite | mp | server → game | A player challenges the player to a two player game, or turns them down. |
MinigameLeaderboard | mlb | server → game | The server gives a minigame’s leaderboard. |
MinigameGems | mg | server → game | The server hands out the serial the next gem award is folded with. |
MinigamePetMastery | ma | server → game | The server hands out the serial the next pet mastery award is folded with. |
MinigameGemAward | mg | game → server | A minigame awards the player gems. |
MinigamePetMasteryAward | ma | game → server | A minigame awards the active pet mastery points. |
MinigameScoreSubmit | msv | game → server | A minigame reports the player’s score. |
MinigameInfoRequest
Asks the server to describe games (MinigameXtCommManager.sendMinigameInfoRequest). The arguments are the games' definition ids, with no count before them.
Fields
| Field | Type | |
|---|---|---|
gameDefIds | number[] | The games to describe, by definition id: every argument, with no count. |
room | number | The room the message was sent in, as the SmartFox room id; -1 when it names none. |
Example
// Each time the game sends it to the server, after it has gone through.
const stop = phantom.packets.client.watch(packets.MinigameInfoRequest, (packet) => {
console.log(packet.gameDefIds);
});MinigameJoin
Asks to play a game (MinigameXtCommManager.sendMinigameJoinRequest, from MinigameManager.launchGame):
%xt%o%mj%<room>%<gameDefId>%<multiplayer>%<proModeId>%<hostUserId>%
multiplayer is set when the player chose the multiplayer button of a lobby, or joins another player's in-room game from their avatar (AvatarWorldView), and hostUserId is that player's id in the room, -1 otherwise. proModeId is only used by game 82.
Fields
| Field | Type | |
|---|---|---|
gameDefId | number | The game to play, by definition id. |
multiplayer | boolean | The player chose multiplayer, or joins another player's in-room game from their avatar. |
proModeId | number | The pro mode to play in. Only game 82 uses it. |
hostUserId | number | The SmartFox user id of the player whose game is joined, or -1. |
room | number | The room the message was sent in, as the SmartFox room id; -1 when it names none. |
Example
// Each time the game sends it to the server, after it has gone through.
const stop = phantom.packets.client.watch(packets.MinigameJoin, (packet) => {
console.log(packet.gameDefId, packet.multiplayer, packet.proModeId);
});MinigameStartRequest
Starts a waiting game now, without waiting for more players (MinigameXtCommManager.sendMinigameStartRequest).
Fields
| Field | Type | |
|---|---|---|
gameDefId | number | The waiting game to start, by definition id. |
room | number | The room the message was sent in, as the SmartFox room id; -1 when it names none. |
Example
// Each time the game sends it to the server, after it has gone through.
const stop = phantom.packets.client.watch(packets.MinigameStartRequest, (packet) => {
console.log(packet.gameDefId);
});MinigameLeave
Leaves an in-room game (MinigameXtCommManager.sendMinigameLeaveRequest): no arguments, sent to the game's sub room. A full-room game is left by joining a room instead (MinigameManager.leave).
Fields
| Field | Type | |
|---|---|---|
room | number | The room the message was sent in, as the SmartFox room id; -1 when it names none. |
Example
// Each time the game sends it to the server, after it has gone through.
const stop = phantom.packets.client.watch(packets.MinigameLeave, (packet) => {
console.log('minigame.leave');
});MinigameSend
What a game says to the server while it is played (MinigameManager.msg, which puts the game's definition id before what the game gave it, then sendMinigameMessageRequest):
%xt%o%mm%<room>%<gameDefId>%<data>...%
The first datum is usually the game's own command (Skee-Ball sends pg to start a round and gr with its folded score). _a is never sent: msg turns it into an emote on the avatar.
Fields
| Field | Type | |
|---|---|---|
gameDefId | number | The game sending it, by definition id. |
data | string[] | What the game gave, as it came: usually its own command first. |
room | number | The room the message was sent in, as the SmartFox room id; -1 when it names none. |
Example
// Each time the game sends it to the server, after it has gone through.
const stop = phantom.packets.client.watch(packets.MinigameSend, (packet) => {
console.log(packet.gameDefId, packet.data);
});MinigamePvp
Challenges a player to a two player game, or answers a challenge (MinigameXtCommManager.sendMinigamePvpMsg):
%xt%o%mp%<room>%<gameDefId>%<action>%<userName>%
action is 0 to challenge or accept, 1 to turn down or cancel. The user name is left out when it is empty.
Fields
| Field | Type | |
|---|---|---|
gameDefId | number | The game, by definition id. |
action | number | 0 to challenge or accept, 1 to turn down or cancel. |
userName | string | The other player, by username; empty when the message leaves it out. |
room | number | The room the message was sent in, as the SmartFox room id; -1 when it names none. |
Example
// Each time the game sends it to the server, after it has gone through.
const stop = phantom.packets.client.watch(packets.MinigamePvp, (packet) => {
console.log(packet.gameDefId, packet.action, packet.userName);
});MinigameCustomPvpJoin
Joins a custom two player game another player set up, from their avatar (MinigameXtCommManager.sendMinigameCustomPvpJoinMsg).
Fields
| Field | Type | |
|---|---|---|
gameDefId | number | The game, by definition id. |
action | number | An action number, as the client passes it. What its values mean is not recorded here. |
userName | string | The player who set the game up, by username. |
room | number | The room the message was sent in, as the SmartFox room id; -1 when it names none. |
Example
// Each time the game sends it to the server, after it has gone through.
const stop = phantom.packets.client.watch(packets.MinigameCustomPvpJoin, (packet) => {
console.log(packet.gameDefId, packet.action, packet.userName);
});MinigameLeaderboardRequest
Asks for a game's leaderboard (MinigameXtCommManager.sendMinigameLeaderboardRequest).
Fields
| Field | Type | |
|---|---|---|
gameDefId | number | The game whose leaderboard to send, by definition id. |
room | number | The room the message was sent in, as the SmartFox room id; -1 when it names none. |
Example
// Each time the game sends it to the server, after it has gone through.
const stop = phantom.packets.client.watch(packets.MinigameLeaderboardRequest, (packet) => {
console.log(packet.gameDefId);
});MinigameInfoResult
Games described (MinigameXtCommManager.handleMinigameInfo): a count, then nineteen fields for each game.
Fields
| Field | Type | |
|---|---|---|
games | MinigameInfo[] | The games described, after their count. |
room | number | The room the message was sent in, as the SmartFox room id; -1 when it names none. |
Example
// Each time the server sends it to the game, after it has gone through.
const stop = phantom.packets.server.watch(packets.MinigameInfoResult, (packet) => {
console.log(packet.games);
});MinigameJoinResult
The answer to a join (MinigameManager.joinGameResponse). A refusal is one of MINIGAME_JOIN_REFUSALS with its detail after it; anything else seats the player, and lists the players waiting in the lobby:
%xt%mj%<gameRoom>%<userId>%<userId>%...% %xt%mj%<room>%pf%<petDefId>%
Fields
| Field | Type | |
|---|---|---|
joined | boolean | The player was seated: the first argument is not a refusal. |
refusal | "as" | "hc" | "pf" | "mo" | "ul" | null | Why the player was not seated (MINIGAME_JOIN_REFUSALS), or null when seated. |
waitingUserIds | number[] | The players waiting in the lobby, by their ids in the room. Empty for a refusal. |
detail | string[] | What follows a refusal, such as the pet's def id after pf; empty when seated. |
room | number | The room the message was sent in, as the SmartFox room id; -1 when it names none. |
Example
// Each time the server sends it to the game, after it has gone through.
const stop = phantom.packets.server.watch(packets.MinigameJoinResult, (packet) => {
console.log(packet.joined, packet.refusal, packet.waitingUserIds);
});MinigameStarted
The game starts (MinigameManager.startGame, then createGameWindow):
%xt%ms%<gameRoom>%<playerCount>%<userId>...%<data>...%
The game is started with the player ids, then handed the rest as its first message. In a two player game data[3] is the opponent's user name (param1[8]).
Fields
| Field | Type | |
|---|---|---|
playerIds | number[] | The players, by their SmartFox user ids, after their count. |
data | string[] | The rest, as it came, handed to the game as its first message. |
room | number | The room the message was sent in, as the SmartFox room id; -1 when it names none. |
Example
// Each time the server sends it to the game, after it has gone through.
const stop = phantom.packets.server.watch(packets.MinigameStarted, (packet) => {
console.log(packet.playerIds, packet.data);
});MinigameMessage
A game's own message to the client (mm). The first datum is usually the game's command: Skee-Ball's pz and pg carry the serials its score is folded with.
Fields
| Field | Type | |
|---|---|---|
data | string[] | Every argument after the room, as it came, for the game's movie. |
room | number | The room the message was sent in, as the SmartFox room id; -1 when it names none. |
Example
// Each time the server sends it to the game, after it has gone through.
const stop = phantom.packets.server.watch(packets.MinigameMessage, (packet) => {
console.log(packet.data);
});MinigameLeft
A player left the game (ml), passed to the game as a message.
Fields
| Field | Type | |
|---|---|---|
data | string[] | Every argument after the room, as it came, for the game's movie. |
room | number | The room the message was sent in, as the SmartFox room id; -1 when it names none. |
Example
// Each time the server sends it to the game, after it has gone through.
const stop = phantom.packets.server.watch(packets.MinigameLeft, (packet) => {
console.log(packet.data);
});MinigameEnded
The game ended on the server (MinigameManager.minigameEndResponse): passed to the game's end. A full-room game then shows the "game over" message and leaves.
Fields
| Field | Type | |
|---|---|---|
data | string[] | Every argument after the room, as it came, for the game's movie. |
room | number | The room the message was sent in, as the SmartFox room id; -1 when it names none. |
Example
// Each time the server sends it to the game, after it has gone through.
const stop = phantom.packets.server.watch(packets.MinigameEnded, (packet) => {
console.log(packet.data);
});MinigameRoomRemoved
The game's room was removed (MinigameManager.minigameRoomRemovedResponse); nothing is read.
Fields
| Field | Type | |
|---|---|---|
data | string[] | Every argument after the room, as it came, for the game's movie. |
room | number | The room the message was sent in, as the SmartFox room id; -1 when it names none. |
Example
// Each time the server sends it to the game, after it has gone through.
const stop = phantom.packets.server.watch(packets.MinigameRoomRemoved, (packet) => {
console.log(packet.data);
});MinigamePvpInvite
A two player game challenge, or its refusal (MinigameManager.pvpResponse):
%xt%mp%<room>%<gameDefId>%0%<userName>%<nameVisible>% %xt%mp%<room>%<gameDefId>%1%
When nameVisible is 0 the popup says "a Jammer" in place of the name.
Fields
| Field | Type | |
|---|---|---|
gameDefId | number | The game, by definition id. |
action | number | 0 a challenge, anything else a refusal. |
userName | string | The player challenging, by username; empty for a refusal. |
nameVisible | boolean | The name may be shown; otherwise the popup says "a Jammer". False for a refusal. |
extra | string[] | Whatever follows, as it came. |
room | number | The room the message was sent in, as the SmartFox room id; -1 when it names none. |
Example
// Each time the server sends it to the game, after it has gone through.
const stop = phantom.packets.server.watch(packets.MinigamePvpInvite, (packet) => {
console.log(packet.gameDefId, packet.action, packet.userName);
});MinigameLeaderboard
A game's leaderboard (MinigameManager.leaderBoardResponse): all time, this week, and buddies, each a count and that many names and scores. A game id of -1 means there is none.
Fields
| Field | Type | |
|---|---|---|
gameDefId | number | The game, by definition id; -1 when there is no leaderboard. |
allTime | LeaderboardEntry[] | The all time board, after its count. Empty when there is none. |
thisWeek | LeaderboardEntry[] | This week's board, after its count. Empty when there is none. |
buddies | LeaderboardEntry[] | The player's buddies' board, after its count. Empty when there is none. |
room | number | The room the message was sent in, as the SmartFox room id; -1 when it names none. |
Example
// Each time the server sends it to the game, after it has gone through.
const stop = phantom.packets.server.watch(packets.MinigameLeaderboard, (packet) => {
console.log(packet.gameDefId, packet.allTime, packet.thisWeek);
});MinigameGems
The serial the next gem award is folded with (MinigameManager.minigameGems):
%xt%mg%<room>%<serial>%<forScore>%
The client keeps serial as _gemSerialNumber, sends any award it had queued at once, and forgets the serial again as soon as it has used it. When forScore is 1 the same serial is also kept as _scoreSN, the one a score is folded with (getScoreSN).
Fields
| Field | Type | |
|---|---|---|
serial | number | The serial the next gem award is folded with (_gemSerialNumber). |
forScore | boolean | The same serial is also the one scores are folded with (_scoreSN): the field is 1. |
room | number | The room the message was sent in, as the SmartFox room id; -1 when it names none. |
Example
// Each time the server sends it to the game, after it has gone through.
const stop = phantom.packets.server.watch(packets.MinigameGems, (packet) => {
console.log(packet.serial, packet.forScore);
});MinigamePetMastery
The serial the next pet mastery award is folded with (MinigameManager.minigamePetMastery):
%xt%ma%<room>%<serial>%<showPopup>%
The client keeps serial as _petMasterySerialNumber and sends any award it had queued. When showPopup is 1 it offers the pet mastery popup once the player leaves the in-room game (_petMasteryQueuePopup, then PetManager.checkAndOpenMasteryPopup).
Fields
| Field | Type | |
|---|---|---|
serial | number | The serial the next mastery award is folded with (_petMasterySerialNumber). |
showPopup | boolean | The pet mastery popup is due once the player leaves the game: the field is 1. |
room | number | The room the message was sent in, as the SmartFox room id; -1 when it names none. |
Example
// Each time the server sends it to the game, after it has gone through.
const stop = phantom.packets.server.watch(packets.MinigamePetMastery, (packet) => {
console.log(packet.serial, packet.showPopup);
});MinigameGemAward
A gem award for playing a game (MinigameManager.sendGemAward, reached through awardGems), folded with the serial minigame.gems handed out:
%xt%o%mg%<room>%<amountSum>%<gameSum>%<checkSum>%
unfoldMinigameAward reads the amount and the game back, given that serial.
Fields
| Field | Type | |
|---|---|---|
amountSum | number | (amount + 29) * 7 + (userId + 99) * 3 + (serial + 49) * 5. |
gameSum | number | (gameDefId + 49) * 3 + (serial + 83) * 5. |
checkSum | number | (serial + userId + amount) * 3 + amount * 3. |
room | number | The room the message was sent in, as the SmartFox room id; -1 when it names none. |
Example
// Each time the game sends it to the server, after it has gone through.
const stop = phantom.packets.client.watch(packets.MinigameGemAward, (packet) => {
console.log(packet.amountSum, packet.gameSum, packet.checkSum);
});MinigamePetMasteryAward
A pet mastery award for playing a game (MinigameManager.sendMasteryPoints, reached through awardPetMasteryPoints), folded as a gem award is with the serial minigame.pet-mastery handed out:
%xt%o%ma%<room>%<amountSum>%<gameSum>%<checkSum>%
Fields
| Field | Type | |
|---|---|---|
amountSum | number | (amount + 29) * 7 + (userId + 99) * 3 + (serial + 49) * 5. |
gameSum | number | (gameDefId + 49) * 3 + (serial + 83) * 5. |
checkSum | number | (serial + userId + amount) * 3 + amount * 3. |
room | number | The room the message was sent in, as the SmartFox room id; -1 when it names none. |
Example
// Each time the game sends it to the server, after it has gone through.
const stop = phantom.packets.client.watch(packets.MinigamePetMasteryAward, (packet) => {
console.log(packet.amountSum, packet.gameSum, packet.checkSum);
});MinigameScoreSubmit
A score for a game (MinigameManager.sendScore, from GameBase.valueTrackerCommit), folded with the score serial:
%xt%o%msv%<room>%<mainSum>%<valueSum>%<numSum>%<varRefSum>%<gameSum>%
unfoldMinigameScore reads the score, the leaderboard variable and the game back, given that serial.
Fields
| Field | Type | |
|---|---|---|
mainSum | number | trackerMain + 3 * varRef. |
valueSum | number | trackerVal - 8 * varRef. |
numSum | number | trackerNum + 5 * varRef. |
varRefSum | number | varRef * 5 + 7 * serial. |
gameSum | number | gameDefId * 3 + serial. |
room | number | The room the message was sent in, as the SmartFox room id; -1 when it names none. |
Example
// Each time the game sends it to the server, after it has gone through.
const stop = phantom.packets.client.watch(packets.MinigameScoreSubmit, (packet) => {
console.log(packet.mainSum, packet.valueSum, packet.numSum);
});