示例#1
0
        private static void WriteDelegate(ByteWriter writer, Delegate del)
        {
            writer.WriteBool(del != null);
            if (del == null)
            {
                return;
            }

            SyncSerialization.WriteSync(writer, del.GetType());
            SyncSerialization.WriteSync(writer, del.Method.DeclaringType);
            SyncSerialization.WriteSync(writer, del.Method.Name); // todo Handle the signature for ambiguous methods

            writer.WriteBool(del.Target != null);
            if (del.Target != null)
            {
                var targetType = del.Target.GetType();
                SyncSerialization.WriteSync(writer, targetType);

                var fieldPaths = GetFields(targetType).ToArray();
                var fieldTypes = fieldPaths.Select(path => MpReflection.PathType(path)).ToArray();

                void SyncObj(object obj, Type type, string debugInfo)
                {
                    if (type.IsCompilerGenerated())
                    {
                        return;
                    }

                    if (writer is LoggingByteWriter log1)
                    {
                        log1.Log.Enter(debugInfo);
                    }

                    try
                    {
                        if (typeof(Delegate).IsAssignableFrom(type))
                        {
                            WriteDelegate(writer, (Delegate)obj);
                        }
                        else
                        {
                            SyncSerialization.WriteSyncObject(writer, obj, type);
                        }
                    }
                    finally
                    {
                        if (writer is LoggingByteWriter log2)
                        {
                            log2.Log.Exit();
                        }
                    }
                }

                for (int i = 0; i < fieldPaths.Length; i++)
                {
                    SyncObj(del.Target.GetPropertyOrField(fieldPaths[i]), fieldTypes[i], fieldPaths[i]);
                }
            }
        }
        /// <summary>
        /// Returns whether the original should be cancelled
        /// </summary>
        public bool DoSync(object target, params object[] args)
        {
            if (!Multiplayer.ShouldSync)
            {
                return(false);
            }

            // todo limit per specific target/argument
            //if (Utils.MillisNow - lastSendTime < minTime)
            //    return true;

            LoggingByteWriter writer  = new LoggingByteWriter();
            MpContext         context = writer.MpContext();

            writer.Log.Node(ToString());

            writer.WriteInt32(syncId);
            SyncUtil.WriteContext(this, writer);

            var map = context.map;

            void SyncObj(object obj, SyncType type, string debugInfo)
            {
                writer.Log.Enter(debugInfo);

                try
                {
                    SyncSerialization.WriteSyncObject(writer, obj, type);
                }
                finally
                {
                    writer.Log.Exit();
                }

                if (type.contextMap && obj is Map contextMap)
                {
                    map = contextMap;
                }

                if (context.map is Map newMap)
                {
                    if (map != null && map != newMap)
                    {
                        throw new Exception($"{this}: map mismatch ({map?.uniqueID} and {newMap?.uniqueID})");
                    }
                    map = newMap;
                }
            }

            if (targetTransformer != null)
            {
                SyncObj(targetTransformer.Writer.DynamicInvoke(target, target, args), targetTransformer.NetworkType, "Target (transformed)");
            }
            else
            {
                WriteTarget(target, args, SyncObj);
            }

            for (int i = 0; i < argTypes.Length; i++)
            {
                if (argTransformers[i] == null)
                {
                    SyncObj(args[i], argTypes[i], $"Arg {i} {argNames[i]}");
                }
            }

            for (int i = 0; i < argTypes.Length; i++)
            {
                if (argTransformers[i] is { } trans)
                {
                    SyncObj(trans.Writer.DynamicInvoke(args[i], target, args), trans.NetworkType, $"Arg {i} {argNames[i]} (transformed)");
                }
            }

            int mapId = map?.uniqueID ?? ScheduledCommand.Global;

            writer.Log.Node("Map id: " + mapId);
            Multiplayer.WriterLog.AddCurrentNode(writer);

            Multiplayer.Client.SendCommand(CommandType.Sync, mapId, writer.ToArray());

            lastSendTime = Utils.MillisNow;

            return(true);
        }