Beispiel #1
0
        // todo support methods with arguments (currently there has been no need for it)
        public static SyncDelegate RegisterSyncDelegate(Type inType, string nestedType, string methodName, string[] fields, Type[] args = null)
        {
            string typeName = $"{inType}+{nestedType}";
            Type   type     = MpReflection.GetTypeByName(typeName);

            if (type == null)
            {
                throw new Exception($"Couldn't find type {typeName}");
            }

            MethodInfo method = AccessTools.Method(type, methodName, args);

            if (method == null)
            {
                throw new Exception($"Couldn't find method {typeName}::{methodName}");
            }

            MpUtil.MarkNoInlining(method);

            SyncDelegate handler = new SyncDelegate(type, method, fields);

            syncMethods[handler.method] = handler;
            handlers.Add(handler);

            PatchMethodForSync(method);

            return(handler);
        }
Beispiel #2
0
        public static string MethodNameFromAddr(long addr, bool harmonyOriginals)
        {
            var domain = DomainPtr;
            var ji     = mono_jit_info_table_find(domain, (IntPtr)addr);

            if (ji == IntPtr.Zero)
            {
                return(null);
            }

            var ptrToPrint = mono_jit_info_get_method(ji);
            var codeStart  = (long)mono_jit_info_get_code_start(ji);

            if (harmonyOriginals)
            {
                var original = MpUtil.GetOriginalFromHarmonyReplacement(codeStart);
                if (original != null)
                {
                    ptrToPrint = original.MethodHandle.Value;
                }
            }

            var name = mono_debug_print_stack_frame(ptrToPrint, -1, domain);

            return(string.IsNullOrEmpty(name) ? null : name);
        }
Beispiel #3
0
        static void DrawSkippingWindow()
        {
            if (Multiplayer.Client == null || TickPatch.skipTo < 0)
            {
                return;
            }

            string text        = $"{"MpSimulating".Translate()}{MpUtil.FixedEllipsis()}";
            float  textWidth   = Text.CalcSize(text).x;
            float  windowWidth = Math.Max(240f, textWidth + 40f);
            Rect   rect        = new Rect(0, 0, windowWidth, 75f).CenterOn(new Rect(0, 0, UI.screenWidth, UI.screenHeight));

            if (Multiplayer.IsReplay && !TickPatch.disableSkipCancel && Event.current.type == EventType.KeyUp && Event.current.keyCode == KeyCode.Escape)
            {
                TickPatch.ClearSkipping();
                Event.current.Use();
            }

            Find.WindowStack.ImmediateWindow(SkippingWindowId, rect, WindowLayer.Super, () =>
            {
                Text.Anchor = TextAnchor.MiddleCenter;
                Text.Font   = GameFont.Small;
                Widgets.Label(rect.AtZero(), text);
                Text.Anchor = TextAnchor.UpperLeft;
            }, absorbInputAroundWindow: true);
        }
Beispiel #4
0
        public override void DoWindowContents(Rect inRect)
        {
            string label = IsConnecting ? (ConnectingString + MpUtil.FixedEllipsis()) : result;

            if (Multiplayer.Client?.StateObj is ClientJoiningState joining && joining.state == JoiningState.Downloading)
            {
                label = $"MpDownloading".Translate(Multiplayer.Client.FragmentProgress);
            }

            const float buttonHeight = 40f;
            const float buttonWidth  = 120f;

            Rect textRect = inRect;

            textRect.yMax -= (buttonHeight + 10f);
            Text.Anchor    = TextAnchor.MiddleCenter;

            Widgets.Label(textRect, label);
            Text.Anchor = TextAnchor.UpperLeft;

            Rect buttonRect = new Rect((inRect.width - buttonWidth) / 2f, inRect.height - buttonHeight - 10f, buttonWidth, buttonHeight);

            if (Widgets.ButtonText(buttonRect, "CancelButton".Translate(), true, false, true))
            {
                Close();
            }
        }
        public HostWindow(SaveFile file = null, bool withSimulation = false)
        {
            closeOnAccept = false;
            doCloseX      = true;

            settings = MultiplayerMod.settings.serverSettings;

            this.withSimulation = withSimulation;
            this.file           = file;
            settings.gameName   = file?.gameName ?? Multiplayer.session?.gameName ?? $"{Multiplayer.username}'s game";

            MultiplayerWorldComp.asyncTime = file?.asyncTime ?? false;
            if (file?.asyncTime ?? false)
            {
                asyncTimeLocked = true; // once enabled in a save, cannot be disabled
            }

            var localAddr = MpUtil.GetLocalIpAddress() ?? "127.0.0.1";

            settings.lanAddress = localAddr;

            if (MpVersion.IsDebug)
            {
                debugMode       = true;
                logDesyncTraces = true;
            }
        }
