Skip to content

Commit

Permalink
Refactor game patches to separate class
Browse files Browse the repository at this point in the history
  • Loading branch information
Extremelyd1 committed Jul 25, 2024
1 parent 57747a4 commit 0ac08b5
Show file tree
Hide file tree
Showing 5 changed files with 259 additions and 226 deletions.
41 changes: 0 additions & 41 deletions HKMP/Animation/AnimationManager.cs
Original file line number Diff line number Diff line change
Expand Up @@ -455,9 +455,6 @@ ServerSettings serverSettings

// Register when the player dies to send the animation
ModHooks.BeforePlayerDeadHook += OnDeath;

// Register IL hook for changing the behaviour of tink effects
IL.TinkEffect.OnTriggerEnter2D += TinkEffectOnTriggerEnter2D;

// Set the server settings for all animation effects
foreach (var effect in AnimationEffects.Values) {
Expand Down Expand Up @@ -1134,42 +1131,4 @@ public static AnimationClip GetCurrentAnimationClip() {

return 0;
}

/// <summary>
/// IL hook to change the TinkEffect OnTriggerEnter2D to not trigger on remote players.
/// This method will insert IL to check whether the player responsible for the attack is the local player.
/// </summary>
private void TinkEffectOnTriggerEnter2D(ILContext il) {
try {
// Create a cursor for this context
var c = new ILCursor(il);

// Find the first return instruction in the method to branch to later
var retInstr = il.Instrs.First(i => i.MatchRet());

// Load the 'collision' argument onto the stack
c.Emit(OpCodes.Ldarg_1);

// Emit a delegate that pops the TinkEffect from the stack, checks whether the parent
// of the effect is the knight and pushes a bool on the stack based on this
c.EmitDelegate<Func<Collider2D, bool>>(collider => {
var parent = collider.transform.parent;
if (parent == null) {
return true;
}

parent = parent.parent;
if (parent == null) {
return true;
}

return parent.gameObject.name != "Knight";
});

// Based on the bool we pushed to the stack earlier, we conditionally branch to the return instruction
c.Emit(OpCodes.Brtrue, retInstr);
} catch (Exception e) {
Logger.Error($"Could not change TinkEffect#OnTriggerEnter2D IL:\n{e}");
}
}
}
1 change: 1 addition & 0 deletions HKMP/Game/Client/ClientManager.cs
Original file line number Diff line number Diff line change
Expand Up @@ -190,6 +190,7 @@ ModSettings modSettings
_saveManager.Initialize();

new PauseManager(netClient).RegisterHooks();
new GamePatcher().RegisterHooks();
new FsmPatcher().RegisterHooks();

_commandManager = new ClientCommandManager();
Expand Down
130 changes: 0 additions & 130 deletions HKMP/Game/Client/Entity/EntityManager.cs
Original file line number Diff line number Diff line change
Expand Up @@ -65,17 +65,6 @@ public EntityManager(NetClient netClient) {
UnityEngine.SceneManagement.SceneManager.activeSceneChanged += OnSceneChanged;

FindGameObject.Find += OnFindGameObject;

On.BridgeLever.OnTriggerEnter2D += BridgeLeverOnTriggerEnter2D;

var type = typeof(BridgeLever).GetNestedType("<OpenBridge>d__13",
BindingFlags.NonPublic | BindingFlags.Instance);

// TODO: store this hook and unregister if entity system is not used
new ILHook(
type.GetMethod("MoveNext", BindingFlags.NonPublic | BindingFlags.Instance),
BridgeLeverOnOpenBridge
);
}

/// <summary>
Expand Down Expand Up @@ -512,123 +501,4 @@ private void OnFindGameObject(FindGameObject.orig_Find orig, HutongGames.PlayMak

Logger.Debug(" Name did not match any entity");
}

/// <summary>
/// Whether the local player hit the bridge lever.
/// </summary>
private bool _localPlayerBridgeLever;

