Hey,
I played around a bit and found an issue in the library in line 102:
This line must be removed, otherwise the return code after a score submission will always be 1 ( success ), no matter if the character limit of 32 was exceeded or the gameKey was not recognized.
I made some minor changes so the library works with #option_explicit, and also added 2 functions that simply check if there is an active submit or request connection, so that a new submission/request is only made if there are no active connections open.
EDIT: Updated to newest version on 12/12/2023
Here's the updated library:
REM ***********************************************
REM Title: Purple Token Library
REM Author: Phaelax
REM Downloaded from: http://dbcc.zimnox.com/
REM ***********************************************
/*
*
* Author: Phaelax
* Date: Nov 13, 2023
*
* Description: The Purple Token library was created to make it
* easier for users to incorporate the functionality
* of the Purple Token high-score service from within
* AGK Tier 1.
*
* Score format: No_Of_Entries,User1,Score1,User2,Score2,User3,Score3
*
*/
REM ########################################
REM ### MODIFIED BY PSY Dec 11, 2023 ###
REM ########################################
// Internally used variables. You should never need to access
// _PT directly in your application
Type _PurpleToken
key as string
submitConn as integer
retrieveConn as integer
scoresRetrieved as integer
scoreSubmitted as integer
scores as string
Endtype
Global _PT as _PurpleToken
// This array is safe to access from your application
// and contains the return codes possible for score submission
// The exception is an error code of -1, which is an unknown error
Global _PT_Codes as string[4]
// Must be called before using any other PT commands
function PT_Initialize ( gameKey as string )
_PT.key = gameKey
_PT_Codes[1] = "Highscore submission successful"
_PT_Codes[2] = "Name length exceeds 32 characters"
_PT_Codes[3] = "Gamekey not recognized"
_PT_Codes[4] = "Score too low"
endfunction
// Submit a score
function PT_SubmitScore ( _player$ as string, _score as integer )
local vars$ as string
_PT.scoreSubmitted = 0
_PT.submitConn = CreateHTTPConnection()
SetHTTPHost ( _PT.submitConn, "purpletoken.com", 1, "", "" )
vars$ = "player=" + _player$ + "&score=" + str ( _score ) + "&gamekey=" + _PT.key
SendHTTPRequestASync ( _PT.submitConn, "update/index.php", vars$ )
endfunction
// Handles the http responses for submitting and requesting scores
// It is safe to call this every iteration of your game loop
function PT_Listener()
local ptResponse as integer
local res as integer
// Score retrieval
if _PT.retrieveConn > 0
if _PT.scoresRetrieved = 0
ptResponse = GetHTTPResponseReady ( _PT.retrieveConn )
if ptResponse = -1
// Error
elseif ptResponse = 1
_PT.scores = GetHTTPResponse ( _PT.retrieveConn )
_PT.scoresRetrieved = 1
endif
if ptResponse <> 0 // If either success or failed request, end connection
CloseHTTPConnection ( _PT.retrieveConn )
DeleteHTTPConnection ( _PT.retrieveConn )
_PT.retrieveConn = 0
endif
endif
endif
// Score submission
if _PT.submitConn > 0
res = GetHTTPResponseReady ( _PT.submitConn )
if res = -1
// Error
_PT.scoreSubmitted = -1
elseif res = 1
_PT.scoreSubmitted = val ( GetHTTPResponse ( _PT.submitConn ) )
endif
if _PT.scoreSubmitted <> 0
CloseHTTPConnection ( _PT.submitConn )
DeleteHTTPConnection ( _PT.submitConn )
_PT.submitConn = 0
endif
endif
endfunction
// If a score is submitted this will return '1' upon completion of the http request, otherwise 0
// Codes can be looked up using the PT_Codes[] array
function PT_SubmitCompleted()
if _PT.scoreSubmitted <> 0 then exitfunction 1
endfunction 0
// After a score submission has finished a code is generated (for success or possible errors)
// Once this function is called the code is cleared until a new submission is made
function PT_GetSubmitCode()
local code as integer
code = _PT.scoreSubmitted
_PT.scoreSubmitted = 0
endfunction code
// Check if new score data is available after a request is made through PT_RequestScores()
// Returns 1 for true, 0 otherwise. If scores are available, command will continue to return 1
// until the data has been retrieved at least once.
function PT_ScoresAvailable()
endfunction _PT.scoresRetrieved
// Returns the raw score data (comma delimited single-line string)
// Once this function is called, PT_ScoresAvailable() will return 0 until a new request is made.
// However, the last retrieved score data can continue to be accessed through this function
function PT_GetScores()
_PT.scoresRetrieved = 0
endfunction _PT.scores
// Initiate the connection to get list of scores
// Once the request has completed, PT_scoresAvailable() will return 1
function PT_RequestScores()
local vars$ as string
_PT.scoresRetrieved = 0
_PT.retrieveConn = CreateHTTPConnection()
SetHTTPHost ( _PT.retrieveConn, "purpletoken.com", 1, "", "" )
vars$ = "gamekey=" + _PT.key
SendHTTPRequestASync ( _PT.retrieveConn, "update/index.php", vars$ )
endfunction
// Same as above but also retrieves the submission date/time of the scores
// The returned format will then look like: No_Of_Entries,User1,Score1,Date1,User2,Score2,Date2,User3,Score3,Date3
function PT_RequestScoresWithDates()
local vars$ as string
_PT.scoresRetrieved = 0
_PT.retrieveConn = CreateHTTPConnection()
SetHTTPHost ( _PT.retrieveConn, "purpletoken.com", 1, "", "" )
vars$ = "dates=yes&gamekey=" + _PT.key
SendHTTPRequestASync ( _PT.retrieveConn, "update/index.php", vars$ )
endfunction
// Returns 1 if there's an active connection for score retrieval, otherwise 0
function PT_RetrieveConnectionActive()
if _PT.retrieveConn <> 0 then exitfunction 1
endfunction 0
// Returns 1 if there's an active connection for score submission, otherwise 0
function PT_SubmitConnectionActive()
if _PT.submitConn <> 0 then exitfunction 1
endfunction 0
Here's an example code where you can submit a legit score, submit a score with an invalid name, and request the score table. You just need to enter your
gameKey.
#option_explicit
SetErrorMode ( 2 )
#insert "purpletoken.agc"
type HighscoreTableType
name as string
score as integer
timestamp as string
endtype
global scoreboard as HighscoreTableType[]
global scores$ as string
global submitCode as integer
global submit_result$ as string
global request_result$ as string
SetWindowTitle ( "PurpleToken Highscore Generator" )
SetWindowSize ( 1024, 768, 0 )
SetWindowAllowResize ( 1 )
SetVirtualResolution ( 1024, 768 )
SetOrientationAllowed ( 1, 1, 1, 1 )
SetSyncRate ( 60, 0 )
SetScissor ( 0, 0, 0, 0 )
UseNewDefaultFonts ( 1 )
PT_Initialize ( "GAME KEY" )
repeat
// Press ENTER key to request retrieval of game scores
if GetRawKeyPressed ( 13 ) and NOT PT_RetrieveConnectionActive()
request_result$ = "Requesting..."
PT_RequestScoresWithDates()
endif
// Press SPACE key to submit a score
if GetRawKeyPressed ( 32 ) and NOT PT_SubmitConnectionActive()
submit_result$ = "Submitting...."
PT_SubmitScore ( "DAISY", random ( 10000, 99999 ) )
endif
// Press '2' key to submit a score with a name exceeding the char limit
if GetRawKeyPressed ( 50 ) and NOT PT_SubmitConnectionActive()
submit_result$ = "Submitting...."
PT_SubmitScore ( "THISNAMEISEXCEEDINGTHELIMITOF32CHARS", random ( 10000, 99999 ) )
endif
// If score data is available, this will return 1
if PT_ScoresAvailable()
// Once you call PT_GetScores(), PT_ScoresAvailable() will return 0 until a new request is made
scores$ = PT_GetScores()
// Parse scores how you see fit
ParseScoresWithDates ( scores$ )
//ParseScores(scores$)
request_result$ = "Highscore request completed"
endif
// If a score is submitted this will return 1 upon completion of the http request, otherwise 0
if PT_SubmitCompleted()
// Once PT_GetSubmitCode() is called, the code is wiped clear and
// PT_SubmitCompleted() will again return 0 until a new submission is made
submitCode = PT_GetSubmitCode()
if submitCode = -1
submit_result$ = "Unknown error"
else
submit_result$ = _PT_Codes[submitCode]
endif
endif
// See status
print ( "Press [ENTER] to retrieve scores" )
print ( "Press [SPACE] to submit a random score" )
print ( "Press [2] to submit a random score and a name that has too many characters" )
print ( "" ) : print ( "" )
print ( "Last score submission: " + submit_result$ )
print ( "Last score request: " + request_result$ )
print ( "" ) : print ( "" )
// Display scores however you want
DisplayScoresWithDates()
//DisplayScores()
// Listens for the http request responses
// No sockets are left open or connections in memory if
// there have been no requests or submissions
PT_Listener()
Sync()
until GetRawKeyReleased ( 27 )
END
// Score format: No_Of_Entries,User1,Score1,User2,Score2,User3,Score3
function ParseScores ( _scores as string )
local count as integer
local size as integer
local player$ as string
local score as integer
local i as integer
local j as integer
count = CountStringTokens ( _scores, "," )
size = val ( GetStringToken ( _scores, ",", 1 ) )
scoreboard.length = size
j = 1
for i = 2 to count step 2
player$ = GetStringToken ( _scores, ",", i )
score = val ( GetStringToken ( _scores, ",", i+1 ) )
scoreboard[j].name = player$
scoreboard[j].score = score
inc j
next i
endfunction
// Score format: No_Of_Entries,User1,Score1,Date1,User2,Score2,Date2,User3,Score3,Date3
function ParseScoresWithDates ( _scores as string )
local count as integer
local size as integer
local i as integer
local j as integer
local player$ as string
local score as integer
local t$ as string
count = CountStringTokens ( _scores, "," )
size = val ( GetStringToken ( _scores, ",", 1 ) )
scoreboard.length = size
j = 1
for i = 2 to count step 3
player$ = GetStringToken ( _scores, ",", i)
score = val ( GetStringToken ( _scores, ",", i+1 ) )
t$ = GetStringToken ( _scores, ",", i+2 )
scoreboard[j].name = player$
scoreboard[j].score = score
scoreboard[j].timestamp = t$
inc j
next i
endfunction
function DisplayScores()
local size as integer
local i as integer
size = scoreboard.length
for i = 1 to size
print ( scoreboard[i].name + " - " + str ( scoreboard[i].score ) )
next i
endfunction
function DisplayScoresWithDates()
local blank$ as string
local size as integer
local i as integer
blank$ = spaces ( 20 )
size = scoreboard.length
for i = 1 to size
print ( left ( scoreboard[i].name + blank$, 20 ) + " - " + right ( spaces ( 5 ) + str ( scoreboard[i].score), 6 ) + " : " + scoreboard[i].timestamp )
next i
endfunction
PSY