In response to Kitsueki
Kitsueki wrote:

I would include [ckey] in your debugging output. The issue here in particular is we don't want any player mobs popping up that don't actually have any clients driving them.

Edit: After I tried to load a character, another entry was made.

Edit2: My conclusion is that everything is happening when a character is being loaded since the extra mob isn't logged until that happens.

Agreed. But if this were the case, it seems most likely that the cause would be from the contents of your savefile itself, but since we have been checking that it shouldn't be the problem.

Just because I have to ask, are you sure you've been using ExportText() AFTER the savefile is being updated?

Which means there's an issue in the load_proc(). As I look at it I keep thinking something is weird about trying to output a mob to a mob...

You actually aren't outputting a mob to a mob. Loading something from a savefile should just loop through any vars stored in the savefile and update them as necessary. "F["SRC"] >> src" should just be the equivalent of typing src.Read() as far as I know.



As for your current situation and where to go from here: now that you've narrowed down where the phenomenon is coming from, I suggest you try circumventing parts of the code in question and seeing if you can make the problems stop happening. Specifically, the problem where you get disconnected. Also, are you checking your Options & Messages screen to make sure you aren't getting runtimes when you are getting d/c'd?
Ah.. That explains why changing it to;

var/mob/loaded = F["SRC"]
for(var/x in loaded.vars)
src.vars[x] = loaded.vars[x]


Made no difference.

As far as the ExportText() thing goes, I'm showing how I'm using it. I placed it in the save_proc, at the end. I'm assuming everything is updated before it is ran?

Somehow a new mob is getting created. I'm assuming you've verified that the load_proc() is clean and makes sense. I dunno' here, this is so wonky. I'm starting to think it might be better if I let someone more experienced look at the project and find the culprit here, I'm not finding much (although it has been narrowed down considerably, thanks to you mostly.)

I just tried deleting all saves and using load to see if it logs any mobs, and the answer is no. Which means the extra mob is getting created once an actual save is getting loaded.

I just tested it trying to load the .txt files we were generating, which thankfully were saved in the player's .sav directory as well. It didn't generate any mob logs, which means it has to be a valid .sav for it to happen. I'll look into it a bit more.


Edit: I started logging for Logouts too, which gave me something interesting. When it says I log out, I stay viewing the roaming mob, and the game continues running. I can even continue trying to load and create characters. It logs one instance of a mob when I try to load a character..

Nothing happens to the default mob I stay connected to.. maybe the character thats being loaded is getting loaded onto that duplicate mob, since there are no messages getting added to the log for a Logout() instance. Yet it says "Kitsueki has been logged out", so Logout() has to be running..?
It sounds like this problem is definitely going to need an outside eye on your project itself. You'll want to find an experienced programmer to look through and try to identify the issue.

I was hoping to be able to help guide you to finding the solution yourself, but it seems that the issue is a bit too convoluted for that (at least for my abilities, maybe someone else will pop in and see something I missed).
Here's an update, which some knowledge I acquired.

client/New() looks for a mob with a matching key and calls mob/Login(). That means, mob/New() runs before mob/Login()

Therefore, no client exists in mob/New().

I changed the check for adding bodyparts to npcs, to this instead:

mob
New()
..()
if(istype(src, /mob/NPC))
add_bparts()


Duplicate bodyparts are fixed. However, the loading problem persists.
In response to Kitsueki
Kitsueki wrote:
client/New() looks for a mob with a matching key and calls mob/Login(). That means, mob/New() runs before mob/Login()

Therefore, no client exists in mob/New().

Well you taught me something. The mob doesn't get its client until after New() passes a return value. Personally I don't override New() directly, my customized initialization procs are always ran after New() has already returned.
How do you mean.. already returned? Are you talking about using '.()'?

Anyhow, I've gotten somewhere once again. I reverted to my old system where I give each variable a directory and save them individually. This system works fine. I'm saving all the variables I define, so this tells me the issue isn't in one of my variables, it's in how I was coding it before. I'm not interested in going back and fooling with that old system.. I'm honestly tired of it lol. I'm going to stick with this way, since it works fine.

Problem solved.
In response to Kitsueki
Kitsueki wrote:
How do you mean.. already returned? Are you talking about using '.()'?

.() is similar to ..(), but instead of calling the parent proc it calls the current proc. Unless you have multiple ways for that proc to return out (some of them not featuring the .() call) it will be infinitely recursive.

There are a few ways to create a scenario as I described.

Move() is a common place where you would want to use this sort of behavior.
mob/Move()
.=..()
if(.) //if move was successful
return //do stuff here


In my case for the topic of New() already being returned:
My init procs are called by a proc called in New(). The last line being called is spawn() MyInit(). The very next line is the one that would cause New() to pass a return value, which means it returns the value first and then calls MyInit()
Ah.. so you spawn in a proc that handles this kind of stuff. Since it's spawned in, New() finishes before it's run, nice technique.
In response to Kitsueki
Kitsueki wrote:
Ah.. so you spawn in a proc that handles this kind of stuff. Since it's spawned in, New() finishes before it's run, nice technique.

It was never intentionally for the purpose of waiting until the mob is given a client, however I do have a few init procs that rely on that data being available, so if it didn't function this way I would have encountered some issues up until this point.

However yes, it has turned out to be a very happy accident.

Just a note: It is spawned() at the very END of the proc. If you put it at the beginning, the results may not be guaranteed to be the same. Depends on when BYOND comes back to run the spawned proc.


But yes, I keep New() separate from my own Init procs. Whenever defining core mechanics, engine related systems, etc, I will include them in the parent-most procs, then I will have custom children procs that are intended for being overridden and customized for later use. This guarantees that no matter what I'm doing I maintain a necessary order of operations, makes debugging a breeze in a few different of my situations, etc.
Thanks for the all the help you've given in this topic, AJX!
Page: 1 2