Page 1 of 1

Implementing persistent inventory for 1.3

Posted: Sat Oct 11, 2014 12:42 pm
by haxmurderer
Hi guys,

With Zandronum 1.3 out, I think it should be possible to implement a persistent inventory system in ACS. (Konda's coop stats mod does this in 1.2 but doesn't save across server restarts.)

I'm going to start working on this for my Survivalism mod, but before I write some code I figured I'd ask and see if anyone had any ideas about how to approach it. AFAIK the only documentation for the new database functions is the changelog that Torr posted, along with the actual Zandronum source code.

Anyways, the simplest approach I can think of is using:

Code: Select all

        void SetDBEntry ( string Namespace, string Key, int Value )
        int GetDBEntry ( string Namespace, string Key )
Pseudocode:

Code: Select all

On player disconnect:
   str persistentInventory[10] = { "Clip", "Rocket", "Shotgun", "SuperShotgun", etc... }
   for (int i = 0; i < 10; i++) {
       SetDBEntry(PlayerName + "_inventory", persistentInventory[i], GetActorInventory(playerTid, persistentInventory[i]));
   }

When a player reconnects:

   for (int i = 0; i < 10; i++) {
       GiveActorInventory(playerTid, GetDBEntry(PlayerName + "_inventory", persistentInventory[i]));
   }

Thoughts? Any obvious problems with this approach?

I think the hardcoded list of inventory items to save is probably necessary since I don't think you can iterate over all inventory items in ACS. Also, it has the advantage that you won't be serializing dummy inventory items...

Thanks!
Hax

RE: Implementing persistent inventory for 1.3

Posted: Sat Oct 11, 2014 1:28 pm
by Watermelon
Good ideas for a first start! However I don't recommend doing the player's name, because someone can spoof in as their name and mess with their inventory.

There's three ways to go about this.


1) Use the account system if available:
This way you know the person is who they say they are. Since this is not streamlined yet, this might not be an option right now.


2) Send them a randomly generated number:
Another option is to generate a random number (make sure compat_oldrandom is not on) and store this on the client. I am unsure if this is possible since it would use console command... which might be phased out.
You are also hoping that two people don't generate the same ID (which is unliked since there's maybe ~1000 doom players, and having one of those match 4.2 billion numbers is pretty low). If you wanted to take it further, you can store more than 1 number... like two random numbers instead (making it 2^63 or 2^64 I think, which is some massive number)


3) Since #2 might not even be optional anymore, the next best way is to append things onto the name
Using http://zdoom.org/wiki/GetPlayerInfo
Append to the name some values that you hope don't change (ex: movebob, gender, aimdistance, color... etc)

Example: "playername_gendernumber_aimdistance_color_movebob" might come out as "water_1_123_8319723_68888"

That way if someone tries to spoof someone's name, the chances they have the same settings are lower.

Hope that helps.

RE: Implementing persistent inventory for 1.3

Posted: Sat Oct 11, 2014 6:25 pm
by Ijon Tichy
Watermelon wrote: 2) Send them a randomly generated number:
Another option is to generate a random number (make sure compat_oldrandom is not on) and store this on the client. I am unsure if this is possible since it would use console command... which might be phased out.
You are also hoping that two people don't generate the same ID (which is unliked since there's maybe ~1000 doom players, and having one of those match 4.2 billion numbers is pretty low). If you wanted to take it further, you can store more than 1 number... like two random numbers instead (making it 2^63 or 2^64 I think, which is some massive number)
One problem with this. When a server starts or does a map command, the RNG is set to a predictable state, so unless you specifically build in code to read from a CVar or DB entry and 'seed' it (by calling random() a lot), you get the same random numbers every time.

a tracker entry for the bug
(it does not require mm8bdm to see it. hangman will demonstrate it with its word generation, for example)

RE: Implementing persistent inventory for 1.3

Posted: Sat Oct 11, 2014 6:46 pm
by Konar6
I would say 1) is the way to go. This is exactly why the accounts were implemented.

3) is really bad because it depends on user preferences that tend to change. Even on the fly.

