ID:837654
 
BYOND Version:494
Operating System:Windows 7 Home Premium
Web Browser:Chrome 19.0.1084.56
Applies to:Dream Daemon
Status: Unverified

Thus far we've been unable to verify or reproduce this bug. Or, it has been observed but it cannot be triggered with a reliable test case. You can help us out by editing your report or adding a comment with more information.
Descriptive Problem Summary:
I have code in my game that affects the color of turfs upon their creation, based upon the area that the turfs occupy.

For me when I'm playing locally on my desktop and testing they work fine, but when I host the game and allow others to play, they login and see nothing but black space where the grass should be.
Upon having this pointed out to me I tested it, and it seems that it only occurs when connecting using Dream Daemon. It's rather inconvenient since I have one grass turf that the colors get changed to 5-6 times throughout my project for different areas of the game.

Logging out and logging back in seems to fix this problem, but after posting on the forum to no avail and asking around I can't really track down an issue or way to fix this. Thus I'm thinking it may be something that might need to be fixed by the Byond Gurus.

Numbered Steps to Reproduce Problem:

Code Snippet (if applicable) to Reproduce Problem:
ChangeC(var/seccolor,var/xx,var/yy)
var/icon/hx=new(icon)
var/currcolor=hx.GetPixel(xx,yy,icon_state,0,1,0)
hx.SwapColor(currcolor,seccolor)
src.icon=hx
grass
New()//,,
var/area/A=src.loc
if(A)
switch(A.bgset)
if("cave")//20,186,82-12,110,48
ChangeC(rgb(30,104,0),1,1)//dark
ChangeC(rgb(39,125,0),2,2)//med
ChangeC(rgb(57,181,0),5,6)//light
if("volcano")
ChangeC(rgb(84,87,34),1,1)//dark
ChangeC(rgb(106,117,43),2,2)//med
ChangeC(rgb(120,156,99),5,6)//light
if("swamp")
ChangeC(rgb(72,110,85),1,1)//dark
ChangeC(rgb(113,150,126),2,2)//med
ChangeC(rgb(140,186,156),5,6)//light
..()
icon_state="grass"



densegrass
New()//,,
var/area/A=src.loc
if(A)
switch(A.bgset)
if("cave")
ChangeC(rgb(46,54,0),1,1)//light
ChangeC(rgb(55,79,0),2,2)//med
ChangeC(rgb(56,105,0),5,6)//dark
if("volcano")
ChangeC(rgb(84,87,34),1,1)//dark
ChangeC(rgb(106,117,43),2,2)//med
ChangeC(rgb(120,156,99),5,6)//light
if("swamp")
ChangeC(rgb(72,110,85),1,1)//light
ChangeC(rgb(113,150,126),2,2)//med
ChangeC(rgb(140,186,156),5,6)//dark
..()
icon_state="grass"
density=1



stillgrass
New()//,,
var/area/A=src.loc
if(A)
switch(A.bgset)
if("cave")
ChangeC(rgb(46,54,0),1,1)//light
ChangeC(rgb(55,79,0),2,2)//med
ChangeC(rgb(56,105,0),5,6)//dark
if("volcano")
ChangeC(rgb(84,87,34),1,1)//dark
ChangeC(rgb(106,117,43),2,2)//med
ChangeC(rgb(120,156,99),5,6)//light
if("swamp")
ChangeC(rgb(72,110,85),1,1)//light
ChangeC(rgb(113,150,126),2,2)//med
ChangeC(rgb(140,186,156),5,6)//dark
..()
icon_state="stillgrass"

//---
medgrass
New()//,,
var/area/A=src.loc
if(A)
switch(A.bgset)
if("cave")
ChangeC(rgb(30,104,0),1,1)//dark
ChangeC(rgb(39,125,0),4,3)//med
ChangeC(rgb(57,181,0),4,10)//light
if("volcano")
ChangeC(rgb(84,87,34),1,1)//dark
ChangeC(rgb(106,117,43),4,3)//med
ChangeC(rgb(120,156,99),4,10)//light
if("swamp")
ChangeC(rgb(140,186,156),4,10)//light
ChangeC(rgb(113,150,126),4,3)//med
ChangeC(rgb(72,110,85),1,1)//dark
..()
icon='Props.dmi'
icon_state="medgrass"

