Skip to content

Commit 88eae5a

Browse files
committed
Add sync for prefab picking deleting the giver object (required for melons)
1 parent 775cf86 commit 88eae5a

File tree

5 files changed

+98
-2
lines changed

5 files changed

+98
-2
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
using HarmonyLib;
2+
using NitroxTest.Patcher;
3+
4+
namespace NitroxPatcher.Patches.Dynamic;
5+
6+
[TestClass]
7+
public class PickPrefab_AddToContainerAsync_PatchTest
8+
{
9+
[TestMethod]
10+
public void Sanity()
11+
{
12+
IEnumerable<CodeInstruction> originalIl = PatchTestHelper.GetInstructionsFromMethod(PickPrefab_AddToContainerAsync_Patch.TARGET_METHOD);
13+
IEnumerable<CodeInstruction> transformedIl = PickPrefab_AddToContainerAsync_Patch.Transpiler(originalIl);
14+
transformedIl.Count().Should().Be(originalIl.Count() + 4);
15+
}
16+
}

NitroxClient/GameLogic/SimulationOwnership.cs

+1-1
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ public SimulationOwnership(IMultiplayerSession muliplayerSession, IPacketSender
2222
}
2323
public bool PlayerHasMinLockType(NitroxId id, SimulationLockType lockType)
2424
{
25-
if (simulatedIdsByLockType.TryGetValue(id, out SimulationLockType playerLock))
25+
if (id != null && simulatedIdsByLockType.TryGetValue(id, out SimulationLockType playerLock))
2626
{
2727
return playerLock <= lockType;
2828
}

NitroxPatcher/Patches/Dynamic/ItemsContainer_NotifyAddItem_Patch.cs

+2-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
using System.Reflection;
22
using NitroxClient.GameLogic;
3+
using NitroxClient.MonoBehaviours;
34
using NitroxModel.Helper;
45

56
namespace NitroxPatcher.Patches.Dynamic;
@@ -10,7 +11,7 @@ public sealed partial class ItemsContainer_NotifyAddItem_Patch : NitroxPatch, ID
1011

1112
public static void Postfix(ItemsContainer __instance, InventoryItem item)
1213
{
13-
if (item != null)
14+
if (item != null && Multiplayer.Main && Multiplayer.Main.InitialSyncCompleted)
1415
{
1516
Resolve<ItemContainers>().BroadcastItemAdd(item.item, __instance.tr);
1617
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
using System.Collections.Generic;
2+
using System.Reflection;
3+
using System.Reflection.Emit;
4+
using HarmonyLib;
5+
using NitroxClient.Communication.Abstract;
6+
using NitroxModel.DataStructures;
7+
using NitroxModel.Helper;
8+
using NitroxModel.Packets;
9+
using UnityEngine;
10+
11+
namespace NitroxPatcher.Patches.Dynamic;
12+
13+
/// <summary>
14+
/// Sync destruction of giver object when required.
15+
/// </summary>
16+
public sealed partial class PickPrefab_AddToContainerAsync_Patch : NitroxPatch, IDynamicPatch
17+
{
18+
internal static readonly MethodInfo TARGET_METHOD = AccessTools.EnumeratorMoveNext(Reflect.Method((PickPrefab t) => t.AddToContainerAsync(default, default)));
19+
20+
/*
21+
* 1st injection:
22+
* if (!component)
23+
* {
24+
* UnityEngine.Object.Destroy(gameObject);
25+
* BroadcastDeletion(this); <------- [INSERTED LINE]
26+
*
27+
* 2nd injection:
28+
* else if (!container.HasRoomFor(component))
29+
* {
30+
* UnityEngine.Object.Destroy(gameObject);
31+
* BroadcastDeletion(this); <------- [INSERTED LINE]
32+
*/
33+
public static IEnumerable<CodeInstruction> Transpiler(IEnumerable<CodeInstruction> instructions)
34+
{
35+
// The 2 injections are similar (looking for a destroy instruction and adding our callback after it)
36+
return new CodeMatcher(instructions).MatchEndForward(new CodeMatch(OpCodes.Call, Reflect.Method(() => Object.Destroy(default))))
37+
.Advance(1)
38+
.InsertAndAdvance([
39+
new CodeInstruction(OpCodes.Ldarg_0),
40+
new CodeInstruction(OpCodes.Call, Reflect.Method(() => BroadcastDeletion(default)))
41+
])
42+
.MatchEndForward(new CodeMatch(OpCodes.Call, Reflect.Method(() => Object.Destroy(default))))
43+
.Advance(1)
44+
.InsertAndAdvance([
45+
new CodeInstruction(OpCodes.Ldarg_0),
46+
new CodeInstruction(OpCodes.Call, Reflect.Method(() => BroadcastDeletion(default)))
47+
])
48+
.InstructionEnumeration();
49+
}
50+
51+
public static void BroadcastDeletion(PickPrefab pickPrefab)
52+
{
53+
if (pickPrefab.TryGetNitroxId(out NitroxId objectId) ||
54+
(pickPrefab.TryGetComponent(out GrownPlant grownPlant) && grownPlant.seed && grownPlant.seed.TryGetNitroxId(out objectId)))
55+
{
56+
Resolve<IPacketSender>().Send(new EntityDestroyed(objectId));
57+
}
58+
}
59+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
using System.Reflection;
2+
using NitroxModel.Helper;
3+
4+
namespace NitroxPatcher.Patches.Dynamic;
5+
6+
/// <summary>
7+
/// Sync destruction of giver object when required.
8+
/// </summary>
9+
public sealed partial class PickPrefab_SetPickedState_Patch : NitroxPatch, IDynamicPatch
10+
{
11+
private static readonly MethodInfo TARGET_METHOD = Reflect.Method((PickPrefab t) => t.SetPickedState(default));
12+
13+
public static void Postfix(PickPrefab __instance, bool newPickedState)
14+
{
15+
if (newPickedState && __instance.destroyOnPicked)
16+
{
17+
PickPrefab_AddToContainerAsync_Patch.BroadcastDeletion(__instance);
18+
}
19+
}
20+
}

0 commit comments

Comments
 (0)