// CommandBank.cs — ładuje commands.json z StreamingAssets, udostępnia losowe // polecenia per-level. Samoistny MonoBehaviour; podepnij do dowolnego GameObject. // // Plik commands.json generuj offline: // python -m ipin_vr export --per-level 300 --out commands.json // Następnie umieść go w Assets/StreamingAssets/commands.json. using System; using System.Collections; using System.Collections.Generic; using System.IO; using UnityEngine; using UnityEngine.Networking; namespace IpinVr { [Serializable] public class CommandEntry { public int level; public string text; } [Serializable] internal class BankMeta { public string version; public int per_level; } [Serializable] internal class BankData { public BankMeta meta; public List commands; } public class CommandBank : MonoBehaviour { [SerializeField] private string jsonFileName = "commands.json"; private readonly Dictionary> _byLevel = new(); private bool _loaded; public bool IsLoaded => _loaded; /// Wczytaj bank asynchronicznie. onDone wywoływane po załadowaniu. public void Load(Action onDone = null) { StartCoroutine(LoadCoroutine(onDone)); } private IEnumerator LoadCoroutine(Action onDone) { string srcPath = Path.Combine(Application.streamingAssetsPath, jsonFileName); string json; #if UNITY_ANDROID && !UNITY_EDITOR // Na Androidzie StreamingAssets są wewnątrz APK — czytamy przez WebRequest. using var req = UnityWebRequest.Get(srcPath); yield return req.SendWebRequest(); if (req.result != UnityWebRequest.Result.Success) { Debug.LogError($"[CommandBank] Błąd wczytywania {jsonFileName}: {req.error}"); yield break; } json = req.downloadHandler.text; #else if (!File.Exists(srcPath)) { Debug.LogError($"[CommandBank] Plik nie istnieje: {srcPath}"); yield break; } json = File.ReadAllText(srcPath); yield return null; #endif var data = JsonUtility.FromJson(json); if (data?.commands == null) { Debug.LogError("[CommandBank] Nie można sparsować commands.json"); yield break; } _byLevel.Clear(); foreach (var entry in data.commands) { if (!_byLevel.TryGetValue(entry.level, out var list)) _byLevel[entry.level] = list = new List(); list.Add(entry.text); } int total = data.commands.Count; Debug.Log($"[CommandBank] Wczytano {total} poleceń (v{data.meta?.version})"); _loaded = true; onDone?.Invoke(); } /// Zwraca losowe polecenie dla danego poziomu, lub null jeśli brak. public string GetRandom(int level) { if (!_loaded) { Debug.LogWarning("[CommandBank] Bank nie jest jeszcze wczytany"); return null; } if (!_byLevel.TryGetValue(level, out var list) || list.Count == 0) { Debug.LogWarning($"[CommandBank] Brak poleceń dla poziomu {level}"); return null; } return list[UnityEngine.Random.Range(0, list.Count)]; } public int CountForLevel(int level) => _byLevel.TryGetValue(level, out var l) ? l.Count : 0; } }