On-line ScoreBoard [Not maintained .. new extension available ]

jazzuo

  • Posts: 23
hi what is meaning of this

Type: Number, Time or Text. You can store these types as value-type.

i mean score is number, name is text. So type of waht should be number, time or text?
 

mdotedot

  • Posts: 1640
Hello Jazzuo,

You can store a number as a high-score for a player, but you can also store a high/low time. The sort is different on time than it is on number. The same applies to text.
Usually people seem to be satisfied with number!

Hope this clarifies a bit!

Best regards from
M.E.
Hanging out in the Chat:  http://www.stencyl.com/chat/

Proud member of the League of Idiotic Stencylers! Doing things in Stencyl that probably shouldn't be done.

jazzuo

  • Posts: 23
hi i have a problem, when i am checking my game, i can always put up name and score the first time around but when i come to it second time i am unable to do it. If i close and open the game again, it works fine. Is there a need to close the web connection at a moment of closing the room that draws the highscore table?


slso what is "debug on off" and the  "score board is connected"?
thx

« Last Edit: February 04, 2015, 06:25:41 am by jazzuo »

cabinfever

  • Posts: 159
Page 3 on this thread:
http://community.stencyl.com/index.php/topic,37281.30.html

Last post on that page by mdotedot....

lilpoboy1978

  • Posts: 82
what if your players do not have names?  I'd like to show a list with no names.   Or just player 1, 2 etc

mdotedot

  • Posts: 1640
Hello Lilpoboy,

You can use a block containing a counter to use as the name. In the example just replace 'mdotedot' with Text contatenation block: [player] & [counter]
A future enhancement will be a block that will retrieve the number of entries in the database so you could use that value+1 for a new name.
Until then you could query the scoreboard for all entries and retrieve it in a list. The [number of items] block in the List panel can  be used to get the number.
But the purpose of a scoreboard is to know how well you did compare to previous entries, so you could also use a random block and check if that entry exists (usually not since it is random) and if not exists use that name to display to the user and use it to store the entry.
Such as ' set name to [player]&[random 1 to 99999]'  and 'request score from playername [name]'
if the list is empty you know that you have a new entry. If not empty repeat using a loop block.

Hope this helps.

Best regards from
M.E.
Hope this helps for now.
Hanging out in the Chat:  http://www.stencyl.com/chat/

Proud member of the League of Idiotic Stencylers! Doing things in Stencyl that probably shouldn't be done.

lilpoboy1978

  • Posts: 82
Hello Lilpoboy,

You can use a block containing a counter to use as the name. In the example just replace 'mdotedot' with Text contatenation block: [player] & [counter]
A future enhancement will be a block that will retrieve the number of entries in the database so you could use that value+1 for a new name.
Until then you could query the scoreboard for all entries and retrieve it in a list. The [number of items] block in the List panel can  be used to get the number.
But the purpose of a scoreboard is to know how well you did compare to previous entries, so you could also use a random block and check if that entry exists (usually not since it is random) and if not exists use that name to display to the user and use it to store the entry.
Such as ' set name to [player]&[random 1 to 99999]'  and 'request score from playername [name]'
if the list is empty you know that you have a new entry. If not empty repeat using a loop block.

Hope this helps.

Best regards from
M.E.
Hope this helps for now.

Thanks for the explanation, I think I pretty much understand now.  I will mess around with it.

jazzuo

  • Posts: 23
is this code correct?
could anyone please post correct code?
thx


//
// Scoreboard extension
//
// Author: MdotEdot
//
// Use at your own risk
//
//
// No backups or guarantees are made on the availability of servers.
//
// The server to which you connect must supply you with application-id and score-id.
//
// Supplies:
//      ScoreBoard URL [ your scoreboard server ] AppID [ the given application id ] SecretID: [ the given scoreboard id ]
//      Scoreboard: isConnected
//      ScoreBoard AppID [ Application ID ] Level: [nr] set score type [number|time|text] playername [text] score [anything]
//      ScoreBoard request List AppID [] Level [] get type [] number of rows
  • order by [Ascending|Descending] with ID [nr]

//      ScoreBoard get list with ID [nr] (list with both name and score)
//      ScoreBoard request score from player name: [] AppID []
//      ScoreBoard Get Names from ID [nr] (list)
//      ScoreBoard Get Scores from ID [nr] (list)
//           
import nme.net.URLLoader;
import nme.net.URLLoaderDataFormat;
import nme.net.URLRequest;
import nme.events.Event;
import nme.events.IOErrorEvent;


class ScoreBoard{
   private static var loader:URLLoader=null;
   public static var debug:Bool=true;
   public static var isConnected:Bool=false;

