Odd problem

01/31/2010 01:27 ipwnudont#1
Recently had a problem with this bug its kinda hard to explain so bear with me xD
lets say i have an character named Bob and i got 20 cps i log on and i trade my cps without logging out i load another client and login Bob again kicking me off One client and loading him on the new/other client causeing the account to not save and i still have my 20 cps even though i traded them.... <.< any ideas of how to fix it?
01/31/2010 01:32 LetterX#2
Quote:
Originally Posted by ipwnudont View Post
Recently had a problem with this bug its kinda hard to explain so bear with me xD
lets say i have an character named Bob and i got 20 cps i log on and i trade my cps without logging out i load another client and login Bob again kicking me off One client and loading him on the new/other client causeing the account to not save and i still have my 20 cps even though i traded them.... <.< any ideas of how to fix it?
When trading is a success, save the client in the DB?
01/31/2010 01:40 .Ocularis#3
Does the DCHandler have a call to save the character file on any sort of disconnect?
Also does the server check for more than one instance of the same account logged in?
01/31/2010 01:43 LetterX#4
Quote:
Originally Posted by Mentalis View Post
Does the DCHandler have a call to save the character file on any sort of disconnect?
Also does the server check for more than one instance of the same account logged in?
I believe his server does, since it disconnects the already connected client...but the saving on a disconnect should be added (along with saving when a trade is completed), if it's not already.
01/31/2010 01:57 ipwnudont#5
Letter X how would you add that?
*edit- The saving on the disconnect that is
01/31/2010 02:42 LetterX#6
Quote:
Originally Posted by ipwnudont View Post
Letter X how would you add that?
*edit- The saving on the disconnect that is
-removed

edit: I looked at the source (LOTF 5165), and from the Disconnect it goes to "LogOff" which the char is saved there. You should still save your char once trading is completed, for more protection. D;

edit2: Go to the Trade.cs; find "ent.MessageID, "SYSTEM", Who.Name, "Trading succeeded!", 2005, 0));". Under it add:
Code:
Database.SaveCharacter(Who, Who.MyClient.AuthInfo.Account);
and then find "C.AddSend(Packets.ChatMessage(C.MessageID, "SYSTEM", C.MyChar.Name, "Trading succeeded!", 2005, 0));" (should be last line before the bracket), under it add:
Code:
Database.SaveCharacter(C.MyChar, C.AuthInfo.Account);
01/31/2010 10:28 ipwnudont#7
OK fail there thought it worked but can still do it i got a better explanation though...

open first client....login Bob. open 2nd client and login...Phil to trade items/cps/anything to..open 3rd client and relog bob dcing him from the first client. trade the cps from bob to Phil. Close out of the 3rd client and login bob on the first client and still has the cps/items/ect ect
01/31/2010 13:30 Korvacs#8
Quote:
Originally Posted by ipwnudont View Post
OK fail there thought it worked but can still do it i got a better explanation though...

open first client....login Bob. open 2nd client and login...Phil to trade items/cps/anything to..open 3rd client and relog bob dcing him from the first client. trade the cps from bob to Phil. Close out of the 3rd client and login bob on the first client and still has the cps/items/ect ect
Sounds to me like the server is still saving "bob" at the time that you log "bob" back in, so the server loads bob before it finshes saving.

Durring your login script, where it signals for "bob" to be disconnected, put a Thread.Sleep(10000) in and see if that helps, this will delay login for 10 seconds while the server performs a complete save.

Thats my theory anyway.
02/01/2010 01:03 .Ocularis#9
Quote:
Originally Posted by LetterX View Post
-removed

edit: I looked at the source (LOTF 5165), and from the Disconnect it goes to "LogOff" which the char is saved there. You should still save your char once trading is completed, for more protection. D;

edit2: Go to the Trade.cs; find "ent.MessageID, "SYSTEM", Who.Name, "Trading succeeded!", 2005, 0));". Under it add:
Code:
Database.SaveCharacter(Who, Who.MyClient.AuthInfo.Account);
and then find "C.AddSend(Packets.ChatMessage(C.MessageID, "SYSTEM", C.MyChar.Name, "Trading succeeded!", 2005, 0));" (should be last line before the bracket), under it add:
Code:
Database.SaveCharacter(C, C.AuthInfo.Account);
The correct save for this
Code:
Database.SaveCharacter(C, C.AuthInfo.Account);
Is this
Code:
Database.SaveCharacter(C.MyChar, C.AuthInfo.Account);
It just don't work without C.MyChar :P
02/01/2010 05:10 LetterX#10
Quote:
Originally Posted by Mentalis View Post
The correct save for this
Code:
Database.SaveCharacter(C, C.AuthInfo.Account);
Is this
Code:
Database.SaveCharacter(C.MyChar, C.AuthInfo.Account);
It just don't work without C.MyChar :P
Thank you for telling me ;o

I guess my lack of knowledge on that source is already showing D:
02/01/2010 19:48 Nullable#11
Quote:
Originally Posted by Mentalis View Post
Edit:
Since we have this
I didn't look into that source yet, but i have one comment to point out, in your first example
you are using many useless try catch blocks, this takes more time to process, just one on the whole block of sentences would do the same, and you might want to do some notification :}
And about stopping people from login if the character is already online, check if the character id exists in the client pool, if it does, disconnect the socket of the client that is requesting to login