Beispiel #6
0
        public static void TryConnectWithWindow(string address, int port, bool returnToServerBrowser = true)
        {
            Find.WindowStack.Add(new ConnectingWindow(address, port)
            {
                returnToServerBrowser = returnToServerBrowser
            });

            Multiplayer.session = new MultiplayerSession
            {
                address = address,
                port    = port
            };

            NetManager netClient = new NetManager(new MpClientNetListener())
            {
                EnableStatistics = true,
                IPv6Enabled      = MpUtil.SupportsIPv6() ? IPv6Mode.SeparateSocket : IPv6Mode.Disabled
            };

            netClient.Start();
            netClient.ReconnectDelay     = 300;
            netClient.MaxConnectAttempts = 8;

            Multiplayer.session.netClient = netClient;
            netClient.Connect(address, port, "");
        }
Beispiel #7
0
        public static SyncMethod RegisterSyncMethod(MethodInfo method, SyncType[] argTypes)
        {
            MpUtil.MarkNoInlining(method);

            SyncMethod handler = new SyncMethod((method.IsStatic ? null : method.DeclaringType), method, argTypes);

            syncMethods[method] = handler;
            handlers.Add(handler);

            PatchMethodForSync(method);

            return(handler);
        }
Beispiel #8
0
        public HostWindow(SaveFile file = null)
        {
            closeOnAccept = false;
            doCloseX      = true;

            this.file         = file;
            settings.gameName = file?.gameName ?? $"{Multiplayer.username}'s game";

            var localAddr = MpUtil.GetLocalIpAddress() ?? "127.0.0.1";

            settings.lanAddress = localAddr;
            addressBuffer       = localAddr;

            lan = true;
            settings.arbiter = true;
        }
Beispiel #9
0
        public static void EarlyMarkNoInline(Assembly asm)
        {
            foreach (var type in asm.GetTypes())
            {
                MpPatchExtensions.DoMpPatches(null, type)?.ForEach(m => MpUtil.MarkNoInlining(m));

                var harmonyMethods = type.GetHarmonyMethods();
                if (harmonyMethods?.Count > 0)
                {
                    var original = MpUtil.GetOriginalMethod(HarmonyMethod.Merge(harmonyMethods));
                    if (original != null)
                    {
                        MpUtil.MarkNoInlining(original);
                    }
                }
            }
        }
Beispiel #10
0
        public static void RegisterAllSyncMethods()
        {
            foreach (Type type in MpUtil.AllModTypes())
            {
                foreach (MethodInfo method in type.GetDeclaredMethods())
                {
                    if (!method.TryGetAttribute(out SyncMethodAttribute syncAttr))
                    {
                        continue;
                    }

                    var syncMethod = RegisterSyncMethod(method, null);
                    syncMethod.context   = syncAttr.context;
                    syncMethod.debugOnly = method.HasAttribute <SyncDebugOnlyAttribute>();
                }
            }
        }
Beispiel #11
0
        private void EarlyMarkNoInline()
        {
            foreach (var type in MpUtil.AllModTypes())
            {
                MpPatchExtensions.DoMpPatches(null, type)?.ForEach(m => MpUtil.MarkNoInlining(m));

                var harmonyMethods = type.GetHarmonyMethods();
                if (harmonyMethods?.Count > 0)
                {
                    var original = MpUtil.GetOriginalMethod(HarmonyMethod.Merge(harmonyMethods));
                    if (original != null)
                    {
                        MpUtil.MarkNoInlining(original);
                    }
                }
            }
        }
