Forum BigDB Need advice on server-side BigDB handling.

Discussion and help relating to the PlayerIO database solution, BigDB.

Need advice on server-side BigDB handling.

Postby AquamentosGames » July 7th, 2014, 6:24 am

I'm attempting to create a system that takes 4 keys and generates a map seed and properties based on those 4 keys. (For example - the initial tutorial world uses the keys "Aries", "Learners", "Factory", "Human")

These keys are all stored in their own DatabaseObjects in a table ("WorldWords").

I want to be able to take the keys, process their values and store the final result in a separate table ("Worlds") under the composite heading ("Aries Learners Factory Human") This way worlds can be dynamically created with new keys as players explore them, and destroyed if they haven't been accessed for a while (Anyone who has played .Hack may be somewhat familiar with the concept here.)

I'm having a couple of problems implementing this.
First of all, trying to call BigDB.Load() from the serverside gives me a message about needing an object reference for non-static property. I try to create an object reference using "new BigDB()" but it is an abstract class, so that doesn't work.

Secondly, since I cannot create static fields on the serverside, and the BigDB.Load uses a delegate system (rather than just letting me do something like DatabaseObject word=BigDB.Load()) I'm having trouble 'anchoring' the system to do what it needs to do once all the word are loaded.

I currently am trying to use a class with four variables (one for each key) and then call a method that loads each word four times and use a separate delegate for each one to a different method for each variable (I might condense this to one method and just use a string and a switch case) This feels very wonky and I'm not sure that it's the best way to do it, and I can't even test it because I can't get BigDB.Load() to work since it is non-static.

Any suggestions are appreciated.

EDIT - just in case it's not clear I want to do this server-side because I don't want players hacking the client and creating whatever values suit their fancy - which they could do if I were to load the objects in the client, process the values, then save them.

EDIT 2 - Aha! I'm so clever! I just realised that I can get my WorldSeed class to extend BigDB (probably not the most 'clean' solution, but it works for now) (Edit 3 - actually apparently that doesn't work because now I have to implement stuff because its an abstract class it implements it rather than extends it D: )

Still looking for tips on how I can do this and similar tasks in a better way - this feels very round-about.

BTW the "Multiplayer Reference" examples for BigDB should probably be changed to reflect the fact that it's not a static class. None of the examples work as written for server-side;
https://gamesnet.yahoo.com/documentatio ... rary.bigdb

Final Edit;
Here's what I'm looking at so far. I have no way of testing it still because I can't call BigDB.Load in any way that I've tried. Please let me know if I'm on the right track or completely out to lunch.
Code: Select all
class WorldSeedGenerator : BigDB
    {
        DatabaseObject signDO = null;
        DatabaseObject adjDO = null;
        DatabaseObject flexDO = null;
        DatabaseObject nounDO = null;
       
        void wordLoaded(string group, DatabaseObject val) {
            if (val == null) {
                //the BigDB.Load returned null.  Catch here because we can't check for null later as null is the initialization for our categories.
                //basically this means this word doesn't exist and we need to throw an error and abort this world generation.
            }
            switch (group)
            {
                case "Sign": signDO = val; break;
                case "Adj": adjDO = val; break;
                case "Flex": flexDO = val; break;
                case "Noun": nounDO = val; break;
                default: return; //invalid group.
            }

            if ((signDO !=null) && (adjDO !=null) && (flexDO != null) && (nounDO != null)){
                //combine everything
                Console.WriteLine("Seeds:  "+
                    signDO.GetLong("seed",0)+", "+
                    adjDO.GetLong("seed",0)+", "+
                    flexDO.GetLong("seed",0)+", "+
                    nounDO.GetLong("seed",0));
            }
       
        }

        public DatabaseObject constructWorldPhrase(string sign, string adj, string flex, string noun) {
            Console.Write("constructWorldPhrase:  "+sign+" "+adj+" "+flex+" "+noun);
            Load("WorldWords", sign, delegate(DatabaseObject val) { this.wordLoaded("Sign", val); });
            Load("WorldWords", adj, delegate(DatabaseObject val) { this.wordLoaded("Adj", val); });
            Load("WorldWords", flex, delegate(DatabaseObject val) { this.wordLoaded("Flex", val); });
            Load("WorldWords", noun, delegate(DatabaseObject val) { this.wordLoaded("Noun", val); });

            return null;
        }
    }
AquamentosGames
 
Posts: 27
Joined: December 9th, 2011, 12:44 am

Re: Need advice on server-side BigDB handling.

Postby AndyKerrison » July 7th, 2014, 11:34 am

I suspect where you're going wrong is that the BigDB is a property you can access via your 'Game' instance, not something you instantiate yourself.

So, from within your game class you can do this (as in the documentation)

Code: Select all
PlayerIO.BigDB.Load("test", "test", null);


But outside of that class you'll get the static reference error you've been getting. So you'll need to pass a reference to your game instance and do something like:

Code: Select all
myGame.PlayerIO.BigDB.Load("test", "test", null);
AndyKerrison
 
Posts: 14
Joined: November 29th, 2012, 9:24 am

Re: Need advice on server-side BigDB handling.

Postby AquamentosGames » July 7th, 2014, 2:01 pm

Thanks for that (and while I slept on it I actually figured it might be the case - the same thing happens with MonoBehaviour in Unity). This code does what I want it to do. Still unsure if it's the 'best' way to do it, but working code is working :D.

