Skip to content
Bucky Wolfe edited this page Aug 27, 2014 · 12 revisions

Storing Geospatial data

Use the player's sessionid as the key for a redis/ardb hash, store positional x/y/z and orientation heading/pitch/roll in their own respective keys within the hash. So you'd have something like:

hset session:d34db33f username Igneous
hset session:d34db33f steam_id STEAM_3451923_1
hset session:d34db33f pos_x 239414924493.34
hset session:d34db33f pos_y 394482411413.42
hset session:d34db33f pos_z 2503.11
hset session:d34db33f o_head 35.77
hset session:d34db33f o_pitch 55.13
hset session:d34db33f o_roll 12.40
hset session:d34db33f speed 120.41

This is represented as a bunch of hset calls for readability, but the appropriate redis call to make would actually be HMSET.

Handling Geospatial Player Resolution

One potential option for handling geospatial resolution would be to use ardb with eredis.

When a client sends us a position update, we could use ARDB's GeoAdd to store the player's X and Y coordinates, with a value of the player's sessionid (so we can ask redis to retrieve their real positional data)

After the client has sent us their positional data, we can use their member name (and respectively, their coordinates -- which were just added prior to this call) as the radius-center from which to execute an ARDB GeoSearch. We'd need to wrap this GeoSearch in a function (which I'll refer to as otmpd:get_nearby_players) that resolves real player position/orientation based on the sessionid value we set when the player was GeoAdded. After we've preformed the lookup, we'd resolve the real player locations, and send their positional updates back to the client.

One limitation with this approach is that GeoAdd doesn't appear to have any way to update data for existing records. If this assumption is accurate, we'll need to make otmpd:get_nearby_players aware that multiple records may exist for a player until the stale entries are pruned. Perhaps store GeoAdd "members" with a keyname of $sessionid@+%s%N and prune by splitting on @ and deleting all but the record with the highest timestamp. This filtering mechanism would be present in otmpd:get_nearby_players, but the actual db pruning should ideally be done through database key expiration. If this assumption is not possible, another feasible option would be to use a seperate erlang process, running a prune function, operating on a tight timer loop -- or even as a pub/sub queue subscription, so we could prune as soon as an entry is added.

Clone this wiki locally