RizzeBattleRoyale/Assets/Scripts/AppKitMetadataInjector.cs
2025-10-15 20:28:33 +04:00

440 lines
14 KiB
C#

using System.Collections;
using System.Reflection;
using System.Threading.Tasks;
using UnityEngine;
using Reown.AppKit.Unity;
using Reown.AppKit.Unity.Model;
using System;
using UnityEngine.SceneManagement;
[DefaultExecutionOrder(1000)]
public class AppKitMetadataInjector : MonoBehaviour
{
[Header("WalletConnect Cloud Project ID")]
[SerializeField] private string projectId = "0b840bb98f4fea8ce4647bc0b0de86a0";
[Header("Branding")]
[SerializeField] private string appName = "BR Game";
[SerializeField] private string appDescription = "Public PC build (QR connect via phone)";
[SerializeField] private string appUrl = "https://example.com";
[SerializeField] private string appIconUrl = "https://walletconnect.com/meta/favicon.ico";
[Header("Chains (first one becomes default)")]
[SerializeField] private bool useEthereum = true; // eip155:1
[SerializeField] private bool usePolygon = true; // eip155:137
[SerializeField] private bool useBase = true; // eip155:8453
private bool _initialized;
private string _defaultChainId = "eip155:1";
private IEnumerator Start()
{
// Wait until the prefab set AppKit.Instance
while (AppKit.Instance == null) yield return null;
// Build metadata + config
var md = new Metadata(appName, appDescription, appUrl, appIconUrl);
var cfg = new AppKitConfig(projectId, md)
{
enableEmail = false,
enableOnramp = false,
enableCoinbaseWallet = false,
connectViewWalletsCountDesktop = 2,
connectViewWalletsCountMobile = 3,
};
// Build supported chains list (order matters: first = default)
EnableDesktopWallets(cfg);
var chains = new System.Collections.Generic.List<Chain>();
if (useEthereum) chains.Add(ChainConstants.Chains.Ethereum);
if (usePolygon) chains.Add(ChainConstants.Chains.Polygon);
if (useBase) chains.Add(ChainConstants.Chains.Base);
if (chains.Count == 0) chains.Add(ChainConstants.Chains.Ethereum);
cfg.supportedChains = chains.ToArray();
_defaultChainId = cfg.supportedChains[0].ChainId; // remember default
// Set AppKit.Config via private setter (reflection) BEFORE init
var cfgProp = typeof(AppKit).GetProperty("Config",
BindingFlags.Static | BindingFlags.NonPublic | BindingFlags.Public);
cfgProp.SetValue(null, cfg);
// Initialize (supports InitializeAsync(cfg) / Initialize(cfg) / no-arg)
yield return InitializeAppKit(cfg);
// Select default chain if API exists (some builds require this)
var selectChain = typeof(AppKit).GetMethod("SelectChain",
BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic);
if (selectChain != null)
selectChain.Invoke(null, new object[] { _defaultChainId });
_initialized = true;
Debug.Log($"✅ AppKit initialized. Default chain: {_defaultChainId}");
AppKit.ConnectorController.AccountConnected += OnWalletConnected;
}
// Button hook
public void OnWalletConnectButton()
{
if (!_initialized)
{
StartCoroutine(OpenAfterReady());
return;
}
//AppKit.OpenModal(ViewType.Connect); // shows QR
//AppKit.ConnectorController.AccountConnected += OnWalletConnected;
OpenQrModal();
}
public void OnBrowserExtensionButton()
{
if (!_initialized)
{
StartCoroutine(ConnectDesktopAfterReady());
return;
}
TriggerDesktopConnect();
}
// Waits until initialized; doesn't re-init
private IEnumerator OpenAfterReady()
{
yield return WaitForInitialization();
OpenQrModal();
}
private IEnumerator ConnectDesktopAfterReady()
{
yield return WaitForInitialization();
TriggerDesktopConnect();
}
private IEnumerator WaitForInitialization()
{
var isInitProp = typeof(AppKit).GetProperty("IsInitialized",
BindingFlags.Static | BindingFlags.NonPublic | BindingFlags.Public);
while (isInitProp != null && !(bool)isInitProp.GetValue(null))
yield return null;
yield break;
}
private void OpenQrModal()
{
AppKit.OpenModal(ViewType.Connect);
AppKit.ConnectorController.AccountConnected += OnWalletConnected;
}
private void TriggerDesktopConnect()
{
var controller = AppKit.ConnectorController;
if (controller == null)
{
Debug.LogWarning("AppKit ConnectorController unavailable for desktop connection.");
return;
}
var controllerType = controller.GetType();
var methods = controllerType.GetMethods(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
foreach (var method in methods)
{
if (method.Name != "ConnectAsync") continue;
var parameters = method.GetParameters();
if (parameters.Length == 0) continue;
var args = new object[parameters.Length];
var success = true;
for (int i = 0; i < parameters.Length; i++)
{
var paramType = parameters[i].ParameterType;
if (paramType.IsEnum && paramType.Name.Contains("ConnectMethod"))
{
try
{
args[i] = Enum.Parse(paramType, "Desktop", true);
}
catch
{
success = false;
break;
}
}
else if (paramType.Name.Contains("ConnectParams"))
{
args[i] = Activator.CreateInstance(paramType);
}
else if (paramType.FullName == typeof(System.Threading.CancellationToken).FullName)
{
args[i] = default(System.Threading.CancellationToken);
}
else if (paramType.IsValueType)
{
args[i] = Activator.CreateInstance(paramType);
}
else
{
args[i] = null;
}
}
if (!success) continue;
var result = method.Invoke(controller, args);
if (result is Task task)
{
StartCoroutine(WaitForTask(task));
}
AppKit.ConnectorController.AccountConnected += OnWalletConnected;
return;
}
Debug.LogWarning("Unable to locate desktop ConnectAsync overload; falling back to QR modal.");
OpenQrModal();
}
private IEnumerator WaitForTask(Task task)
{
while (task != null && !task.IsCompleted)
yield return null;
yield break;
}
private IEnumerator InitializeAppKit(AppKitConfig cfg)
{
var isInitProp = typeof(AppKit).GetProperty("IsInitialized",
BindingFlags.Static | BindingFlags.NonPublic | BindingFlags.Public);
if (isInitProp != null && (bool)isInitProp.GetValue(null)) yield break;
var flags = BindingFlags.Static | BindingFlags.NonPublic | BindingFlags.Public;
var initAsync = typeof(AppKit).GetMethod("InitializeAsync", flags);
if (initAsync != null)
{
var ps = initAsync.GetParameters();
var result = ps.Length == 1
? initAsync.Invoke(null, new object[] { cfg })
: initAsync.Invoke(null, null);
if (result is Task t)
while (!t.IsCompleted) yield return null;
yield break;
}
var init = typeof(AppKit).GetMethod("Initialize", flags);
if (init != null)
{
var ps = init.GetParameters();
var result = ps.Length == 1
? init.Invoke(null, new object[] { cfg })
: init.Invoke(null, null);
if (result is Task t)
while (!t.IsCompleted) yield return null;
yield break;
}
// If neither exists, rely on prefab auto-init
yield return null;
}
private void OnWalletConnected(object sender, Reown.AppKit.Unity.Connector.AccountConnectedEventArgs e)
{
Debug.Log("✅ Wallet connected!");
Debug.Log($"Address: {e.Account.Address}");
PlayerPrefs.SetString("WALLET_ADDRESS", e.Account.Address);
PlayerLoginOrSignup();
SceneManager.LoadScene(1);
}
private void EnableDesktopWallets(AppKitConfig cfg)
{
TrySetConfigBoolean(cfg, "enableEIP6963", true);
TrySetConfigBoolean(cfg, "enableInjected", true);
TrySetConfigBoolean(cfg, "enableDesktop", true);
TrySetConfigBoolean(cfg, "enableDesktopWallets", true);
TrySetConfigBoolean(cfg, "enableInjectedWallets", true);
}
private void TrySetConfigBoolean(AppKitConfig cfg, string memberName, bool value)
{
var flags = BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic;
var type = cfg.GetType();
var prop = type.GetProperty(memberName, flags);
if (prop != null && prop.CanWrite && prop.PropertyType == typeof(bool))
{
prop.SetValue(cfg, value);
return;
}
var field = type.GetField(memberName, flags);
if (field != null && field.FieldType == typeof(bool))
{
field.SetValue(cfg, value);
}
}
public async void PlayerLoginOrSignup()
{
try
{
var rec = await GameDb.WalletConnectedAsync(PlayerPrefs.GetString("WALLET_ADDRESS"));
Debug.Log($"[Runtime] ✅ Ensured player: {rec.WalletAddress} kills={rec.TotalKills} currency={rec.InGameCurrency}");
}
catch (System.Exception e)
{
Debug.LogError($"[Runtime] ❌ Ensure failed: {e.Message}");
}
}
[ContextMenu("AddKill")]
public async void AddKill()
{
try
{
var rec = await GameDb.AddKillAsync(PlayerPrefs.GetString("WALLET_ADDRESS"));
Debug.Log($"[Runtime] ✅ Ensured player: {rec.WalletAddress} kills={rec.TotalKills} currency={rec.InGameCurrency}");
}
catch (System.Exception e)
{
Debug.LogError($"[Runtime] ❌ Ensure failed: {e.Message}");
}
}
[ContextMenu("AddCurrency")]
public async void AddCurrency()
{
try
{
var rec = await GameDb.AddCurrencyAsync(PlayerPrefs.GetString("WALLET_ADDRESS"),100);
Debug.Log($"[Runtime] ✅ Ensured player: {rec.WalletAddress} kills={rec.TotalKills} currency={rec.InGameCurrency}");
}
catch (System.Exception e)
{
Debug.LogError($"[Runtime] ❌ Ensure failed: {e.Message}");
}
}
[ContextMenu("GetCurrency")]
public async void GetCurrency()
{
try
{
var rec = await GameDb.GetCurrencyAsync(PlayerPrefs.GetString("WALLET_ADDRESS"));
Debug.Log(rec.ToString());
}
catch (System.Exception e)
{
Debug.LogError($"[Runtime] ❌ Ensure failed: {e.Message}");
}
}
[ContextMenu("GetInventory")]
public async void GetPurchasedItem()
{
try
{
var rec = await GameDb.GetPurchasedItemsJsonAsync(PlayerPrefs.GetString("WALLET_ADDRESS"));
Debug.Log(rec.ToString());
}
catch (System.Exception e)
{
Debug.LogError($"[Runtime] ❌ Ensure failed: {e.Message}");
}
}
[ContextMenu("AddGamesPlayed")]
public async void AddGamesPlayed()
{
try
{
var rec = await GameDb.IncGamesPlayedAsync(PlayerPrefs.GetString("WALLET_ADDRESS"));
Debug.Log(rec.ToString());
}
catch (System.Exception e)
{
Debug.LogError($"[Runtime] ❌ Ensure failed: {e.Message}");
}
}
[ContextMenu("GetplayerData")]
public async void PlayerDataAsync()
{
try
{
var rec = await GameDb.GetPlayerAsync(PlayerPrefs.GetString("WALLET_ADDRESS"));
Debug.Log(rec.ToString());
}
catch (System.Exception e)
{
Debug.LogError($"[Runtime] ❌ Ensure failed: {e.Message}");
}
}
[ContextMenu("Placement")]
public async void PlayerPlacement()
{
try
{
var rec = await GameDb.SendGameWinAsync(PlayerPrefs.GetString("WALLET_ADDRESS"),1);
Debug.Log(rec.ToString());
}
catch (System.Exception e)
{
Debug.LogError($"[Runtime] ❌ Ensure failed: {e.Message}");
}
}
[ContextMenu("ItemBought")]
public async void AddPurchaseItem()
{
try
{
var rec = await GameDb.AddPurchasedItemAsync(PlayerPrefs.GetString("WALLET_ADDRESS"), "ChadGuy");
Debug.Log(rec.ToString());
}
catch (System.Exception e)
{
Debug.LogError($"[Runtime] ❌ Ensure failed: {e.Message}");
}
}
[ContextMenu("CheckName")]
public async void OnWalletConnected(string wallet) // call this from your wallet SDK
{
try
{
// makes sure the row exists (display_name = "" on first create)
await GameDb.GetPlayerNameAsync(wallet);
Debug.Log($"Player ensured for {wallet}");
}
catch (System.Exception e)
{
Debug.LogError(e);
}
}
public void LoginAsGuest()
{
SceneManager.LoadScene(1);
}
}