Beispiel #12
0
        public void TryAddStackTrace(string info = null, bool doTrace = true)
        {
            if (!ShouldCollect)
            {
                return;
            }

            Current.TryMarkSimulating();

            var trace = doTrace ? MpUtil.FastStackTrace(4) : new MethodBase[0];

            Current.traces.Add(new TraceInfo()
            {
                trace = trace, info = info
            });
            current.traceHashes.Add(trace.Hash() ^ (info?.GetHashCode() ?? 0));
        }
Beispiel #13
0
        private void RecreateDialog()
        {
            var session = Multiplayer.WorldComp.trading[selectedTab];

            MpTradeSession.SetTradeSession(session);

            dialog = MpUtil.NewObjectNoCtor <Dialog_Trade>();
            dialog.quickSearchWidget = new QuickSearchWidget();
            dialog.giftsOnly         = session.giftsOnly;
            dialog.sorter1           = TransferableSorterDefOf.Category;
            dialog.sorter2           = TransferableSorterDefOf.MarketValue;
            dialog.CacheTradeables();
            session.deal.uiShouldReset = UIShouldReset.None;

            removed.Clear();
            added.Clear();

            MpTradeSession.SetTradeSession(null);
        }
Beispiel #14
0
        public HostWindow(SaveFile file = null, bool withSimulation = false)
        {
            closeOnAccept = false;
            doCloseX      = true;

            settings = MultiplayerMod.settings.serverSettings;

            this.withSimulation = withSimulation;
            this.file           = file;
            settings.gameName   = file?.gameName ?? Multiplayer.session?.gameName ?? $"{Multiplayer.username}'s game";

            var localAddr = MpUtil.GetLocalIpAddress() ?? "127.0.0.1";

            settings.lanAddress = localAddr;

            if (MpVersion.IsDebug)
            {
                debugMode = true;
            }
        }
Beispiel #15
0
        /// <summary>
        /// Logs the current stack so that in the event of a desync we have some stack traces.
        /// </summary>
        /// <param name="info">Any additional message to be logged with the stack</param>
        /// <param name="doTrace">Set to false to not actually log a stack, only the message</param>
        public void TryAddStackTraceForDesyncLog(string info = null, bool doTrace = true)
        {
            if (!ShouldCollect)
            {
                return;
            }

            CurrentOpinion.TryMarkSimulating();

            //Get the current stack trace
            var trace = doTrace ? MpUtil.FastStackTrace(4) : new MethodBase[0];

            //Add it to the list
            CurrentOpinion.desyncStackTraces.Add(new StackTraceLogItem {
                stackTrace = trace, additionalInfo = info
            });

            //Calculate its hash and add it, for comparison with other opinions.
            currentOpinion.desyncStackTraceHashes.Add(trace.Hash() ^ (info?.GetHashCode() ?? 0));
        }
        static void DrawSkippingWindow()
        {
            if (Multiplayer.Client == null || !TickPatch.Skipping)
            {
                return;
            }

            string text         = $"{TickPatch.skippingTextKey.Translate()}{MpUtil.FixedEllipsis()}";
            float  textWidth    = Text.CalcSize(text).x;
            float  windowWidth  = Math.Max(240f, textWidth + 40f);
            float  windowHeight = TickPatch.cancelSkip != null ? 100f : 75f;
            Rect   rect         = new Rect(0, 0, windowWidth, windowHeight).CenterOn(new Rect(0, 0, UI.screenWidth, UI.screenHeight));

            if (TickPatch.canESCSkip && Event.current.type == EventType.KeyUp && Event.current.keyCode == KeyCode.Escape)
            {
                TickPatch.ClearSkipping();
                Event.current.Use();
            }

            Find.WindowStack.ImmediateWindow(SkippingWindowId, rect, WindowLayer.Super, () =>
            {
                var textRect = rect.AtZero();
                if (TickPatch.cancelSkip != null)
                {
                    textRect.yMin   += 5f;
                    textRect.height -= 50f;
                }

                Text.Anchor = TextAnchor.MiddleCenter;
                Text.Font   = GameFont.Small;
                Widgets.Label(textRect, text);
                Text.Anchor = TextAnchor.UpperLeft;

                if (TickPatch.cancelSkip != null && Widgets.ButtonText(new Rect(0, textRect.yMax, 100f, 35f).CenteredOnXIn(textRect), TickPatch.skipCancelButtonKey.Translate()))
                {
                    TickPatch.cancelSkip();
                }
            }, absorbInputAroundWindow: true);
        }
        public override void DoWindowContents(Rect inRect)
        {
            string label = Ellipsis ? (ConnectingString + MpUtil.FixedEllipsis()) : result;

            const float buttonHeight = 40f;
            const float buttonWidth  = 120f;

            Rect textRect = inRect;

            textRect.yMax -= (buttonHeight + 10f);
            float textWidth = Text.CalcSize(label).x;

            Text.Anchor = TextAnchor.MiddleCenter;
            Widgets.Label(textRect, label);
            Text.Anchor = TextAnchor.UpperLeft;

            Rect buttonRect = new Rect((inRect.width - buttonWidth) / 2f, inRect.height - buttonHeight - 10f, buttonWidth, buttonHeight);

            if (Widgets.ButtonText(buttonRect, "CancelButton".Translate(), true, false, true))
            {
                Close();
            }
        }