   // dbURL = 192.168.x.x:/database/stencyl.php
   // we will add ?a=  (a is the parameter that is used in stencyl.php)
   private static var url:String="";
   private static var SecretID:Float=0;
   private static var _AppID:String="";
   public static var requestFunc:Dynamic=null;
   public static var rsFunc:Dynamic=null;
   public static var setFunc:Dynamic=null;
   public static var initFunc:Dynamic=null;

   private static var scoreIDs:Map<String,Float>=new Map<String, Float>();
   private static var listTypes:Map<String,String>=new Map<String, String>();
   private static var textLists:Map<String,Array<Dynamic>>=new Map<String, Array<Dynamic>>();
   private static var timeLists:Map<String,Array<Dynamic>>=new Map<String, Array<Dynamic>>();
   private static var numberLists:Map<String,Array<Dynamic>>=new Map<String, Array<Dynamic>>();

   public static function setDebug(sw:Bool){
trace("Setting debug to :"+sw);
      debug=sw;
   }

   public static function initScore(dburl:String, appID:String, scoreID:Float, func:Dynamic){
      url=dburl;   
      _AppID=appID;
      SecretID=scoreID;
      scoreIDs.set(""+appID, SecretID);
if(debug)trace("initScore ... URL: "+url+" appid: "+_AppID+" scoreid: "+SecretID);
      isConnected=false;
      initFunc=func;

      var call:String=""+url+"?a=1";

      calling(call);
   }

   public static function setScore(AppID:String, Level:Float, type:String, name:String, value:Dynamic, func:Dynamic){
      // When we are done with setting the score .. continue
      setFunc=func;
      //
      //
      // dbURL
      // use scoreID + RNDwith AppID to make a string
      //
      //
      var scoreid:Float=scoreIDs.get(""+AppID);
              var _RND = 1000000+Std.random(8999999);
      var _SecretID=scoreid;
      var _AppID=AppID;
               var _Caller = ""+(_RND+_SecretID);
      var _reverse = "";
      var _counter = 8;

      //
      // We reverse the random number and then add each positional number to the scoreid
      //
      // random nummber: 212121
      // AppID: AAAAAA
      //
      // 121212 (random reverse)
      // AAAAAA
      // ------
      // BCBCBC

      for (index0 in 0...Std.int(9))
      {
         _reverse = (("" + _reverse) + ("" + ("" + _Caller).charAt(Std.int(_counter))));
         _counter -= 1;
      } 
      var _SendID = "";
      for (index0 in 0...Std.int(8))
      {
         var _appidchar = ("" + _AppID).charAt(Std.int(index0));
         var _p = ("" + _reverse).charAt(Std.int(index0));
         _SendID = (("" + _SendID) + ("" + String.fromCharCode(0+_appidchar.charCodeAt(0)+Std.parseInt(""+_p))));
      }
      //
      // We encode twice: for each argument and then for the whole line to avoid URL problems and obfuscation
if(debug)trace("AppID: "+AppID+" type: "+type+" name : "+name+" value: "+value+" Send ID: "+_SendID);
      var encoded=Base64.encode("sendscore")+","+Base64.encode(AppID)+","+Base64.encode(""+_RND)+","+Base64.encode(""+_SendID)+","+Base64.encode(name)+","+Base64.encode(value)+","+Base64.encode(""+type)+","+Base64.encode(""+Level);
      var call:String=""+url+"?a="+Base64.encode(encoded);

if(debug)trace("Calling: "+call);
      calling(call);
      
   }
   //
   // --
   // Request the data by connecting to the server. We get the ID back from the data so that we can find the type from memory
   //
   // url=a?ID=1
   // onData ID is received from server and then we can push the data in the right ID
   //
   public static function request(AppID:String, Level:Float, type:String, nr:Float, order:String, _id:Float, func:Dynamic){
      // Use URL to connect to PHP/Mysql combination to retrieve a list
      // when succeeded : wrapper function
if(debug)trace("Request list : "+AppID);
      requestFunc=func;
      _AppID=AppID;

      var id:Float=_id;
      
      // Keep track of the type that we request
      listTypes.set(""+id,type);
      
                var encoded=Base64.encode("GetScore")+","+Base64.encode(AppID)+","+Base64.encode(""+Level)+","+Base64.encode(type)+","+Base64.encode(order)+","+Base64.encode(""+nr)+","+Base64.encode(""+id);
      var call:String=""+url+"?a="+Base64.encode(encoded);

if(debug)trace("Calling: "+call);
      calling(call);
   }

