private static IEnumerable <CodeInstruction> InternalUpdate_Transpiler(IEnumerable <CodeInstruction> instructions)
        {
            // Store projectile data after swarm.AddBullet(sailBullet, orbitId) if IsUpdateNeeded == true
            try
            {
                CodeMatcher matcher = new CodeMatcher(instructions)
                                      .MatchForward(false,
                                                    new CodeMatch(OpCodes.Stfld, AccessTools.Field(typeof(SailBullet), nameof(SailBullet.lBegin))) //IL#638
                                                    );
                CodeInstruction loadInstruction = matcher.InstructionAt(-1);
                matcher.MatchForward(false,
                                     new CodeMatch(OpCodes.Callvirt, AccessTools.Method(typeof(DysonSwarm), nameof(DysonSwarm.AddBullet))) //IL#679
                                     )
                .Advance(2)
                .InsertAndAdvance(
                    new CodeInstruction(OpCodes.Ldarg_0),
                    new CodeInstruction(OpCodes.Ldfld, AccessTools.Field(typeof(EjectorComponent), nameof(EjectorComponent.planetId))),
                    loadInstruction,
                    new CodeInstruction(OpCodes.Ldarg_0),
                    new CodeInstruction(OpCodes.Ldfld, AccessTools.Field(typeof(EjectorComponent), nameof(EjectorComponent.orbitId))),
                    HarmonyLib.Transpilers.EmitDelegate <Action <int, Vector3, int> >((planetId, localPos, orbitId) =>
                {
                    // If the dyson sphere has no subscribers anymore, skip this data
                    if (!Multiplayer.IsActive || !Multiplayer.Session.Launch.Snapshots.ContainsKey(planetId / 100 - 1))
                    {
                        return;
                    }

                    // Assume orbitId < 65536
                    DysonLaunchData.Projectile data = new DysonLaunchData.Projectile
                    {
                        PlanetId = planetId,
                        TargetId = (ushort)orbitId,
                        LocalPos = localPos
                    };
                    Multiplayer.Session.Launch.ProjectileBag.Add(data);
                })
                    );
                return(matcher.InstructionEnumeration());
            }
            catch
            {
                NebulaModel.Logger.Log.Error("EjectorComponent.InternalUpdate_Transpiler failed. Mod version not compatible with game version.");
                return(instructions);
            }
        }
Ejemplo n.º 2
0
        private static IEnumerable <CodeInstruction> InternalUpdate_Transpiler(IEnumerable <CodeInstruction> instructions)
        {
            // Store projectile data after sphere.AddDysonRocket(dysonRocket, autoDysonNode) if IsUpdateNeeded == true
            try
            {
                CodeMatcher matcher = new CodeMatcher(instructions)
                                      .MatchForward(false,
                                                    new CodeMatch(OpCodes.Callvirt, AccessTools.Method(typeof(DysonSphere), nameof(DysonSphere.AddDysonRocket))) //IL#310
                                                    );
                CodeInstruction loadInstruction = matcher.InstructionAt(-1);                                                                                     //autoDysonNode
                matcher.Advance(2)
                .InsertAndAdvance(
                    new CodeInstruction(OpCodes.Ldarg_0),
                    new CodeInstruction(OpCodes.Ldfld, AccessTools.Field(typeof(SiloComponent), nameof(SiloComponent.planetId))),
                    new CodeInstruction(OpCodes.Ldarg_0),
                    new CodeInstruction(OpCodes.Ldfld, AccessTools.Field(typeof(SiloComponent), nameof(SiloComponent.localPos))),
                    loadInstruction,
                    HarmonyLib.Transpilers.EmitDelegate <Action <int, Vector3, DysonNode> >((planetId, localPos, autoDysonNode) =>
                {
                    // If the dyson sphere has no subscribers anymore, skip this data
                    if (!Multiplayer.IsActive || !Multiplayer.Session.Launch.Snapshots.ContainsKey(planetId / 100 - 1))
                    {
                        return;
                    }

                    // Assume layerId < 16, nodeId < 4096
                    DysonLaunchData.Projectile data = new DysonLaunchData.Projectile
                    {
                        PlanetId = planetId,
                        TargetId = (ushort)((autoDysonNode.layerId << 12) | (autoDysonNode.id & 0x0FFF)),
                        LocalPos = localPos
                    };
                    Multiplayer.Session.Launch.ProjectileBag.Add(data);
                })
                    );
                return(matcher.InstructionEnumeration());
            }
            catch
            {
                NebulaModel.Logger.Log.Error("SiloComponent.InternalUpdate_Transpiler failed. Mod version not compatible with game version.");
                return(instructions);
            }
        }