Beispiel #18
0
        private static object ReadSyncObjectInternal(ByteReader data, SyncType syncType)
        {
            Type type = syncType.type;

            try
            {
                if (typeof(object) == type)
                {
                    return(null);
                }

                if (type.IsByRef)
                {
                    return(null);
                }

                if (SyncDictFast.syncWorkers.TryGetValue(type, out SyncWorkerEntry syncWorkerEntryEarly))
                {
                    object res = null;

                    if (syncWorkerEntryEarly.shouldConstruct || type.IsValueType)
                    {
                        res = Activator.CreateInstance(type);
                    }

                    syncWorkerEntryEarly.Invoke(new ReadingSyncWorker(data), ref res);

                    return(res);
                }

                if (syncType.expose)
                {
                    if (!typeof(IExposable).IsAssignableFrom(type))
                    {
                        throw new SerializationException($"Type {type} can't be exposed because it isn't IExposable");
                    }

                    byte[] exposableData = data.ReadPrefixedBytes();
                    return(ExposableSerialization.ReadExposable(type, exposableData));
                }

                if (typeof(ISynchronizable).IsAssignableFrom(type))
                {
                    var obj = Activator.CreateInstance(type);

                    ((ISynchronizable)obj).Sync(new ReadingSyncWorker(data));
                    return(obj);
                }

                if (type.IsEnum)
                {
                    Type underlyingType = Enum.GetUnderlyingType(type);

                    return(Enum.ToObject(type, ReadSyncObject(data, underlyingType)));
                }

                if (type.IsArray)
                {
                    if (type.GetArrayRank() != 1)
                    {
                        throw new SerializationException("Multi dimensional arrays aren't supported.");
                    }

                    ushort length = data.ReadUShort();
                    if (length == ushort.MaxValue)
                    {
                        return(null);
                    }

                    Type  elementType = type.GetElementType();
                    Array arr         = Array.CreateInstance(elementType, length);

                    for (int i = 0; i < length; i++)
                    {
                        arr.SetValue(ReadSyncObject(data, elementType), i);
                    }

                    return(arr);
                }

                if (type.IsGenericType)
                {
                    var genericTypeDefinition = type.GetGenericTypeDefinition();

                    if (genericTypeDefinition == typeof(List <>))
                    {
                        ushort size = data.ReadUShort();
                        if (size == ushort.MaxValue)
                        {
                            return(null);
                        }

                        Type  listObjType = type.GetGenericArguments()[0];
                        IList list        = (IList)Activator.CreateInstance(type, size);

                        for (int j = 0; j < size; j++)
                        {
                            list.Add(ReadSyncObject(data, listObjType));
                        }

                        return(list);
                    }

                    if (genericTypeDefinition == typeof(IEnumerable <>))
                    {
                        Type element = type.GetGenericArguments()[0];
                        return(ReadSyncObject(data, typeof(List <>).MakeGenericType(element)));
                    }

                    if (genericTypeDefinition == typeof(Nullable <>))
                    {
                        bool isNull = data.ReadBool();
                        if (isNull)
                        {
                            return(null);
                        }

                        return(Activator.CreateInstance(type, ReadSyncObject(data, Nullable.GetUnderlyingType(type))));
                    }

                    if (genericTypeDefinition == typeof(Dictionary <,>))
                    {
                        Type[] arguments = type.GetGenericArguments();

                        Array keys = (Array)ReadSyncObject(data, arguments[0].MakeArrayType());
                        if (keys == null)
                        {
                            return(null);
                        }

                        Array values = (Array)ReadSyncObject(data, arguments[1].MakeArrayType());

                        IDictionary dictionary = (IDictionary)Activator.CreateInstance(type);
                        for (int i = 0; i < keys.Length; i++)
                        {
                            var key = keys.GetValue(i);
                            if (key != null)
                            {
                                dictionary.Add(key, values.GetValue(i));
                            }
                        }

                        return(dictionary);
                    }

                    if (genericTypeDefinition == typeof(Pair <,>))
                    {
                        Type[]   arguments  = type.GetGenericArguments();
                        object[] parameters =
                        {
                            ReadSyncObject(data, arguments[0]),
                            ReadSyncObject(data, arguments[1]),
                        };

                        return(type.GetConstructors().First().Invoke(parameters));
                    }

                    if (typeof(ITuple).IsAssignableFrom(genericTypeDefinition)) // ValueTuple or Tuple
                    {
                        Type[] arguments = type.GetGenericArguments();

                        int      size   = data.ReadInt32();
                        object[] values = new object[size];

                        for (int i = 0; i < size; i++)
                        {
                            values[i] = ReadSyncObject(data, arguments[i]);
                        }

                        return(type.GetConstructors().First().Invoke(values));
                    }
                }

                if (typeof(ISyncSimple).IsAssignableFrom(type))
                {
                    var obj = MpUtil.NewObjectNoCtor(type);
                    foreach (var field in AccessTools.GetDeclaredFields(type))
                    {
                        field.SetValue(obj, ReadSyncObject(data, field.FieldType));
                    }
                    return(obj);
                }

                // Def is a special case until the workers can read their own type
                if (typeof(Def).IsAssignableFrom(type))
                {
                    ushort defTypeIndex = data.ReadUShort();
                    if (defTypeIndex == ushort.MaxValue)
                    {
                        return(null);
                    }

                    ushort shortHash = data.ReadUShort();

                    var defType = DefSerialization.DefTypes[defTypeIndex];
                    var def     = DefSerialization.GetDef(defType, shortHash);

                    if (def == null)
                    {
                        throw new SerializationException($"Couldn't find {defType} with short hash {shortHash}");
                    }

                    return(def);
                }

                // Designators can't be handled by SyncWorkers due to the type change
                if (typeof(Designator).IsAssignableFrom(type))
                {
                    ushort desId = ReadSync <ushort>(data);
                    type = ImplSerialization.designatorTypes[desId]; // Replaces the type!
                }

                // Where the magic happens
                if (SyncDict.syncWorkers.TryGetValue(type, out var syncWorkerEntry))
                {
                    object res = null;

                    if (syncWorkerEntry.shouldConstruct || type.IsValueType)
                    {
                        res = Activator.CreateInstance(type);
                    }

                    syncWorkerEntry.Invoke(new ReadingSyncWorker(data), ref res);

                    return(res);
                }

                throw new SerializationException("No reader for type " + type);
            }
            catch
            {
                Log.Error($"Multiplayer: Error reading type: {type}");
                throw;
            }
        }
