Jump to content

My newbie approach to Persistent Database nightmares


Loki Eliot
 Share

You are about to reply to a thread that has been inactive for 2713 days.

Please take a moment to consider if this thread is worth bumping.

Recommended Posts

This is basically me typing out a lot of crazythinking

It's taking me FOR EVER to get my head around the Persistant Data Base thing. It's like every time i consider a situation thats deserving of being stored on the Persistant Data Base, i come across scary complexities that confound me.

Ok lets see, where to start...

I've worked out that each XP key has one database that you can create storage 'Keys' with one 'Value'. i figures a scenario for storing Points/Scores.

• Create 'Key' that is the users UUID with a 'Value' that is the score.

From here i thought what if i want to have a score and a levelup, well since i cant have more than one Value for a key, that value would have to be a JSON string something like "Score":1 , "LevelUp":1.

But of course i cant stop there, what if i wanted collected inventory items? The JSON String would end up being like  "Score":1 , "LevelUp":1,"Collected":["sword","shield","pocketwatch","pogostick"]

So am i right in understanding that ever time a player scored a point, leveled up or collected an item, this one JSON string would need updating to the database?

Now comes the kicker. I have my little experience on Escapades Island, but i also want to create an experience in New Babbage City and Vortex Cyberpunk street. We only get one XP key each though, which means the database gets shared between all three experiences. That means each Users UUID key entry to the database is shared, so the JSON string would need to list scores, levels and items from all three experiences AHHHHhh... BRAIn having catastrophic failure. ......... ..

Perhaps i could prefix the Users UUID with a word relating to the different experiences. This would mean each user would have 3 database Key entries associated with them but would be more managable.

I'm hopeing my ramblings actually do add up. I find the database stuff extemly complex i just hope that im on the right track. :)

Link to comment
Share on other sites

You're on the right track, you can also create conventions like these to have multiple keys per avatar, for multiple applications:

llCreateKeyValue("escapades 6573ac05-05cc-47c6-9f41-6e65f55b0d2c score", "12345");
llCreateKeyValue("escapades 6573ac05-05cc-47c6-9f41-6e65f55b0d2c level", "1");
llCreateKeyValue("escapades 6573ac05-05cc-47c6-9f41-6e65f55b0d2c inventory", "sword,shield");

llCreateKeyValue("newbabbagecity 6573ac05-05cc-47c6-9f41-6e65f55b0d2c score", "67890");
llCreateKeyValue("newbabbagecity 6573ac05-05cc-47c6-9f41-6e65f55b0d2c level", "2");
llCreateKeyValue("newbabbagecity 6573ac05-05cc-47c6-9f41-6e65f55b0d2c inventory", "pocketwatch,pogostick");

Your original plan to use one JSON string per experience would be a lot more manageable though, if you ever need to change the keys.  It seems like it would be a nightmare to maintain the data otherwise.  You could have a HUD or other attachment get the stored JSON string when someone returns, and let it keep track of everything, and then only store the data again at intervals.  So you seem to have a good plan if you're already thinking about doing something like this:

llCreateKeyValue("escapades 6573ac05-05cc-47c6-9f41-6e65f55b0d2c", "{'score':'12345', 'level':'1', 'inventory':'sword,shield'}");

llCreateKeyValue("newbabbagecity 6573ac05-05cc-47c6-9f41-6e65f55b0d2c", "{'score':'67890', 'level':'2', 'inventory':'pocketwatch,pogostick'}");

  • Like 2
Link to comment
Share on other sites

Ok yeh, so in setup this seems like a  great idea untill i start thinking about how each little thing gets updated. 

To start with llUpdateKeyValue requires me to name the entire JSON string that i want to update , so for example leveling up would be something like

llUpdateKeyValue("escapades 6573ac05-05cc-47c6-9f41-6e65f55b0d2c", "{'score':'12345', 'level':'1', 'inventory':'sword,shield'}", TRUE, "{'score':'12345', 'level’:’2’, 'inventory':'sword,shield'}");  

i'd have to make a central control program that collects all the HUDS current inventory, score and level up data into one JSON string, then read the current Database key Value in order to create the line of script above that would update the users data.

Link to comment
Share on other sites

I find this so mind numbingly hard. So im trying to set up a 'simple' test where an item gets added to a stored JSON string via a central manager.

 

The XP Persistant Data base

I have set up a Database Key 'COLOR' with the starting value '[ ]' 

 

The Orange box 

