--************************************************************************** -- Copyright (C) 2009 by Lothar May * -- * -- This program is free software; you can redistribute it and/or modify * -- it under the terms of the GNU General Public License as published by * -- the Free Software Foundation; either version 2 of the License, or * -- (at your option) any later version. * -- * -- This program is distributed in the hope that it will be useful, * -- but WITHOUT ANY WARRANTY; without even the implied warranty of * -- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * -- GNU General Public License for more details. * -- * -- You should have received a copy of the GNU General Public License * -- along with this program; if not, write to the * -- Free Software Foundation, Inc., * -- 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * --************************************************************************** POKERTH-PROTOCOL DEFINITIONS IMPLICIT TAGS EXTENSIBILITY IMPLIED ::= BEGIN PokerTHMessage ::= CHOICE { announceMessage AnnounceMessage, initMessage InitMessage, authMessage AuthMessage, initAckMessage InitAckMessage, avatarRequestMessage AvatarRequestMessage, avatarReplyMessage AvatarReplyMessage, playerListMessage PlayerListMessage, gameListMessage GameListMessage, playerInfoRequestMessage PlayerInfoRequestMessage, playerInfoReplyMessage PlayerInfoReplyMessage, subscriptionRequestMessage SubscriptionRequestMessage, joinGameRequestMessage JoinGameRequestMessage, joinGameReplyMessage JoinGameReplyMessage, gamePlayerMessage GamePlayerMessage, kickPlayerRequestMessage KickPlayerRequestMessage, leaveGameRequestMessage LeaveGameRequestMessage, startEventMessage StartEventMessage, startEventAckMessage StartEventAckMessage, gameStartMessage GameStartMessage, handStartMessage HandStartMessage, playersTurnMessage PlayersTurnMessage, myActionRequestMessage MyActionRequestMessage, yourActionRejectedMessage YourActionRejectedMessage, playersActionDoneMessage PlayersActionDoneMessage, dealFlopCardsMessage DealFlopCardsMessage, dealTurnCardMessage DealTurnCardMessage, dealRiverCardMessage DealRiverCardMessage, allInShowCardsMessage AllInShowCardsMessage, endOfHandMessage EndOfHandMessage, endOfGameMessage EndOfGameMessage, askKickPlayerMessage AskKickPlayerMessage, askKickDeniedMessage AskKickDeniedMessage, startKickPetitionMessage StartKickPetitionMessage, voteKickRequestMessage VoteKickRequestMessage, voteKickReplyMessage VoteKickReplyMessage, kickPetitionUpdateMessage KickPetitionUpdateMessage, endKickPetitionMessage EndKickPetitionMessage, statisticsMessage StatisticsMessage, chatRequestMessage ChatRequestMessage, chatMessage ChatMessage, dialogMessage DialogMessage, timeoutWarningMessage TimeoutWarningMessage, resetTimeoutMessage ResetTimeoutMessage, errorMessage ErrorMessage } AnnounceMessage ::= [APPLICATION 0] SEQUENCE { protocolVersion Version, latestGameVersion Version, latestBetaRevision INTEGER(0..65535), serverType ENUMERATED { serverTypeLAN (0), serverTypeInternetNoAuth (1), serverTypeInternetAuth (2) }, numPlayersOnServer INTEGER(0..65535) } -- buildId contains a constant build id (specific for Windows/Linux/Mac builds) InitMessage ::= [APPLICATION 1] SEQUENCE { requestedVersion Version, buildId INTEGER, login CHOICE { guestLogin [0] GuestLogin, authenticatedLogin [1] AuthenticatedLogin, unauthenticatedLogin [2] UnauthenticatedLogin } } Version ::= SEQUENCE { major INTEGER(0..65535), minor INTEGER(0..65535) } GuestLogin ::= SEQUENCE { nickName UTF8String (SIZE(1..64)) } -- Login data is according to SCRAM SHA-1 AuthenticatedLogin ::= SEQUENCE { clientUserData OCTET STRING (SIZE(1..256)), avatar AvatarHash OPTIONAL } UnauthenticatedLogin ::= SEQUENCE { nickName UTF8String (SIZE(1..64)), avatar AvatarHash OPTIONAL } AuthMessage ::= [APPLICATION 2] CHOICE { authServerChallenge [0] AuthServerChallenge, authClientResponse [1] AuthClientResponse, authServerVerification [2] AuthServerVerification } AuthServerChallenge ::= SEQUENCE { serverChallenge OCTET STRING (SIZE(1..256)) } AuthClientResponse ::= SEQUENCE { clientResponse OCTET STRING (SIZE(1..256)) } AuthServerVerification ::= SEQUENCE { serverVerification OCTET STRING (SIZE(1..256)) } InitAckMessage ::= [APPLICATION 3] SEQUENCE { yourSessionId Guid, yourPlayerId NonZeroId } AvatarRequestMessage ::= [APPLICATION 4] SEQUENCE { requestId NonZeroId, avatar AvatarHash } AvatarReplyMessage ::= [APPLICATION 5] SEQUENCE { requestId NonZeroId, avatarResult CHOICE { avatarHeader [0] AvatarHeader, avatarData [1] AvatarData, avatarEnd [2] AvatarEnd, unknownAvatar [3] UnknownAvatar } } AvatarHeader ::= SEQUENCE { avatarType NetAvatarType, avatarSize INTEGER(32..30720) } AvatarData ::= SEQUENCE { avatarBlock OCTET STRING (SIZE(1..256)) } AvatarEnd ::= SEQUENCE { } UnknownAvatar ::= SEQUENCE { } AvatarHash ::= OCTET STRING (SIZE(16)) -- md5 hash value NetAvatarType ::= ENUMERATED { avatarImagePng (1), avatarImageJpg (2), avatarImageGif (3) } PlayerListMessage ::= [APPLICATION 6] SEQUENCE { playerId NonZeroId, playerListNotification ENUMERATED { playerListNew (0), playerListLeft (1) } } GameListMessage ::= [APPLICATION 7] SEQUENCE { gameId NonZeroId, gameListNotification CHOICE { gameListNew [0] GameListNew, gameListUpdate [1] GameListUpdate, gameListPlayerJoined [2] GameListPlayerJoined, gameListPlayerLeft [3] GameListPlayerLeft, gameListAdminChanged [4] GameListAdminChanged } } GameListNew ::= SEQUENCE { gameMode NetGameMode, isPrivate BOOLEAN, playerIds SEQUENCE SIZE(0..10) OF NonZeroId, adminPlayerId NonZeroId, gameInfo NetGameInfo } GameListUpdate ::= SEQUENCE { gameMode NetGameMode } GameListPlayerJoined ::= SEQUENCE { playerId NonZeroId } GameListPlayerLeft ::= SEQUENCE { playerId NonZeroId } GameListAdminChanged ::= SEQUENCE { newAdminPlayerId NonZeroId } NetGameMode ::= ENUMERATED { gameCreated (1), gameStarted (2), gameClosed (3) } PlayerInfoRequestMessage ::= [APPLICATION 8] SEQUENCE { playerId NonZeroId } PlayerInfoReplyMessage ::= [APPLICATION 9] SEQUENCE { playerId NonZeroId, playerInfoResult CHOICE { playerInfoData [0] PlayerInfoData, unknownPlayerInfo [1] UnknownPlayerInfo } } PlayerInfoData ::= SEQUENCE { playerName UTF8String (SIZE(1..32)), isHuman BOOLEAN, avatarData SEQUENCE { avatarType NetAvatarType, avatar AvatarHash } OPTIONAL } UnknownPlayerInfo ::= SEQUENCE { } -- The following request will not be confirmed by the server. It is used, -- optionally, to reduce server traffic. The server might ignore it. SubscriptionRequestMessage ::= [APPLICATION 10] SEQUENCE { subscriptionAction ENUMERATED { unsubscribeGameList (1), resubscribeGameList (2) } } JoinGameRequestMessage ::= [APPLICATION 11] SEQUENCE { joinGameAction CHOICE { joinExistingGame [0] JoinExistingGame, joinNewGame [1] JoinNewGame }, password UTF8String (SIZE(1..64)) OPTIONAL } JoinExistingGame ::= SEQUENCE { gameId NonZeroId } JoinNewGame ::= SEQUENCE { gameInfo NetGameInfo } JoinGameReplyMessage ::= [APPLICATION 12] SEQUENCE { gameId NonZeroId, joinGameResult CHOICE { joinGameAck [0] JoinGameAck, joinGameFailed [1] JoinGameFailed } } JoinGameAck ::= SEQUENCE { areYouAdmin BOOLEAN, gameInfo NetGameInfo } JoinGameFailed ::= SEQUENCE { joinGameFailureReason ENUMERATED { invalidGame (1), gameIsFull (2), gameIsRunning (3), invalidPassword (4) } } NetGameInfo ::= SEQUENCE { gameName UTF8String (SIZE(1..64)), maxNumPlayers INTEGER(2..10), raiseIntervalMode CHOICE { raiseEveryHands [0] INTEGER(1..1000), raiseEveryMinutes [1] INTEGER(1..1000) }, endRaiseMode ENUMERATED { doubleBlinds (1), raiseByEndValue (2), keepLastBlind (3) }, proposedGuiSpeed INTEGER(1..11), delayBetweenHands INTEGER(5..20), -- These are seconds playerActionTimeout INTEGER(5..60), -- These are seconds firstSmallBlind INTEGER(1..20000), endRaiseSmallBlindValue INTEGER(0..20000), startMoney INTEGER(1..1000000), manualBlinds SEQUENCE SIZE(0..30) OF INTEGER(1..20001) } GamePlayerMessage ::= [APPLICATION 13] SEQUENCE { gameId NonZeroId, gamePlayerNotification CHOICE { gamePlayerJoined [0] GamePlayerJoined, gamePlayerLeft [1] GamePlayerLeft, gameAdminChanged [2] GameAdminChanged, removedFromGame [3] RemovedFromGame } } GamePlayerJoined ::= SEQUENCE { playerId NonZeroId, isAdmin BOOLEAN } GamePlayerLeft ::= SEQUENCE { playerId NonZeroId, gamePlayerLeftReason ENUMERATED { leftOnRequest (0), leftKicked (1), leftError (2) } } GameAdminChanged ::= SEQUENCE { newAdminPlayerId NonZeroId } RemovedFromGame ::= SEQUENCE { removedFromGameReason ENUMERATED { removedOnRequest (0), -- No error, client wished to leave. kickedFromGame (1), gameIsFull (2), gameIsRunning (3), gameTimeout (4), removedStartFailed (5) } } KickPlayerRequestMessage ::= [APPLICATION 14] SEQUENCE { gameId NonZeroId, playerId NonZeroId } LeaveGameRequestMessage ::= [APPLICATION 15] SEQUENCE { gameId NonZeroId } StartEventMessage ::= [APPLICATION 16] SEQUENCE { gameId NonZeroId, fillWithComputerPlayers BOOLEAN } StartEventAckMessage ::= [APPLICATION 17] SEQUENCE { gameId NonZeroId } GameStartMessage ::= [APPLICATION 18] SEQUENCE { gameId NonZeroId, startDealerPlayerId NonZeroId, playerSeats SEQUENCE SIZE(2..10) OF NonZeroId } HandStartMessage ::= [APPLICATION 19] SEQUENCE { gameId NonZeroId, yourCard1 Card, yourCard2 Card, smallBlind INTEGER(1..20001) } PlayersTurnMessage ::= [APPLICATION 20] SEQUENCE { gameId NonZeroId, playerId NonZeroId, gameState NetGameState } MyActionRequestMessage ::= [APPLICATION 21] SEQUENCE { gameId NonZeroId, gameState NetGameState, myAction NetPlayerAction, myRelativeBet INTEGER(0..10000000) } YourActionRejectedMessage ::= [APPLICATION 22] SEQUENCE { gameId NonZeroId, gameState NetGameState, yourAction NetPlayerAction, yourRelativeBet INTEGER(0..10000000), rejectionReason ENUMERATED { rejectedInvalidGameState (1), rejectedNotYourTurn (2), rejectedActionNotAllowed (3) } } PlayersActionDoneMessage ::= [APPLICATION 23] SEQUENCE { gameId NonZeroId, playerId NonZeroId, gameState NetGameState, playerAction NetPlayerAction, totalPlayerBet INTEGER(0..10000000), playerMoney INTEGER(0..10000000), highestSet INTEGER(0..10000000), minimumRaise INTEGER(0..10000000) -- TODO } DealFlopCardsMessage ::= [APPLICATION 24] SEQUENCE { gameId NonZeroId, flopCard1 Card, flopCard2 Card, flopCard3 Card } DealTurnCardMessage ::= [APPLICATION 25] SEQUENCE { gameId NonZeroId, turnCard Card } DealRiverCardMessage ::= [APPLICATION 26] SEQUENCE { gameId NonZeroId, riverCard Card } AllInShowCardsMessage ::= [APPLICATION 27] SEQUENCE { gameId NonZeroId, playersAllIn SEQUENCE SIZE(1..10) OF PlayerAllIn } PlayerAllIn ::= SEQUENCE { playerId NonZeroId, allInCard1 Card, allInCard2 Card } EndOfHandMessage ::= [APPLICATION 28] SEQUENCE { gameId NonZeroId, endOfHandType CHOICE { endOfHandShowCards [0] EndOfHandShowCards, endOfHandHideCards [1] EndOfHandHideCards } } EndOfHandShowCards ::= SEQUENCE { playerResults SEQUENCE SIZE(1..10) OF PlayerResult } PlayerResult ::= SEQUENCE { playerId NonZeroId, resultCard1 Card, resultCard2 Card, bestHandPosition SEQUENCE SIZE(5) OF INTEGER, -- TODO size restrictions cardsValue INTEGER, moneyWon INTEGER(0..10000000), playerMoney INTEGER(0..10000000) } EndOfHandHideCards ::= SEQUENCE { playerId NonZeroId, moneyWon INTEGER(0..10000000), playerMoney INTEGER(0..10000000) } EndOfGameMessage ::= [APPLICATION 29] SEQUENCE { gameId NonZeroId, winnerPlayerId NonZeroId } AskKickPlayerMessage ::= [APPLICATION 64] SEQUENCE { gameId NonZeroId, playerId NonZeroId } AskKickDeniedMessage ::= [APPLICATION 65] SEQUENCE { gameId NonZeroId, playerId NonZeroId, kickDeniedReason ENUMERATED { kickDeniedInvalidGameState (0), kickDeniedNotPossible (1), kickDeniedTryAgainLater (2), kickDeniedAlreadyInProgress (3), kickDeniedInvalidPlayerId (4) } } StartKickPetitionMessage ::= [APPLICATION 66] SEQUENCE { gameId NonZeroId, petitionId NonZeroId, proposingPlayerId NonZeroId, kickPlayerId NonZeroId, kickTimeoutSec INTEGER(1..120), numVotesNeededToKick INTEGER(1..9) } VoteKickRequestMessage ::= [APPLICATION 67] SEQUENCE { gameId NonZeroId, petitionId NonZeroId, voteKick BOOLEAN } VoteKickReplyMessage ::= [APPLICATION 68] SEQUENCE { gameId NonZeroId, petitionId NonZeroId, voteKickReplyType CHOICE { voteKickAck [0] VoteKickAck, voteKickDenied [1] VoteKickDenied } } VoteKickAck ::= SEQUENCE { } VoteKickDenied ::= SEQUENCE { voteKickDeniedReason ENUMERATED { voteKickDeniedInvalid (0), voteKickDeniedAlreadyVoted (1) } } KickPetitionUpdateMessage ::= [APPLICATION 69] SEQUENCE { gameId NonZeroId, petitionId NonZeroId, numVotesAgainstKicking INTEGER(0..9), numVotesInFavourOfKicking INTEGER(1..9), numVotesNeededToKick INTEGER(1..9) } EndKickPetitionMessage ::= [APPLICATION 70] SEQUENCE { gameId NonZeroId, petitionId NonZeroId, numVotesAgainstKicking INTEGER(0..9), numVotesInFavourOfKicking INTEGER(1..9), resultPlayerKicked BOOLEAN, petitionEndReason ENUMERATED { petitionEndEnoughVotes (0), petitionEndTooFewPlayers (1), petitionEndPlayerLeft (2), petitionEndTimeout (3) } } StatisticsMessage ::= [APPLICATION 128] SEQUENCE { statisticsData SEQUENCE SIZE(1..32) OF StatisticsData } StatisticsData ::= SEQUENCE { statisticsType ENUMERATED { statNumberOfPlayers (1) }, statisticsValue INTEGER } ChatRequestMessage ::= [APPLICATION 129] SEQUENCE { chatRequestType CHOICE { chatRequestTypeLobby [0] ChatRequestTypeLobby, chatRequestTypeGame [1] ChatRequestTypeGame }, chatText UTF8String (SIZE(1..128)) } ChatRequestTypeLobby ::= SEQUENCE { } ChatRequestTypeGame ::= SEQUENCE { gameId NonZeroId } ChatMessage ::= [APPLICATION 130] SEQUENCE { chatType CHOICE { chatTypeLobby [0] ChatTypeLobby, chatTypeGame [1] ChatTypeGame, chatTypeBot [2] ChatTypeBot, chatTypeBroadcast [3] ChatTypeBroadcast }, chatText UTF8String (SIZE(1..128)) } ChatTypeLobby ::= SEQUENCE { playerId NonZeroId } ChatTypeGame ::= SEQUENCE { gameId NonZeroId, playerId NonZeroId } ChatTypeBroadcast ::= SEQUENCE { } ChatTypeBot ::= SEQUENCE { } DialogMessage ::= [APPLICATION 131] SEQUENCE { notificationText UTF8String (SIZE(1..128)) } TimeoutWarningMessage ::= [APPLICATION 132] SEQUENCE { timeoutReason ENUMERATED { timeoutNoDataReceived (0), timeoutInactiveGame (1) }, remainingSeconds INTEGER } ResetTimeoutMessage ::= [APPLICATION 133] SEQUENCE { } ErrorMessage ::= [APPLICATION 255] SEQUENCE { errorReason ENUMERATED { errorReserved (0), errorInitVersionNotSupported (1), errorInitServerFull (2), errorInitAuthFailure (3), errorInitPlayerNameInUse (4), errorInitInvalidPlayerName (5), errorInitServerMaintenance (6), errorAvatarTooLarge (7), errorAvatarUploadBlocked (8), errorInvalidPacket (256), errorInvalidState (257), errorKickedFromServer (258), errorBannedFromServer (259), errorSessionTimeout (260) } } NetGameState ::= ENUMERATED { statePreflop (0), stateFlop (1), stateTurn (2), stateRiver (3), statePreflopSmallBlind (4), statePreflopBigBlind (5) } NetPlayerAction ::= ENUMERATED { actionNone (0), actionFold (1), actionCheck (2), actionCall (3), actionBet (4), actionRaise (5), actionAllIn (6) } NonZeroId ::= INTEGER(1..4294967295) Id ::= INTEGER(0..4294967295) Guid ::= INTEGER(0..4294967295) -- TODO Card ::= INTEGER(0..51) END