Pushing an Array of Tables to Lua From Java Plugin

@TheBrooster  I have a few more items I am trying to clean up in the plugin and then I will just attach the source to this forum for anyone who wants it.  If you want to share your ads implementation privately you can reach me via admin@cluckeyetea.com.  No hurry.  It will be at least Sunday before I am ready to post my plugin.

I’ve been scouring the web for a couple days now but haven’t been able to
get it worked out. I made some good headway thanks the link @TheBrooster
shared.  I’ve got event, response, leaderboard, count, and desc going.

But now I am trying to nest an array of tables called score and I’m still not quite there. 

My goal is to return a response to the lua program that looks something like
this:

{event { response { leaderboard { desc = “xyz”, count = 2, scores{ {alias =
“player1”, score = 200}, {alias=“player2”, score=100} }}}}}}

But the nested tables are killing me. This is what I have right now.

if (eventType.equals(EVENT_TYPE_GET_ALL_SCORES_FROM_LEADERBOARD)) {
        luaState.newTable(0, 4);
        int idx = luaState.getTop();
        luaState.pushString(“leaderboard”);
        luaState.setField(idx, “name”);
        Leaderboard leaderboard = ((GetScoresResponse)result).getLeaderboard();
        String leaderboardName = leaderboard.getDisplayText();
        luaState.pushString(leaderboardName);
        luaState.setField(idx, “desc”);
        int num = ((GetScoresResponse)result).getNumScores();
        luaState.pushNumber(num);
        luaState.setField(idx, “count”);
        List<Score> scores = ((GetScoresResponse)result).getScores();
        luaState.newTable(0, scores.size()+1);
        int scoresIdx = luaState.getTop();
        luaState.pushString(“scores”);
        luaState.setField(scoresIdx, “name”);
        int i = 0;
        for (Score score : scores){
            luaState.newTable(0, 5);
            int innerIdx = luaState.getTop();
            Player player = score.getPlayer();
            String alias = player.getAlias();
            String id = player.getPlayerId();
            int rank = score.getRank();
            long points = score.getScoreValue();
            luaState.pushString(alias);
            luaState.setField(innerIdx, “alias”);
            luaState.pushString(id);
            luaState.setField(innerIdx, “id”);
            luaState.pushNumber(rank);
            luaState.setField(innerIdx, “rank”);
            luaState.pushNumber(points);
            luaState.setField(innerIdx, “score”);
            i++;
            luaState.pushInteger(i);
            luaState.setField(innerIdx, “name”);
        }
        luaState.setField(-2, CoronaLuaEvent.RESPONSE_KEY);
}
CoronaLua.dispatchEvent(luaState, amazonGamesClientListener, 0);

Clearly I just don’t understand how the LuaState stack works here but in my
defense I’ve failed to find any documentation on the website or in the
folders of the SDK demo I am working with. Thanks for any help anyone can spare. 

As I posted previously once I have the GC code all cleaned up I plan to attach it

to this thread for any other Enterprise users who could make use of it.

I’m currently on vacation but am returning home over the weekend. I’ll take a look then

Had a VERY quick look … are you not missing calls to settable after you push your variables?

luaState.pushString(alias);
luaState.setField(innerIdx, “alias”);
luaState.pushString(id);.
…HERE…

http://docs.coronalabs.com/daily/native/android/html/com/naef/jnlua/LuaState.html#setTable(int

@TheBrooster  I appreciate you taking a closer look when you have minute.  I am absolutely sure you are right about me missing a set table call.  But even with the java docs I am just guessing as to how this works.  I’m not able to visualize what this lua stack looks like so I don’t have any good idea what methods should get called when.

Trying to copy the document you linked me to earlier, I was successful in returning a single table like this:

if (eventType.equals(EVENT_TYPE_GET_YOUR_SCORE_FROM_LEADERBOARD)) {

     GetPlayerScoreResponse player = (GetPlayerScoreResponse) result;

     luaState.newTable(0, 3);

     int idx = luaState.getTop();

     luaState.pushString(“local_player”);

     luaState.setField(idx, “name”);

     luaState.pushNumber(player.getScoreValue());

     luaState.setField(idx, “score”);

     luaState.pushNumber(player.getRank());

     luaState.setField(idx, “rank”);

     luaState.setField(-2, CoronaLuaEvent.RESPONSE_KEY);

}

 