Beispiel #19
0
        private void DrawInfoButtons()
        {
            float x = 0;

            const string WebsiteLink = "https://rimworldmultiplayer.com";
            const string DiscordLink = "https://discord.gg/n5E2cb2Y4Z";

            bool Button(Texture2D icon, string labelKey, string tip, Color baseIconColor, float iconSize = 24f)
            {
                var label      = labelKey.Translate();
                var labelWidth = Text.CalcSize(label).x;
                var btn        = new Rect(x, 0, 24 + 1 + labelWidth, 24);
                var mouseOver  = Mouse.IsOver(btn);

                MouseoverSounds.DoRegion(btn);
                TooltipHandler.TipRegion(btn, tip);

                using (MpStyle.Set(mouseOver ? Color.yellow : baseIconColor))
                {
                    GUI.DrawTexture(new Rect(x += (24 - iconSize) / 2, (24 - iconSize) / 2, iconSize, iconSize), icon);
                    x += 24;
                }

                x += 1;

                using (MpStyle.Set(mouseOver ? Color.yellow : Color.white))
                    using (MpStyle.Set(TextAnchor.MiddleCenter))
                        MpUI.Label(new Rect(x, 0, labelWidth, 24f), labelKey.Translate());

                x += labelWidth;
                x += 10;

                return(Widgets.ButtonInvisible(btn));
            }

            const string compatLabel     = "MpCompatibilityButton";
            const string compatLabelDesc = "MpCompatibilityButtonDesc";

            if (Button(TexButton.ToggleLog, compatLabel, MpUtil.TranslateWithDoubleNewLines(compatLabelDesc, 2), Color.grey, 20))
            {
                Find.WindowStack.Add(new ModCompatWindow(null, false, false, null));
            }

            if (Button(MultiplayerStatic.WebsiteIcon, "MpWebsiteButton", "MpLinkButtonDesc".Translate() + " " + WebsiteLink, Color.grey, 20))
            {
                Application.OpenURL(WebsiteLink);
            }

            if (Button(MultiplayerStatic.DiscordIcon, "MpDiscordButton", "MpLinkButtonDesc".Translate() + " " + DiscordLink, Color.white))
            {
                Application.OpenURL(DiscordLink);
            }

            if (false) // todo
            {
                Button(
                    TexButton.NewItem,
                    "MpActiveConfigsButton",
                    "MpActiveConfigsButtonDesc1".Translate("Player's game") + "\n\n" + "MpActiveConfigsButtonDesc2".Translate(),
                    Color.grey,
                    20
                    );
            }
        }
