diff --git a/API.md b/API.md index fda8f56..e2b5579 100644 --- a/API.md +++ b/API.md @@ -44,7 +44,7 @@ - [QueueOrder_Down](#F-UnofficialMultiplayerAPI-SyncContext-QueueOrder_Down 'UnofficialMultiplayerAPI.SyncContext.QueueOrder_Down') - [WorldSelected](#F-UnofficialMultiplayerAPI-SyncContext-WorldSelected 'UnofficialMultiplayerAPI.SyncContext.WorldSelected') - [SyncMethodAttribute](#T-UnofficialMultiplayerAPI-SyncMethodAttribute 'UnofficialMultiplayerAPI.SyncMethodAttribute') - - [#ctor(context)](#M-UnofficialMultiplayerAPI-SyncMethodAttribute-#ctor-UnofficialMultiplayerAPI-SyncContext- 'UnofficialMultiplayerAPI.SyncMethodAttribute.#ctor(UnofficialMultiplayerAPI.SyncContext)') + - [#ctor(context,cancelIfAnyArgNull,cancelIfNoSelectedMapObjects,cancelIfNoSelectedWorldObjects,exposeParameters)](#M-UnofficialMultiplayerAPI-SyncMethodAttribute-#ctor-UnofficialMultiplayerAPI-SyncContext- 'UnofficialMultiplayerAPI.SyncMethodAttribute.#ctor(UnofficialMultiplayerAPI.SyncContext)') ## IMultiplayerInit `type` @@ -334,7 +334,7 @@ Instructs method to send context along with the call | Name | Type | Description | | ---- | ---- | ----------- | -| context | [UnofficialMultiplayerAPI.SyncContext](#T-UnofficialMultiplayerAPI-SyncContext 'UnofficialMultiplayerAPI.SyncContext') | Context | +| context | [UnofficialMultiplayerAPI.SyncContext](#T-UnofficialMultiplayerAPI-SyncContext 'UnofficialMultiplayerAPI.SyncContext') | [SyncContext](#T-UnofficialMultiplayerAPI-SyncContext 'UnofficialMultiplayerAPI.SyncContext') | ##### Remarks @@ -625,10 +625,10 @@ UnofficialMultiplayerAPI An attribute that is used to mark methods for syncing. -### #ctor(context) `constructor` +### #ctor(context,cancelIfAnyArgNull,cancelIfNoSelectedMapObjects,cancelIfNoSelectedWorldObjects,exposeParameters) `constructor` ##### Parameters | Name | Type | Description | | ---- | ---- | ----------- | -| context | [UnofficialMultiplayerAPI.SyncContext](#T-UnofficialMultiplayerAPI-SyncContext 'UnofficialMultiplayerAPI.SyncContext') | Context | +| context | [UnofficialMultiplayerAPI.SyncContext](#T-UnofficialMultiplayerAPI-SyncContext 'UnofficialMultiplayerAPI.SyncContext') | Context (see [SyncContext](#T-UnofficialMultiplayerAPI-SyncContext 'UnofficialMultiplayerAPI.SyncContext')) | diff --git a/Source/Client/Interfaces.cs b/Source/Client/Interfaces.cs index a100d0a..37d8b8e 100644 --- a/Source/Client/Interfaces.cs +++ b/Source/Client/Interfaces.cs @@ -32,25 +32,31 @@ public enum SyncContext public class SyncMethodAttribute : Attribute { public SyncContext context; - - /// Context + public bool cancelIfAnyArgNull = false; + public bool cancelIfNoSelectedMapObjects = false; + public bool cancelIfNoSelectedWorldObjects = false; + public int[] exposeParameters; + + /// Context (see ) + /// Instructs SyncMethod to cancel synchronization if any arg is null (see ) + /// Instructs SyncMethod to cancel synchronization if no map objects were selected during call replication(see ) + /// Instructs SyncMethod to cancel synchronization if no world objects were selected during call replication(see ) + /// A list of types to expose (see ) public SyncMethodAttribute(SyncContext context = SyncContext.None) { this.context = context; } } - public struct SyncType + public class SyncType { public readonly Type type; - public bool expose; - public bool contextMap; + public bool expose = false; + public bool contextMap = false; public SyncType(Type type) { this.type = type; - this.expose = false; - contextMap = false; } } @@ -162,7 +168,7 @@ public interface ISyncMethod /// Instructs method to send context along with the call /// /// Context is restored after method is called - /// Context + /// /// self ISyncMethod SetContext(SyncContext context); diff --git a/Source/Client/Properties/AssemblyInfo.cs b/Source/Client/Properties/AssemblyInfo.cs index 649d045..a0a2ca0 100644 --- a/Source/Client/Properties/AssemblyInfo.cs +++ b/Source/Client/Properties/AssemblyInfo.cs @@ -33,4 +33,4 @@ // by using the '*' as shown below: // [assembly: AssemblyVersion("1.0.*")] [assembly: AssemblyVersion("1.0.0.0")] -[assembly: AssemblyFileVersion("1.0.0.0")] +[assembly: AssemblyFileVersion("1.0.1.0")] diff --git a/Source/Host/ApiHost.cs b/Source/Host/ApiHost.cs index 6cfeb95..590588d 100644 --- a/Source/Host/ApiHost.cs +++ b/Source/Host/ApiHost.cs @@ -38,8 +38,56 @@ private static void RegisterAllMethods() foreach(MethodInfo method in allMethods) { - Log.Debug($"Installing {method.Name}"); - Sync.RegisterSyncMethod(method, null); + var attribute = method.TryGetAttribute(); + + Log.Debug($"Installing {method.DeclaringType.FullName}::{method}"); + int[] exposeParameters = attribute.exposeParameters; + int paramNum = method.GetParameters().Length; + + if (exposeParameters != null) + { + if (exposeParameters.Length != paramNum) + { + Log.Error($"Failed to register a method: Invalid number of parameters to expose in SyncMethod attribute applied to {method.DeclaringType.FullName}::{method}. Expected {paramNum}, got {exposeParameters.Length}"); + continue; + } + else if(exposeParameters.Any(p => p < 0 || p >= paramNum)) + { + Log.Error($"Failed to register a method: One or more indexes of parameters to expose in SyncMethod attribute applied to {method.DeclaringType.FullName}::{method} is invalid."); + continue; + } + } + + SyncMethod sm = Sync.RegisterSyncMethod(method, null); + + sm.SetContext((SyncContext)(int)attribute.context); + + if (attribute.cancelIfAnyArgNull) + sm.CancelIfAnyArgNull(); + + if (attribute.cancelIfNoSelectedMapObjects) + sm.CancelIfNoSelectedMapObjects(); + + if (attribute.cancelIfNoSelectedWorldObjects) + sm.CancelIfNoSelectedWorldObjects(); + + if(exposeParameters != null) + { + int i = 0; + + try + { + for (; i < exposeParameters.Length; i++) + { + Log.Debug($"Exposing parameter {exposeParameters[i]}"); + sm.ExposeParameter(exposeParameters[i]); + } + } + catch (Exception exc) + { + Log.Error($"An exception occurred while exposing parameter {i} ({method.GetParameters()[i]}) for method {method.DeclaringType.FullName}::{method}: {exc}"); + } + } } var initializers = allTypes.Where(t => !t.IsInterface && typeof(UnofficialMultiplayerAPI.IMultiplayerInit).IsAssignableFrom(t));