ID:2204189
 
BYOND Version:510
Operating System:Linux
Web Browser:Firefox 50.0
Applies to:Dream Daemon
Status: Open

Issue hasn't been assigned a status value.
Descriptive Problem Summary:

When I launch the game in any Linux hosting platform (I used both Ubuntu and
CentOS as examples) it deletes cards (which are the objs) in the menu of this game and over time, deletes them from their decks, which is in the savefiles I assume. This never happened in 508 and 509, but for some reason happens in 510 and 511.

Numbered Steps to Reproduce Problem:
Simply hosting the game via DreamDaemon for the first time and logging in you can see objs missing.

Does the problem occur:
the problem occurs on every Linux-based server. I did not have any issues with Windows ones. Everything appeared normally in Windows.

When does the problem NOT occur?

508 and 509 from what I re-call

Are the cards physical images loaded in one start?

Regardless what permissions do the files have and are you using -trusted ?
I am using -trusted and the cards load as you log into the game. They are pre-loaded.
Found this in the log:

BUG: Sequence number 6DF1 expected but 42 received
BUG: Sequence number A216 expected but 43 received

Don't know what it means. Also, I get a LOT of card errors like this:

Warning: type read from file (/obj/cards/spell/DRLG/EN005) is not defined

Here's the thing though, those cards aren't the ones being affected by the bug, nor are they in the same list or category.
BUG: Sequence number 6DF1 expected but 42 received
BUG: Sequence number A216 expected but 43 received

This is what happens if something opens a connection to the server, authenticates and starts a session, then sends the wrong sequence number. Given the fact that these are consecutive numbers DD received, my guess is someone, not necessarily you, is experimenting with starting BYOND sessions outside of BYOND, using your server.

Warning: type read from file (/obj/cards/spell/DRLG/EN005) is not defined

Are you sure you didn't remove any cards from your code at any point? Perhaps you forgot to include a file?
If you have or remember the info, listing the full version number of every version you tried and rather or not the bug happened in that version will help byond staff narrow down what version added the bug.
I can't give much help but I can say that I experienced the undefined type read despite it clearly being defined in the source code
The issue just sort of went away though
There was a bug at one point in which savefiles didn't load type paths correctly. It happened only in very large games, typically, and was a result of a very very ancient mistake in the internal routine that handles text2path().

Oddly I can't seem to find the release notes for that one so I can't pin down what version it was fixed in, but I want to say it was a 510 build.

This issue sounds very similar, except that bug was most definitely quashed and I don't see how it could arise again in even a similar way.
In response to Lummox JR
Lummox JR wrote:
There was a bug at one point in which savefiles didn't load type paths correctly. It happened only in very large games, typically, and was a result of a very very ancient mistake in the internal routine that handles text2path().

Oddly I can't seem to find the release notes for that one so I can't pin down what version it was fixed in, but I want to say it was a 510 build.

This issue sounds very similar, except that bug was most definitely quashed and I don't see how it could arise again in even a similar way.

This sounds like the issue because decks are saved to people's savefiles, and when they log in, random cards from their deck are gone. So this sounds exactly like the problem at hand. Also, it HAS to be 510 because it worked fine in 509
In response to WorldWideDuelist
WorldWideDuelist wrote:
Lummox JR wrote:
There was a bug at one point in which savefiles didn't load type paths correctly. It happened only in very large games, typically, and was a result of a very very ancient mistake in the internal routine that handles text2path().

Oddly I can't seem to find the release notes for that one so I can't pin down what version it was fixed in, but I want to say it was a 510 build.

This issue sounds very similar, except that bug was most definitely quashed and I don't see how it could arise again in even a similar way.

This sounds like the issue because decks are saved to people's savefiles, and when they log in, random cards from their deck are gone. So this sounds exactly like the problem at hand. Also, it HAS to be 510 because it worked fine in 509

But what I said is, that bug was fixed. The fix is in use right now. There is no chance that that specific fix broke something else; it was a clear case of the wrong var having been used for something.
In response to Lummox JR
Lummox JR wrote:
WorldWideDuelist wrote:
Lummox JR wrote:
There was a bug at one point in which savefiles didn't load type paths correctly. It happened only in very large games, typically, and was a result of a very very ancient mistake in the internal routine that handles text2path().

Oddly I can't seem to find the release notes for that one so I can't pin down what version it was fixed in, but I want to say it was a 510 build.

This issue sounds very similar, except that bug was most definitely quashed and I don't see how it could arise again in even a similar way.

This sounds like the issue because decks are saved to people's savefiles, and when they log in, random cards from their deck are gone. So this sounds exactly like the problem at hand. Also, it HAS to be 510 because it worked fine in 509

But what I said is, that bug was fixed. The fix is in use right now. There is no chance that that specific fix broke something else; it was a clear case of the wrong var having been used for something.