Code: Select all
class WorldSeedGenerator
    {
        World gameInstance; //the initializing game instance - needed for Player.IO functionality.

        DatabaseObject signDO = null;
        DatabaseObject adjDO = null;
        DatabaseObject flexDO = null;
        DatabaseObject nounDO = null;
       
        void wordLoaded(string group, DatabaseObject val) {
            if (val == null) {
                //the BigDB.Load returned null.  Catch here because we can't check for null later as null is the initialization for our categories.
                //basically this means this word doesn't exist and we need to throw an error and abort this world generation.
            }
            switch (group)
            {
                case "Sign": signDO = val; break;
                case "Adj": adjDO = val; break;
                case "Flex": flexDO = val; break;
                case "Noun": nounDO = val; break;
                default: return; //invalid group.
            }

            if ((signDO !=null) && (adjDO !=null) && (flexDO != null) && (nounDO != null)){
                //combine everything
                string testDist = "Seeds:  "+
                    signDO.GetUInt("seed",0)+", "+
                    adjDO.GetUInt("seed", 0) + ", " +
                    flexDO.GetUInt("seed", 0) + ", " +
                    nounDO.GetUInt("seed", 0);
                gameInstance.Broadcast(testDist);


            }
       
        }
       
        public DatabaseObject constructWorldPhrase(World __game, string __sign, string __adj, string __flex, string __noun) {

            gameInstance = __game;

            Console.Write("constructWorldPhrase:  "+__sign+" "+__adj+" "+__flex+" "+__noun);
            gameInstance.PlayerIO.BigDB.Load("WorldWords", __sign, delegate(DatabaseObject val) { this.wordLoaded("Sign", val); });
            gameInstance.PlayerIO.BigDB.Load("WorldWords", __adj, delegate(DatabaseObject val) { this.wordLoaded("Adj", val); });
            gameInstance.PlayerIO.BigDB.Load("WorldWords", __flex, delegate(DatabaseObject val) { this.wordLoaded("Flex", val); });
            gameInstance.PlayerIO.BigDB.Load("WorldWords", __noun, delegate(DatabaseObject val) { this.wordLoaded("Noun", val); });

            return null;
        }
    }


Code: Select all
Input (from client, for testing debugging);
  mess = Message.Create("createWorld");
  mess.Add ("Aries");
  mess.Add ("Learners");
  mess.Add ("Factory");
  mess.Add ("Human");
  value.Send(mess);

  mess = Message.Create("createWorld");
  mess.Add ("Taurus");
  mess.Add ("Learners");
  mess.Add ("Factory");
  mess.Add ("Dwarf");
  value.Send(mess);

  mess = Message.Create("createWorld");
  mess.Add ("Libra");
  mess.Add ("Learners");
  mess.Add ("Factory");
  mess.Add ("Elf");
  value.Send(mess);

Output (in order received)
msg.Type= Seeds:  2, 1, 2, 5, 0 entries (This is correct for Taurus Learners Factory Dwarf)
msg.Type= Seeds:  64, 1, 2, 4, 0 entries (This is correct for Libra Learners Factory Elf)
msg.Type= Seeds:  1, 1, 2, 3, 0 entries (This is correct for Aries Learners Factory Human)


An interesting thing for me to be aware of - the messages did not come back in the same order I sent them (due to asynchronous BigDB handling and delegate() stuff.) However that's perfectly acceptable. These return values were for testing purposes - I now intend to create the world values and store them in a separate Table.
AquamentosGames
 
Posts: 27
Joined: December 9th, 2011, 12:44 am

Re: Need advice on server-side BigDB handling.

Postby Henrik » July 13th, 2014, 8:55 pm

Instead of four separate calls to Load, and four separate delegates, you should use the LoadKeys method:

https://gamesnet.yahoo.com/documentatio ... b#LoadKeys

Code: Select all
LoadKeys("WorldWords",
    new string[]{ "sign", "adj", "flex", "noun" },
    delegate(DatabaseObject[] result) {
        signDO = result[0];
        adjDO = result[1];
        flexDO = result[2];
        nounDO = result[3];
        //...or whatever you wanted to do when you had all four objects loaded...
    },
    delegate(PlayerIOError error) {
        //Something went wrong
    });
Henrik
.IO
 
Posts: 1880
Joined: January 4th, 2010, 1:53 pm

Re: Need advice on server-side BigDB handling.

Postby AquamentosGames » July 18th, 2014, 8:36 pm

Thanks, Henrick. I actually figured that out a few days after my last post, but didn't feel the need to correct myself. LoadKeys definitely sped the whole thing up and made it less complicated.

I also wound up using an enum so that I knew which value in the array was which and it worked like a charm.

posting what I'm now using in case it helps others;

Code: Select all
enum valOrder{
            Sign,
            Adj,
            Flex,
            Noun,
            Fire,
            Earth,
            Air,
            Water,
            Cardinal,
            Fixed,
            Muteable
}

void wordsLoaded(DatabaseObject[] vals){
            string group;
            foreach (valOrder vo in Enum.GetValues(typeof(valOrder)))
            {
                group = vo.ToString();
                DatabaseObject val = vals[(int)vo];
                //Console.WriteLine(vo.toString()+": "+val);
                if (val == null)
                {
                 //handle case where the database object doesn't exist
               } else {
                 // do stuff with it
              }
}

public override void process(){
        gameInstance.PlayerIO.BigDB.LoadKeys(
                    "WorldWords",
                    new string[]{_sign, _adj, _flex, _noun,
                    "Fire", "Earth","Air","Water",
                    "Cardinal","Fixed","Muteable"},
                    this.wordsLoaded
                    );
}
AquamentosGames
 
Posts: 27
Joined: December 9th, 2011, 12:44 am


Return to BigDB



cron