medstillgrass
New()//,,
var/area/A=src.loc
if(A)
switch(A.bgset)
if("cave")
ChangeC(rgb(30,104,0),1,1)//dark
ChangeC(rgb(39,125,0),4,3)//med
ChangeC(rgb(57,181,0),4,10)//light
if("volcano")
ChangeC(rgb(84,87,34),1,1)//dark
ChangeC(rgb(106,117,43),4,3)//med
ChangeC(rgb(120,156,99),4,10)//light
if("swamp")
ChangeC(rgb(140,186,156),4,10)//light
ChangeC(rgb(113,150,126),4,3)//med
ChangeC(rgb(72,110,85),1,1)//dark
..()
icon='Props.dmi'
icon_state="medstillgrass"




//---
tallgrass
New()//,,
var/area/A=src.loc
if(A)
switch(A.bgset)
if("cave")
ChangeC(rgb(30,104,0),1,13)//dark
ChangeC(rgb(39,125,0),5,16)//med
ChangeC(rgb(57,181,0),2,37)//light
//----------
if("volcano")
ChangeC(rgb(84,87,34),1,13)//dark
ChangeC(rgb(106,117,43),5,16)//med
ChangeC(rgb(120,156,99),2,37)//light
if("swamp")
ChangeC(rgb(140,186,156),2,37)//light
ChangeC(rgb(113,150,126),5,16)//med
ChangeC(rgb(72,110,85),1,13)//dark

..()
icon='Props.dmi'
icon_state="tallgrass"

tallstillgrass
New()//,,
var/area/A=src.loc
if(A)
switch(A.bgset)
if("cave")
ChangeC(rgb(30,104,0),1,13)//dark
ChangeC(rgb(39,125,0),5,16)//med
ChangeC(rgb(57,181,0),2,37)//light
if("volcano")
ChangeC(rgb(84,87,34),1,13)//dark
ChangeC(rgb(106,117,43),5,16)//med
ChangeC(rgb(120,156,99),2,37)//light
if("swamp")
ChangeC(rgb(140,186,156),2,37)//light
ChangeC(rgb(113,150,126),5,16)//med
ChangeC(rgb(72,110,85),1,13)//dark
..()
icon='Props.dmi'
icon_state="tallstillgrass"
/*since the problem seems to be fixed by the player logging in or out, I included code for the login and logout.*/

Login()
..()
if(copytext(key,1,6) == "Guest")
alert("This game cannot be played as a Guest. Please Login with your pager active.","Ok")
Logout()
else
saveable=0
world<<"[src.ckey] has logged in."
world<<sound('loginsound.ogg',0,0,0,25)
spawn(30)
winset(usr,"CoverWindow","pos=200x50")
OpenNewWindow(usr,"CoverWindow")
usr << sound('startscreentheme.ogg',1,0,0,50)
winset(usr,"StartScreen","pos=200x50")
OpenNewWindow(usr,"StartScreen")
var/obj/HUD/CherryBlossoms/b=new
client.screen+=b


Logout()
if(!CheckSafeArea())
src << "Logging out -- You may lose unsaved data."
spawn(30)
icon_state="idle"
src << "Thanks for playing."
world<<"[src.ckey] has logged out."
del(src)
..()
else
spawn(30)
icon_state="idle"
RecordProgress()
src << "Logging out. Thanks for playing."
world<<"[src.ckey] has logged out."
world<<sound('logoutsound.ogg',0,0,0,25)
del(src)
..()


Expected Results:
The turf "grass" and all of its forms would change a different color, based on the area type.
Actual Results:
It does work, but will only show up if other players logout, then log back in to the game.
Does the problem occur:
Every time. In other games and only on maps where the turf's color is changed/affected.
In other user accounts? Yes
On other computers? Yes

When does the problem NOT occur?
It's been a persistent problem.

Workarounds:
Logout/Login
How long does that take to start up? You're creating a unique icon for every single turf. Not every type of turf, not every type of turf for every background set, but every single turf.

