Beispiel #1
0
        public void Write(ByteWriter writer)
        {
            writer.WriteInt32(SessionId);
            writer.MpContext().map = map;

            SyncSerialization.WriteSync(writer, data);
        }
Beispiel #2
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]);
                }
            }
        }
Beispiel #3
0
        public void Read(ByteReader reader)
        {
            SessionId = reader.ReadInt32();
            reader.MpContext().map = map;

            data = SyncSerialization.ReadSync <RitualData>(reader);
            data.assignments.session = this;
        }
        protected virtual object ReadTarget(ByteReader data)
        {
            if (targetType != null)
            {
                return(SyncSerialization.ReadSyncObject(data, targetType));
            }

            return(null);
        }
Beispiel #5
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)
                       ));
        }
Beispiel #6
0
        public static TempGameData SaveAndReload()
        {
            //SimpleProfiler.Start();
            Multiplayer.reloading = true;

            var worldGridSaved     = Find.WorldGrid;
            var worldRendererSaved = Find.World.renderer;
            var tweenedPos         = new Dictionary <int, Vector3>();
            var drawers            = new Dictionary <int, MapDrawer>();
            var localFactionId     = Multiplayer.RealPlayerFaction.loadID;
            var mapCmds            = new Dictionary <int, Queue <ScheduledCommand> >();
            var planetRenderMode   = Find.World.renderer.wantedMode;
            var chatWindow         = ChatWindow.Opened;

            var selectedData = new ByteWriter();

            SyncSerialization.WriteSync(selectedData, Find.Selector.selected.OfType <ISelectable>().ToList());

            //Multiplayer.RealPlayerFaction = Multiplayer.DummyFaction;

            foreach (Map map in Find.Maps)
            {
                drawers[map.uniqueID] = map.mapDrawer;
                //RebuildRegionsAndRoomsPatch.copyFrom[map.uniqueID] = map.regionGrid;

                foreach (Pawn p in map.mapPawns.AllPawnsSpawned)
                {
                    tweenedPos[p.thingIDNumber] = p.drawer.tweener.tweenedPos;
                }

                mapCmds[map.uniqueID] = map.AsyncTime().cmds;
            }

            mapCmds[ScheduledCommand.Global] = Multiplayer.WorldComp.cmds;

            DeepProfiler.Start("Multiplayer SaveAndReload: Save");
            //WriteElementPatch.cachedVals = new Dictionary<string, object>();
            //WriteElementPatch.id = 0;
            var gameData = SaveGameData();

            DeepProfiler.End();
            //Log.Message($"Saving took {WriteElementPatch.cachedVals.Count} {WriteElementPatch.cachedVals.FirstOrDefault()}");

            MapDrawerRegenPatch.copyFrom      = drawers;
            WorldGridCachePatch.copyFrom      = worldGridSaved;
            WorldGridExposeDataPatch.copyFrom = worldGridSaved;
            WorldRendererCachePatch.copyFrom  = worldRendererSaved;

            MusicManagerPlay musicManager = null;

            if (Find.MusicManagerPlay.gameObjectCreated)
            {
                var musicTransform = Find.MusicManagerPlay.audioSource.transform;
                if (musicTransform.parent == Find.Root.soundRoot.sourcePool.sourcePoolCamera.cameraSourcesContainer.transform)
                {
                    musicTransform.parent = musicTransform.parent.parent;
                }

                musicManager = Find.MusicManagerPlay;
            }

            //SpawnSetupPatch.total = 0;
            //SpawnSetupPatch.total2 = new long[SpawnSetupPatch.total2.Length];

            LoadInMainThread(gameData);

            if (musicManager != null)
            {
                Current.Root_Play.musicManagerPlay = musicManager;
            }

            Multiplayer.RealPlayerFaction = Find.FactionManager.GetById(localFactionId);

            foreach (Map m in Find.Maps)
            {
                foreach (Pawn p in m.mapPawns.AllPawnsSpawned)
                {
                    if (tweenedPos.TryGetValue(p.thingIDNumber, out Vector3 v))
                    {
                        p.drawer.tweener.tweenedPos    = v;
                        p.drawer.tweener.lastDrawFrame = Time.frameCount;
                    }
                }

                m.AsyncTime().cmds = mapCmds[m.uniqueID];
            }

            if (chatWindow != null)
            {
                Find.WindowStack.Add_KeepRect(chatWindow);
            }

            var selectedReader = new ByteReader(selectedData.ToArray())
            {
                context = new MpContext()
                {
                    map = Find.CurrentMap
                }
            };

            Find.Selector.selected = SyncSerialization.ReadSync <List <ISelectable> >(selectedReader).AllNotNull().Cast <object>().ToList();

            Find.World.renderer.wantedMode = planetRenderMode;
            Multiplayer.WorldComp.cmds     = mapCmds[ScheduledCommand.Global];

            Multiplayer.reloading = false;
            //SimpleProfiler.Pause();

            //Log.Message($"allocs {(double)SpawnSetupPatch.total2.Sum() / Stopwatch.Frequency * 1000} ({SpawnSetupPatch.total2.Select((l,i) => $"{SpawnSetupPatch.methods[i]}: {(double)l / Stopwatch.Frequency * 1000}").Join(delimiter: "\n")}) {SpawnSetupPatch.total} {AllocsPrefixClass.allocs} {CustomXmlElement.n} {CustomXmlElement.m} {CustomXmlElement.n - CustomXmlElement.m} {(double)CustomXmlElement.n/CustomXmlElement.m}");

            return(gameData);
        }
        /// <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);
        }
        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);
        }