Files
bd2/plugins/LocalIdentity/LocalAccountPolicy.cs
T
Flechazo d8771caef2 feat(all): add hunting and events, commerce and rewards, binary calendars, GameData caching and login diagnostics
Implement hunting AP and progress, event tasks, exchanges, games, stories and actions; connect battle and reward handling.

Add CashShop plugin and installation, server purchases and entitlements, recharge rules and plugin version metadata.

Distribute binary calendars independently; cache GameData in memory and fix single-connection query deadlocks.

Improve automatic login and recovery diagnostics; document configuration and release flows.
2026-10-05 11:50:31 +08:00

84 lines
3.3 KiB
C#

using System;
using BD2.GameNames;
using static BD2.GameNames.Game;
using System.Reflection;
using BepInEx.Logging;
using HarmonyLib;
using UnityEngine;
namespace Bd2LocalIdentity;
internal static class LocalAccountPolicy
{
private static ManualLogSource Log;
internal static void Initialize(ManualLogSource logger) => Log = logger;
internal static void InstallAgeGatePersistence(Harmony harmony)
{
// LoginUserResponse field 13 is the client's sole gate for opening
// AgeGatePopupUI. Retain the original first-run UI and request; only
// change a later LoginUser parse after its successful local state has
// been read from disk.
Type commonPacket = typeof(BDNetwork.CommonPacket);
MethodInfo updateAgeGate = commonPacket?.GetGameMethod(
nameof(BDNetwork.CommonPacket.SendUpdateAgeGateRequest),
BindingFlags.Static | BindingFlags.Public,
null,
new[] { typeof(bool), typeof(int), typeof(int), typeof(int), typeof(Action) },
null);
if (updateAgeGate == null)
{
throw new MissingMethodException("CommonPacket.SendUpdateAgeGateRequest(bool, int, int, int, Action) was not found");
}
Type loginUserResponse = typeof(Proto.Net.LoginUserResponse);
MethodInfo needsAgeVerificationSetter = loginUserResponse?.GetGameProperty(
nameof(Proto.Net.LoginUserResponse.NeedsAgeVerification),
BindingFlags.Instance | BindingFlags.Public)?.GetSetMethod();
if (needsAgeVerificationSetter == null)
{
throw new MissingMethodException("LoginUserResponse.NeedsAgeVerification setter was not found");
}
harmony.Patch(
updateAgeGate,
prefix: new HarmonyMethod(typeof(LocalAccountPolicy), nameof(UpdateAgeGateRequestPrefix)));
harmony.Patch(
needsAgeVerificationSetter,
prefix: new HarmonyMethod(typeof(LocalAccountPolicy), nameof(NeedsAgeVerificationSetterPrefix)));
Log?.LogInfo("Local age-gate confirmation persistence active (confirmed=" + AgeGateState.IsConfirmed() + ")");
}
private static void NeedsAgeVerificationSetterPrefix(ref bool value)
{
if (value && AgeGateState.IsConfirmed())
{
value = false;
Log?.LogInfo("Used persisted local age-gate confirmation for LoginUser");
}
}
private static void UpdateAgeGateRequestPrefix(ref Action __4)
{
// CommonPacket invokes this callback only after it has parsed the
// empty UpdateAgeGateResponse and accepted errorType == 0. Wrapping
// it therefore never records failed/cancelled submissions.
Action continuation = __4;
__4 = delegate
{
try
{
AgeGateState.MarkConfirmed();
Log?.LogInfo("Stored successful local age-gate confirmation");
}
catch (Exception ex)
{
// Preserve the original continuation: inability to persist
// should not break a successfully completed first login.
Log?.LogWarning("Could not persist local age-gate confirmation: " + ex.Message);
}
continuation?.Invoke();
};
}
}