ID:261149
 
Doesn't appear to work for me. Not sure if this is a code problem or a geniune BYOND bug, but I'm treating it as a code problem.

Basically, I want to save player preferences to a client side savefile, loading it at login. Eventually I'll have more than preferences in this savefile, but since I can only have one per client, I want to be ultra-safe and reload (Import) the savefile from disk just before saving back out in client.Del(). Maybe I'll forego that altogether if this doesn't end up working and just keep the savefile in memory while the player is logged in. But here's what I'm trying for now:

mob
Logout()
world.log << "[src].Logout()"
. = ..()

client
Del()
world.log << "Client [src].Del()"
// var/client_file
var/client_file = src.Import()
var/savefile/sf
if (client_file)
sf = new(client_file)
else
sf = new()
sf["/prefs/[src.ckey]"] << "prefs"
world.log << "[src] saving src.prefs in /prefs/[src.ckey]"
src.Export(sf)
del(sf)
. = ..()
world.log << "Called ..()"

Run this and type .logout, I get the following output:

Client Air Mapster.Del()
Air Mapster.Logout()
BYOND BUG: bad ref (5:0) in DecRefCount
Connection closed.


I really expected to see the messages about saving prefs and called ..() as well. If I comment out the line calling Import() and uncomment the other, I get something more like what I would expect:

Client Air Mapster.Del()
Air Mapster saving src.prefs in /prefs/airmapster
Called ..()
Air Mapster.Logout()
Connection closed.


So I thought perhaps the Import() call is taking more than one tick and by the time it's done, the client is already disconnected and deleted? If so, is there something I can do to get around that? And if not, could it be the noted BYOND BUG?
Air Mapster wrote:
Doesn't appear to work for me. Not sure if this is a code problem or a geniune BYOND bug, but I'm treating it as a code problem.

Looks like a bug to me. Help is on the way!
In general, sleeping operations will not work as expected in client.Del(). Whatever does not complete immediately is silently aborted when the client object is deleted (just like outstanding procs on all other types of objects) unless you explicitly set src to null in the proc. The BYOND BUG report you were getting was an error that has been fixed in this next upcoming release.

Even if you were to set src to null, it would obviously not help in this case, because you need to interact with the client object to do the Import()/Export(), both of which are sleeping operations, since they involve a network query + response.

In the future, client.Del() may be extended to handle sleeping operations. The reason it does not currently do so is that the client object can be deleted for several reasons, including unexpected network failures (which currently necessitate immediate deletion of the object). Technically, one should not assume that the client is even accessible via the network in client.Del().

To solve this, we need to add client.LogingOut() which would only get called before doing a graceful closure, rather than an abrupt network disconnection. It would allow you to do any last-minute interaction before the network connection is severed.

For the time being, you can accomplish the same thing by providing your own "quit" verb or similar mechanism allowing the user to gracefully disconnect. Or if your client-side data is rarely modified, you could just update it whenever it is changed.

--Dan
In response to Dan (#2)
Dan wrote:
Or if your client-side data is rarely modified, you could just update it whenever it is changed.

Thanks for the explanation, that's pretty much what I figured was going on. I think this strategy will work better for me in this case anyway - preferences only need to be saved when they are changed, which probably doesn't happen in every game session. Later, when I add automatic saving of the game state, I may have to revisit this problem, but I've got a few ideas that I can try.