/// <summary>
/// On Hook that stores a boolean depending on whether the local player hit the bridge lever or not. Used in the
/// IL Hook below.
/// </summary>
private void BridgeLeverOnTriggerEnter2D(On.BridgeLever.orig_OnTriggerEnter2D orig, BridgeLever self, Collider2D collision) {
Logger.Debug("BridgeLeverOnTriggerEnter2D");

var activated = ReflectionHelper.GetField<BridgeLever, bool>(self, "activated");

Logger.Debug($" activated: {activated}, collision tag: {collision.tag}");
if (!activated && collision.tag == "Nail Attack") {
_localPlayerBridgeLever = collision.transform.parent?.parent?.tag == "Player";
Logger.Debug($" Bridge lever hit: bool: {_localPlayerBridgeLever}");
}

orig(self, collision);
}

/// <summary>
/// IL Hook to modify the OpenBridge method of BridgeLever to exclude locking players in place that did not hit
/// the lever.
/// </summary>
private void BridgeLeverOnOpenBridge(ILContext il) {
Logger.Debug("BridgeLeverOnOpenBridge IL");
try {
// Create a cursor for this context
var c = new ILCursor(il);

// Define the collection of instructions that matches the FreezeMoment call
Func<Instruction, bool>[] freezeMomentInstructions = [
i => i.MatchCall(typeof(global::GameManager), "get_instance"),
i => i.MatchLdcI4(1),
i => i.MatchCallvirt(typeof(global::GameManager), "FreezeMoment")
];

// Goto after the FreezeMoment call
c.GotoNext(MoveType.Before, freezeMomentInstructions);

// Emit a delegate that puts the boolean on the stack
c.EmitDelegate(() => _localPlayerBridgeLever);

// Define the label to branch to
var afterFreezeLabel = c.DefineLabel();

// Then emit an instruction that branches to after the freeze if the boolean is false
c.Emit(OpCodes.Brfalse, afterFreezeLabel);

// Goto after the FreezeMoment call
c.GotoNext(MoveType.After, freezeMomentInstructions);

// Mark the label after the FreezeMoment call so we branch here
c.MarkLabel(afterFreezeLabel);

// Goto after the rumble call
c.GotoNext(
MoveType.After,
i => i.MatchCall(typeof(GameCameras), "get_instance"),
i => i.MatchLdfld(typeof(GameCameras), "cameraShakeFSM"),
i => i.MatchLdstr("RumblingMed"),
i => i.MatchLdcI4(1),
i => i.MatchCall(typeof(FSMUtility), "SetBool")
);

// Emit a delegate that puts the boolean on the stack
c.EmitDelegate(() => _localPlayerBridgeLever);

// Define the label to branch to
var afterRoarEnterLabel = c.DefineLabel();

// Emit another instruction that branches over the roar enter FSM calls
c.Emit(OpCodes.Brfalse, afterRoarEnterLabel);

// Goto after the roar enter call
c.GotoNext(
MoveType.After,
i => i.MatchLdstr("ROAR ENTER"),
i => i.MatchLdcI4(0),
i => i.MatchCall(typeof(FSMUtility), "SendEventToGameObject")
);

// Mark the label after the Roar Enter call so we branch here
c.MarkLabel(afterRoarEnterLabel);

// Define the collection of instructions that matches the roar exit FSM call
Func<Instruction, bool>[] roarExitInstructions = [
i => i.MatchCall(typeof(HeroController), "get_instance"),
i => i.MatchCallvirt(typeof(UnityEngine.Component), "get_gameObject"),
i => i.MatchLdstr("ROAR EXIT"),
i => i.MatchLdcI4(0),
i => i.MatchCall(typeof(FSMUtility), "SendEventToGameObject")
];

// Goto before the roar exit FSM call
c.GotoNext(MoveType.Before, roarExitInstructions);

// Emit a delegate that puts the boolean on the stack
c.EmitDelegate(() => _localPlayerBridgeLever);

// Define the label to branch to
var afterRoarExitLabel = c.DefineLabel();

// Emit the last instruction to branch over the roar exit call
c.Emit(OpCodes.Brfalse, afterRoarExitLabel);

// Goto after the roar exit FSM call
c.GotoNext(MoveType.After, roarExitInstructions);

// Mark the label so we branch here
c.MarkLabel(afterRoarExitLabel);
} catch (Exception e) {
Logger.Error($"Could not change BridgeLever#OnOpenBridge IL: \n{e}");
}
}
}
Loading

0 comments on commit 0ac08b5

Please sign in to comment.