Skip to content
48 changes: 47 additions & 1 deletion KSPCommunityFixes/BugFixes/DoubleCurvePreserveTangents.cs
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,14 @@ class DoubleCurvePreserveTangents : BasePatch

protected override void ApplyPatches()
{
AddPatch(PatchType.Transpiler, typeof(DoubleCurve), nameof(DoubleCurve.RecomputeTangents));
if (!KSPCommunityFixes.IsCleanedDll)
{
AddPatch(PatchType.Transpiler, typeof(DoubleCurve), nameof(DoubleCurve.RecomputeTangents));
}
else
{
AddPatch(PatchType.Prefix, typeof(DoubleCurve), nameof(DoubleCurve.RecomputeTangents));
}
}

static IEnumerable<CodeInstruction> DoubleCurve_RecomputeTangents_Transpiler(IEnumerable<CodeInstruction> instructions)
Expand All @@ -37,5 +44,44 @@ static IEnumerable<CodeInstruction> DoubleCurve_RecomputeTangents_Transpiler(IEn

return code;
}

static bool DoubleCurve_RecomputeTangents_Prefix(DoubleCurve __instance)
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since we're unconditionally overriding the method this should be PatchType.Override, and the method renamed to suit. It's a bit more efficient and you can then remove the bool return.

{
int count = __instance.keys.Count;
DoubleKeyframe doubleKeyframe;
if (count == 1)
{
return false;
}
doubleKeyframe = __instance.keys[0];
if (doubleKeyframe.autoTangent)
{
doubleKeyframe.inTangent = 0.0;
doubleKeyframe.outTangent = (__instance.keys[1].value - doubleKeyframe.value) / (__instance.keys[1].time - doubleKeyframe.time);
__instance.keys[0] = doubleKeyframe;
}
int num3 = count - 1;
doubleKeyframe = __instance.keys[num3];
if (doubleKeyframe.autoTangent)
{
doubleKeyframe.inTangent = (doubleKeyframe.value - __instance.keys[num3 - 1].value) / (doubleKeyframe.time - __instance.keys[num3 - 1].value);
doubleKeyframe.outTangent = 0.0;
__instance.keys[num3] = doubleKeyframe;
}
if (count > 2)
{
for (int i = 1; i < num3; i++)
{
doubleKeyframe = __instance.keys[i];
if (doubleKeyframe.autoTangent)
{
double num4 = (doubleKeyframe.value - __instance.keys[i - 1].value) / (doubleKeyframe.time - __instance.keys[i - 1].value);
double num5 = (__instance.keys[i + 1].value - doubleKeyframe.value) / (__instance.keys[i + 1].time - doubleKeyframe.time);
doubleKeyframe.inTangent = (doubleKeyframe.outTangent = (num4 + num5) * 0.5);
}
}
}
return false;
}
}
}
124 changes: 113 additions & 11 deletions KSPCommunityFixes/BugFixes/ExtendedDeployableParts.cs
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,6 @@ class ExtendedDeployableParts : BasePatch
protected override void ApplyPatches()
{
AddPatch(PatchType.Transpiler, typeof(ModuleDeployablePart), nameof(ModuleDeployablePart.startFSM));

AddPatch(PatchType.Transpiler, typeof(ModuleDeployableSolarPanel), nameof(ModuleDeployablePart.OnStart));
}

Expand Down Expand Up @@ -88,22 +87,125 @@ static IEnumerable<CodeInstruction> ModuleDeployableSolarPanel_OnStart_Transpile
// We remove that entire if statement by replacing the if (Brtrue_S) by an unconditional jump (Br_S)

FieldInfo ModuleDeployablePart_deployState = AccessTools.Field(typeof(ModuleDeployablePart), nameof(ModuleDeployablePart.deployState));
if (!KSPCommunityFixes.IsCleanedDll)
{
List<CodeInstruction> code = new List<CodeInstruction>(instructions);
for (int i = 0; i < code.Count; i++)
{
if (code[i].opcode == OpCodes.Ldarg_0
&& code[i + 1].opcode == OpCodes.Ldfld && ReferenceEquals(code[i + 1].operand, ModuleDeployablePart_deployState)
&& code[i + 2].opcode == OpCodes.Brtrue_S)
{
code[i].opcode = OpCodes.Br_S;
code[i].operand = code[i + 2].operand; // grab the target instruction from the original jump
break;
}
}

List<CodeInstruction> code = new List<CodeInstruction>(instructions);

for (int i = 0; i < code.Count; i++)
return code;
}
else
{
if (code[i].opcode == OpCodes.Ldarg_0
&& code[i + 1].opcode == OpCodes.Ldfld && ReferenceEquals(code[i+1].operand, ModuleDeployablePart_deployState)
&& code[i + 2].opcode == OpCodes.Brtrue_S)
List<CodeInstruction> code = new List<CodeInstruction>(instructions);
for (int i = 0; i < code.Count; i++)
{
code[i].opcode = OpCodes.Br_S;
code[i].operand = code[i + 2].operand; // grab the target instruction from the original jump
break;
if (code[i].opcode == OpCodes.Ldarg_0
&& code[i + 1].opcode == OpCodes.Ldfld
&& code[i + 2].opcode == OpCodes.Ldarg_0
&& code[i + 3].opcode == OpCodes.Ldfld
&& code[i + 4].opcode == OpCodes.Callvirt)
{
code[i].opcode = OpCodes.Nop;
code[i + 1].opcode = OpCodes.Nop;
code[i + 2].opcode = OpCodes.Nop;
code[i + 3].opcode = OpCodes.Nop;
code[i + 4].opcode = OpCodes.Nop; // change call to stop to nop, no idea why this works and the other doesn't in cleaned dlls
break;
}
}

return code;
}
}