The box when clicked simply tells the Central Manager it has collected the colour ORANGE.

default{    touch_start(integer total_number)    {      llWhisper(-77, "orange");      llSay(0, "sending message");    }}

 

 

The Central Control Box

The Central Control receieves the message 'orange' from the Orange Box then starts the process of retrieving the current Value from the Database Key COLOR which is '[ ]'

It then appends the value to '[ORANGE] before attempting to update the key value to the persistant database. 

 

 

key trans;key transupdate;string value;string output;string append;string oldkey;default{    state_entry()    {      llListen( -77, "", NULL_KEY, "" );    }    touch_start(integer total_number)    {        trans = llReadKeyValue("COLOR");    }        listen(integer chan, string name, key id, string msg)    {          append = msg;
trans = llReadKeyValue("COLOR"); }dataserver(key t, string value) { if (t == trans) { // our llReadKeyValue transaction is done if (llGetSubString(value, 0, 0) == "1") { // the key-value pair was successfully read llSay(0, "Key Value is " + llGetSubString(value, 2, -1)); oldkey = llGetSubString(value, 2, -1); output = llJsonSetValue(value, [JSON_APPEND], append); llSay(0, "New Value is " + output); llSay(0, "old Value is " + oldkey); transupdate = llUpdateKeyValue("COLOR", oldkey, TRUE, output); } else { // the key-value pair failed to read integer error = (integer)llGetSubString(value, 2, -1); llSay(0, "Key-value failed to read: " + llGetExperienceErrorMessage(error)); } } if (t == transupdate) { value = oldkey; llSay(0, "Update old Value is " + value); llSay(0, "Update New Value is " + output); // our llUpdateKeyValue transaction is done list result = llCSV2List(value); if (llList2Integer(result, 0) == 1) { // the key-value pair was successfully updated llSay(0, "ey-value successfully updated"); } else { integer error = llList2Integer(result, 1); if(error == XP_ERROR_RETRY_UPDATE) llSay(0, "Key-value update failed, checked value is out of date"); else llSay(0, "Key-value update failed: " + llGetExperienceErrorMessage(error) ); } } }}

It all seems to work as planned. The Central Control recieves current Key Value [ ], appends it to [ORANGE] but at the very end it fails to update resulting in the error message that there is 'no error'.

[05:13] MCP: Hello Orange
[05:13] MCP: Key Value is []
[05:13] MCP: New Value is ["ORANGE"]
[05:13] MCP: old Value is []
[05:13] MCP: Update old Value is []
[05:13] MCP: Update New Value is ["ORANGE"]
[05:13] MCP: Key-value update failed: no error

 Upon reading the current Key Value the update confirms as having failed. Is there somethign claringly obvious that i havent done or am doing thats not allowing the update to happen?

Link to comment
Share on other sites

So after a cup of tea litrally a few minutes after i posted the above post, i realised 'oldkey' and 'output' where the wrogn way around. So it was trying to update with an identical string while being unable to confirm the current value.

transupdate = llUpdateKeyValue("COLOR", oldkey, TRUE, output);

 

Correcting allowed the Database to be updated correctly, yet i still got the error message 'Key-value update failed: no error'

 transupdate = llUpdateKeyValue("COLOR", output, TRUE, oldkey);

So onwards we go.....

Link to comment
Share on other sites

Thanx to Clara Niosaki for helping me add a checker to make sure Colours were not recorded multiple times. So the Central Control now gets the current Database Value then checks the colour that was clicked against the JSON list from the database, if not there it will append the list and update the database with the appended JSON list.

dataserver(key t, string value)    {        if (t == trans)        {            // our llReadKeyValue transaction is done          if (llGetSubString(value, 0, 0) == "1")            {
oldkey = llGetSubString(value, 2, -1); if (~llSubStringIndex(oldkey,append)) { llSay(0, append + " already in list"); } else { output = llJsonSetValue(oldkey, [JSON_APPEND], append); transupdate = llUpdateKeyValue("COLOR", output, TRUE, oldkey); } } else { // the key-value pair failed to read integer error = (integer)llGetSubString(value, 2, -1); llSay(0, "Key-value failed to read: " + llGetExperienceErrorMessage(error)); } }
Link to comment
Share on other sites

You are about to reply to a thread that has been inactive for 2713 days.

Please take a moment to consider if this thread is worth bumping.

Please sign in to comment

You will be able to leave a comment after signing in



Sign In Now
 Share

×
×
  • Create New...