public void Write(ByteWriter writer) { writer.WriteInt32(SessionId); writer.MpContext().map = map; SyncSerialization.WriteSync(writer, data); }
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]); } } }
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); }
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 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); }