Scoreoid for Monkey
Monkey Forums/User Modules/Scoreoid for Monkey
| ||
I've started a module to help integrate Scoreoid functionality into monkey games. Check out Scoreoid here: http://www.scoreoid.net The Google Code repo (in hg) is here: http://code.google.com/p/scoreoid-for-monkey/ Why Scoreoid? No SDKs. It's all RESTful via http/https. This means it can be done in pure monkey. And since my first game project is pretty simple, I don't need anything more complicated than Scoreoid can provide right now. UPDATES: 2013.03.04.01 Added *.java POST() function for mnet to this article for Android compatibility. 2012.08.06.02 All API calls (22) are now available. I'm building a test app now to test all of this. I don't expect any problems... FLW. 2012.08.06 - The module is incomplete, but the skeletal structure is ready. I suspect it will be complete in a few days, since there are only 22 API calls. If anybody is interested in helping out, please get in touch. I will accept changes/updates to the code here in this thread (which I'll then commit), or, if you'd like, I can give you commit permission. At the moment, the Scoreoid module utilizes mnet, but I'm probably going to switch it to the NativeHTTP, since NativeHTTP has implementations for all platforms that monkey supports. Current problem with NativeHTTP: can't make HTTP POST work in HTML5. :-/ Oh! Almost forgot! You have to make the following changes in your code for this to work: In mnet.monkey, add HTTP POST functionality: [monkeycode] 'Http stuff Class Http = "MNet_Http" Method Get:String( url:String, timeoutConnection:Int = 3000, timeoutSocket:Int = 5000 ) Method AGet:String( url:String, timeoutConnection:Int = 3000, timeoutSocket:Int = 5000 ) Method GetResult:String() Method Post:String(url:String, param:String, timeoutConnection:Int = 3000, timeoutSocket:Int = 5000) '<<--- add this End Class [/monkeycode] In mnet.html5.js, add this entire function: [monkeycode] MNet_Http.prototype.Post = function( url, params, timeoutConnection, timeoutSocket ) { try { var client = new XMLHttpRequest(); client.open( "POST", url, false ); client.setRequestHeader( "Content-type", "application/x-www-form-urlencoded" ); client.setRequestHeader( "Content-length", params.length ); client.setRequestHeader( "Connection", "close" ); client.send( params ); var serverResponse = client.responseText; return serverResponse; } catch( e ) { return ""; } } [/monkeycode] For Android compatibility, make sure you have POST() functionality in your mnet *.java file. It should look something like this: [monkeycode] public String Post( String url, String param, int timeoutConnection, int timeoutSocket ) { HttpURLConnection con = null; InputStream is = null; try { URL connectToURL = new URL( url + "?" + param ); con = ( HttpURLConnection )connectToURL.openConnection(); con.setReadTimeout( timeoutSocket ); con.setConnectTimeout( timeoutConnection ); con.setRequestMethod( "POST" ); con.setDoInput( true ); // Start the query con.connect(); is = con.getInputStream(); } catch( IOException e ) { _result = "ERR_HttpGet " + e.getMessage(); return ""; } return convertStreamToString( is ); } [/monkeycode] That should be it, though I wouldn't be surprised if I left something critical out of this post. If you have any questions, let me know. :-) |
| ||
That would be awesome to get this working. I've been meaning to look into getting monkey to work with Scoreoid for a while now. Glad to be seeing this :). |
| ||
I've tested it with createPlayer() and deletePlayer(), and it works with those. It should work with all functions now. If not, let me know. I'll be adding functionality to my game as the days go by, so I will be putting it through the ringer and will be exploring more efficient algorithms for it. In particular, the createPlayer() and editPlayer() functions have many many optional parameters, so I'm wondering what the best way to handle that is (right now, you have to pass it a parameters string that you build, as opposed to passing parameters and letting the module build the string for you). If you have ideas, let me know. |
| ||
Gonna give this a test later on today. At the moment, the Scoreoid module utilizes mnet, but I'm probably going to switch it to the NativeHTTP, since NativeHTTP has implementations for all platforms that monkey supports. Current problem with NativeHTTP: can't make HTTP POST work in HTML5. :-/ I do agree with making it with NativeHTTP. But for just HTML5, couldn't you just check the current target for HTML5 and use MNET only for that? |
| ||
If @Xaron wants to get on the ball and finish mnet, then it won't be a problem... :-) One of the issues with NativeHTTP (or maybe the issue), is that it is asynchronous (mnet is synchronous, meaning it doesn't return until it gets the result from the server). That means, I think, that it has to be constantly queried until it finishes. I guess that would be done in the OnUpdate() method of the scoreoid module, right? I did try making the call to NativeHTTP synchronous, but didn't get it working yet... |
| ||
I'm changing up the internals so that each function returns a boolean, and you can get the results with Scoreoid.result. Seems to make it easier to use. Example: [monkeycode] If Not Scoreoid.getPlayer("", playername) Then ' player does not exist so create him If Scoreoid.createPlayer(playername, "&password=" + password) Then lblMessage.SetText("Your profile has been created!") Else lblMessage.SetText("Could not create you. :-/") EndIf Else ' player exists, so are we logging in? If Not Scoreoid.getPlayer("", playername, password) Then lblMessage.SetText("ERROR: Bad username or password.") Else 'successful login? lblMessage.SetText("You are now signed in!") EndIf EndIf [/monkeycode] How does that work for y'all? I'm wondering if I should create a player object, a game object, and a scores object... That way, when you do getPlayer(), you can then access a Scoreoid.player object to get/set attributes. We'll see... Any input welcome! :-) |
| ||
I'm wondering if I should create a player object, a game object, and a scores object... That way, when you do getPlayer(), you can then access a Scoreoid.player object to get/set attributes. Agrees with this :) |
| ||
hey c.k., before I start hacking away, is this still active? |
| ||
Somewhat. You are welcome to do with it as you please. If you want commit rights to the current repo, let me know. |
| ||
Has anyone got this running on android? for some reason i get "Error invalid API Key" on android, but it works fine on html5. |
| ||
Is the google code repository empty? I can't find any downloads there. I also would like to use this with Android if it's working? |
| ||
You need to click on source, then browse http://code.google.com/p/scoreoid-for-monkey/source/browse/ as for working on android, it should work, but for some reason it does not add the api key to the url string(i think lol) you also have to add the post function to mnet.android.java, c.k was nice enough to send me his as its not in the main post, public String Post( String url, String param, int timeoutConnection, int timeoutSocket ) { HttpURLConnection con = null; InputStream is = null; try { URL connectToURL = new URL( url ); con = ( HttpURLConnection )connectToURL.openConnection(); con.setReadTimeout( timeoutSocket ); con.setConnectTimeout( timeoutConnection ); con.setRequestMethod( "POST" ); con.setDoInput( true ); // Start the query con.connect(); is = con.getInputStream(); } catch( IOException e ) { _result = "ERR_HttpGet " + e.getMessage(); return ""; } return convertStreamToString( is ); } i am honestly not sure why it doesn't work on android, or even if its something simple my end, someone with more coding experience and brain power than me will have to figure that out lol |
| ||
You need to use a mercurial client to grab the code, or you can grab it via the source/browse like Moggy said. The Android code is in the main post, as of a few days ago I think. Moggy, as I'm looking over the code, nowhere does the params variable get used. Am I missing something? I suspect there's more that should be there than there is. |
| ||
in your mnet *.java file.changeURL connectToURL = new URL( url ); to this URL connectToURL = new URL( url + "?" + param ); fixed my issue on android, all works fine now :) |
| ||
Hey guys wonder if I could get some help on this. Scoreoid looks perfect as a solution for high score stuff but I'm having trouble getting it to work. Firstly, for HTML5, I can't seem to download the php file you mention in the readme.txt - I can see the link in the extra security page but it doesn't seem to work for me. Anyone else got this problem? But I've tried on Android and can't seem to get a high score posted. This is what I've done: scoreEngine = New BaaSEngine scoreEngine.setAPIKey("myAPIKey") scoreEngine.setGameID("gameID") scoreEngine.createScore("20", "testUser") Any thoughts? |
| ||
i think you have to set the url before you call itscoreEngine = New BaaSEngine scoreEngine.setAPIKey("myAPIKey") scoreEngine.setGameID("gameID") scoreEngine.setURL("https://www.scoreoid.com/api/createScore") scoreEngine.createScore("20", "testUser") |
| ||
The URL should be the base. When you call createScore(), it should append "createScore" to the URL. The URL is defaulted to "https://www.scoreoid.com/", so you don't have to call it for non-HTML5 apps. I think. :-D For HTML5, the base is going to be a local PHP file that acts as a proxy. On my system, it's called "scoreoid_proxy.php". THIS WILL NOT WORK WITH MSERVER! You have to use Apache, or some other server. I think. :-D |
| ||
I've updated the repo. Primarily, I added a test program that you can use to make sure you can connect to scoreoid. Requires your own custom scoreoid.txt in /data, so check it out and see if it's helpful. It works for me with HTML and my own scoreoid_proxy.php file being served by Apache. Doesn't seem to work with MSERVER. |
| ||
Thanks for your help guys! Unfortunately still couldn't download the php file from scoreoid. Android version still doesn't work despite the ping and other commands returning true. I can't create a new score from within the game :/ Ah well, I think I'll leave it for this project and look at it again when I can focus on just getting this aspect to work. |
| ||
Andrew, contact Scoreoid. They are pretty responsive and will help you get your file if you need it. In fact, now that you mention it, I think they have to send it to you because that part of their process is broke right now... Oops. I'll try running some Android tests tonight. I haven't had my PC at home because of a move, but that should be restored today. |
| ||
Righto, dropped them a line about it. I would be great to have something as simple as this to use in future for sure, plus with all the other functionality that comes with it other than just the high score stuff :) If you do get anywhere with the Android version please let me know! |
| ||
Hi c.k., We're trying to use your module but we get this error when importing scoroidnet.monkey: Monkey Runtime Error : TypeError: Cannot call method 'call' of undefined Any idea? |
| ||
You get that when just importing the module? What version of monkey are y'all using? |
| ||
Thanks for helping! We're using v69 and mongoose as web server. |
| ||
C.K. can you try to help us? We'll try today with Apache. |
| ||
We try under Apache, same result. Monkey Runtime Error : TypeError: Cannot call method 'call' of undefined The issue in not in your code, but with mnet. The mnet lib is very old (2012!!), do we have to use the version from https://code.google.com/p/mnet or do you use a modified version? |
| ||
We did a lot of tried, and managed to have the module working. It was, perhaps, the way we inserted your changes in mnet.html5.js. We restarted our project from scratch and it compile now! We'll let you know when the game will be online :) |
| ||
Awesome! Sorry I was unresponsive. I was out of town over the weekend and not able to get here. Good luck! Keep us up to date. :-) |
| ||
I recently used this module and it's been a great help, but it's kind of broken now due to changes at scoreoid's end. I changed the POST method to: Method POST:String(apiCall:String, param:String = "") Local URL:String = ScoreoidURL + "api/" + apiCall #If TARGET="html5" Then Local params:String = "game_id=" + game_id + "&api_key=" + api_key + "&response=" + response Local skipCheck:Bool = True #Else Local params:String = "game_id=" + game_id + "&api_key=" + api_key + "&response=" + response Local skipCheck:Bool = False #End Local res:String = "" If api_key.Length() > 0 Or skipCheck Then If param.Length() > 0 Then params += "&" + param EndIf res = httpPost(URL, params) Else #If TARGET="html5" Then res = "[{~qerror~q:~qBaaSEngine Problem!~q}]" #Else res = "[{~qerror~q:~qBaaSEngine NOT INITIALIZED!~q}]" #End EndIf Return res End I changed the format to fit with the way scoreoid works now. Note i also removed the https:// as I found http:// was much faster and for my purposes security isn't much of a worry, you may want to keep it how it is, though and i changed the CountBestScores method to Method getBestScores:Bool(order_by:String = "", order:String = "", limit:String = "", start_date:String = "", end_date:String = "", platform:String = "", difficulty:String = "") Local params:String = "" params = add_param(params, "order_by", order_by) params = add_param(params, "order", order) params = add_param(params, "limit", limit) params = add_param(params, "start_date", start_date) params = add_param(params, "end_date", end_date) params = add_param(params, "platform", platform) params = add_param(params, "difficulty", difficulty) resultText = POST("getBestScores", params) success = resultText.Contains("success") resultMap.Clear() Return success End it's actually far dirtier than the original code but the original would only post the single top score. This will reply back with the json feed as a single string and you'll need to edit the important information out. Sorry, but I struggled with the json module for ages without really knowing what I was doing and decided this was easier for me. Notice that I've changed success to be determined by reading success from the file rather than not finding an error because I found that not having a connection would make the resultText just read "" Finally, there are no checks in the module's end for non net compatible characters in the fields and this meant usernames with a space were being truncated and possibly usernames with a quotation mark or comma to fail so I wrote a little function that would make the username net compatible before feeding it to the scoreoid module Function NetChars:String(str:String) str = str.Replace("%", "%25") str = str.Replace("$", "%24") str = str.Replace("&", "%26") str = str.Replace("+", "%2B") str = str.Replace(",", "%2C") str = str.Replace("/", "%2F") str = str.Replace(":", "%3A") str = str.Replace(";", "%3B") str = str.Replace("=", "%3D") str = str.Replace("?", "%3F") str = str.Replace("@", "%40") str = str.Replace(" ", "%20") str = str.Replace("~q", "%22") str = str.Replace("<", "%3C") str = str.Replace(">", "%3E") str = str.Replace("#", "%23") str = str.Replace("{", "%7B") str = str.Replace("}", "%7D") str = str.Replace("|", "%7C") str = str.Replace("\", "%5C") 'this line totally contains a backslash but the forum doesn't like it str = str.Replace("^", "%5E") str = str.Replace("~~", "%7E") str = str.Replace("[", "%5B") str = str.Replace("]", "%5D") str = str.Replace("`", "%60") Return str End hope this helps someone |
| ||
Well done, although I have not used Scoreoid with Monkey, I have used it in the past. It's a very nice little feature to add to any-ones games. It's nice to see that this option is now (re)open for Monkey users again. |
| ||
Hi Capn Lee, I tried to use the lib an have some problems :( Some question: First: The MNET Lib that you used is this: https://code.google.com/p/mnet without changes ? Second: The json lib that the scoroid lib use is the one that made for warpy ? (/bananas/warpy/json) And finally the error that i get: "expecting class member declaration: when the field playerParams will be set to string Can you give a little help here please ? PS: I has adjusted the scoroid lib with your code ;) thanks |
| ||
I did just download the newest mnet and made the changes in the initial post (replaced the http class etc) the json module i think it uses is this one https://code.google.com/p/monkey-json/ what function is being called that causes this problem, the only thing I've really tested is GetBestScores() and CreateScore() as I'm not using much of the advanced stuff so it could be that changes I've made muck up other areas of the module I don't use. because this thread is a little bit lost with changes and such I'll upload the modules as I know them to be working. Mnet has been altered as stated in the 1st post in this thread, json is the old monkey-json project unaltered and scoreoid has my changes in there https://dl.dropboxusercontent.com/u/2021720/modules.zip |
| ||
scratch all that, I tried to build my app for iOS and found that the code this module is reliant on (mnet) will not work with newer xcode. I've written my own little class for this instead that uses brl.httprequest instead and it's much nicer than the previous. I'm a terrible coder so feel free to correct anything here but I can assure you this works on Android, iOS and HTML5 without the messing around that the module needs. this is the module: Import brl.httprequest Class Scoreoid Implements IOnHttpRequestComplete Field game_id:String Field api_key:String Field responseText:String Field complete:Bool = True Field scoreoidURL:String = "https://api.scoreoid.com/" Method New(api_key:String = "", game_id:String = "") Self.game_id = game_id Self.api_key = api_key End Method Complete:Bool() If complete = True ' Print("true") Return True Else ' Print("false") Return False EndIf End Method SetApiKey(api_key:String) Self.api_key = api_key End Method SetGameID(game_id:String) Self.game_id = game_id End Method Update() If complete = False UpdateAsyncEvents() EndIf End Method Response:String() Return responseText End Method OnHttpRequestComplete:Void(req:HttpRequest) responseText = req.ResponseText() complete = True End Method CreateScore(score:String, username:String, unique_id:String = "", platform:String = "", difficulty:String = "", data:String = "") complete = False Local req:HttpRequest = New HttpRequest("GET", scoreoidURL + "v1/createScore?api_key=" + api_key + "&game_id=" + game_id + "&score=" + score + "&username=" + username + "&unique_id=" + unique_id + "&platform=" + platform + "&difficulty=" + difficulty + "&data=" + data + "&response=json", Self) req.Send() End Method GetBestScores(order_by:String = "score", order:String = "desc", limit:String = "25", start_date:String = "", end_date:String = "", platform:String = "", difficulty:String = "", usernames:String = "") complete = False Local req:HttpRequest = New HttpRequest("GET", scoreoidURL + "v1/getBestScores?api_key=" + api_key + "&game_id=" + game_id + "&order_by=" + order_by + "&order=" + order + "&limit=" + limit + "&start_date=" + start_date + "&end_date=" + end_date + "&platform=" + platform + "&difficulty=" + difficulty + "&usernames=" + usernames + "&response=json", Self) req.Send() End End and here is example code on how to use it: Import mojo Import scoreoid Global g:ScoreoidTest Function Main() g = New ScoreoidTest End Class ScoreoidTest Extends App Field scoreoid:Scoreoid Method OnCreate() SetUpdateRate(60) scoreoid = New Scoreoid("0000000000a000a00a000a00a0", "000a000a00a") 'obviously this needs to be a correct key and id scoreoid.CreateScore("99999", "capnlee") End Method OnUpdate() scoreoid.Update() End End |