Beispiel #20
0
        static void DoDebugInfo()
        {
            if (Multiplayer.ShowDevInfo)
            {
                int           timerLag = (TickPatch.tickUntil - TickPatch.Timer);
                StringBuilder text     = new StringBuilder();
                text.Append($"{Faction.OfPlayer.loadID} {Multiplayer.RealPlayerFaction?.loadID} {Find.UniqueIDsManager.nextThingID} j:{Find.UniqueIDsManager.nextJobID} {Find.TickManager.TicksGame} {TickPatch.Timer} {TickPatch.tickUntil} {timerLag} {TickPatch.maxBehind}");
                text.Append($"\n{Time.deltaTime * 60f:0.0000} {TickPatch.tickTimer.ElapsedMilliseconds}");
                text.Append($"\n{avgDelta = (avgDelta * 59.0 + Time.deltaTime * 60.0) / 60.0:0.0000}");
                text.Append($"\n{avgTickTime = (avgTickTime * 59.0 + TickPatch.tickTimer.ElapsedMilliseconds) / 60.0:0.0000} {Find.World.worldObjects.settlements.Count}");
                text.Append($"\n{Multiplayer.session?.localCmdId} {Multiplayer.session?.remoteCmdId} {Multiplayer.session?.remoteTickUntil}");
                Rect rect = new Rect(80f, 60f, 330f, Text.CalcHeight(text.ToString(), 330f));
                Widgets.Label(rect, text.ToString());

                if (Input.GetKey(KeyCode.End))
                {
                    avgDelta    = 0;
                    avgTickTime = 0;
                }
            }

            if (Multiplayer.ShowDevInfo && Multiplayer.Client != null && Find.CurrentMap != null)
            {
                var           async = Find.CurrentMap.AsyncTime();
                StringBuilder text  = new StringBuilder();
                text.Append($"{Multiplayer.game.sync.knownClientOpinions.FirstOrDefault()?.isLocalClientsOpinion} {async.mapTicks} {TickPatch.shouldPause} {TickPatch.pausedAt} ");

                text.Append($"z: {Find.CurrentMap.haulDestinationManager.AllHaulDestinationsListForReading.Count()} d: {Find.CurrentMap.designationManager.allDesignations.Count} hc: {Find.CurrentMap.listerHaulables.ThingsPotentiallyNeedingHauling().Count}");

                if (Find.CurrentMap.ParentFaction != null)
                {
                    int faction             = Find.CurrentMap.ParentFaction.loadID;
                    MultiplayerMapComp comp = Find.CurrentMap.MpComp();
                    FactionMapData     data = comp.factionData.GetValueSafe(faction);

                    if (data != null)
                    {
                        text.Append($" h: {data.listerHaulables.ThingsPotentiallyNeedingHauling().Count}");
                        text.Append($" sg: {data.haulDestinationManager.AllGroupsListForReading.Count}");
                    }
                }

                text.Append($" {Multiplayer.GlobalIdBlock.Current} {Find.IdeoManager.IdeosInViewOrder.FirstOrDefault()?.id}");

                text.Append($"\n{SyncFieldUtil.bufferedChanges.Sum(kv => kv.Value.Count)} {Find.UniqueIDsManager.nextThingID}");
                text.Append($"\n{DeferredStackTracing.acc} {MpInput.Mouse2UpWithoutDrag} {Input.GetKeyUp(KeyCode.Mouse2)} {Input.GetKey(KeyCode.Mouse2)}");
                text.Append($"\n{(uint)async.randState} {(uint)(async.randState >> 32)}");
                text.Append($"\n{(uint)Multiplayer.WorldComp.randState} {(uint)(Multiplayer.WorldComp.randState >> 32)}");
                text.Append($"\n{async.cmds.Count} {Multiplayer.WorldComp.cmds.Count} {async.slower.forceNormalSpeedUntil} {Multiplayer.GameComp.asyncTime}");
                text.Append($"\nt{DeferredStackTracing.maxTraceDepth} p{SimplePool<StackTraceLogItemRaw>.FreeItemsCount} {DeferredStackTracingImpl.hashtableEntries}/{DeferredStackTracingImpl.hashtableSize} {DeferredStackTracingImpl.collisions}");

                text.Append(Find.WindowStack.focusedWindow is ImmediateWindow win
                    ? $"\nImmediateWindow: {MpUtil.DelegateMethodInfo(win.doWindowFunc?.Method)}"
                    : $"\n{Find.WindowStack.focusedWindow}");

                text.Append($"\n{UI.CurUICellSize()} {Find.WindowStack.windows.ToStringSafeEnumerable()}");

                Rect rect1 = new Rect(80f, 170f, 330f, Text.CalcHeight(text.ToString(), 330f));
                Widgets.Label(rect1, text.ToString());
            }

            //if (Event.current.type == EventType.Repaint)
            //    RandGetValuePatch.tracesThistick = 0;
        }
