Skip to content

Commit

Permalink
Few changes and more logic added :
Browse files Browse the repository at this point in the history
- The plugin is now loading the protocol assemblies if they're not by default
- Protocol is dumped from all the relevant assemblies instead of only one
- Added StringExtensions
- Added ReflectionExtensions
  • Loading branch information
thenameless314159 committed Aug 19, 2024
1 parent d26fcca commit b60634c
Show file tree
Hide file tree
Showing 4 changed files with 87 additions and 11 deletions.
8 changes: 1 addition & 7 deletions src/ProtocolDumper/Infrastructure/DescriptorExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -172,18 +172,12 @@ static string GetLabelFor(FieldDescriptorProto proto)
{
FieldDescriptorProto.Types.Type.Message or FieldDescriptorProto.Types.Type.Enum
=> proto.HasTypeName
? TrimTypeName(proto.TypeName) + " "
? proto.TypeName.GetLastSegment() + " "
: throw new InvalidOperationException("Missing type name for enum or message !"),
_ => GetPrimitiveTypeName(proto.Type) + " "
};
static string TrimTypeName(string typeName)
{
var lastIndexOfDot = typeName.LastIndexOf('.');
return lastIndexOfDot == -1 ? typeName : typeName[(lastIndexOfDot + 1)..];
}
static string GetPrimitiveTypeName(FieldDescriptorProto.Types.Type type) => type switch
{
FieldDescriptorProto.Types.Type.Double => "double",
Expand Down
9 changes: 9 additions & 0 deletions src/ProtocolDumper/Infrastructure/ReflectionExtensions.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
using System.Reflection;

namespace ProtocolDumper.Infrastructure;

internal static class ReflectionExtensions
{
public static bool IsProtocolAssembly(this Assembly assembly)
=> assembly.FullName?.Contains("Dofus.Protocol") ?? false;
}
15 changes: 15 additions & 0 deletions src/ProtocolDumper/Infrastructure/StringExtensions.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace ProtocolDumper.Infrastructure;
internal static class StringExtensions
{
public static string GetLastSegment(this string typeName, char separator = '.')
{
var lastIndexOf = typeName.LastIndexOf(separator);
return lastIndexOf == -1 ? typeName : typeName[(lastIndexOf + 1)..];
}
}
66 changes: 62 additions & 4 deletions src/ProtocolDumper/ProtocolDumperPlugin.cs
Original file line number Diff line number Diff line change
@@ -1,17 +1,48 @@
using BepInEx;
using UnityEngine;
using BepInEx.Logging;
using System.Reflection;
using BepInEx.Unity.IL2CPP;
using Google.Protobuf.Reflection;
using ProtocolDumper.Infrastructure;

namespace ProtocolDumper;

[BepInPlugin(MyPluginInfo.PLUGIN_GUID, MyPluginInfo.PLUGIN_NAME, MyPluginInfo.PLUGIN_VERSION)]
public class ProtocolDumperPlugin : BasePlugin
{
static readonly string ProtocolDumpPath = Path.Combine(Paths.PluginPath, "protocol");

public override void Load()
{
Log.LogInfo($"Plugin '{MyPluginInfo.PLUGIN_NAME}' has successfully been loaded!");

// First we need to make sure that we have all the protocol assemblies loaded
var gameAssembliesPath = Path.Combine(Paths.BepInExRootPath, "interop");
var gameAssemblies = Directory.GetFiles(gameAssembliesPath, "*.dll");

var protocolAssembliesPaths = gameAssemblies
.Where(static p => p.Contains("Protocol"))
.ToArray();

// Compare the protocol assemblies against the loaded assemblies
var loadedAssemblies = AppDomain.CurrentDomain.GetAssemblies();
foreach (var protocolAssemblyPath in protocolAssembliesPaths)
{
var assemblyName = Path.GetFileNameWithoutExtension(protocolAssemblyPath);
Log.LogDebug($"Checking if assembly '{assemblyName}' is loaded...");

var hasAssembly = loadedAssemblies.Any(assembly => assembly.GetName().Name?.Contains(assemblyName) ?? false);
Log.LogDebug($"Assembly '{assemblyName}' is {(hasAssembly ? "already" : "not yet")} loaded.");

if (hasAssembly)
continue;

Log.LogDebug($"Loading assembly '{protocolAssemblyPath}'...");
Assembly.LoadFrom(protocolAssemblyPath);
}

// Now we can dump the protocol files, let's create a new GameObject to do that
AddComponent<DumpProtocolBehavior>();
}

Expand All @@ -23,10 +54,37 @@ void Start()
{
try
{
var connectionMessages = Com.Ankama.Dofus.Server.Connection.Protocol.MessageReflection.Descriptor;

logger.LogInfo("Connection messages:");
logger.LogInfo(connectionMessages.ToProtoFile());
var protocolTypes = AppDomain.CurrentDomain.GetAssemblies()
.Where(ReflectionExtensions.IsProtocolAssembly)
.SelectMany(assembly => assembly.GetTypes());

foreach (var type in protocolTypes)
{
if (!type.Name.EndsWith("Reflection"))
continue;

if (type.GetProperty("Descriptor") is not { } descriptorProperty)
continue;

if (descriptorProperty.PropertyType != typeof(FileDescriptor))
continue;

if (descriptorProperty.GetValue(null) is not FileDescriptor descriptor)
continue;

logger.LogDebug($"Dumping protocol for '{descriptor.Name}'...");

var protoFile = descriptor.ToProtoFile();
var fileName = descriptor.Name.StartsWith("message")
? "message." + type.Assembly.GetName().Name!.GetLastSegment().ToLowerInvariant() + ".proto"
: descriptor.Name;

var filePath = Path.Combine(ProtocolDumpPath, fileName);
Directory.CreateDirectory(Path.GetDirectoryName(filePath)!);
File.WriteAllText(filePath, protoFile);

logger.LogInfo($"Successfully dumped protocol at '{fileName}'");
}
}
finally { Destroy(this); } // we only need to run this once
}
Expand Down

0 comments on commit b60634c

Please sign in to comment.