Skip to content

Commit a3a650d

Browse files
feat: Add UpgradedInventoryItem and UpgradedPickup on Scp914 (#579)
* Add UpgradedInventoryItem and UpgradedPickup * please * Improved code (thanks to @MS-crew)
1 parent 79d5f41 commit a3a650d

7 files changed

Lines changed: 312 additions & 4 deletions

File tree

Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
// -----------------------------------------------------------------------
2+
// <copyright file="UpgradedInventoryItemEventArgs.cs" company="ExMod Team">
3+
// Copyright (c) ExMod Team. All rights reserved.
4+
// Licensed under the CC BY-SA 3.0 license.
5+
// </copyright>
6+
// -----------------------------------------------------------------------
7+
8+
namespace Exiled.Events.EventArgs.Scp914
9+
{
10+
using API.Features;
11+
using API.Features.Items;
12+
using global::Scp914;
13+
using Interfaces;
14+
using InventorySystem.Items;
15+
using InventorySystem.Items.Pickups;
16+
17+
/// <summary>
18+
/// Contains all information before SCP-914 upgrades an item.
19+
/// </summary>
20+
public class UpgradedInventoryItemEventArgs : IItemEvent
21+
{
22+
/// <summary>
23+
/// Initializes a new instance of the <see cref="UpgradedInventoryItemEventArgs" /> class.
24+
/// </summary>
25+
/// <param name="player">
26+
/// <inheritdoc cref="Player" />
27+
/// </param>
28+
/// <param name="item">
29+
/// <inheritdoc cref="Item" />
30+
/// </param>
31+
/// <param name="knobSetting">
32+
/// <inheritdoc cref="KnobSetting" />
33+
/// </param>
34+
/// <param name="result">
35+
/// <inheritdoc cref="Result" />
36+
/// </param>
37+
public UpgradedInventoryItemEventArgs(Player player, ItemBase item, Scp914KnobSetting knobSetting, ItemBase[] result)
38+
{
39+
Player = player;
40+
Item = Item.Get(item);
41+
KnobSetting = knobSetting;
42+
Result = result;
43+
}
44+
45+
/// <summary>
46+
/// Gets SCP-914 working knob setting.
47+
/// </summary>
48+
public Scp914KnobSetting KnobSetting { get; }
49+
50+
/// <summary>
51+
/// Gets a list of items to be upgraded inside SCP-914.
52+
/// </summary>
53+
public Item Item { get; }
54+
55+
/// <summary>
56+
/// Gets the <see cref="Player" /> who owns the item to be upgraded.
57+
/// </summary>
58+
public Player Player { get; }
59+
60+
/// <summary>
61+
/// Gets the array of items created as a result of SCP-914 upgraded.
62+
/// </summary>
63+
public ItemBase[] Result { get; }
64+
}
65+
}
Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
// -----------------------------------------------------------------------
2+
// <copyright file="UpgradedPickupEventArgs.cs" company="ExMod Team">
3+
// Copyright (c) ExMod Team. All rights reserved.
4+
// Licensed under the CC BY-SA 3.0 license.
5+
// </copyright>
6+
// -----------------------------------------------------------------------
7+
8+
namespace Exiled.Events.EventArgs.Scp914
9+
{
10+
using Exiled.API.Features.Pickups;
11+
using Exiled.Events.EventArgs.Interfaces;
12+
using global::Scp914;
13+
using InventorySystem.Items.Pickups;
14+
using UnityEngine;
15+
16+
/// <summary>
17+
/// Contains all information before SCP-914 upgrades an item.
18+
/// </summary>
19+
public class UpgradedPickupEventArgs : IPickupEvent
20+
{
21+
/// <summary>
22+
/// Initializes a new instance of the <see cref="UpgradedPickupEventArgs" /> class.
23+
/// </summary>
24+
/// <param name="item">
25+
/// <inheritdoc cref="Pickup" />
26+
/// </param>
27+
/// <param name="newPos">
28+
/// <inheritdoc cref="OutputPosition" />
29+
/// </param>
30+
/// <param name="knobSetting">
31+
/// <inheritdoc cref="KnobSetting" />
32+
/// </param>
33+
/// <param name="result">
34+
/// <inheritdoc cref="Result" />
35+
/// </param>
36+
public UpgradedPickupEventArgs(ItemPickupBase item, Vector3 newPos, Scp914KnobSetting knobSetting, ItemPickupBase[] result)
37+
{
38+
Pickup = Pickup.Get(item);
39+
OutputPosition = newPos;
40+
KnobSetting = knobSetting;
41+
Result = result;
42+
}
43+
44+
/// <summary>
45+
/// Gets a list of items to be upgraded inside SCP-914.
46+
/// </summary>
47+
public Pickup Pickup { get; }
48+
49+
/// <summary>
50+
/// Gets the position the item will be output to.
51+
/// </summary>
52+
public Vector3 OutputPosition { get; }
53+
54+
/// <summary>
55+
/// Gets SCP-914 working knob setting.
56+
/// </summary>
57+
public Scp914KnobSetting KnobSetting { get; }
58+
59+
/// <summary>
60+
/// Gets the array of items created as a result of SCP-914 upgraded.
61+
/// </summary>
62+
public ItemPickupBase[] Result { get; }
63+
}
64+
}

EXILED/Exiled.Events/Handlers/Scp914.cs

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,11 +22,21 @@ public static class Scp914
2222
/// </summary>
2323
public static Event<UpgradingPickupEventArgs> UpgradingPickup { get; set; } = new();
2424

25+
/// <summary>
26+
/// Invoked after SCP-914 upgrades a Pickup.
27+
/// </summary>
28+
public static Event<UpgradedPickupEventArgs> UpgradedPickup { get; set; } = new();
29+
2530
/// <summary>
2631
/// Invoked before SCP-914 upgrades an item in a player's inventory.
2732
/// </summary>
2833
public static Event<UpgradingInventoryItemEventArgs> UpgradingInventoryItem { get; set; } = new();
2934

35+
/// <summary>
36+
/// Invoked after SCP-914 upgrades an item in a player's inventory.
37+
/// </summary>
38+
public static Event<UpgradedInventoryItemEventArgs> UpgradedInventoryItem { get; set; } = new();
39+
3040
/// <summary>
3141
/// Invoked before SCP-914 upgrades a player.
3242
/// </summary>
@@ -48,12 +58,24 @@ public static class Scp914
4858
/// <param name="ev">The <see cref="UpgradingPickupEventArgs" /> instance.</param>
4959
public static void OnUpgradingPickup(UpgradingPickupEventArgs ev) => UpgradingPickup.InvokeSafely(ev);
5060

61+
/// <summary>
62+
/// Called after SCP-914 upgrades a item.
63+
/// </summary>
64+
/// <param name="ev">The <see cref="UpgradedPickupEventArgs" /> instance.</param>
65+
public static void OnUpgradedPickup(UpgradedPickupEventArgs ev) => UpgradedPickup.InvokeSafely(ev);
66+
5167
/// <summary>
5268
/// Called before SCP-914 upgrades an item in a player's inventory.
5369
/// </summary>
5470
/// <param name="ev">The <see cref="UpgradingInventoryItemEventArgs" /> instance.</param>
5571
public static void OnUpgradingInventoryItem(UpgradingInventoryItemEventArgs ev) => UpgradingInventoryItem.InvokeSafely(ev);
5672

73+
/// <summary>
74+
/// Called after SCP-914 upgrades an item in a player's inventory.
75+
/// </summary>
76+
/// <param name="ev">The <see cref="UpgradedInventoryItemEventArgs" /> instance.</param>
77+
public static void OnUpgradedInventoryItem(UpgradedInventoryItemEventArgs ev) => UpgradedInventoryItem.InvokeSafely(ev);
78+
5779
/// <summary>
5880
/// Called before SCP-914 upgrades a player.
5981
/// </summary>
Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
// -----------------------------------------------------------------------
2+
// <copyright file="UpgradedPickup.cs" company="ExMod Team">
3+
// Copyright (c) ExMod Team. All rights reserved.
4+
// Licensed under the CC BY-SA 3.0 license.
5+
// </copyright>
6+
// -----------------------------------------------------------------------
7+
8+
namespace Exiled.Events.Patches.Events.Scp914
9+
{
10+
using System.Collections.Generic;
11+
using System.Reflection.Emit;
12+
13+
using API.Features.Pools;
14+
using Exiled.Events.Attributes;
15+
using Exiled.Events.EventArgs.Scp914;
16+
17+
using global::Scp914;
18+
19+
using Handlers;
20+
21+
using HarmonyLib;
22+
23+
using static HarmonyLib.AccessTools;
24+
25+
/// <summary>
26+
/// Patches <see cref="Scp914Upgrader.ProcessPickup" />.
27+
/// Adds the <see cref="Scp914.UpgradedPickup" /> event.
28+
/// </summary>
29+
[EventPatch(typeof(Scp914), nameof(Scp914.UpgradedPickup))]
30+
[HarmonyPatch(typeof(Scp914Upgrader), nameof(Scp914Upgrader.ProcessPickup))]
31+
internal static class UpgradedPickup
32+
{
33+
private static IEnumerable<CodeInstruction> Transpiler(IEnumerable<CodeInstruction> instructions, ILGenerator generator)
34+
{
35+
List<CodeInstruction> newInstructions = ListPool<CodeInstruction>.Pool.Get(instructions);
36+
37+
int index = newInstructions.FindLastIndex(instruction => instruction.opcode == OpCodes.Ldloc_2);
38+
39+
List<Label> label = newInstructions[index].ExtractLabels();
40+
41+
newInstructions.InsertRange(
42+
index,
43+
new CodeInstruction[]
44+
{
45+
// pickup
46+
new(OpCodes.Ldarg_0),
47+
48+
// outputPos
49+
new(OpCodes.Ldloc_1),
50+
51+
// knobSetting
52+
new(OpCodes.Ldarg_2),
53+
54+
// resultingPickups
55+
new(OpCodes.Ldloc_S, 4),
56+
new(OpCodes.Ldfld, Field(typeof(Scp914Result), nameof(Scp914Result.ResultingPickups))),
57+
58+
// UpgradedPickupEventArgs ev = new(pickup, outputPos, knobSetting, resultingPickups)
59+
new(OpCodes.Newobj, GetDeclaredConstructors(typeof(UpgradedPickupEventArgs))[0]),
60+
61+
// Handlers.Scp914.OnUpgradingPickup(ev);
62+
new(OpCodes.Call, Method(typeof(Scp914), nameof(Scp914.OnUpgradedPickup))),
63+
});
64+
65+
newInstructions[index].WithLabels(label);
66+
67+
foreach (CodeInstruction t in newInstructions)
68+
yield return t;
69+
70+
ListPool<CodeInstruction>.Pool.Return(newInstructions);
71+
}
72+
}
73+
}
Lines changed: 84 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,84 @@
1+
// -----------------------------------------------------------------------
2+
// <copyright file="UpgradedPlayer.cs" company="ExMod Team">
3+
// Copyright (c) ExMod Team. All rights reserved.
4+
// Licensed under the CC BY-SA 3.0 license.
5+
// </copyright>
6+
// -----------------------------------------------------------------------
7+
8+
namespace Exiled.Events.Patches.Events.Scp914
9+
{
10+
using System.CodeDom;
11+
using System.Collections.Generic;
12+
using System.Reflection;
13+
using System.Reflection.Emit;
14+
15+
using API.Features;
16+
using API.Features.Pools;
17+
using Exiled.Events.Attributes;
18+
using Exiled.Events.EventArgs.Scp914;
19+
using global::Scp914;
20+
using HarmonyLib;
21+
using Mono.Cecil.Cil;
22+
using PlayerRoles.FirstPersonControl;
23+
using UnityEngine;
24+
25+
using static HarmonyLib.AccessTools;
26+
27+
using OpCode = System.Reflection.Emit.OpCode;
28+
using Scp914 = Handlers.Scp914;
29+
30+
/// <summary>
31+
/// Patches <see cref="Scp914Upgrader.ProcessPlayer" />
32+
/// to add the <see cref="Scp914.UpgradedInventoryItem" /> event.
33+
/// </summary>
34+
[EventPatch(typeof(Scp914), nameof(Scp914.UpgradedInventoryItem))]
35+
[HarmonyPatch(typeof(Scp914Upgrader), nameof(Scp914Upgrader.ProcessPlayer))]
36+
internal static class UpgradedPlayer
37+
{
38+
private static IEnumerable<CodeInstruction> Transpiler(IEnumerable<CodeInstruction> instructions, ILGenerator generator)
39+
{
40+
List<CodeInstruction> newInstructions = ListPool<CodeInstruction>.Pool.Get(instructions);
41+
42+
int index = newInstructions.FindIndex(x => x.opcode == OpCodes.Stloc_S && x.operand is LocalBuilder lb && lb.LocalIndex == 11) + 1;
43+
44+
LocalBuilder curSetting = generator.DeclareLocal(typeof(Scp914KnobSetting));
45+
List<Label> label = newInstructions[index].ExtractLabels();
46+
47+
newInstructions.InsertRange(
48+
index,
49+
new CodeInstruction[]
50+
{
51+
// setting = curSetting
52+
new(OpCodes.Ldloc_S, curSetting.LocalIndex),
53+
new(OpCodes.Starg_S, 3),
54+
55+
// Player.Get(ply)
56+
new(OpCodes.Ldarg_0),
57+
new(OpCodes.Call, Method(typeof(Player), nameof(Player.Get), new[] { typeof(ReferenceHub) })),
58+
59+
// itemBase
60+
new(OpCodes.Ldloc_S, 7),
61+
62+
// setting
63+
new(OpCodes.Ldarg_S, 3),
64+
65+
// resultingItems
66+
new(OpCodes.Ldloc_S, 11),
67+
new(OpCodes.Ldfld, Field(typeof(Scp914Result), nameof(Scp914Result.ResultingItems))),
68+
69+
// UpgradedInventoryItemEventArgs ev = new(player, itemBase, setting, resultingItems)
70+
new(OpCodes.Newobj, GetDeclaredConstructors(typeof(UpgradedInventoryItemEventArgs))[0]),
71+
72+
// Handlers.Scp914.OnUpgradedInventoryItem(ev);
73+
new(OpCodes.Call, Method(typeof(Scp914), nameof(Scp914.OnUpgradedInventoryItem))),
74+
});
75+
76+
newInstructions[index].WithLabels(label);
77+
78+
foreach (CodeInstruction t in newInstructions)
79+
yield return t;
80+
81+
ListPool<CodeInstruction>.Pool.Return(newInstructions);
82+
}
83+
}
84+
}

EXILED/Exiled.Events/Patches/Events/Scp914/UpgradingItem.cs renamed to EXILED/Exiled.Events/Patches/Events/Scp914/UpgradingPickup.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
// -----------------------------------------------------------------------
2-
// <copyright file="UpgradingItem.cs" company="ExMod Team">
2+
// <copyright file="UpgradingPickup.cs" company="ExMod Team">
33
// Copyright (c) ExMod Team. All rights reserved.
44
// Licensed under the CC BY-SA 3.0 license.
55
// </copyright>
@@ -28,7 +28,7 @@ namespace Exiled.Events.Patches.Events.Scp914
2828
/// </summary>
2929
[EventPatch(typeof(Scp914), nameof(Scp914.UpgradingPickup))]
3030
[HarmonyPatch(typeof(Scp914Upgrader), nameof(Scp914Upgrader.ProcessPickup))]
31-
internal static class UpgradingItem
31+
internal static class UpgradingPickup
3232
{
3333
private static IEnumerable<CodeInstruction> Transpiler(IEnumerable<CodeInstruction> instructions, ILGenerator generator)
3434
{

EXILED/Exiled.Events/Patches/Events/Scp914/UpgradingPlayer.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -116,14 +116,14 @@ private static IEnumerable<CodeInstruction> Transpiler(IEnumerable<CodeInstructi
116116
offset = 1;
117117

118118
// index = newInstructions.FindIndex(x => x.opcode == OpCodes.Stloc_S && x.operand is LocalBuilder { LocalIndex: 10 }) + offset;
119-
ConstructorInfo plugin_api_constructor = typeof(LabApi.Events.Arguments.Scp914Events.Scp914ProcessingInventoryItemEventArgs)
119+
ConstructorInfo lab_api_constructor = typeof(LabApi.Events.Arguments.Scp914Events.Scp914ProcessingInventoryItemEventArgs)
120120
.GetConstructor(new[]
121121
{
122122
typeof(InventorySystem.Items.ItemBase),
123123
typeof(Scp914KnobSetting),
124124
typeof(ReferenceHub),
125125
});
126-
index = newInstructions.FindIndex(x => x.Is(OpCodes.Newobj, plugin_api_constructor)) + offset;
126+
index = newInstructions.FindIndex(x => x.Is(OpCodes.Newobj, lab_api_constructor)) + offset;
127127

128128
// ridtp lcz914
129129
// noclip

0 commit comments

Comments
 (0)