Files
BoneSync/BoneSync/Patching/PoolPatches.cs
2025-03-23 20:19:39 +02:00

212 lines
7.8 KiB
C#

using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading.Tasks;
using BoneSync.Data;
using BoneSync.Networking.Messages;
using BoneSync.Sync;
using BoneSync.Sync.Components;
using HarmonyLib;
using MelonLoader;
using StressLevelZero;
using StressLevelZero.Pool;
using StressLevelZero.Props.Weapons;
using UnityEngine;
namespace BoneSync.Patching
{
public static class PoolBlacklist
{
private static Dictionary<Pool, bool> _blacklistedCache = new Dictionary<Pool, bool>();
private static Dictionary<Pool, bool> _clientSpawnCache = new Dictionary<Pool, bool>();
private static bool _isBlacklistedPool(Pool pool)
{
if (pool.name.Contains("RigidbodyProjectile")) return true;
if (pool.name.Contains("VFX Despawn Mesh")) return true;
if (pool.name.Contains("AudioPlayer")) return true;
if (pool.name.Contains("Decal")) return true;
if (pool.name.Contains("PopupText")) return true;
//if (pool.name.Contains("Nimbus")) return true;
if (pool.Prefab.GetComponent<SpawnFragment>() != null) return true;
if (pool.Prefab.GetComponent<SpawnFragmentArray>() != null) return true;
return false;
}
private static bool _isClientSpawnPool(Pool pool)
{
if (pool.Prefab.GetComponent<Magazine>() != null) return true;
return false;
}
public static bool isBlacklistedPool(Pool pool)
{
if (_blacklistedCache.ContainsKey(pool))
return _blacklistedCache[pool];
_blacklistedCache[pool] = _isBlacklistedPool(pool);
return _blacklistedCache[pool];
}
public static bool IsClientSpawnPool(Pool pool)
{
if (_clientSpawnCache.ContainsKey(pool))
return _clientSpawnCache[pool];
_clientSpawnCache[pool] = _isClientSpawnPool(pool);
return _clientSpawnCache[pool];
}
}
[HarmonyPatch(typeof(Pool))]
public static class PoolPatches
{
[HarmonyPatch(nameof(Pool.InstantiatePoolee), new Type[] { typeof(Vector3), typeof(Quaternion) }), HarmonyPrefix]
private static bool InstantiatePooleePatchPre(Pool __instance)
{
if (!__instance.Prefab)
return false;
return true;
}
[HarmonyPatch(nameof(Pool.InstantiatePoolee), new Type[] { typeof(Vector3), typeof(Quaternion) }), HarmonyPostfix]
private static void InstantiatePooleePatchPost(Pool __instance, Poolee __result, Vector3 position, Quaternion rotation)
{
if (CallPatchedMethods.allowPatchedMethodCall) return;
if (__instance == null) return;
if (PoolBlacklist.isBlacklistedPool(__instance)) return;
//SyncLogger.Msg("Patched Instantiating object in pool: " + __instance.name);
__result.onSpawnDelegate = Il2CppSystem.Delegate.Combine(__result.onSpawnDelegate, (Il2CppSystem.Action<GameObject>)((g) => { PooleePatches.OnSpawnPatchPost(__result); })).Cast<Il2CppSystem.Action<GameObject>>();
__result.onDespawnDelegate = Il2CppSystem.Delegate.Combine(__result.onDespawnDelegate, (Il2CppSystem.Action<GameObject>)((g) => { PooleePatches.OnDespawnPatchPost(__result); })).Cast<Il2CppSystem.Action<GameObject>>();
}
/*[HarmonyPatch(nameof(Pool.Spawn))]
[HarmonyPostfix]
private static void SpawnPatchPost(Pool __instance, ref GameObject __result)
{
if (__instance == null) return;
if (__instance.Prefab == null) return;
if (CallPatchedMethods.allowPatchedMethodCall) return;
if (PoolBlacklist.isBlacklistedPool(__instance)) return;
if (BoneSync.IsConnected)
{
SyncLogger.Msg("Patched Spawning object in pool: " + __instance.name);
bool isHost = BoneSync.lobby.IsHost;
if (!isHost) GameObject.DestroyImmediate(__result);
}
}*/
/*[HarmonyPatch(nameof(Pool.Spawn))]
[HarmonyPrefix]
private static bool SpawnPatchPre(Pool __instance, ref Vector3 position, ref Quaternion rotation, ref Il2CppSystem.Nullable<Vector3> scale, ref Il2CppSystem.Nullable<bool> autoEnable)
{
if (__instance == null) return true;
if (__instance.Prefab == null) return true;
if (CallPatchedMethods.allowPatchedMethodCall) return true;
if (PoolBlacklist.isBlacklistedPool(__instance)) return true;
if (BoneSync.IsConnected)
{
SyncLogger.Msg("Patched Spawning object in pool: " + __instance.name);
return BoneSync.lobby.IsHost; // only allow host to spawn objects naturally
}
__instance.
return true;
}
*/
}
[HarmonyPatch(typeof(Poolee))]
public static class PooleePatches
{
public static void OnSpawnPatchPost(Poolee __instance)
{
if (CallPatchedMethods.allowPatchedMethodCall) return;
if (!BoneSync.IsConnected) return;
SyncLogger.Msg("Poolee.OnSpawn: " + __instance.gameObject.transform.GetPath());
Syncable syncable = ObjectSync.MakeOrGetSyncable(__instance);
bool spawnNormally = BoneSync.lobby.IsHost || PoolBlacklist.IsClientSpawnPool(__instance.pool);
SyncLogger.Msg("Poolee.OnSpawn: " + __instance.gameObject.transform.GetPath() + " syncid:" + syncable?.GetSyncId() + " spawnNormally" + spawnNormally);
if (!spawnNormally) {
MelonCoroutines.Start(OnSpawnClient(__instance)); // block object from spawning
return;
}
if (syncable == null) return;
//
//
//
//.Msg("Poolee.OnSpawn: " + __instance.gameObject.transform.GetPath() + " " + syncable.GetSyncId());
}
public static void OnDespawnPatchPost(Poolee __instance)
{
if (CallPatchedMethods.allowPatchedMethodCall) return;
if (!BoneSync.IsConnected) return;
SyncLogger.Msg("Poolee.OnDespawn: " + __instance.gameObject.transform.GetPath());
//Syncable syncable = ObjectSync.MakeOrGetSyncable(__instance);
//if (syncable == null) return;
//if (syncable.isOwner) return;
//syncable.DiscardSyncable(true);
}
public static IEnumerator OnSpawnClient(Poolee poolee)
{
GameObject go = poolee.gameObject;
if (SceneLoader.loading)
{
while (SceneLoader.loading)
{
go.SetActive(false);
yield return null;
}
}
for (int i = 0; i < 2; i++)
{
go.SetActive(false);
yield return null;
}
}
public static IEnumerator OnSpawnHost(Poolee poolee)
{
return null;
}
/* // DONT USE THIS PATCH, CRASHES GAME WITH NO ERROR
[HarmonyPatch(nameof(Poolee.Despawn), new Type[] { typeof(Il2CppSystem.Nullable<bool>), typeof(Il2CppSystem.Nullable<Color>) }), HarmonyPrefix]
private static bool DespawnPatchPre(Poolee __instance, ref Il2CppSystem.Nullable<bool> playVFX, ref Il2CppSystem.Nullable<Color> despawnColor)
{
if (CallPatchedMethods.allowPatchedMethodCall) return true;
if (!BoneSync.IsConnected) return true;
Syncable syncable = ObjectSync.MakeOrGetSyncable(__instance);
if (syncable == null) return true;
if (!syncable.isOwner) return false; // if not owner, don't despawn
return true;
}
*/
}
}