Skip to content

Commit

Permalink
fix(server): fix packet writer to more closely match the Godot API
Browse files Browse the repository at this point in the history
  • Loading branch information
DanielMcAssey committed Jan 11, 2025
1 parent 6cf3f23 commit e4b2b4f
Show file tree
Hide file tree
Showing 4 changed files with 68 additions and 66 deletions.
1 change: 0 additions & 1 deletion GLOKON.Baiters.Core/BaitersServer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -113,7 +113,6 @@ public virtual async Task RunAsync(CancellationToken cancellationToken)
break;
}

SteamClient.RunCallbacks();
ReceivePackets();

foreach (var actor in _actors)
Expand Down
19 changes: 11 additions & 8 deletions GLOKON.Baiters.GodotInterop/GodotReader.cs
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ limitations under the License.
*/
using GLOKON.Baiters.GodotInterop.Models;
using System.Numerics;
using System.Text;

namespace GLOKON.Baiters.GodotInterop
{
Expand Down Expand Up @@ -88,7 +89,7 @@ private static double ReadFloat(BinaryReader reader, int flags)

private static bool ReadBool(BinaryReader reader)
{
return reader.ReadInt32() != 0;
return reader.ReadUInt32() != 0;
}

private static Quaternion ReadQuaternion(BinaryReader reader)
Expand Down Expand Up @@ -119,33 +120,34 @@ private static long ReadInt(BinaryReader reader, int flags)
{
if ((flags & 1) == 1)
{
return reader.ReadInt64();
return (long)reader.ReadUInt64();
}
else
{
return reader.ReadInt32();
return (int)reader.ReadUInt32();
}
}

private static string ReadString(BinaryReader reader)
{
int stringLength = reader.ReadInt32();
char[] stringValue = reader.ReadChars(stringLength);
int stringLength = (int)reader.ReadUInt32();
string stringValue = Encoding.UTF8.GetString(reader.ReadBytes(stringLength));

// this field is padded to 4 bytes
if (4 - ((int)reader.BaseStream.Position % 4) != 4)
{
reader.ReadBytes(4 - ((int)reader.BaseStream.Position % 4));
}

return new string(stringValue);
return stringValue;
}

private static Dictionary<int, object> ReadArray(BinaryReader reader)
{
Dictionary<int, object> array = [];

int elementCount = reader.ReadInt32() & 0x7FFFFFFF;
int elementCount = (int)reader.ReadUInt32();
elementCount &= 0x7FFFFFFF;

for (int i = 0; i < elementCount; i++)
{
Expand All @@ -159,7 +161,8 @@ private static Dictionary<string, object> ReadDictionary(BinaryReader reader)
{
Dictionary<string, object> dic = [];

int elementCount = reader.ReadInt32() & 0x7FFFFFFF;
int elementCount = (int)reader.ReadUInt32();
elementCount &= 0x7FFFFFFF;

for (int i = 0; i < elementCount; i++)
{
Expand Down
4 changes: 3 additions & 1 deletion GLOKON.Baiters.GodotInterop/GodotTypes.cs
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,8 @@ internal enum GodotTypes
RID = 16, // ns
Object = 17, //ns
Dictionary = 18,
Array = 19
Array = 19,
Long = 65538,
Double = 65539,
}
}
110 changes: 54 additions & 56 deletions GLOKON.Baiters.GodotInterop/GodotWriter.cs
Original file line number Diff line number Diff line change
Expand Up @@ -30,123 +30,122 @@ public static byte[] WritePacket(Dictionary<string, object> packet)

using (var writer = new BinaryWriter(stream, Encoding.UTF8))
{
WriteDictionary(packet, writer);
Write(packet, writer);
}

return stream.ToArray();
}

private static void WriteAny(object packet, BinaryWriter writer)
private static void WriteVariant(object packet, BinaryWriter writer)
{
if (packet == null)
{
writer.Write(0);
}
else if (packet is Dictionary<string, object> pktStrDict)
{
WriteDictionary(pktStrDict, writer);
Write(pktStrDict, writer);
}
else if (packet is string pktString)
{
WriteString(pktString, writer);
Write(pktString, writer);
}
else if (packet is int pktInt)
{
WriteInt(pktInt, writer);
Write(pktInt, writer);
}
else if (packet is long pktLong)
{
WriteLong(pktLong, writer);
Write(pktLong, writer);
}
else if (packet is float pktSingle)
{
WriteSingle(pktSingle, writer);
Write(pktSingle, writer);
}
else if (packet is double pktDouble)
{
WriteDouble(pktDouble, writer);
Write(pktDouble, writer);
}
else if (packet is bool pktBool)
{
WriteBool(pktBool, writer);
Write(pktBool, writer);
}
else if (packet is Dictionary<int, object> pktIntDict)
{
WriteArray(pktIntDict, writer);
Write(pktIntDict, writer);
}
else if (packet is Vector3 pktVect3)
{
WriteVector3(pktVect3, writer);
Write(pktVect3, writer);
}
else if (packet is Vector2 pktVect2)
{
WriteVector2(pktVect2, writer);
Write(pktVect2, writer);
}
else
{
throw new Exception("Unknown type: " + packet.GetType());
}
}

private static void WriteVector2(Vector2 packet, BinaryWriter writer)
private static void Write(GodotTypes type, BinaryWriter writer)
{
writer.Write((int)GodotTypes.Vector2);
writer.Write(packet.X);
writer.Write(packet.Y);
writer.Write(BitConverter.GetBytes((uint)type));
}

private static void WriteVector3(Vector3 packet, BinaryWriter writer)
private static void Write(Vector2 packet, BinaryWriter writer)
{
writer.Write((int)GodotTypes.Vector3);
writer.Write(packet.X);
writer.Write(packet.Y);
writer.Write(packet.Z);
Write(GodotTypes.Vector2, writer);
writer.Write(BitConverter.GetBytes(packet.X));
writer.Write(BitConverter.GetBytes(packet.Y));
}

private static void WriteBool(bool packet, BinaryWriter writer)
private static void Write(Vector3 packet, BinaryWriter writer)
{
writer.Write((int)GodotTypes.Bool);
writer.Write(packet ? 1 : 0);
Write(GodotTypes.Vector3, writer);
writer.Write(BitConverter.GetBytes(packet.X));
writer.Write(BitConverter.GetBytes(packet.Y));
writer.Write(BitConverter.GetBytes(packet.Z));
}

private static void WriteInt(int packet, BinaryWriter writer)
private static void Write(bool packet, BinaryWriter writer)
{
writer.Write((int)GodotTypes.Int);
writer.Write(packet);
Write(GodotTypes.Bool, writer);
writer.Write(BitConverter.GetBytes((uint)(packet ? 1 : 0)));
}

private static void WriteLong(long packet, BinaryWriter writer)
private static void Write(int packet, BinaryWriter writer)
{
writer.Write((int)65538); // write the int value header! this is the same as above but with the 64 bit header!
writer.Write(packet);
Write(GodotTypes.Int, writer);
writer.Write(BitConverter.GetBytes((uint)packet));
}

private static void WriteSingle(float packet, BinaryWriter writer)
private static void Write(long packet, BinaryWriter writer)
{
writer.Write((int)GodotTypes.Float);
writer.Write((float)packet);
Write(GodotTypes.Long, writer);
writer.Write(BitConverter.GetBytes((ulong)packet));
}

private static void WriteDouble(double packet, BinaryWriter writer)
private static void Write(float packet, BinaryWriter writer)
{
writer.Write((int)65539);// write the float value header! this is the same as above but with the 64 bit header!
writer.Write((double)packet);
Write(GodotTypes.Float, writer);
writer.Write(BitConverter.GetBytes(packet));
}

private static void WriteString(string packet, BinaryWriter writer)
private static void Write(double packet, BinaryWriter writer)
{
writer.Write((int)GodotTypes.String);

byte[] bytes = Encoding.UTF8.GetBytes(packet);

writer.Write((int)bytes.Length);
// get the ammount to pad by!
Write(GodotTypes.Double, writer);
writer.Write(BitConverter.GetBytes(packet));
}

// Step 3: Write the actual bytes of the string
writer.Write(bytes);
private static void Write(string packet, BinaryWriter writer)
{
Write(GodotTypes.String, writer);
writer.Write(BitConverter.GetBytes((uint)packet.Length)); // Length
writer.Write(Encoding.UTF8.GetBytes(packet)); // String Content

// Step 4: Calculate padding needed to make the total length a multiple of 4
int padding = (4 - (bytes.Length % 4)) % 4; // Calculate padding
int padding = (4 - (packet.Length % 4)) % 4;

// Step 5: Write padding bytes (if needed)
for (int i = 0; i < padding; i++)
Expand All @@ -155,27 +154,26 @@ private static void WriteString(string packet, BinaryWriter writer)
}
}

private static void WriteArray(Dictionary<int, object> packet, BinaryWriter writer)
private static void Write(Dictionary<int, object> packet, BinaryWriter writer)
{
// because we have a dic we need to write the correct byte info!
writer.Write((int)GodotTypes.Array);
writer.Write((int)packet.Count);
Write(GodotTypes.Array, writer);
writer.Write(BitConverter.GetBytes((uint)packet.Count));

for (int i = 0; i < packet.Count; i++)
{
WriteAny(packet[i], writer);
WriteVariant(packet[i], writer);
}
}

private static void WriteDictionary(Dictionary<string, object> packet, BinaryWriter writer)
private static void Write(Dictionary<string, object> packet, BinaryWriter writer)
{
writer.Write((int)GodotTypes.Dictionary);
writer.Write((int)packet.Count);
Write(GodotTypes.Dictionary, writer);
writer.Write(BitConverter.GetBytes((uint)packet.Count));

foreach (var pair in packet)
{
WriteAny(pair.Key, writer);
WriteAny(pair.Value, writer);
WriteVariant(pair.Key, writer);
WriteVariant(pair.Value, writer);
}
}
}
Expand Down

0 comments on commit e4b2b4f

Please sign in to comment.