diff --git a/Source/Client/Debug/DebugActions.cs b/Source/Client/Debug/DebugActions.cs index 09a8da90..08e84cb1 100644 --- a/Source/Client/Debug/DebugActions.cs +++ b/Source/Client/Debug/DebugActions.cs @@ -8,6 +8,7 @@ using HarmonyLib; using LudeonTK; +using Multiplayer.Client.Util; using RimWorld; using RimWorld.Planet; using UnityEngine; @@ -175,6 +176,33 @@ public static void DumpDefTypes() } } + [DebugAction(MultiplayerCategory, "Dump IRenameable Types", allowedGameStates = AllowedGameStates.Entry)] + static void DumpIRenameableTypes() + { + var synced = new List(); + var unsynced = new List(); + var methods = typeof(IRenameable).AllImplementing() + .Select(t => AccessTools.DeclaredPropertySetter(t, nameof(IRenameable.RenamableLabel))) + .AllNotNull(); + + foreach (var method in methods) + { + // Check if a method is synced or not + if (Sync.methodBaseToInternalId.ContainsKey(method)) + synced.Add(method.DeclaringType); + else + unsynced.Add(method.DeclaringType); + } + + Log.Warning("== Synced IRenameable types =="); + Log.Message(!synced.Any() ? "No types" : synced.Select(GetNameWithNamespace).Join(delimiter: "\n")); + + Log.Warning("== Unsynced IRenameable types =="); + Log.Message(!unsynced.Any() ? "No types" : unsynced.Select(GetNameWithNamespace).Join(delimiter: "\n")); + + static string GetNameWithNamespace(Type t) => t.Namespace.NullOrEmpty() ? t.Name : $"{t.Namespace}.{t.Name}"; + } + [DebugAction(MultiplayerCategory, allowedGameStates = AllowedGameStates.Playing)] static void LogAllPatch() { diff --git a/Source/Client/Syncing/Game/SyncMethods.cs b/Source/Client/Syncing/Game/SyncMethods.cs index 5790a8c9..d2351e09 100644 --- a/Source/Client/Syncing/Game/SyncMethods.cs +++ b/Source/Client/Syncing/Game/SyncMethods.cs @@ -407,6 +407,28 @@ public static void Init() SyncMethod.Register(typeof(Building_BioferriteHarvester), nameof(Building_BioferriteHarvester.EjectContents)); // Eject contents SyncMethod.Lambda(typeof(Building_BioferriteHarvester), nameof(Building_BioferriteHarvester.GetGizmos), 1); // Toggle unload SyncMethod.Lambda(typeof(Building_BioferriteHarvester), nameof(Building_BioferriteHarvester.GetGizmos), 3).SetDebugOnly(); // Dev add +1 + + // Double ExecuteWhenFinished ensures it'll load after MP Compat late patches, + // so it will have registered all its sync workers already. + LongEventHandler.ExecuteWhenFinished(() => LongEventHandler.ExecuteWhenFinished(() => + { + // Only get methods for types which we can sync. The syncing of renaming is of low enough importance + // that we don't need to worry about having errors if there's any that can't be synced + var methods = typeof(IRenameable).AllImplementing() + .Where(t => Multiplayer.serialization.CanHandle(t)) + .Select(t => AccessTools.DeclaredPropertySetter(t, nameof(IRenameable.RenamableLabel))) + .AllNotNull(); + + foreach (var method in methods) + MP.RegisterSyncMethod(method); + + // This OnRenamed method will create a storage group, which needs to be synced. + // No other vanilla rename dialogs need syncing OnRenamed, but modded ones potentially could need it. + MP.RegisterSyncMethod(typeof(Dialog_RenameBuildingStorage_CreateNew), nameof(Dialog_RenameBuildingStorage_CreateNew.OnRenamed)) + .TransformTarget(Serializer.New( + (Dialog_RenameBuildingStorage_CreateNew dialog) => dialog.building, + (IStorageGroupMember member) => new Dialog_RenameBuildingStorage_CreateNew(member))); + })); } [MpPrefix(typeof(PawnColumnWorker_CopyPasteTimetable), nameof(PawnColumnWorker_CopyPasteTimetable.PasteTo))]