protected virtual object ReadTarget(ByteReader data)
        {
            if (targetType != null)
            {
                return(SyncSerialization.ReadSyncObject(data, targetType));
            }

            return(null);
        }
Beispiel #2
0
        private static Delegate ReadDelegate(ByteReader reader)
        {
            if (!reader.ReadBool())
            {
                return(null);
            }

            var    delegateType = SyncSerialization.ReadSync <Type>(reader);
            var    type         = SyncSerialization.ReadSync <Type>(reader);
            var    methodName   = SyncSerialization.ReadSync <string>(reader);
            object target       = null;

            if (reader.ReadBool())
            {
                var targetType = SyncSerialization.ReadSync <Type>(reader);
                var fieldPaths = GetFields(targetType).ToArray();
                var fieldTypes = fieldPaths.Select(path => MpReflection.PathType(path)).ToArray();

                target = Activator.CreateInstance(targetType);

                for (int i = 0; i < fieldPaths.Length; i++)
                {
                    string path       = fieldPaths[i];
                    string noTypePath = MpReflection.RemoveType(path);
                    Type   fieldType  = fieldTypes[i];
                    object value;

                    if (fieldType.IsCompilerGenerated())
                    {
                        value = Activator.CreateInstance(fieldType);
                    }
                    else if (typeof(Delegate).IsAssignableFrom(fieldType))
                    {
                        value = ReadDelegate(reader);
                    }
                    else
                    {
                        value = SyncSerialization.ReadSyncObject(reader, fieldType);
                    }

                    MpReflection.SetValue(target, path, value);
                }
            }

            return(Delegate.CreateDelegate(
                       delegateType,
                       target,
                       AccessTools.Method(type, methodName)
                       ));
        }
        public override void Handle(ByteReader data)
        {
            object target;

            if (targetTransformer != null)
            {
                target = targetTransformer.Reader.DynamicInvoke(SyncSerialization.ReadSyncObject(data, targetTransformer.NetworkType));
            }
            else
            {
                target = ReadTarget(data);
            }

            if (targetType != null && target == null)
            {
                MpLog.Debug($"SyncMethod {this} read target null");
                return;
            }

            if (!instancePath.NullOrEmpty())
            {
                target = target.GetPropertyOrField(instancePath);
            }

            var args = new object[argTypes.Length];

            for (int i = 0; i < argTypes.Length; i++)
            {
                if (argTransformers[i] == null)
                {
                    args[i] = SyncSerialization.ReadSyncObject(data, argTypes[i]);
                }
            }

            for (int i = 0; i < argTypes.Length; i++)
            {
                if (argTransformers[i] is { } trans)
                {
                    args[i] = trans.Reader.DynamicInvoke(SyncSerialization.ReadSyncObject(data, trans.NetworkType));
                }
            }

            if (cancelIfAnyArgNull && args.Any(a => a == null))
            {
                return;
            }

            if (context.HasFlag(SyncContext.MapSelected) && cancelIfNoSelectedMapObjects && Find.Selector.selected.Count == 0)
            {
                return;
            }

            if (context.HasFlag(SyncContext.WorldSelected) && cancelIfNoSelectedWorldObjects && Find.WorldSelector.selected.Count == 0)
            {
                return;
            }

            beforeCall?.Invoke(target, args);

            MpLog.Debug($"Invoked {method} on {target} with {args.Length} params {args.ToStringSafeEnumerable()}");
            method.Invoke(target, args);

            afterCall?.Invoke(target, args);
        }