feat(sdk): migrate to EventBus 2.0
Replace the legacy EventBase runtime with generated multi-bus bindings and explicit scheduling. Migrate app, data, network, demo, and mod consumers; add generated network-event registration and owner-scoped mod content overrides.
This commit is contained in:
@@ -37,7 +37,6 @@ namespace ShrinkShared.CodeGen
|
||||
|
||||
try
|
||||
{
|
||||
InjectEventBusAutoRegister(module);
|
||||
InjectShrinkCommandRegistry(module);
|
||||
InjectShrinkNetworkRegistry(module);
|
||||
InjectShrinkAppRegistry(module);
|
||||
@@ -75,56 +74,6 @@ namespace ShrinkShared.CodeGen
|
||||
AddAssemblyTypeArrayAttribute(module, registryCtor, subscriberTypes);
|
||||
}
|
||||
|
||||
private void InjectEventBusAutoRegister(ModuleDefinition module)
|
||||
{
|
||||
var subscriberType = FindType(module, "ShrinkEventBus.EventBusSubscriberAttribute", "ShrinkEventBus.Runtime");
|
||||
var eventBusType = FindType(module, "ShrinkEventBus.EventBus", "ShrinkEventBus.Runtime");
|
||||
var subscribeAttributeType = FindType(module, "ShrinkEventBus.EventSubscribeAttribute", "ShrinkEventBus.Runtime");
|
||||
var staticRegistryCtor = FindTypeArrayConstructor(module,
|
||||
"ShrinkEventBus.EventBusStaticRegistryAttribute",
|
||||
"ShrinkEventBus.Runtime");
|
||||
if (subscriberType == null || eventBusType == null)
|
||||
return;
|
||||
|
||||
var eventBusTypeDef = eventBusType.Resolve();
|
||||
var autoRegisterMethod = eventBusTypeDef?.Methods.FirstOrDefault(method =>
|
||||
method.Name == "AutoRegister" &&
|
||||
method.IsStatic &&
|
||||
method.Parameters.Count == 1);
|
||||
var unregisterMethod = eventBusTypeDef?.Methods.FirstOrDefault(method =>
|
||||
method.Name == "UnregisterInstance" &&
|
||||
method.IsStatic &&
|
||||
method.Parameters.Count == 1);
|
||||
if (autoRegisterMethod == null || unregisterMethod == null)
|
||||
return;
|
||||
|
||||
var autoRegisterMethodRef = module.ImportReference(autoRegisterMethod);
|
||||
var unregisterMethodRef = module.ImportReference(unregisterMethod);
|
||||
|
||||
foreach (var type in module.Types)
|
||||
{
|
||||
if (!HasAttribute(type, subscriberType) || !InheritsFromMonoBehaviour(type))
|
||||
continue;
|
||||
|
||||
if (subscribeAttributeType != null && !HasInstanceSubscribeMethod(type, subscribeAttributeType))
|
||||
continue;
|
||||
|
||||
InjectAutoRegister(type, module, autoRegisterMethodRef);
|
||||
InjectAutoUnregister(type, module, unregisterMethodRef);
|
||||
}
|
||||
|
||||
if (subscribeAttributeType != null && staticRegistryCtor != null)
|
||||
{
|
||||
var staticSubscriberTypes = module.Types
|
||||
.Where(type => HasAttribute(type, subscriberType))
|
||||
.Where(type => type.Methods.Any(method => method.IsStatic && HasAttribute(method, subscribeAttributeType)))
|
||||
.Select(type => module.ImportReference(type))
|
||||
.ToArray();
|
||||
if (staticSubscriberTypes.Length > 0)
|
||||
AddAssemblyTypeArrayAttribute(module, staticRegistryCtor, staticSubscriberTypes);
|
||||
}
|
||||
}
|
||||
|
||||
private void InjectShrinkNetworkRegistry(ModuleDefinition module)
|
||||
{
|
||||
var messageAttributeType = FindType(module, "ShrinkNetwork.ShrinkNetworkMessageAttribute", "ShrinkNetwork.Runtime");
|
||||
@@ -180,164 +129,6 @@ namespace ShrinkShared.CodeGen
|
||||
return provider.CustomAttributes.Any(attribute => attribute.AttributeType.FullName == expectedAttributeType.FullName);
|
||||
}
|
||||
|
||||
private static bool HasInstanceSubscribeMethod(TypeDefinition type, TypeReference subscribeAttributeType)
|
||||
{
|
||||
var current = type;
|
||||
while (current != null && current.Name != "MonoBehaviour")
|
||||
{
|
||||
if (current.Methods.Any(method => !method.IsStatic && HasAttribute(method, subscribeAttributeType)))
|
||||
return true;
|
||||
|
||||
var baseTypeRef = current.BaseType;
|
||||
if (baseTypeRef == null)
|
||||
return false;
|
||||
|
||||
TypeDefinition? resolvedBase;
|
||||
try
|
||||
{
|
||||
resolvedBase = baseTypeRef.Resolve();
|
||||
}
|
||||
catch
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
if (resolvedBase == null)
|
||||
return true;
|
||||
|
||||
current = resolvedBase;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
private static bool InheritsFromMonoBehaviour(TypeDefinition type)
|
||||
{
|
||||
var current = type.BaseType;
|
||||
while (current != null)
|
||||
{
|
||||
if (current.Name == "MonoBehaviour")
|
||||
return true;
|
||||
|
||||
try
|
||||
{
|
||||
current = current.Resolve()?.BaseType;
|
||||
}
|
||||
catch
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
private static void InjectAutoRegister(TypeDefinition type, ModuleDefinition module, MethodReference autoRegisterMethodRef)
|
||||
{
|
||||
var awake = type.Methods.FirstOrDefault(method => method.Name == "Awake" && !method.IsStatic);
|
||||
if (awake == null)
|
||||
{
|
||||
var baseAwakeRef = FindBaseMethodReference(type, "Awake", module);
|
||||
if (baseAwakeRef != null)
|
||||
{
|
||||
awake = new MethodDefinition("Awake",
|
||||
MethodAttributes.Family | MethodAttributes.HideBySig | MethodAttributes.Virtual,
|
||||
module.TypeSystem.Void);
|
||||
var il = awake.Body.GetILProcessor();
|
||||
il.Emit(Mono.Cecil.Cil.OpCodes.Ldarg_0);
|
||||
il.Emit(Mono.Cecil.Cil.OpCodes.Call, baseAwakeRef);
|
||||
il.Emit(Mono.Cecil.Cil.OpCodes.Ldarg_0);
|
||||
il.Emit(Mono.Cecil.Cil.OpCodes.Call, autoRegisterMethodRef);
|
||||
il.Emit(Mono.Cecil.Cil.OpCodes.Ret);
|
||||
type.Methods.Add(awake);
|
||||
return;
|
||||
}
|
||||
|
||||
awake = new MethodDefinition("Awake",
|
||||
MethodAttributes.Private | MethodAttributes.HideBySig,
|
||||
module.TypeSystem.Void);
|
||||
var retIl = awake.Body.GetILProcessor();
|
||||
retIl.Emit(Mono.Cecil.Cil.OpCodes.Ret);
|
||||
type.Methods.Add(awake);
|
||||
}
|
||||
|
||||
var processor = awake.Body.GetILProcessor();
|
||||
var instructions = new List<Mono.Cecil.Cil.Instruction>
|
||||
{
|
||||
processor.Create(Mono.Cecil.Cil.OpCodes.Ldarg_0),
|
||||
processor.Create(Mono.Cecil.Cil.OpCodes.Call, autoRegisterMethodRef),
|
||||
processor.Create(Mono.Cecil.Cil.OpCodes.Nop)
|
||||
};
|
||||
instructions.Reverse();
|
||||
instructions.ForEach(instruction => processor.Body.Instructions.Insert(0, instruction));
|
||||
}
|
||||
|
||||
private static void InjectAutoUnregister(TypeDefinition type, ModuleDefinition module, MethodReference unregisterMethodRef)
|
||||
{
|
||||
var onDestroy = type.Methods.FirstOrDefault(method => method.Name == "OnDestroy" && !method.IsStatic);
|
||||
if (onDestroy == null)
|
||||
{
|
||||
var baseOnDestroyRef = FindBaseMethodReference(type, "OnDestroy", module);
|
||||
if (baseOnDestroyRef != null)
|
||||
{
|
||||
onDestroy = new MethodDefinition("OnDestroy",
|
||||
MethodAttributes.Family | MethodAttributes.HideBySig | MethodAttributes.Virtual,
|
||||
module.TypeSystem.Void);
|
||||
var il = onDestroy.Body.GetILProcessor();
|
||||
il.Emit(Mono.Cecil.Cil.OpCodes.Ldarg_0);
|
||||
il.Emit(Mono.Cecil.Cil.OpCodes.Call, unregisterMethodRef);
|
||||
il.Emit(Mono.Cecil.Cil.OpCodes.Ldarg_0);
|
||||
il.Emit(Mono.Cecil.Cil.OpCodes.Call, baseOnDestroyRef);
|
||||
il.Emit(Mono.Cecil.Cil.OpCodes.Ret);
|
||||
type.Methods.Add(onDestroy);
|
||||
return;
|
||||
}
|
||||
|
||||
onDestroy = new MethodDefinition("OnDestroy",
|
||||
MethodAttributes.Private | MethodAttributes.HideBySig,
|
||||
module.TypeSystem.Void);
|
||||
var retIl = onDestroy.Body.GetILProcessor();
|
||||
retIl.Emit(Mono.Cecil.Cil.OpCodes.Ret);
|
||||
type.Methods.Add(onDestroy);
|
||||
}
|
||||
|
||||
var processor = onDestroy.Body.GetILProcessor();
|
||||
var instructions = new List<Mono.Cecil.Cil.Instruction>
|
||||
{
|
||||
processor.Create(Mono.Cecil.Cil.OpCodes.Ldarg_0),
|
||||
processor.Create(Mono.Cecil.Cil.OpCodes.Call, unregisterMethodRef),
|
||||
processor.Create(Mono.Cecil.Cil.OpCodes.Nop)
|
||||
};
|
||||
instructions.Reverse();
|
||||
instructions.ForEach(instruction => processor.Body.Instructions.Insert(0, instruction));
|
||||
}
|
||||
|
||||
private static MethodReference? FindBaseMethodReference(TypeDefinition type, string methodName, ModuleDefinition module)
|
||||
{
|
||||
try
|
||||
{
|
||||
var baseTypeRef = type.BaseType;
|
||||
while (baseTypeRef != null)
|
||||
{
|
||||
var baseTypeDef = baseTypeRef.Resolve();
|
||||
if (baseTypeDef == null)
|
||||
break;
|
||||
|
||||
var method = baseTypeDef.Methods.FirstOrDefault(candidate =>
|
||||
candidate.Name == methodName && !candidate.IsStatic && candidate.IsVirtual);
|
||||
if (method != null)
|
||||
return module.ImportReference(method);
|
||||
|
||||
baseTypeRef = baseTypeDef.BaseType;
|
||||
}
|
||||
}
|
||||
catch
|
||||
{
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
private static void AddAssemblyTypeArrayAttribute(ModuleDefinition module, MethodReference ctor, TypeReference[] types)
|
||||
{
|
||||
var attribute = new CustomAttribute(ctor);
|
||||
|
||||
Reference in New Issue
Block a user