return code;
static bool ModuleDeployablePart_startFSM_Prefix(ModuleDeployableSolarPanel __instance)
{
if (__instance.useAnimation)
{
__instance.anim[__instance.animationName].wrapMode = WrapMode.ClampForever;
switch (__instance.deployState)
{
case ModuleDeployablePart.DeployState.RETRACTED:
__instance.anim[__instance.animationName].normalizedTime = 0f;
__instance.anim[__instance.animationName].enabled = true;
__instance.anim[__instance.animationName].weight = 1f;
__instance.anim[__instance.animationName].speed = 0f;
__instance.bypassSetupAnimation = true;
__instance.Events["Retract"].active = false;
__instance.Events["Extend"].active = true;
break;
case ModuleDeployablePart.DeployState.EXTENDED:
__instance.anim[__instance.animationName].normalizedTime = 1f;
__instance.anim[__instance.animationName].enabled = true;
__instance.anim[__instance.animationName].speed = 0f;
__instance.anim[__instance.animationName].weight = 1f;
__instance.Events["Extend"].active = false;
__instance.Events["Retract"].active = __instance.retractable || HighLogic.LoadedSceneIsEditor;
if (__instance.hasPivot)
{
__instance.panelRotationTransform.localRotation = __instance.currentRotation;
}
break;
case ModuleDeployablePart.DeployState.RETRACTING:
__instance.Events["Retract"].active = false;
__instance.Events["Extend"].active = false;
break;
case ModuleDeployablePart.DeployState.EXTENDING:
__instance.Events["Retract"].active = false;
__instance.Events["Extend"].active = false;
break;
}
if (__instance.deployState == ModuleDeployablePart.DeployState.RETRACTING || __instance.deployState == ModuleDeployablePart.DeployState.EXTENDING || __instance.deployState == ModuleDeployablePart.DeployState.BROKEN)
{
__instance.anim[__instance.animationName].normalizedTime = __instance.storedAnimationTime;
__instance.anim[__instance.animationName].speed = __instance.storedAnimationSpeed;
}
if (!__instance.bypassSetupAnimation)
{
__instance.anim.Play(__instance.animationName);
}
if (!__instance.playAnimationOnStart && __instance.deployState != ModuleDeployablePart.DeployState.EXTENDING && __instance.deployState != ModuleDeployablePart.DeployState.RETRACTING)
{
__instance.stopAnimation = true;
}
}
else
{
if (__instance.hasPivot)
{
__instance.panelRotationTransform.localRotation = __instance.originalRotation;
}
if (__instance.deployState != ModuleDeployablePart.DeployState.BROKEN)
{
__instance.deployState = ModuleDeployablePart.DeployState.EXTENDED;
}
__instance.Events["Retract"].active = false;
__instance.Events["Extend"].active = false;
__instance.Actions["ExtendPanelsAction"].active = false;
__instance.Actions["ExtendAction"].active = false;
__instance.Actions["RetractAction"].active = false;
__instance.Fields["status"].guiActiveEditor = false;
}
if (__instance.deployState == ModuleDeployablePart.DeployState.BROKEN)
{
__instance.Events["Retract"].active = false;
__instance.Events["Extend"].active = false;
if (__instance.panelBreakTransform)
{
__instance.panelBreakTransform.gameObject.SetActive(false);
}
}
return false;
}
}
}
114 changes: 87 additions & 27 deletions KSPCommunityFixes/BugFixes/ModuleIndexingMismatch.cs
Original file line number Diff line number Diff line change
Expand Up @@ -28,8 +28,7 @@ public class ModuleIndexingMismatch : BasePatch
{
private const string VALUENAME_MODULEPARTCONFIGID = "modulePartConfigId";
private static readonly HashSet<string> multiModules = new HashSet<string>();
private static readonly Dictionary<string, Type> allModuleTypes = new Dictionary<string, Type>();

private static readonly Dictionary<string, Type> allModuleTypes = new Dictionary<string, Type>();
protected override Version VersionMin => new Version(1, 8, 0);

protected override void ApplyPatches()
Expand All @@ -44,7 +43,6 @@ protected override void ApplyPatches()
{
AddPatch(PatchType.Transpiler, typeof(ProtoPartSnapshot), "ConfigurePart");
}

AddPatch(PatchType.Transpiler, typeof(ShipConstruct), "LoadShip", new Type[] { typeof(ConfigNode), typeof(uint), typeof(bool), typeof(string).MakeByRefType() });

Type multiModuleType = typeof(IMultipleModuleInPart);
Expand Down Expand Up @@ -208,8 +206,8 @@ static IEnumerable<CodeInstruction> ProtoPartSnapshot_ConfigurePart_Transpiler(I

return code;
}

/// <summary>
/// <summary>
/// Our own version of ProtoPartModuleSnapshot.Load(). We reimplement it because :
/// - Stock would do again all the indice / module matching that we just did
/// - That stock logic would prevent our handling of loading derived into base / base into derived modules.
Expand All @@ -222,6 +220,7 @@ private static void LoadProtoPartSnapshotModule(ProtoPartModuleSnapshot protoMod
protoModule.moduleRef = module;
}


static void LoadModules(ProtoPartSnapshot protoPart, Part part)
{
int protoModuleCount = protoPart.modules.Count;
Expand Down Expand Up @@ -379,31 +378,92 @@ static IEnumerable<CodeInstruction> ShipConstruct_LoadShip_Transpiler(IEnumerabl

// first, remove the original module load call
bool originalFound = false;
for (int i = 0; i < code.Count - 6; i++)

if (!KSPCommunityFixes.IsCleanedDll)
{
//// part.LoadModule(configNode2, ref moduleIndex);
// ldloc.s 6
// ldloc.3
// ldloca.s 39
// callvirt instance class PartModule Part::LoadModule(class ConfigNode, int32&)
// dup
// pop
// pop
if (code[i].opcode == OpCodes.Ldloc_S
&& code[i + 1].opcode == OpCodes.Ldloc_3
&& code[i + 2].opcode == OpCodes.Ldloca_S
&& code[i + 3].opcode == OpCodes.Callvirt && ReferenceEquals(code[i + 3].operand, Part_LoadModule)
&& code[i + 4].opcode == OpCodes.Dup
&& code[i + 5].opcode == OpCodes.Pop
&& code[i + 6].opcode == OpCodes.Pop)
for (int i = 0; i < code.Count - 6; i++)
{
originalFound = true;
for (int j = i; j < i + 7; j++)
//// part.LoadModule(configNode2, ref moduleIndex);
// ldloc.s 6
// ldloc.3
// ldloca.s 39
// callvirt instance class PartModule Part::LoadModule(class ConfigNode, int32&)
// dup
// pop
// pop
if (code[i].opcode == OpCodes.Ldloc_S
&& code[i + 1].opcode == OpCodes.Ldloc_3
&& code[i + 2].opcode == OpCodes.Ldloca_S
&& code[i + 3].opcode == OpCodes.Callvirt && ReferenceEquals(code[i + 3].operand, Part_LoadModule)
&& code[i + 4].opcode == OpCodes.Dup
&& code[i + 5].opcode == OpCodes.Pop
&& code[i + 6].opcode == OpCodes.Pop)
{
code[j].opcode = OpCodes.Nop;
code[j].operand = null;
originalFound = true;
for (int j = i; j < i + 7; j++)
{
code[j].opcode = OpCodes.Nop;
code[j].operand = null;
}
break;
}
}
}
else
{
for (int i = 0; i < code.Count - 5; i++)
{
//// part.LoadModule(configNode2, ref moduleIndex);
// ldloc.s 6
// ldloc.3
// ldloca.s 39
// callvirt instance class PartModule Part::LoadModule(class ConfigNode, int32&)
// pop
// br
if (code[i].opcode == OpCodes.Ldloc_S
&& code[i + 1].opcode == OpCodes.Ldloc_3
&& code[i + 2].opcode == OpCodes.Ldloca_S
&& code[i + 3].opcode == OpCodes.Callvirt && ReferenceEquals(code[i + 3].operand, Part_LoadModule)
&& code[i + 4].opcode == OpCodes.Pop
&& code[i + 5].opcode == OpCodes.Br)
{
originalFound = true;
for (int j = i; j < i + 6; j++)
{
code[j].opcode = OpCodes.Nop;
code[j].operand = null;
}
break;
}
}
if (!originalFound)
{
code = new List<CodeInstruction>(instructions);
for (int i = 0; i < code.Count - 5; i++)
{
//// part.LoadModule(configNode2, ref moduleIndex);
// ldloc.s 6
// ldloc.3
// ldloca.s 39
// callvirt instance class PartModule Part::LoadModule(class ConfigNode, int32&)
// pop
// br
if (code[i].opcode == OpCodes.Ldloc_S
&& code[i + 1].opcode == OpCodes.Ldloc_S
&& code[i + 2].opcode == OpCodes.Ldloca_S
&& code[i + 3].opcode == OpCodes.Callvirt && ReferenceEquals(code[i + 3].operand, Part_LoadModule)
&& code[i + 4].opcode == OpCodes.Pop
&& code[i + 5].opcode == OpCodes.Br_S)
{
originalFound = true;
for (int j = i; j < i + 6; j++)
{
code[j].opcode = OpCodes.Nop;
code[j].operand = null;
}
break;
}
}
break;
}
}

Expand Down Expand Up @@ -611,4 +671,4 @@ static void LoadShipModuleNodes(Part part, ConfigNode partNode)
}
}
}
}
}
Loading