The result in my LUA app is {event.response{score=100, rank=1}}  But honestly it was more trial and error than anything.  I’d love to see Corona write a tutorial on how this works that goes beyond the java doc annotations.  I will continue plugging away at it as I get a chance over the weekend and will keep an eye out in case you find some time to show me the light :slight_smile:

Give me until Monday to respond…I am travelling from Tunisia back to the UK tomorrow.

If you reply to this message tomorrow, i will get a notification and will be back at my computer and will post up an example for you.

FYI: http://www.lua.org/pil/24.2.html

As promised, here is an example:

// Event task private static class LuaCallBackListenerTask implements CoronaRuntimeTask&nbsp; { &nbsp; &nbsp; private int fLuaListenerRegistryId; &nbsp; &nbsp; private String fPhase = null; &nbsp; &nbsp; &nbsp; public LuaCallBackListenerTask( int luaListenerRegistryId, String phase )&nbsp; &nbsp; &nbsp; { &nbsp; &nbsp; &nbsp; &nbsp; fLuaListenerRegistryId = luaListenerRegistryId; &nbsp; &nbsp; &nbsp; &nbsp; fPhase = phase; &nbsp; &nbsp; } &nbsp; &nbsp; &nbsp; @Override &nbsp; &nbsp; public void executeUsing( CoronaRuntime runtime ) &nbsp; &nbsp; { &nbsp; &nbsp; &nbsp; &nbsp; try&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; { &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; // Fetch the Corona runtime's Lua state. &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; final LuaState L = runtime.getLuaState(); &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; // Dispatch the lua callback &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; if ( CoronaLua.REFNIL != fLuaListenerRegistryId )&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; { &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; // Create event table &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; L.newTable(); &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; // Create event.data table &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; L.newTable(); &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; // Key/Value pair &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; L.pushString( "Hello" ); // Value &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; L.setField( -2, "personName" ); // Key &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; // Another Key/Value pair &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; L.pushNumber( 28 ); // Value &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; L.setField( -2, "age" ); // Key &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; // Set data table - this becomes event.data from the Lua side (with key value pairs of personName and age, defined above) &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; L.setField( -2, "data" ); &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; // Event name - this is set on the outer table &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; L.pushString( "myEventName" ); // Value &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; L.setField( -2, "name" ); // Key &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; // Event Type - this is set on the outer table &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; L.pushString( "myEventType" ); // Value &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; L.setField( -2, "type" ); // Key &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; // Event Phase - this is set on the outer table &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; L.pushString( fPhase ); // Value &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; L.setField( -2, "phase" ); // Key &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; // Dispatch the event &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; CoronaLua.dispatchEvent( L, fLuaListenerRegistryId, 1 ); &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; } &nbsp; &nbsp; &nbsp; &nbsp; } &nbsp; &nbsp; &nbsp; &nbsp; catch ( Exception ex )&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; { &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ex.printStackTrace(); &nbsp; &nbsp; &nbsp; &nbsp; } &nbsp; &nbsp; } }

@TheBrooster & Gremlin Interactive --> You guys are awesome.

Here is a zip of my GC plugin.  It is implemented inside the default Corona Enterprise template structure.  The main.lua file acts as a container to test out the functionality.  It is not all inclusive by any means but I have all the leaderboard and achievement functionality is in place that I require for my current Kindle Fire project.  I haven’t done a whole lot of testing at this point so expect to run into some bugs along the way.

If you want to pull down the source I’ve uploaded it here for the time being: http://www.thingerjiggy.com/downloads/AGC.zip

If it makes since at some point I can make it into a bitbucket repo but right now I just need to get it into my own project and back on schedule to meet my commitments.  Thanks again everyone for helping me out with this.

Glad to hear it is all up and running. I am now back at work, I’ill take a look at the plugin after I have caught up on things here, probably first thing next week.

Nice one!