Closed valkyrienyanko closed 1 year ago
Test Plan
.PrintFull()
whenever they were updated unlike the console that just spams every log message.Testing with 3 clients. Position packets have been disabled.
The server has all 3 clients accounted for.
Client 0 has clients 1 and 2. Client 1 has clients 0 and 2. Client 2 only has client 1 <--- this is where the issue lies
Client 2 receives client id 1 twice which is what is causing the same key added error.
E 0:01:15:0446 :0 @ void System.ThrowHelper.ThrowAddingDuplicateWithKeyArgumentException<T >(T ): System.ArgumentException: An item with the same key has already been added. Key: 1
<C++ Error> System.ArgumentException
<C++ Source> :0 @ void System.ThrowHelper.ThrowAddingDuplicateWithKeyArgumentException<T >(T )
<Stack Trace> :0 @ void System.ThrowHelper.ThrowAddingDuplicateWithKeyArgumentException<T >(T )
:0 @ Boolean System.Collections.Generic.Dictionary`2.TryInsert(TKey , TValue , System.Collections.Generic.InsertionBehavior )
:0 @ void System.Collections.Generic.Dictionary`2.Add(TKey , TValue )
GameMaster.cs:47 @ void Sandbox2.GameMaster.AddPlayer(UInt32 , Godot.Vector2 )
SPacketPlayerJoin.cs:22 @ void Sandbox2.SPacketPlayerJoin.Handle()
ENetClient.cs:114 @ void GodotUtils.Netcode.Client.ENetClient.HandlePackets()
GameMaster.cs:18 @ void Sandbox2.GameMaster._PhysicsProcess(Double )
Node.cs:1771 @ Boolean Godot.Node.InvokeGodotClassMethod(Godot.NativeInterop.godot_string_name& , Godot.NativeInterop.NativeVariantPtrArgs , Godot.NativeInterop.godot_variant& )
Sandbox2.GameMaster_ScriptMethods.generated.cs:33 @ Boolean Sandbox2.GameMaster.InvokeGodotClassMethod(Godot.NativeInterop.godot_string_name& , Godot.NativeInterop.NativeVariantPtrArgs , Godot.NativeInterop.godot_variant& )
CSharpInstanceBridge.cs:24 @ Godot.NativeInterop.godot_bool Godot.Bridge.CSharpInstanceBridge.Call(IntPtr , Godot.NativeInterop.godot_string_name* , Godot.NativeInterop.godot_variant** , Int32 , Godot.NativeInterop.godot_variant_call_error* , Godot.NativeInterop.godot_variant* )
So why does it work for the first 2 clients but not the 3rd?
I have checked the server side and it is indeed sending all the correct data!
I found the issue. Putting things back to the way they were fixed this. Instead of enqueing the packet to the Godot queue and handling it on the Godot thread. I handle it like I did before, on the ENet-Client thread. And now everything fixed. But why what was causing such a big issue??
/*
* Instead of packets being handled client-side, they are handled
* on the Godot thread.
* //handlePacket.Handle();
*/
handlePacket.Handle();
//GodotPackets.Enqueue(handlePacket);
packetReader.Dispose();
After more research into this I have found out that ConcurrentQueue
https://www.google.com/search?q=C%23+concurrentqueue+trydequeue+duplicate+data
I have tried switching to BlockingCollection
I'm going to be trying to do ConcurrentDictionary
Someone answering some elses question on stackoverflow said they needed to deep clone before enqueuing the instance. I have found a newtonsoft util function that deep clones classes. But it did not work because my instance is from a abstract class. And I'm not even sure if deep cloning is the play here...
ConcurrentDictionary did not work either...
I have no idea what I am doing anymore. Nothing I am trying is working...
No matter what I do, there is always the duplicate data on the other end 100% of the time.
Solution is to send over packet reader and handle packet instead of just handle packet.
No idea why this fixes everything...
Some black magic I'd say.
Issue
The error spam happens when the 3rd client joins.
Steps to Reproduce
Where the issue happens in the code
https://github.com/Valks-Games/Multiplayer-Template/blob/1635b43c5010af6fb23b77570d292b4be1d1bfa0/Scripts/GameMaster.cs#L47
Preview