Beispiel #21
0
        private void EarlyPatches()
        {
            // special case?
            MpUtil.MarkNoInlining(AccessTools.Method(typeof(OutfitForcedHandler), nameof(OutfitForcedHandler.Reset)));

            foreach (var asm in AppDomain.CurrentDomain.GetAssemblies())
            {
                var firstMethod = asm.GetType("Harmony.AccessTools")?.GetMethod("FirstMethod");
                if (firstMethod != null)
                {
                    harmony.Patch(firstMethod, new HarmonyMethod(typeof(AccessTools_FirstMethod_Patch), nameof(AccessTools_FirstMethod_Patch.Prefix)));
                }

                if (asm == typeof(HarmonyPatch).Assembly)
                {
                    continue;
                }

                var emitCallParameter = asm.GetType("Harmony.MethodPatcher")?.GetMethod("EmitCallParameter", AccessTools.all);
                if (emitCallParameter != null)
                {
                    harmony.Patch(emitCallParameter, new HarmonyMethod(typeof(PatchHarmony), emitCallParameter.GetParameters().Length == 4 ? nameof(PatchHarmony.EmitCallParamsPrefix4) : nameof(PatchHarmony.EmitCallParamsPrefix5)));
                }
            }

            {
                var prefix = new HarmonyMethod(AccessTools.Method(typeof(CaptureThingSetMakers), "Prefix"));
                harmony.Patch(AccessTools.Constructor(typeof(ThingSetMaker_MarketValue)), prefix);
                harmony.Patch(AccessTools.Constructor(typeof(ThingSetMaker_Nutrition)), prefix);
            }

            harmony.Patch(
                AccessTools.Method(typeof(ThingCategoryDef), "get_DescendantThingDefs"),
                new HarmonyMethod(typeof(ThingCategoryDef_DescendantThingDefsPatch), "Prefix"),
                new HarmonyMethod(typeof(ThingCategoryDef_DescendantThingDefsPatch), "Postfix")
                );

            harmony.Patch(
                AccessTools.Method(typeof(ThingCategoryDef), "get_ThisAndChildCategoryDefs"),
                new HarmonyMethod(typeof(ThingCategoryDef_ThisAndChildCategoryDefsPatch), "Prefix"),
                new HarmonyMethod(typeof(ThingCategoryDef_ThisAndChildCategoryDefsPatch), "Postfix")
                );

            harmony.Patch(
                AccessTools.Method(typeof(LoadedModManager), nameof(LoadedModManager.ParseAndProcessXML)),
                transpiler: new HarmonyMethod(typeof(ParseAndProcessXml_Patch), "Transpiler")
                );

            harmony.Patch(
                AccessTools.Method(typeof(XmlNode), "get_ChildNodes"),
                postfix: new HarmonyMethod(typeof(XmlNodeListPatch), nameof(XmlNodeListPatch.XmlNode_ChildNodes_Postfix))
                );

            harmony.Patch(
                AccessTools.Method(typeof(XmlInheritance), nameof(XmlInheritance.TryRegisterAllFrom)),
                new HarmonyMethod(typeof(XmlInheritance_Patch), "Prefix"),
                new HarmonyMethod(typeof(XmlInheritance_Patch), "Postfix")
                );

            harmony.Patch(
                AccessTools.Constructor(typeof(LoadableXmlAsset), new[] { typeof(string), typeof(string), typeof(string) }),
                new HarmonyMethod(typeof(LoadableXmlAssetCtorPatch), "Prefix")
                );

            // Cross os compatibility
            harmony.Patch(
                AccessTools.Method(typeof(DirectXmlLoader), nameof(DirectXmlLoader.XmlAssetsInModFolder)), null,
                new HarmonyMethod(typeof(XmlAssetsInModFolderPatch), "Postfix")
                );

            // Might fix some mod desyncs
            harmony.Patch(
                AccessTools.Constructor(typeof(Def), new Type[0]),
                new HarmonyMethod(typeof(RandPatches), nameof(RandPatches.Prefix)),
                new HarmonyMethod(typeof(RandPatches), nameof(RandPatches.Postfix))
                );
        }