Makes sense. It fustrates me that I can't really help at all in this situation. I'm just a host, not the guy who made the game. All I can say is something happened in 510 that caused this. Is there any way I can help? Maybe look into the memory reader?
In response to WorldWideDuelist
WorldWideDuelist wrote:
Makes sense. It fustrates me that I can't really help at all in this situation. I'm just a host, not the guy who made the game. All I can say is something happened in 510 that caused this. Is there any way I can help? Maybe look into the memory reader?

I don't know what you mean by "memory reader".

The best way to solve this is to try narrowing down which exact build the problem appeared in. That will give me an idea of what to look for and where.
The issue with that is I don't have access to older versions of the game, so if I host the game with a later compiled version, it'll behave differently.
Since I'm the currently the only active coder for the game in question, I'll try to help out with this issue in any way I can. It's definitely been an ongoing problem with the game.

I'm not an expert on byond coding and had some basic understandings when I started and more or less been learning and dealing with issues as I need to. Thankfully I have experience with a few other coding languages which helps a lot but it's still a learning experience.

In regards to large games, yeah, if there's a game on byond with a larger resource than this game, I'll be shocked. We're currently clocking in at 182mb.

There are somewhere around 11,000 obj paths for the cards themselves. Plus all the obj that arent related to the cards.

proc/Check_Objs(mob/M,deck,name)

var/list/tmpdeck[]=new()
var/kill = 0

for(var/A in deck)

if(A in typesof(/obj/cards))

var/obj/cards/C = new A

tmpdeck += A

del C

else
kill ++

if(kill) M<<{"<font color=#670000><b>Please check the Deck '[name]' for [kill] missing card\s.</b></font>"}

return tmpdeck


Decks are stored in the save as lists of obj paths.

When someone logs in to the server a proc runs that checks each deck in the player's save file.

The proc creates a new list (tmpdeck), checks every variable in the deck stored in the player's save for a matching obj/card, if it finds a match, the matched card is added to the new list. if it's not, it doesn't add the card and it increases the count for the error output. Then it returns the new list as the player's deck and gives the error output.


If it will help, I do have every version of the source code I've personally worked on going back to 11/10/15.
I take it cards are added and removed often, which is why that awful check even exists?
In response to A.T.H.K
A.T.H.K wrote:
I take it cards are added and removed often, which is why that awful check even exists?

How it works is he has sets, some cards that are released don't have an official set, so when the card is either printed IRL or the set changes, he moves the cards to the new set, thus, the reason the check exists. Also, it removes cards you are not supposed to access in-game, like variants.
Ahh right, that makes sense.
This has been an ongoing issue since at least 2012, but that's just when I first noticed it.

I had rented a server host and had the same issue back then. I made a post about it with no resolution.

http://www.byond.com/forum/?post=1089523

To make things clear, it's not as if those objs are just being skipped over by the game. The obj themselves are readable still and if you end up losing a card when you first log on, you can go and re-add the same card back to your deck.

The objs themselves that get removed from a person's deck are unique to each individual person but they're consistent for that person.

There's around 11000 cards but 1 person may only have 10 or so cards removed from their decks but all cards of that obj type will be removed. They can re-add them to their decks but if they relog, they'll lose the same cards again. If the server restarts, the cards that a player loses will be different.

The obj paths in the game dont have any special characters that would throw them off.

Since it's seemingly random which cards get removed each time the server restarts, it doesn't seem like it's a specific line in the save file that's failing to be read.

But since the cards that give the error are different for each person, it also doesn't seem like it's an error with the server not being able to read certain objs.

I can make an exact copy of a player's deck and end up losing completely different cards.
    Save()

var/savefile/F = new()

if(mob.z == 6)

for(var/obj/items/helmet/X in mob.items)
if(!X.o_icon)
alert(usr,{"You appear to be on a Duel Runner with no Helmet. Cannot save."},"Duel Runner Save Error")
return
if(!get_default_ico(X.o_icon))
F["icon"] << X.o_icon

F["icon_state"] << X.o_icon_state

else
if(!get_default_ico(mob.icon))
F["icon"] << mob.icon

F["icon_state"] << mob.icon_state

F["lastloc"] << list(mob.x,mob.y,mob.z)
F["pixel_c"] << mob.pixel_c
F["msize"] << mob.msize
F["name"] << mob.name
F["block"] << mob.block
F["buddy"] << mob.buddy
F["active"] << mob.active
F["Config"] << mob.Config
F["Text"] << mob.Text
F["lastv"] << world.version
F["my_atks"] << mob.my_atks
F["pixel_c"] << mob.pixel_c
F["chat"] << mob.chat
F["vol"] << mob.vol
F["avatar"] << mob.avatar

// START TRUNK

var/list/Tt[] = new()
Tt += mob.trunk

for(var/obj/decks/D in Tt) if(D.overlays) D.overlays = null

F["trunk"] << Tt

// END TRUNK

var/savefile/F_safe = safe_save(F)

if(F_safe)

Export(F_safe)

if(mob.loc)
mob.overlays += typesof(/obj/overlays/emote/save_g)
spawn(10) if(mob) mob.overlays -= typesof(/obj/overlays/emote/save_g)

