It's my understanding that appearances more or less are tracked internally as either a struct or an object, and have a unique reference ID. Every time you change an atom's appearance, it checks the global appearance dictionary and looks to see if that unique combination of appearance values exists. If it doesn't exist, it creates a new appearance instance and communicates that appearance to connected clients.
Appearances seem to be refcounted just like any other object. They are immutable by default in DM, however. Attempting to locate() an appearance by it's reference gives you read-only access to the appearance.
I'm proposing that appearances finally be exposed to the developer for both direct (no-hack) reading and writing.
1) expose /appearance as a type to DM.
2) allow /appearance's variables to be modified. This would update the appearance object on the server and generate a network message.
This would modify the communication protocol to add a new message, which would communicate changes to appearance objects. This would basically be analogous to the existing appearance communication that's done to the client on a new appearance being sent in the first place, only instead of appending to the client's appearance dictionary, it would replace the old element.
3) finally, expose atom.appearance to DM, which gives you a direct reference to the atom's appearance object. This would simply be moving an existing field from the C side of things into the DM side of things, I'm assuming.
The benefits of this change to the server's appearance management would allow developers to implement global ambient lighting changes merely by changing a single appearance, rather than looping through hundreds of objects per connected player. This would also allow easy implementation of things like global season changes merely by looping over a much smaller number of appearances rather than potentially hundreds of thousands of objects.
Now, there are some potential complications: If you set an appearance to an identical appearance that's already in use, it could result in either duplicate appearances, or accidentally merging two appearances into one another. Those complications could be easily explained in the documentation, and could be easily designed around by the developer if they understood those complications. They might even be taken advantage of as "not bugs" (read: features) for interesting effects.
My suggestion for fixing those two bugs is to bring appearances in line with datums and give them a "tag" variable that counts as a part of its unique ID for indexing the appearances. That way, you can tag appearances you want to remain visually the same, but still have a single variable that remains different to avoid merging appearances you don't mean to.
And finally, here's a basic code example:
var
list/seasonal_appearances = list()
season = "summer"
proc
change_season(Season)
var/endl
for(var/appearance/a in seasonal_appearances)
endl = length(a.icon_state) - length(global.season)
if(endl)
a.icon_state = copytext(a.icon_state,1,endl) + Season
else
a.icon_state = Season
sleep(-1)
global.season = Season
season_ticker()
set waitfor = 0
sleep(6000)
change_season("fall")
sleep(6000)
change_season("winter")
sleep(6000)
change_season("spring")
sleep(6000)
change_season("summer")
spawn() season_ticker()
world
New()
season_ticker()
turf
seasonal
var
appearance_tag = null
New()
icon_state += season
appearance.tag = appearance_tag
var/val = seasonal_appearances[appearance]
if(val)
seasonal_appearances[appearance] = val+1
else
seasonal_appearances[appearance] = 1
Del()
var/val = seasonal_appearances[appearance]
if(val>1)
seasonal_appearances[appearance] = val-1
else
seasonal_appearances.Remove(appearance)
appearance.tag = null
This is of course, assuming that the client actually indexes resources according to their reference number (which it seems that they do), and the renderer seeks the file via an abstracted reference on render every frame during render.
For the webclient, you would swap the texture handles in OpenGL. Stage3D at some point should be storing and referencing a GL memory location for textures. Switch that around and you've got yourself a resource swap without updating every object that references the resource.
Mutable icons could be approached via a function: