Пример #1
0
        public override void OnBeforeSimulationFrame()
        {
            base.OnBeforeSimulationFrame();

            if (firstFrame)
            {
                firstFrame = false;
                Log.Info("ThreadingExtension.OnBeforeSimulationFrame: First frame detected. Checking detours.");

                List <string> missingDetours = new List <string>();

                foreach (Detour detour in Detours)
                {
                    if (!RedirectionHelper.IsRedirected(
                            detour.OriginalMethod,
                            detour.CustomMethod))
                    {
                        missingDetours.Add(
                            string.Format(
                                "<Manual> {0}.{1} with {2} parameters ({3})",
                                detour.OriginalMethod.DeclaringType.Name,
                                detour.OriginalMethod.Name,
                                detour.OriginalMethod.GetParameters().Length,
                                detour.OriginalMethod.DeclaringType.AssemblyQualifiedName));
                    }
                }

                foreach (KeyValuePair <MethodBase, RedirectCallsState> entry in HarmonyMethodStates)
                {
                    MethodBase         method   = entry.Key;
                    RedirectCallsState oldState = entry.Value;
                    RedirectCallsState newState =
                        RedirectionHelper.GetState(method.MethodHandle.GetFunctionPointer());

                    if (!oldState.Equals(newState))
                    {
                        missingDetours.Add(
                            string.Format(
                                "<Harmony> {0}.{1} with {2} parameters ({3})",
                                method.DeclaringType.Name,
                                method.Name,
                                method.GetParameters().Length,
                                method.DeclaringType.AssemblyQualifiedName));
                    }
                }

                Log.Info($"ThreadingExtension.OnBeforeSimulationFrame: First frame detected. " +
                         $"Detours checked. Result: {missingDetours.Count} missing detours");

                if (missingDetours.Count > 0)
                {
                    string error =
                        "Traffic Manager: President Edition detected an incompatibility with another " +
                        "mod! You can continue playing but it's NOT recommended. Traffic Manager will " +
                        "not work as expected. See TMPE.log for technical details.";
                    Log.Error(error);
                    string log = "The following methods were overriden by another mod:";

                    foreach (string missingDetour in missingDetours)
                    {
                        log += $"\n\t{missingDetour}";
                    }

                    Log.Info(log);

                    if (GlobalConfig.Instance.Main.ShowCompatibilityCheckErrorMessage)
                    {
                        Singleton <SimulationManager> .instance.m_ThreadingWrapper.QueueMainThread(
                            () => {
                            UIView
                            .library
                            .ShowModal <ExceptionPanel>(
                                "ExceptionPanel").SetMessage(
                                "Incompatibility Issue",
                                error,
                                true);
                        });
                    }
                }
            }

            if (Options.timedLightsEnabled)
            {
                tlsMan.SimulationStep();
            }
        }
Пример #2
0
 public Detour(MethodInfo originalMethod, MethodInfo customMethod)
 {
     this.OriginalMethod = originalMethod;
     this.CustomMethod   = customMethod;
     this.Redirect       = RedirectionHelper.RedirectCalls(originalMethod, customMethod);
 }
Пример #3
0
        public void initDetours()
        {
            // TODO realize detouring with annotations
            if (!DetourInited)
            {
                Log.Info("Init detours");
                bool detourFailed = false;

                try {
                    Log.Info("Deploying Harmony patches");
#if DEBUG
                    HarmonyInstance.DEBUG = true;
#endif
                    Assembly assembly = Assembly.GetExecutingAssembly();

                    HarmonyMethodStates.Clear();

                    // Harmony attribute-driven patching
                    Log.Info($"Performing Harmony attribute-driven patching");
                    HarmonyInst = HarmonyInstance.Create(HARMONY_ID);
                    HarmonyInst.PatchAll(assembly);

                    foreach (Type type in assembly.GetTypes())
                    {
                        object[] attributes = type.GetCustomAttributes(typeof(HarmonyPatch), true);
                        if (attributes.Length <= 0)
                        {
                            continue;
                        }

                        foreach (object attr in attributes)
                        {
                            HarmonyPatch       harmonyPatchAttr = (HarmonyPatch)attr;
                            MethodBase         info             = HarmonyUtil.GetOriginalMethod(harmonyPatchAttr.info);
                            IntPtr             ptr   = info.MethodHandle.GetFunctionPointer();
                            RedirectCallsState state = RedirectionHelper.GetState(ptr);
                            HarmonyMethodStates[info] = state;
                        }
                    }

                    // Harmony manual patching
                    Log.Info($"Performing Harmony manual patching");
                    foreach (ManualHarmonyPatch manualPatch in ManualHarmonyPatches)
                    {
                        Log.Info($"Manually patching method {manualPatch.method.DeclaringType.FullName}.{manualPatch.method.Name}. Prefix: {manualPatch.prefix?.method}, Postfix: {manualPatch.postfix?.method}, Transpiler: {manualPatch.transpiler?.method}");
                        HarmonyInst.Patch(manualPatch.method, manualPatch.prefix, manualPatch.postfix, manualPatch.transpiler);

                        IntPtr             ptr   = manualPatch.method.MethodHandle.GetFunctionPointer();
                        RedirectCallsState state = RedirectionHelper.GetState(ptr);
                        HarmonyMethodStates[manualPatch.method] = state;
                    }
                } catch (Exception e) {
                    Log.Error("Could not deploy Harmony patches");
                    Log.Info(e.ToString());
                    Log.Info(e.StackTrace);
                    detourFailed = true;
                }

                try {
                    Log.Info("Deploying attribute-driven detours");
                    DetouredMethodStates = AssemblyRedirector.Deploy();
                } catch (Exception e) {
                    Log.Error("Could not deploy attribute-driven detours");
                    Log.Info(e.ToString());
                    Log.Info(e.StackTrace);
                    detourFailed = true;
                }

                if (detourFailed)
                {
                    Log.Info("Detours failed");
                    Singleton <SimulationManager> .instance.m_ThreadingWrapper.QueueMainThread(() => {
                        UIView.library.ShowModal <ExceptionPanel>("ExceptionPanel").SetMessage("TM:PE failed to load", "Traffic Manager: President Edition failed to load. You can continue playing but it's NOT recommended. Traffic Manager will not work as expected.", true);
                    });
                }
                else
                {
                    Log.Info("Detours successful");
                }

                DetourInited = true;
            }
        }
Пример #4
0
        public override void OnUpdate(float realTimeDelta, float simulationTimeDelta)
        {
            base.OnUpdate(realTimeDelta, simulationTimeDelta);

            if (LoadingExtension.Instance == null)
            {
                return;
            }

            if (LoadingExtension.Instance.ToolMode != TrafficManagerMode.None && ToolsModifierControl.toolController.CurrentTool != LoadingExtension.Instance.TrafficLightTool)
            {
                LoadingExtension.Instance.SetToolMode(TrafficManagerMode.None);
            }

            if (ToolsModifierControl.toolController.CurrentTool != LoadingExtension.Instance.TrafficLightTool && LoadingExtension.Instance.UI.isVisible())
            {
                LoadingExtension.Instance.UI.Close();
            }

            if (!LoadingExtension.Instance.detourInited)
            {
                LoadingExtension.Instance.revertMethods[0] = RedirectionHelper.RedirectCalls(
                    typeof(CarAI).GetMethod("CalculateSegmentPosition",
                                            BindingFlags.NonPublic | BindingFlags.Instance,
                                            null,
                                            new Type[]
                {
                    typeof(ushort), typeof(Vehicle).MakeByRefType(), typeof(PathUnit.Position),
                    typeof(PathUnit.Position), typeof(uint), typeof(byte), typeof(PathUnit.Position),
                    typeof(uint), typeof(byte), typeof(Vector3).MakeByRefType(),
                    typeof(Vector3).MakeByRefType(), typeof(float).MakeByRefType()
                },
                                            null),
                    typeof(CustomCarAI).GetMethod("CalculateSegmentPosition"));

                LoadingExtension.Instance.revertMethods[1] = RedirectionHelper.RedirectCalls(
                    typeof(RoadBaseAI).GetMethod("SimulationStep",
                                                 new Type[] { typeof(ushort), typeof(NetNode).MakeByRefType() }),
                    typeof(CustomRoadAI).GetMethod("SimulationStep", BindingFlags.NonPublic | BindingFlags.Instance));

                LoadingExtension.Instance.revertMethods[2] = RedirectionHelper.RedirectCalls(typeof(HumanAI).GetMethod("CheckTrafficLights",
                                                                                                                       BindingFlags.NonPublic | BindingFlags.Instance,
                                                                                                                       null,
                                                                                                                       new Type[] { typeof(ushort), typeof(ushort) },
                                                                                                                       null),
                                                                                             typeof(CustomHumanAI).GetMethod("CheckTrafficLights"));

                LoadingExtension.Instance.revertMethods[3] =
                    RedirectionHelper.RedirectCalls(
                        typeof(CarAI).GetMethod("SimulationStep",
                                                new Type[] { typeof(ushort), typeof(Vehicle).MakeByRefType(), typeof(Vector3) }),
                        typeof(CustomCarAI).GetMethod("SimulationStep", BindingFlags.NonPublic | BindingFlags.Instance));


                LoadingExtension.Instance.revertMethods[4] =
                    RedirectionHelper.RedirectCalls(
                        typeof(PassengerCarAI).GetMethod("SimulationStep",
                                                         new Type[] { typeof(ushort), typeof(Vehicle).MakeByRefType(), typeof(Vector3) }),
                        typeof(CustomPassengerCarAI).GetMethod("SimulationStep",
                                                               BindingFlags.NonPublic | BindingFlags.Instance));

                LoadingExtension.Instance.revertMethods[5] =
                    RedirectionHelper.RedirectCalls(
                        typeof(CargoTruckAI).GetMethod("SimulationStep",
                                                       new Type[] { typeof(ushort), typeof(Vehicle).MakeByRefType(), typeof(Vector3) }),
                        typeof(CustomCargoTruckAI).GetMethod("SimulationStep",
                                                             BindingFlags.NonPublic | BindingFlags.Instance));

                LoadingExtension.Instance.revertMethods[6] = RedirectionHelper.RedirectCalls(typeof(CarAI).GetMethod("CalculateSegmentPosition",
                                                                                                                     BindingFlags.NonPublic | BindingFlags.Instance,
                                                                                                                     null,
                                                                                                                     new Type[]
                {
                    typeof(ushort), typeof(Vehicle).MakeByRefType(), typeof(PathUnit.Position), typeof(uint),
                    typeof(byte), typeof(Vector3).MakeByRefType(), typeof(Vector3).MakeByRefType(),
                    typeof(float).MakeByRefType()
                },
                                                                                                                     null),
                                                                                             typeof(CustomCarAI).GetMethod("CalculateSegmentPosition2"));

                //srcMethod8 = typeof(CarAI).GetMethod("StartPathFind",
                //    BindingFlags.NonPublic | BindingFlags.Instance,
                //    null,
                //    new Type[] { typeof(ushort), typeof(Vehicle).MakeByRefType(), typeof(Vector3), typeof(Vector3), typeof(bool), typeof(bool) },
                //    null);

                //destMethod[8 = typeof(CustomCarAI).GetMethod("StartPathFind");

                //srcMethod9 = typeof (TransportLineAI).GetMethod("StartPathFind");

                //destMethod[9 = typeof(CustomTransportLineAI).GetMethod("StartPathFind", BindingFlags.NonPublic | BindingFlags.Static);

                //srcMethod10 = typeof(PassengerCarAI).GetMethod("StartPathFind",
                //    BindingFlags.NonPublic | BindingFlags.Instance,
                //    null,
                //    new Type[] { typeof(ushort), typeof(Vehicle).MakeByRefType(), typeof(Vector3), typeof(Vector3), typeof(bool), typeof(bool) },
                //    null);

                //destMethod[10 = typeof(CustomPassengerCarAI).GetMethod("StartPathFind2");

                //srcMethod11 = typeof(CargoTruckAI).GetMethod("StartPathFind",
                //    BindingFlags.NonPublic | BindingFlags.Instance,
                //    null,
                //    new Type[] { typeof(ushort), typeof(Vehicle).MakeByRefType(), typeof(Vector3), typeof(Vector3), typeof(bool), typeof(bool) },
                //    null);

                //destMethod[11 = typeof(CustomCargoTruckAI).GetMethod("StartPathFind2");

                //LoadingExtension.Instance.revertMethods[1] = RedirectionHelper.RedirectCalls(typeof (NetNode).GetMethod("RefreshJunctionData",
                //    BindingFlags.NonPublic | BindingFlags.Instance,
                //    null,
                //    new Type[]
                //    {
                //        typeof (ushort), typeof (int), typeof (ushort), typeof (Vector3), typeof (uint).MakeByRefType(),
                //        typeof (RenderManager.Instance).MakeByRefType()
                //    },
                //    null),
                //    typeof (CustomNetNode).GetMethod("RefreshJunctionData"));

                LoadingExtension.Instance.detourInited = true;

                if (!LoadingExtension.Instance.nodeSimulationLoaded)
                {
                    LoadingExtension.Instance.nodeSimulationLoaded = true;
                    ToolsModifierControl.toolController.gameObject.AddComponent <CustomRoadAI>();
                }
            }

            if (Input.GetKeyDown(KeyCode.Escape))
            {
                LoadingExtension.Instance.UI.Close();
            }
        }
        public override void OnBeforeSimulationFrame()
        {
            base.OnBeforeSimulationFrame();

            if (firstFrame)
            {
                firstFrame = false;
                Log.Info($"ThreadingExtension.OnBeforeSimulationFrame: First frame detected. Checking detours.");

                List <string> missingDetours = new List <string>();
                foreach (Detour detour in LoadingExtension.Detours)
                {
                    if (!RedirectionHelper.IsRedirected(detour.OriginalMethod, detour.CustomMethod))
                    {
                        missingDetours.Add($"{detour.OriginalMethod.DeclaringType.Name}.{detour.OriginalMethod.Name} with {detour.OriginalMethod.GetParameters().Length} parameters ({detour.OriginalMethod.DeclaringType.AssemblyQualifiedName})");
                    }
                }

                Log.Info($"ThreadingExtension.OnBeforeSimulationFrame: First frame detected. Detours checked. Result: {missingDetours.Count} missing detours");

                if (missingDetours.Count > 0)
                {
                    string error = "Traffic Manager: President Edition detected an incompatibility with another mod! You can continue playing but it's NOT recommended. Traffic Manager will not work as expected. See TMPE.log for technical details.";
                    Log.Error(error);
                    string log = "The following methods were overriden by another mod:";
                    foreach (string missingDetour in missingDetours)
                    {
                        log += $"\n\t{missingDetour}";
                    }
                    Log.Info(log);
                    if (GlobalConfig.Instance.Main.ShowCompatibilityCheckErrorMessage)
                    {
                        Singleton <SimulationManager> .instance.m_ThreadingWrapper.QueueMainThread(() => {
                            UIView.library.ShowModal <ExceptionPanel>("ExceptionPanel").SetMessage("Incompatibility Issue", error, true);
                        });
                    }
                }
            }

#if BENCHMARK
            using (var bm = new Benchmark(null, "RoutingManager.SimulationStep")) {
#endif
            routeMan.SimulationStep();
#if BENCHMARK
        }
#endif

#if BENCHMARK
            using (var bm = new Benchmark(null, "TrafficLightSimulationManager.SimulationStep")) {
#endif

            if (Options.timedLightsEnabled)
            {
                //try {
                tlsMan.SimulationStep();

                /*} catch (Exception ex) {
                 *      Log.Warning($"Error occured while simulating traffic lights: {ex.ToString()}");
                 * }*/
            }
#if BENCHMARK
        }
#endif
        }
Пример #6
0
        public void initDetours()
        {
            Log.Warning("Init detours");
            if (!LoadingExtension.Instance.DetourInited)
            {
                Log.Message("Redirecting Car AI Calculate Segment Calls");
                try {
                    LoadingExtension.Instance.OriginalMethods[0] = typeof(CarAI).GetMethod("CalculateSegmentPosition",
                                                                                           BindingFlags.NonPublic | BindingFlags.Instance,
                                                                                           null,
                                                                                           new[]
                    {
                        typeof(ushort), typeof(Vehicle).MakeByRefType(), typeof(PathUnit.Position),
                        typeof(PathUnit.Position), typeof(uint), typeof(byte), typeof(PathUnit.Position),
                        typeof(uint), typeof(byte), typeof(Vector3).MakeByRefType(),
                        typeof(Vector3).MakeByRefType(), typeof(float).MakeByRefType()
                    },
                                                                                           null);
                    LoadingExtension.Instance.CustomMethods[0]   = typeof(CustomCarAI).GetMethod("TmCalculateSegmentPosition");
                    LoadingExtension.Instance.CustomRedirects[0] = RedirectionHelper.RedirectCalls(LoadingExtension.Instance.OriginalMethods[0], LoadingExtension.Instance.CustomMethods[0]);
                } catch (Exception) {
                    Log.Error("Could not redirect CarAI::CalculateSegmentPosition.");
                }

                Log.Message("Redirecting SimulationStep");
                try {
                    LoadingExtension.Instance.OriginalMethods[1] = typeof(RoadBaseAI).GetMethod("SimulationStep", new[] { typeof(ushort), typeof(NetNode).MakeByRefType() });
                    LoadingExtension.Instance.CustomMethods[1]   = typeof(CustomRoadAI).GetMethod("CustomSimulationStep");
                    LoadingExtension.Instance.CustomRedirects[1] = RedirectionHelper.RedirectCalls(LoadingExtension.Instance.OriginalMethods[1], LoadingExtension.Instance.CustomMethods[1]);
                } catch (Exception) {
                    Log.Error("Could not redirect RoadBaseAI::SimulationStep.");
                }

                Log.Message("Redirecting Human AI Calls");
                try {
                    LoadingExtension.Instance.OriginalMethods[2] = typeof(HumanAI).GetMethod("CheckTrafficLights",
                                                                                             BindingFlags.NonPublic | BindingFlags.Instance,
                                                                                             null,
                                                                                             new[] { typeof(ushort), typeof(ushort) },
                                                                                             null);
                    LoadingExtension.Instance.CustomMethods[2]   = typeof(CustomHumanAI).GetMethod("CustomCheckTrafficLights");
                    LoadingExtension.Instance.CustomRedirects[2] = RedirectionHelper.RedirectCalls(LoadingExtension.Instance.OriginalMethods[2], LoadingExtension.Instance.CustomMethods[2]);
                } catch (Exception) {
                    Log.Error("Could not redirect HumanAI::CheckTrafficLights.");
                }

                if (LoadingExtension.IsPathManagerCompatible)
                {
                    Log.Message("Traffic++ Not detected. Loading Pathfinder.");
                    Log.Message("Redirecting CarAI Simulation Step Calls");
                    try {
                        LoadingExtension.Instance.OriginalMethods[3] = typeof(CarAI).GetMethod("SimulationStep",
                                                                                               new[] {
                            typeof(ushort),
                            typeof(Vehicle).MakeByRefType(),
                            typeof(Vector3)
                        });
                        LoadingExtension.Instance.CustomMethods[3]   = typeof(CustomCarAI).GetMethod("TrafficManagerSimulationStep");
                        LoadingExtension.Instance.CustomRedirects[3] = RedirectionHelper.RedirectCalls(LoadingExtension.Instance.OriginalMethods[3], LoadingExtension.Instance.CustomMethods[3]);
                    } catch (Exception) {
                        Log.Error("Could not redirect CarAI::SimulationStep.");
                    }

                    Log.Message("Redirecting PassengerCarAI Simulation Step Calls");
                    try {
                        LoadingExtension.Instance.OriginalMethods[4] = typeof(PassengerCarAI).GetMethod("SimulationStep",
                                                                                                        new[] { typeof(ushort), typeof(Vehicle).MakeByRefType(), typeof(Vector3) });
                        LoadingExtension.Instance.CustomMethods[4]   = typeof(CustomPassengerCarAI).GetMethod("CustomSimulationStep");
                        LoadingExtension.Instance.CustomRedirects[4] = RedirectionHelper.RedirectCalls(LoadingExtension.Instance.OriginalMethods[4], LoadingExtension.Instance.CustomMethods[4]);
                    } catch (Exception) {
                        Log.Error("Could not redirect PassengerCarAI::SimulationStep.");
                    }

                    Log.Message("Redirecting CargoTruckAI Simulation Step Calls");
                    try {
                        LoadingExtension.Instance.OriginalMethods[5] = typeof(CargoTruckAI).GetMethod("SimulationStep",
                                                                                                      new[] { typeof(ushort), typeof(Vehicle).MakeByRefType(), typeof(Vector3) });
                        LoadingExtension.Instance.CustomMethods[5]   = typeof(CustomCargoTruckAI).GetMethod("CustomSimulationStep");
                        LoadingExtension.Instance.CustomRedirects[5] = RedirectionHelper.RedirectCalls(LoadingExtension.Instance.OriginalMethods[5], LoadingExtension.Instance.CustomMethods[5]);
                    } catch (Exception) {
                        Log.Error("Could not redirect CargoTruckAI::SimulationStep.");
                    }

                    Log.Message("Redirection CarAI Calculate Segment Position calls for non-Traffic++");
                    try {
                        LoadingExtension.Instance.OriginalMethods[6] = typeof(CarAI).GetMethod("CalculateSegmentPosition",
                                                                                               BindingFlags.NonPublic | BindingFlags.Instance,
                                                                                               null,
                                                                                               new[]
                        {
                            typeof(ushort), typeof(Vehicle).MakeByRefType(), typeof(PathUnit.Position),
                            typeof(uint),
                            typeof(byte), typeof(Vector3).MakeByRefType(), typeof(Vector3).MakeByRefType(),
                            typeof(float).MakeByRefType()
                        },
                                                                                               null);
                        LoadingExtension.Instance.CustomMethods[6]   = typeof(CustomCarAI).GetMethod("TmCalculateSegmentPositionPathFinder");
                        LoadingExtension.Instance.CustomRedirects[6] =
                            RedirectionHelper.RedirectCalls(LoadingExtension.Instance.OriginalMethods[6], LoadingExtension.Instance.CustomMethods[6]);
                    } catch (Exception) {
                        Log.Error("Could not redirect CarAI::CalculateSegmentPosition");
                    }
                }

                LoadingExtension.Instance.DetourInited = true;
            }
        }