104 lines
4.0 KiB
C#
104 lines
4.0 KiB
C#
using System;
|
|
using System.Collections;
|
|
using System.Collections.Generic;
|
|
using BD2.GameNames;
|
|
using BepInEx.Logging;
|
|
using gamfs;
|
|
using HarmonyLib;
|
|
using Proto.Net;
|
|
using UnityEngine.SceneManagement;
|
|
|
|
namespace Bd2LocalIdentity;
|
|
|
|
internal static class FieldRewardPosition
|
|
{
|
|
private static readonly HashSet<FieldRewardObjectController> Pending = [];
|
|
private static ManualLogSource Log;
|
|
|
|
internal static void Install(Harmony harmony, ManualLogSource logger)
|
|
{
|
|
Log = logger;
|
|
harmony.Patch(Game.Method(() => FieldPacket.SendFieldObjectRewardRequest(null, true)),
|
|
prefix: new HarmonyMethod(typeof(FieldRewardPosition), nameof(SaveBeforeReward)));
|
|
}
|
|
|
|
private static bool SaveBeforeReward(FieldRewardObjectController __0, bool __1)
|
|
{
|
|
if (__0 == null || MiniGameHubSupporter.IsPlayEventHubOrMiniEventHub() ||
|
|
(FieldRewardObjectController.EFieldRewardObjectGroupType)__0.FieldRewardObjectGroupDTO.Type ==
|
|
FieldRewardObjectController.EFieldRewardObjectGroupType.LostCoin)
|
|
{
|
|
return true;
|
|
}
|
|
if (Pending.Contains(__0))
|
|
{
|
|
return false;
|
|
}
|
|
GameFieldManager field = GameFieldManager.Instance;
|
|
if (UsesDedicatedPosition(field))
|
|
{
|
|
return true;
|
|
}
|
|
int packId = SG.Pack?.PlayingPackID ?? 0;
|
|
Scene scene = __0.gameObject.scene;
|
|
if (IsReady(field, packId, scene))
|
|
{
|
|
FieldPacket.SendSaveUserPositionRequest(packId, false, true);
|
|
return true;
|
|
}
|
|
if (field == null || packId <= 0 || !scene.IsValid() || !scene.isLoaded)
|
|
{
|
|
Log.LogWarning("Field reward skipped without a loaded field: pack=" + packId);
|
|
return false;
|
|
}
|
|
Pending.Add(__0);
|
|
field.StartCoroutine(WaitForPosition(field, __0, __1, packId, scene));
|
|
return false;
|
|
}
|
|
|
|
private static bool UsesDedicatedPosition(GameFieldManager field)
|
|
{
|
|
var packType = (Define_PackType)(SG.Pack?.EnterPackDTO?.PackType ?? -1);
|
|
return packType is Define_PackType.PackHidden or Define_PackType.PackIb ||
|
|
(packType == Define_PackType.PackSkyWay && field?.CurrentMapInfo?.MapType == 1) ||
|
|
(packType == Define_PackType.PackEvilCastle && EvilCastleManager.Instance != null &&
|
|
EvilCastleInfo.IsEvilCastleBType(EvilCastleManager.Instance.CurrentEvilCastleType));
|
|
}
|
|
|
|
private static bool IsReady(GameFieldManager field, int packId, Scene scene)
|
|
{
|
|
return field != null && field.PlayerController != null && field.IsLoadedField &&
|
|
!field.IsMoveMapProcessing && field.CurrentMapInfo != null &&
|
|
packId > 0 && field.CurrentMapInfo.PackId == packId && SG.Net != null &&
|
|
scene.IsValid() && scene.isLoaded && scene == UnityEngine.SceneManagement.SceneManager.GetActiveScene() &&
|
|
string.Equals(field.CurrentMapScenePath, scene.name, StringComparison.Ordinal);
|
|
}
|
|
|
|
private static IEnumerator WaitForPosition(GameFieldManager field,
|
|
FieldRewardObjectController reward, bool showIndicator, int packId, Scene scene)
|
|
{
|
|
try
|
|
{
|
|
// The caller finishes its interaction state after the patched method returns.
|
|
yield return null;
|
|
while (field != null && reward != null && scene.isLoaded &&
|
|
GameFieldManager.Instance == field && SG.Pack != null &&
|
|
SG.Pack.PlayingPackID == packId && reward.gameObject.scene == scene)
|
|
{
|
|
if (IsReady(field, packId, scene))
|
|
{
|
|
Pending.Remove(reward);
|
|
FieldPacket.SendFieldObjectRewardRequest(reward, showIndicator);
|
|
yield break;
|
|
}
|
|
yield return null;
|
|
}
|
|
Log.LogWarning("Deferred field reward cancelled after its field changed: pack=" + packId);
|
|
}
|
|
finally
|
|
{
|
|
Pending.Remove(reward);
|
|
}
|
|
}
|
|
}
|