RE: Implementing persistent inventory for 1.3

Posted: Sat Oct 11, 2014 7:09 pm
by Watermelon
Since 3 is a bad example because of ^ reasons, I've assigned myself tracker ticket posted previously and waiting on Torr's response. That should be fixed ASAP.

RE: Implementing persistent inventory for 1.3

Posted: Sat Oct 11, 2014 8:52 pm
by haxmurderer
Right, I forgot to mention I'd definitely use the account system to get the player name!

Soooooo.... I have an implementation based on my pseudocode above that works! I'm going to upload a new version of Survivalism later today or tomorrow and we'll see if there's any other gotchas that happen during testing. I'll share the code here once I know it works (it's in the WAD though anyways). However, there's a couple things I've noticed so far:

1) The sqlite database writes seem A) slow and B) done in the same thread as the playsim, so the server kinda lags out for a split second when a save is happening. This is when using a file-based database, of course.
2) In a DISCONNECT script, the player is already gone (according to the wiki, at least), so you can't actually access their inventory and do something like automatic saving. To workaround this, I've given the player a way to manually save their inventory (via a menu).

Lastly, another super awesome possibility about this is that multiple servers can share a single database, so you could do something crazy like expand the Survivalism game world across 3 servers running 3 different maps, where only certain resources or items are available in each map. :D

RE: Implementing persistent inventory for 1.3

Posted: Sat Oct 11, 2014 9:17 pm
by Watermelon
haxmurderer wrote: Right, I forgot to mention I'd definitely use the account system to get the player name!

Soooooo.... I have an implementation based on my pseudocode above that works! I'm going to upload a new version of Survivalism later today or tomorrow and we'll see if there's any other gotchas that happen during testing. I'll share the code here once I know it works (it's in the WAD though anyways). However, there's a couple things I've noticed so far:

1) The sqlite database writes seem A) slow and B) done in the same thread as the playsim, so the server kinda lags out for a split second when a save is happening. This is when using a file-based database, of course.
2) In a DISCONNECT script, the player is already gone (according to the wiki, at least), so you can't actually access their inventory and do something like automatic saving. To workaround this, I've given the player a way to manually save their inventory (via a menu).

Lastly, another super awesome possibility about this is that multiple servers can share a single database, so you could do something crazy like expand the Survivalism game world across 3 servers running 3 different maps, where only certain resources or items are available in each map. :D

If there's lag in game due to DB writing, consider posting that on the tracker. I don't recall anyone having lag issues yet (I assume your computer is not old?)

RE: Implementing persistent inventory for 1.3

Posted: Sun Oct 12, 2014 5:04 pm
by Torr Samaho
haxmurderer wrote: Lastly, another super awesome possibility about this is that multiple servers can share a single database, so you could do something crazy like expand the Survivalism game world across 3 servers running 3 different maps, where only certain resources or items are available in each map. :D
If the servers run on the same machine, they should already be able to share the same db.

EDIT:
haxmurderer wrote: 2) In a DISCONNECT script, the player is already gone (according to the wiki, at least), so you can't actually access their inventory and do something like automatic saving. To workaround this, I've given the player a way to manually save their inventory (via a menu).
I checked the code and think the current behavior is inconsistent: When the player leaves the game by turning into a spectator, the inventory is still there when the DISCONNECT script is called. When the player immediately leaves, the inventory is already gone when the DISCONNECT script is called. If you create a tracker ticket including a minimal example wad that demonstrates the inconsistency, I'll take care of this.

RE: Implementing persistent inventory for 1.3

Posted: Sun Oct 12, 2014 5:14 pm
by Hypnotoad
Just a warning that you need to be careful with saving armor due to a problem I identified here: http://zandronum.com/tracker/view.php?id=1852

RE: Implementing persistent inventory for 1.3

Posted: Sun Oct 12, 2014 5:19 pm
by Watermelon
Hypnotoad wrote: Just a warning that you need to be careful with saving armor due to a problem I identified here: http://zandronum.com/tracker/view.php?id=1852
I'm going to look into that