While this may be a bug, I would still suggest you cache the icons so you don't have to create 10000 of them (for a 100x100 map)
In response to DarkCampainger
DarkCampainger wrote:
How long does that take to start up? You're creating a unique icon for every single turf. Not every type of turf, not every type of turf for every background set, but every single turf.

While this may be a bug, I would still suggest you cache the icons so you don't have to create 10000 of them (for a 100x100 map)

It doesn't take very long to start up at all.(approx 2-3 seconds)

How might I go about doing that though?(the cache)
Typically you would create an associative list, where you use a text string identifier to represent the particular combination and associate the generated icon with it. Here's an example specific to your color-swapping, but technically you could share one list across multiple icon operations so long as the identifiers stay unique to each combination:
// Create a global associative list to store cached icons
var/list/MasterIconCache = list()

proc
ColorSwapList(identifier, icon, icon_state, /* variadic */)
// Count of arguments must be a multiple of 3
// and be in triplets of <newColor, oldColorSampleX, oldColorSampleY>
ASSERT(args.len % 3 == 0)

// Generate a unique ID to reference this combination
var/id = "[identifier];;[icon];;[icon_state]"

// If cached icon already exists, just return it
if(id in MasterIconCache)
return MasterIconCache[id]
else
// Otherwise we need to generate the icon
var/icon/I = icon(icon, icon_state)

// Loop through the triplets (starting after id/icon/state args)
for(var/index = 4, index <= args.len, index+=3)
var
newColor = args[index]
oldColorSampleX = args[index+1]
oldColorSampleY = args[index+2]

ASSERT(istext(newColor) && isnum(oldColorSampleX) && isnum(oldColorSampleY))

// Find the old color at the specified X and Y
var/oldColor = I.GetPixel(oldColorSampleX, oldColorSampleY)

// Swap the colors
I.SwapColor(oldColor, newColor)

// Save the icon to the cache
MasterIconCache[id] = I

// Return the resulting icon
return I

area/var/bgset = "cave"

turf
Grass
icon = 'grass.dmi'
icon_state = "grassy"

New()
var/area/A = loc
switch(A.bgset)
if("cave")
src.icon = ColorSwapList(A.bgset, src.icon, src.icon_state,
rgb( 30,104, 0), 1, 1, //dark
rgb( 39,125, 0), 2, 2, //med
rgb( 57,181, 0), 5, 6) //light
if("volcano")
src.icon = ColorSwapList(A.bgset, src.icon, src.icon_state,
rgb( 84, 87, 34), 1, 1, //dark
rgb(106,117, 43), 2, 2, //med
rgb(120,156, 99), 5, 6) //light


I also batched the color swaps to use a single icon.
It's like poetry to my EYES o_O
Does caching them help fix your missing icon issue?
I haven't tried it yet. I'll let you know.
I'm going to move this to Unverified for the time being since it needs more information (including whether caching fixed your problem). I do think the icons not showing is still a bug even though generating them in turf/New() without caching is a very bad idea; it could be something as simple as a timing issue playing havoc with the way the icons are downloaded.

The main reason I'm putting this in Unverified is that I'll need a sample project that shows this issue. Your code sample is too complex and not easily adapted to a simple test. It also relies on other objects and values that would need to be defined, and on icons I don't have to test with. Building up my own project from scratch to test this would take too long and I wouldn't be sure of seeing the same issue you're seeing. Additionally, you did not include any numbered steps to reproduce the problem so I'm not sure what the requirements are to see it--such as if I'd have to be joining in Dream Seeker but hosting in Dream Daemon, or if it occurs even when running directly in DS.
Lummox JR changed status to 'Unverified'
It seems to me that it just occurs because the image isn't ready at runtime.

Cacheing seems like it will work and I'll try it out in a minute, but what would be even better is if I could generate a physical version of each icon and save them to my computer.
Is there anyway I can do that?
You can use fcopy() and fcopy_rsc() to do that:
fcopy(fcopy_rsc(src.icon), "[some_naming_scheme].dmi")


The fcopy_rsc() may be superfluous, I can't remember. You can also replace fcopy() with ftp() if you want a dialog for saving each file.
Thanks. This works for me since I can now make as many variations of the tiles as I like and save them without having to edit each frame itself individually. To note I never tested the cache, but I'm pretty sure it would have worked as well to fix this problem.