   // Get Players Score
   public static function requestPlayerScore(AppID:String, Level:Float, type:String,  name:String, _id:Float, func:Dynamic){
      // Use URL to connect to PHP/Mysql combination to retrieve a list
      // when succeeded : wrapper function
      rsFunc=func;
      _AppID=AppID;

      var id:Float=_id;
      
      // Keep track of the type that we request
      listTypes.set(""+id,type);
      
if(debug)trace("GetPlayerScore"+","+AppID+","+Level+","+type+","+name+","+id);
                var encoded=Base64.encode("GetPlayerScore")+","+Base64.encode(AppID)+","+Base64.encode(""+Level)+","+Base64.encode(type)+","+Base64.encode(name)+","+Base64.encode(""+id);
      var call:String=""+url+"?a="+Base64.encode(encoded);
if(debug)trace("Calling: "+call);
      calling(call);
   }

   public static function calling(call:String){
      // Execute the HTML
            loader = new URLLoader();

                loader.addEventListener( Event.COMPLETE, onData);
                loader.addEventListener( IOErrorEvent.IO_ERROR, onError);
        loader.load(new URLRequest(call));
      
   }

   public static function onError(e:Event){
      isConnected=false;
if(debug)trace("onError called: "+e);
      callBack(); // call the inside block functions
   
   }

   public static function onData(e:Event){
      var theData="";
isConnected=true;
      if(e != null){
         if(e.target != null){
            theData=""+e.target.data;
         }else{
            if(debug)trace("===");
            if(debug)trace("The e.target is null!!!");
         }
      }else{   
         if(debug)trace("-----");
         if(debug)trace("The event is null!!!");
         if(debug)trace("-----");
      }
if(theData == null)theData="";
if(debug)trace("Data length:("+theData.length+") =  ["+theData+"]");
// keep code running and do not use RETURN   <-- we are calling functions wrapper
if(theData.length < 1){if(debug)trace("Length is null!"); }
      
      var theResult="";


           var p1=StringTools.replace(""+theData, ":", "+");
                var p2=StringTools.replace(p1, "_", "/");
                var p3=StringTools.replace(p2, ".", "=");
                var result="";
if(debug)trace("Before decode :["+p3+"]");
      if(p3 == null){
         if(debug)trace("Data is null!");
      }else{
if(debug)trace("Found text: "+p3.indexOf("RESULTSTENCYL"));
         if(p3.indexOf("RESULTSTENCYL") > -1){
            // special decoding since the external website puts javascript at the end
            result=Base64.decode(p3.substr(p3.indexOf("RESULTSTENCYL")+13,p3.length));
         }else{
            result=p3;
         }
      }
if(debug)trace("Received text from server: After decode :["+result+"]");

if(debug)trace("What is the indexOf returnid: "+result.indexOf("RETURNID"));
      // We should have AppID now
      //var AppID:String=_AppID;
      var data:String="";
      var id:Float=0;
      if(result.indexOf("RETURNID") > -1){
         var an_id=result.substr(result.indexOf("RETURNID")+8, result.indexOf("DINRUTER")-8);
         id=Std.parseFloat(an_id);
//if(debug)trace("Found appid due to returnId :"+id);
      }
      if(result.indexOf("RETURNVAL") > -1){
         data=result.substr(result.indexOf("RETURNVAL")+9);
      }
      // Get the Type
      var type=listTypes.get(""+id);
   
      // Investigate the data
      var r:Array<Dynamic>=new Array<Dynamic>();
      if(data.length > 0){
if(debug)trace("received List : ["+data+"]");
         var spl=data.split("!");   
         for(adata in spl){
//if(debug)trace("Adata :" +adata);
            var ddata=adata.split("#");
            if(ddata[1] != null){
               // name value pushed
                    var p1=StringTools.replace(""+ddata[0], ":", "+");
                         var p2=StringTools.replace(p1, "_", "/");
                         var p3=StringTools.replace(p2, ".", "=");
               var store:Array<Dynamic>=new Array<Dynamic>();
               store.push(Base64.decode(p3));

               // if we have text decode it once more
               if(type=="Text"){
                         var p_1=StringTools.replace(""+ddata[1], ":", "+");
                              var p_2=StringTools.replace(p_1, "_", "/");
                               var p_3=StringTools.replace(p_2, ".", "=");
                  store.push(Base64.decode(p_3));
               }else{
                  store.push(ddata[1]);
               }
               r.push(store);
            } // if column?
         } // if line
      } // if data
      //
      //
      // Get the AppID from the resulting data ...
      //
      if(r == null) r = new Array<Dynamic>();   

      if(type=="Text"){
         textLists.set(""+id, r);
      }
      if(type=="Number"){
         numberLists.set(""+id,r);
      }
      if(type=="Time"){
         timeLists.set(""+id,r);
      }

      callBack();


   }