Beispiel #22
0
        private void DrawLan(Rect inRect)
        {
            Text.Anchor = TextAnchor.MiddleCenter;
            Widgets.Label(new Rect(inRect.x, 8f, inRect.width, 40), "MpLanSearching".Translate() + MpUtil.FixedEllipsis());
            Text.Anchor  = TextAnchor.UpperLeft;
            inRect.yMin += 40f;

            float margin  = 100;
            Rect  outRect = new Rect(margin, inRect.yMin + 10, inRect.width - 2 * margin, inRect.height - 20);

            float height   = servers.Count * 40;
            Rect  viewRect = new Rect(0, 0, outRect.width - 16f, height);

            Widgets.BeginScrollView(outRect, ref lanScroll, viewRect, true);

            float y = 0;
            int   i = 0;

            foreach (LanServer server in servers)
            {
                Rect entryRect = new Rect(0, y, viewRect.width, 40);
                if (i % 2 == 0)
                {
                    Widgets.DrawAltRect(entryRect);
                }

                Text.Anchor = TextAnchor.MiddleLeft;
                Widgets.Label(entryRect.Right(5), "" + server.endpoint);

                Text.Anchor = TextAnchor.MiddleCenter;
                Rect playButton = new Rect(entryRect.xMax - 75, entryRect.y + 5, 70, 40 - 10);
                if (Widgets.ButtonText(playButton, ">>"))
                {
                    Close(false);
                    Log.Message("Connecting to lan server");
                    Find.WindowStack.Add(new ConnectingWindow(server.endpoint.Address, server.endpoint.Port)
                    {
                        returnToServerBrowser = true
                    });
                }

                Text.Anchor = TextAnchor.UpperLeft;

                y += entryRect.height;
                i++;
            }

            Widgets.EndScrollView();
        }