else if(mob.loc)
mob.overlays += typesof(/obj/overlays/emote/save_n)
spawn(10) if(mob) mob.overlays -= typesof(/obj/overlays/emote/save_n)

return


    Load()

if(!src || !mob || copytext(mob.key,1,6)=="Guest") return

var/loop = 0
var/savefile/temp = new(Import())

while(length(temp)<1000)
if(loop>=3) break
loop++
sleep(5)

if(!length(temp))

mob << output("No previous Save File found?", "_load.info")
ResetMob(mob)

else

var/savefile/c_file = safe_load(temp)

if(c_file)

if(!isnull(c_file["name"])) c_file["name"] >> mob.name
if(!isnull(c_file["items"])) c_file["items"] >> mob.items
if(!isnull(c_file["trunk"])) c_file["trunk"] >> mob.trunk
if(!isnull(c_file["active"])) c_file["active"] >> mob.active
if(!isnull(c_file["icon_state"])) c_file["icon_state"] >> mob.icon_state
if(!isnull(c_file["pixel_c"])) c_file["pixel_c"] >> mob.pixel_c
if(!isnull(c_file["msize"])) c_file["msize"] >> mob.msize
if(!isnull(c_file["lastloc"])) c_file["lastloc"] >> mob.lastloc
if(!isnull(c_file["lastv"])) c_file["lastv"] >> mob.lastv
if(!isnull(c_file["chat"])) c_file["chat"] >> mob.chat
if(!isnull(c_file["icon"])) c_file["icon"] >> mob.icon
else mob.icon = get_pico(mob.icon_state)
if(!isnull(c_file["Config"])) c_file["Config"] >> mob.Config
if(!isnull(c_file["Text"])) c_file["Text"] >> mob.Text
if(!isnull(c_file["my_atks"])) c_file["my_atks"] >> mob.my_atks
if(!isnull(c_file["pixel_c"])) c_file["pixel_c"] >> mob.pixel_c
if(!isnull(c_file["block"])) c_file["block"] >> mob.block
if(!isnull(c_file["buddy"])) c_file["buddy"] >> mob.buddy
if(!isnull(c_file["vol"])) c_file["vol"] >> mob.vol
if(!isnull(c_file["avatar"])) c_file["avatar"] >> mob.avatar

for(var/obj/items/Z in mob.items)

if(!Z) mob.items-=Z
else

if("[initial(Z.icon_state)]_i" in icon_states(Z.icon))
Z.icon_state = "[initial(Z.icon_state)]_i"

Z.Move(mob)

if(length(c_file)<1024) mob << output("Save loaded ([length(c_file)]bytes)", "_load.info")
else mob << output("Save loaded ([round(length(c_file)/1024,1)]kb)", "_load.info")

else
mob << output("Save currupt or tampering detected. It has not been loaded.", "_load.info")
ResetMob(mob)

winset(mob, "_load.progress", "value=45")

return


Here's the save and load procs that the game uses if it'll help.
mob/proc/save_deck()

if(isbusy) return
if(!isedit) return

isbusy = 1

var/list/newdeck[] = new()
var/list/newside[] = new()
var/list/newextra[] = new()

var/timed_input/I = new()
I.Input(src,"Save currently loaded Deck? [DeckName]\nTip: Save New will save the current deck to a new slot.","Save Deck", 60 ,list("Save","Save New") ,"Save")

deckcodeup(Deck,newdeck)
deckcodeup(Extra,newextra)
deckcodeup(Side,newside)

if(I && isedit && newdeck.len)

switch(I.response)
if("Save")

var/S = 0

for(var/obj/decks/Z in trunk) if(Z.name == DeckName)

Z.main = newdeck
Z.side = newside
Z.extra = newextra
Z.owner = src.key

S++

alert(usr,"'[DeckName]' has been updated.","Saved")

if(!S)

if(trunk.len >= trunk_num) alert(usr,"You can only have a maximum of [trunk_num] Decks. Delete 1 or more to make room.")
else

var/obj/decks/F = new/obj/decks(src)

F.owner = src.key
F.name = "[DeckName]"
F.main = newdeck
F.side = newside
F.extra = newextra
F.code = makeobjcode(src)

trunk += F
F.Move(src)

alert(usr,"'[DeckName]' has been updated.","Saved")

client.Save()

if("Save New")

if(trunk.len >= trunk_num)

alert(src,"You can only have a maximum of [trunk_num] Decks. Delete 1 or more to make room.")

else

var/obj/decks/F = new/obj/decks(src)
F.owner = src.key
F.name = deck_name(F.name)
F.main = newdeck
F.side = newside
F.extra = newextra
F.code = makeobjcode(src)
trunk += F

F.Move(src)

src << "Saved Copy of Deck as [F.name]."

SortByName(trunk)

client.Save()

isbusy = 0

return

    deckcodeup(list/D,list/code)

for(var/obj/cards/C in D) code += C.type

return 1


Here's the code that's being used for the actual saving of decks.
Page: 1 2