Soggy_Pancake-CodeYapper_Protobuf icon

CodeYapper Protobuf

Protobuf packets for CodeYapper

Last updated a day ago
Total downloads 8
Total rating 0 
Categories Libraries
Dependency string Soggy_Pancake-CodeYapper_Protobuf-1.0.1
Dependants 0 other packages depend on this package

This mod requires the following mods to function

Soggy_Pancake-protobuf_net-3.2.56 icon
Soggy_Pancake-protobuf_net

Provides simple access to fast and efficient "Protocol Buffers" serialization from .NET applications

Preferred version: 3.2.56
Soggy_Pancake-CodeYapper-2.2.2 icon
Soggy_Pancake-CodeYapper

A simple library to abstract away networking

Preferred version: 2.2.2

README

An optional addon for CodeYapper. This is for mod developers that need or want smaller packets than what JSON provides, but don't understand or aren't comfortable making a standard binary packet.

This mod works by creating a new base packet ProtobufPacketBase that derives from BinaryPacketBase.

Notable changes from binary packets

  • No deserialize or serialize methods need to be defined
  • Attributes must be added to each member you want to serialize

License

The license is LGPLv3


JSON to Protobuf Conversion Example

Converting from json packets to protobuf packets is fairly straightforward. I will use the example packet from CodeYapper for this example conversion. Feel free to check out the guide from the protobuf-net library itself.

public class ExamplePacket(string payload) : PacketBase
{
    public override string PacketSourceGUID => LCMPluginInfo.PLUGIN_GUID;
    
    [JsonProperty]
    public string Payload { get; set; } = payload;
}

First you need to add the attribute [ProtoContract] to your packet class. And derive from ProtobufPacketBase

[ProtoContract] <---
public class ExamplePacket(string payload) : ProtobufPacketBase
{

Next, replace all [JsonProperty] attributes with [ProtoMember(n)] where n is a unique value.

This doesn't need to be globally unique! Just per class or struct.

Now, you need to pick a unique name for your packet. This doesn't need to match the class name, but it should not match your plugin guid unless it is the only packet you plan to make! JSON packets use PacketSourceGUID as a debugging option, but binary packets use the name as their identifier!

Replace PacketSourceGUID with PacketSignature (This comes from deriving from binary packets). Some example signature names for this packet would be:

  • [PluginGUID].ExamplePacket
  • [Name or PluginName].ExamplePacket
  • [Name].[PluginName].ExamplePacket
  • [Name or PluginName].ExPkt
  • [PluginGUID].ExPkt

CodeYapper doesn't care what the name is or check for any formatting, but this pattern should help prevent any collisions from happening

Protobuf is now all set up to work properly but there will still be errors due to deriving from the new base class! The example packet's constructor requires a parameter, and there are no parameterless constructors, and codeyapper requires a parameterless constructor to instantiate your class.

The constructor of the example packet will be this:

public ExamplePacket(string payload) // <--- Copy the class definition then remove `class` and everything after the closing parenthesis
{ 
    Payload = payload; // This is now set manually here instead of on the definition of the field
}

The parenthesis and arguments of the class constructor in the example are after the class name at the top. This must be converted as shown above to allow a parameterless constructor to be added!

This is an example of a paremeterless constructor:

public ExamplePacket() { }

Note: This can still contain code! As long as it takes no arguments it is valid. Keep in mind that this is called before deserialization.

Your packet should now look something like this

[ProtoContract]
public class ExamplePacket : ProtobufPacketBase
{
    public override string PacketSignature => "Protobuf.ExamplePacket";
    
    [ProtoMember(1)]
    public string Payload { get; set; }
    
    public ExamplePacket() { }
  
    public ExamplePacket(string payload)
    {
      Payload = payload;
    }
}

All that's left to do is hook up the listener and you will have a working packet! Since this follows the same path as binary packets past this stage you should read the documentation for binary packets here.