Update: just looked at the code you suggested, i don't think adding anything to that case will work, since the client is already logged on this case just informs your friends and enemies that you are online..
02/01/2010 21:41 .Ocularis#12
@ Nullable
That really didn't help. It's still on and off with the dupes, the same as it was when I switched the time that the server saves the character to the database. However that was a excellent job of optimizing that code. I wouldn't have thought of that myself. Thank you.
02/01/2010 22:02 Nullable#13
Quote:
Originally Posted by Mentalis View Post
@ Nullable
That really didn't help. It's still on and off with the dupes, the same as it was when I switched the time that the server saves the character to the database. However that was a excellent job of optimizing that code. I wouldn't have thought of that myself. Thank you.


The most secure and most thorough fix for this problem would be to disable the ability to kick someone that is already logged in but logging in to the same account with a second client while the other person is logged in.

If this change was made the dupe problem would be no more.

Right now we're running a server with this dupe bug and there is over 150+ online
It's it's our highest priority to fix this damn thing.
Actually my comment about the OnElapsed event was never to fix that error.. just to make that code clearer, never said to minimize that error you're having or remove it, as i mentioned in my post, before accepting any client, before the actual client object gets created you should check in the client hashtable if they exist or not, if the same exact character exists in the online players, disconnect the client before his or her instance on the server gets created, thus the already online client will not disconnect, and the one who is trying to log on the connected client will always disconnect..
02/02/2010 10:12 Nullable#14
Kk, back from the damn exam and took a look at the source, here ya go:
at GameWorker.cs:
search for:
Quote:
If (PacketID == 1052)
Scroll down a bit, till you see this:
Code:
if (Game.World.H_Chars.Contains(GC.MyChar.EntityID))
{
     Game.Character Old = (Game.Character)Game.World.H_Chars[GC.MyChar.EntityID];
     Old.MyClient.Disconnect();
     if (!Game.World.H_Chars.Contains(GC.MyChar.EntityID))
            Game.World.H_Chars.Add(GC.MyChar.EntityID, GC.MyChar);
     GC.MyChar = Database.LoadCharacter(GC.AuthInfo.Character, ref Acc);
     GC.MyChar.MyClient = GC;
     GC.AddSend(Packets.SystemMessage(GC.MessageID, "ANSWER_OK"));
     GC.AddSend(Packets.CharacterInfo(GC.MyChar));
     GC.AddSend(Packets.Status(GC.MyChar.EntityID, Game.Status.VIPLevel, GC.MyChar.VipLevel));
     GC.AddSend(Packets.Time());
     GC.AddSend(Packets.Donators(GC.MyChar));
     GC.AddSend(Packets.Packet1012(GC.MyChar.EntityID));
     GC.AddSend(Packets.Status(GC.MyChar.EntityID, Game.Status.Effect, 0));
}
and change it with its corresponding else statement to this:
Code:
if (Game.World.H_Chars.Contains(GC.MyChar.EntityID))
{
      GC.AddSend(Packets.SystemMessage(GC.MessageID, "Error! The character is already logged on."));
      GC.Disconnect();
}
else
{
       Game.World.H_Chars.Add(GC.MyChar.EntityID, GC.MyChar);
       GC.MyChar = Database.LoadCharacter(GC.AuthInfo.Character, ref Acc);
       GC.MyChar.MyClient = GC;
       GC.AddSend(Packets.SystemMessage(GC.MessageID, "ANSWER_OK"));
       GC.AddSend(Packets.CharacterInfo(GC.MyChar));
       GC.AddSend(Packets.Status(GC.MyChar.EntityID, Game.Status.VIPLevel, GC.MyChar.VipLevel));
       GC.AddSend(Packets.Time());
       GC.AddSend(Packets.Donators(GC.MyChar));
       GC.AddSend(Packets.Packet1012(GC.MyChar.EntityID));
       GC.AddSend(Packets.Status(GC.MyChar.EntityID, Game.Status.Effect, 0));
}
02/02/2010 11:27 Nullable#15
Quote:
Originally Posted by Mentalis View Post
I WANT YOUR $&#@ING PAYPAL

you are getting money for this.
Thanks but i've got my cash already :P, feel free to ask anything(better send me a private message)
Well, as my method is not working properly, why don't you retrieve the old same code, and save the character manually, then disconnect it:
Code:
if (Game.World.H_Chars.Contains(GC.MyChar.EntityID))
{
     Game.Character Old = (Game.Character)Game.World.H_Chars[GC.MyChar.EntityID];
     [B]Database.SaveCharacter(Old, Old.MyClient.AuthInfo.Account);[/B]
     Old.MyClient.Disconnect();
     if (!Game.World.H_Chars.Contains(GC.MyChar.EntityID))
            Game.World.H_Chars.Add(GC.MyChar.EntityID, GC.MyChar);
     GC.MyChar = Database.LoadCharacter(GC.AuthInfo.Character, ref Acc);
     GC.MyChar.MyClient = GC;
     GC.AddSend(Packets.SystemMessage(GC.MessageID, "ANSWER_OK"));
     GC.AddSend(Packets.CharacterInfo(GC.MyChar));
     GC.AddSend(Packets.Status(GC.MyChar.EntityID, Game.Status.VIPLevel, GC.MyChar.VipLevel));
     GC.AddSend(Packets.Time());
     GC.AddSend(Packets.Donators(GC.MyChar));
     GC.AddSend(Packets.Packet1012(GC.MyChar.EntityID));
     GC.AddSend(Packets.Status(GC.MyChar.EntityID, Game.Status.Effect, 0));
}