5

There are 3 projects:

  1. Server - game server
  2. Client - game client
  3. Shared - code shared between the Client and Server

Server communicates with Client by sending MessagePack-serialized class instances from Shared. When trying to deserialize one class instance on client

var packet = MessagePackSerializer.Deserialize<IPacket>(packetReader.GetRemainingBytesSegment());

the following exception is throwed:

MessagePack.MessagePackSerializationException
  HResult=0x80131500
  Message=Failed to deserialize World2D.Shared.Networking.Packets+IPacket value.
  Source=MessagePack
  StackTrace:
   at MessagePack.MessagePackSerializer.Deserialize[T](MessagePackReader& reader, MessagePackSerializerOptions options)
   at MessagePack.MessagePackSerializer.Deserialize[T](ReadOnlyMemory`1 buffer, MessagePackSerializerOptions options, CancellationToken cancellationToken)
   at World2D.Client.Networking.NetworkingSystem.<>c.<.ctor>b__2_0(NetPeer peer, NetPacketReader packetReader, DeliveryMethod deliveryMethod) in C:\Users\dclip\Desktop\world2d\client\world2d\src\Networking\NetworkingSystem.cs:line 25
   at LiteNetLib.NetManager.ProcessEvent(NetEvent evt)
   at LiteNetLib.NetManager.PollEvents()
   at World2D.Client.Networking.NetworkingSystem.Update(GameTime gameTime) in C:\Users\dclip\Desktop\world2d\client\world2d\src\Networking\NetworkingSystem.cs:line 51
   at MonoGame.Extended.Entities.World.Update(GameTime gameTime) in C:\Users\dclip\Desktop\world2d\shared\Shared\MonoGame.Extended\MonoGame.Extended.Entities\World.cs:line 89
   at World2D.Client.Game1.Update(GameTime gameTime) in C:\Users\dclip\Desktop\world2d\client\world2d\Game1.cs:line 36
   at Microsoft.Xna.Framework.Game.DoUpdate(GameTime gameTime)
   at Microsoft.Xna.Framework.Game.Tick()
   at Microsoft.Xna.Framework.SdlGamePlatform.RunLoop()
   at Microsoft.Xna.Framework.Game.Run(GameRunBehavior runBehavior)
   at World2D.Client.Program.Main() in C:\Users\dclip\Desktop\world2d\client\world2d\Program.cs:line 11

Inner Exception 1:
FileNotFoundException: Could not load file or assembly 'Server, Version=0.0.1.0, Culture=neutral, PublicKeyToken=null'. The system cannot find the file specified.

Though I am not referencing the Server in code in any way in Client (that's the purpose of Shared), this exception is happening over and over. If the Server is added as a dependency in the Reference Manager, everything works. But why?

What might be the reason? What are ways to debug it?

namespace World2D.Shared.Networking
{
    public class Packets
    {
        [Union(0, typeof(Entities))]
        [Union(1, typeof(Entity))]
        public interface IPacket
        {
            [MessagePackObject]
            public class Entities : IPacket
            {
                [Key(0)] 
                public List<MonoGame.Extended.Entities.Entity> entities;

                [SerializationConstructor]
                public Entities(List<MonoGame.Extended.Entities.Entity> entities)
                {
                    this.entities = entities;
                }
            }

            [MessagePackObject]
            public class Entity : IPacket
            {
                [Key(0)]
                public MonoGame.Extended.Entities.Entity Value { get; set; }

                [SerializationConstructor]
                public Entity(MonoGame.Extended.Entities.Entity entity)
                {
                    Value = entity;
                }
            }
        }
    }
}
dclipca
  • 1,739
  • 1
  • 16
  • 51
  • Maybe because your constructor is `internal`? – stuartd Mar 13 '22 at 01:33
  • Check that `Packets` and `IPacket` are not referencing anything from the Server project. Also, is `IPacket` an interface? – Alberto Mar 15 '22 at 11:02
  • @Alberto checking. Yes `IPacket` is an interface. I added the code for it here. – dclipca Mar 15 '22 at 11:08
  • @Alberto they are sharing the same namespace start though (World2D). There is `World2D.Server`, `World2D.Client` and `World2D.Shared` namespaces. Could this play a role? – dclipca Mar 15 '22 at 11:11
  • Not the case because I changed it to `Shared.Networking` and still same thing. – dclipca Mar 15 '22 at 11:15
  • 3
    I would guess that the assembly information is embedded in the serialized 'packet'. Are you serializing the packet from the Shared library as well? Or is that one specific to the server library? – Jesse de Wit Mar 15 '22 at 11:38
  • @JessedeWit no, it is serialized in the `Server` project. Let me try serializing it on `Shared` and see how it goes. – dclipca Mar 15 '22 at 12:06
  • Same unfortunately. Moved the serialization logic to `Shared` but it doesn't change anything. – dclipca Mar 15 '22 at 12:22
  • Are you serializing a class that derives from `IPacket` but it is defined on the server? in particular `World2D.Shared.Networking.Packets+IPacket` – Alberto Mar 15 '22 at 14:39
  • @Alberto not to my knowledge but it must be that I am, otherwise why this behavior. Will search for more. – dclipca Mar 15 '22 at 15:46
  • Obviously, your code doesn't contain everything you use. How do you serialize? Do you have a small reproducing project? – Simon Mourier Mar 15 '22 at 17:48
  • I wonder if this is similar to an issue I had with drag-and-drop. With 2 instances of the same program running, I could not drag from one instance to the other as the typeof(CustomClass) used to identify the dragged object would cause the second instance to crash. To correct, I needed to expose the class on COM, giving it a GUID. – Adam Mar 15 '22 at 18:37
  • Make sure the packet class that you're serializing is defined in the Shared project and not in the Server project. I mean the implementation, not the interface. – Jesse de Wit Mar 16 '22 at 10:38
  • @JessedeWit like https://i.imgur.com/nZPQg9R.png this? – dclipca Mar 17 '22 at 17:15
  • @Adam I don't run two instances of the same program. `Client` and `Server` are two different Visual Studio projects. All of the reference `Shared` as a DLL. – dclipca Mar 17 '22 at 17:18
  • @SimonMourier I can do one but it's not very simple and I doubt someone will give it a try. To run a reproduction, you need the server, then serialize a message on the server then send it to client. You get the error on client. – dclipca Mar 17 '22 at 17:22
  • From your description, the problem you have should not be that difficult to reproduce. If you can't reproduce easily, that maybe because it in fact depends on your context, environment, etc. and we may not be able to help. That's the whole point of trying to reproduce on a simple sample https://stackoverflow.com/help/minimal-reproducible-example – Simon Mourier Mar 17 '22 at 18:03
  • @SimonMourier will make one. – dclipca Mar 17 '22 at 18:07
  • dclipca, what I was getting at is could it be possible that your data is losing its managed context when going from server to client. Thus, the JIT is trying to rebuild the context from which it was created, which would be the server, even though it is part of the shared. In this sense it is similar to my issue where it could not share through drag-and-drop between 2 instances as they did not both exist within the same managed space. If this is the case, you need a way to get it out of managed; one way is through COM. – Adam Mar 17 '22 at 19:15
  • Not sure how `msgpack` serialization is done, but from [MonoGame Entity source code](https://github.com/craftworkgames/MonoGame.Extended/blob/develop/src/cs/MonoGame.Extended.Entities/Entity.cs) it looks like you can "attach" an arbitrary object to the entity, which potentially is serialized. Perhaps there's an object from `Server` domain attached to the `Entity` you're serializing and then trying to deserialize? Looking at the serialized form might shed some light on the subject if the serialized form is anywhere near human-readable. – Grx70 Mar 18 '22 at 12:54
  • @Adam oh yes this makes a lot of sense. Can you point me maybe towards a resource explaining how it can be done? Not sure what I find on Google is related to this. – dclipca Mar 19 '22 at 12:58
  • @Grx70 Indeed and I just thought of a perfect test for this. Will get back. – dclipca Mar 19 '22 at 12:58
  • It's strange I tried to reproduce this again. Removed all server references in client but I don't get the same error. I'm happy but terrified I don't know why it was happening in the first place. – dclipca Mar 19 '22 at 13:42
  • 1
    dclipca, the resource I used was Microsoft Docs on exposing class to COM https://learn.microsoft.com/en-us/dotnet/csharp/programming-guide/interop/example-com-class – Adam Mar 20 '22 at 00:07
  • That's exactly why I was asking a simple reproducing sample. – Simon Mourier Mar 20 '22 at 12:55

0 Answers0