   // When onData/ onError are done, call the inside-block functions

   public static function callBack(){
      if(isConnected){

         if(requestFunc!=null){requestFunc(); requestFunc=null;}
         if(rsFunc!=null){rsFunc(); rsFunc=null;}
         if(setFunc!=null){ if(debug)trace("calling setfunc "); setFunc(); setFunc=null;}
         if(initFunc!=null){ if(debug)trace("initFunc called"); initFunc(); initFunc=null;}
      }

   }

   public static function getScores(id:Float):Array<Dynamic>{
      var retval:Array<Dynamic>=new Array<Dynamic>();
      var type=listTypes.get(""+id);
      // default
if(debug)trace("GetList : type:"+type);
      if(type=="Text"){
         retval=textLists.get(""+id);
      }
      if(type=="Number"){
         retval=numberLists.get(""+id);
      }
      if(type=="Time"){
         retval=timeLists.get(""+id);

      }
      if(retval == null) retval=new Array<Dynamic>();
      var scores:Array<Dynamic>=new Array<Dynamic>();
      for(a in retval){
         scores.push(a[1]);
      }
      return scores;
   }

   public static function getNames(id:Float):Array<Dynamic>{
      var retval:Array<Dynamic>=new Array<Dynamic>();
      var type=listTypes.get(""+id);
      if(type=="Text"){
         retval=textLists.get(""+id);
      }
      if(type=="Number"){
         retval=numberLists.get(""+id);
      }
      if(type=="Time"){
         retval=timeLists.get(""+id);

      }
      if(retval == null) retval=new Array<Dynamic>();
      var names:Array<Dynamic>=new Array<Dynamic>();
      for(a in retval){
         names.push(a[0]);
      }
      return names;
   }
   
   public static function getList(id:Float):Array<Dynamic>{
      var retval:Array<Dynamic>=new Array<Dynamic>();
      var type=listTypes.get(""+id);
      // default
if(debug)trace("GetList : type:"+type);
      retval=numberLists.get(""+id);
      if(type=="Text"){
         retval=textLists.get(""+id);
      }
      if(type=="Number"){
         retval=numberLists.get(""+id);
      }
      if(type=="Time"){
         retval=timeLists.get(""+id);

      }
      
      if(retval == null) retval=new Array<Dynamic>();
      return retval;
   } // remember URL to call the mysql functions

} // class

mdotedot

  • Posts: 1640
Jazzuo,

Replace all lines with call:String  to:
Code: [Select]
  var call:String=""+url+"?a="+Base64.encode(encoded)+"&date="+Base64.encode(""+Date.now());
So only those lines.

I am making enhancements to the code as I go along, so in the end there will be a new extension with those codes in them, but for now the changes to the code need to be made by yourself.



Hanging out in the Chat:  http://www.stencyl.com/chat/

Proud member of the League of Idiotic Stencylers! Doing things in Stencyl that probably shouldn't be done.

jazzuo

  • Posts: 23
hi i did it and then disable the extention then intall new zip called scoreboard2 with the file updated. And the game dont work at all no more.  :'(

jazzuo

  • Posts: 23
ok done, i change it in the game folder

cabinfever

  • Posts: 159
In the import section:
'openfl' needs to used, when there is a refrence to 'nme'
(for Stencyl 3.3)

Joraanpe

  • Posts: 288
@mdotedot Heya bro, i know you are very busy nowadays and so on, but would there be any chance you could add that feature to show the user his position on the rank any time soon?

mdotedot

  • Posts: 1640
Today I uploaded a new version.

It includes two new blocks for position and number of items in scoreboard.

I didn't figure out how to use the extension for both 3.2 and 3.3, so for 3.3  you need to modify the ScoreBoard.hx and uncomment the openfl imports and comment out the nme ones.
I was hoping to use a #if macro but could not find one!

Hope this helps!

Best regards from
M.E.
Hanging out in the Chat:  http://www.stencyl.com/chat/

Proud member of the League of Idiotic Stencylers! Doing things in Stencyl that probably shouldn't be done.

Chitro

  • Posts: 3
Hi Mdot Edot, awesome extension! Great job, kudos man. Sorry if this is a noob question but
is there anyway I could make a list of scoreboards which will display the top five scores/ or last ten scores - anything similar to this?
I tried the extension and it only shows one score for now. How do I get a list of scores displaying on the scene? Thank you!
And really appreciate the extension and the server you set up.