diff --git a/Assets/Addressable.meta b/Assets/Addressable.meta
new file mode 100644
index 0000000000..d945c2191d
--- /dev/null
+++ b/Assets/Addressable.meta
@@ -0,0 +1,8 @@
+fileFormatVersion: 2
+guid: 296cac0f54860484f8e9c81696536cf2
+folderAsset: yes
+DefaultImporter:
+ externalObjects: {}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Assets/Addressable/elements.txt b/Assets/Addressable/elements.txt
new file mode 100644
index 0000000000..abd564ec7f
Binary files /dev/null and b/Assets/Addressable/elements.txt differ
diff --git a/Assets/Addressable/elements.txt.meta b/Assets/Addressable/elements.txt.meta
new file mode 100644
index 0000000000..c9ce2a827b
--- /dev/null
+++ b/Assets/Addressable/elements.txt.meta
@@ -0,0 +1,7 @@
+fileFormatVersion: 2
+guid: 4e7b437eecb43c64b87ab9700f5850c9
+TextScriptImporter:
+ externalObjects: {}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Assets/Addressable/gshop.txt b/Assets/Addressable/gshop.txt
new file mode 100644
index 0000000000..60cdbd69ae
Binary files /dev/null and b/Assets/Addressable/gshop.txt differ
diff --git a/Assets/Addressable/gshop.txt.meta b/Assets/Addressable/gshop.txt.meta
new file mode 100644
index 0000000000..83ea29658a
--- /dev/null
+++ b/Assets/Addressable/gshop.txt.meta
@@ -0,0 +1,7 @@
+fileFormatVersion: 2
+guid: 6e02334765e10654e874714298f4eef1
+TextScriptImporter:
+ externalObjects: {}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Assets/Addressable/gshop1.txt b/Assets/Addressable/gshop1.txt
new file mode 100644
index 0000000000..3e74172f6d
Binary files /dev/null and b/Assets/Addressable/gshop1.txt differ
diff --git a/Assets/Addressable/gshop1.txt.meta b/Assets/Addressable/gshop1.txt.meta
new file mode 100644
index 0000000000..72b5247e9a
--- /dev/null
+++ b/Assets/Addressable/gshop1.txt.meta
@@ -0,0 +1,7 @@
+fileFormatVersion: 2
+guid: 98b87a70ddccda2459742976c2b90262
+TextScriptImporter:
+ externalObjects: {}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Assets/AddressableAssetsData/AssetGroups/configuration.asset b/Assets/AddressableAssetsData/AssetGroups/configuration.asset
index e38dbe1fed..21b2b75d11 100644
--- a/Assets/AddressableAssetsData/AssetGroups/configuration.asset
+++ b/Assets/AddressableAssetsData/AssetGroups/configuration.asset
@@ -15,18 +15,18 @@ MonoBehaviour:
m_GroupName: configuration
m_GUID: 402389c9c8797a8489a1d8188e497c23
m_SerializeEntries:
- - m_GUID: 1d3ff15805e2a8548ac19cce5f6d4e09
- m_Address: Assets/PerfectWorld/Data/tasks.bytes
+ - m_GUID: 4e7b437eecb43c64b87ab9700f5850c9
+ m_Address: Assets/Addressable/elements.txt
m_ReadOnly: 0
m_SerializedLabels: []
FlaggedDuringContentUpdateRestriction: 0
- - m_GUID: 26ddd95c5aad09441ad4f582e1fde148
- m_Address: Assets/PerfectWorld/Data/dyn_tasks.bytes
+ - m_GUID: 6e02334765e10654e874714298f4eef1
+ m_Address: Assets/Addressable/gshop.txt
m_ReadOnly: 0
m_SerializedLabels: []
FlaggedDuringContentUpdateRestriction: 0
- - m_GUID: 97ca8e0d62d124346a82d5a441c55cf8
- m_Address: Assets/PerfectWorld/Data/task_npc.bytes
+ - m_GUID: 98b87a70ddccda2459742976c2b90262
+ m_Address: Assets/Addressable/gshop1.txt
m_ReadOnly: 0
m_SerializedLabels: []
FlaggedDuringContentUpdateRestriction: 0
diff --git a/Assets/PerfectWorld/Scripts/Addressable/AddressableManager.cs b/Assets/PerfectWorld/Scripts/Addressable/AddressableManager.cs
index 1d1ba9fdfa..4938674568 100644
--- a/Assets/PerfectWorld/Scripts/Addressable/AddressableManager.cs
+++ b/Assets/PerfectWorld/Scripts/Addressable/AddressableManager.cs
@@ -1,5 +1,6 @@
using System;
using System.Collections.Generic;
+using System.Linq;
using System.Threading.Tasks;
using UnityEngine;
using UnityEngine.AddressableAssets;
@@ -43,7 +44,8 @@ namespace BrewMonster.Scripts
}
///
- /// Load a text asset asynchronously. The address should look like this: "elements.data"
+ /// Load a text asset asynchronously.
+ /// NOTE: The key must match the Addressables "Address" (or another valid key like a label/GUID).
///
///
///
@@ -54,21 +56,119 @@ namespace BrewMonster.Scripts
{
return _loadedTextAssets[assetPath].Result;
}
+
try
{
- var handle = Addressables.LoadAssetAsync(assetPath);
- await handle.Task;
+ // First, try the key exactly as provided. If it doesn't exist in the catalog,
+ // fall back to common project conventions (e.g. full Asset path).
+ foreach (var key in GetCandidateKeys(assetPath))
+ {
+ var locationsHandle = Addressables.LoadResourceLocationsAsync(key, typeof(TextAsset));
+ await locationsHandle.Task;
- _loadedTextAssets[assetPath] = handle;
- return handle.Result;
+ if (locationsHandle.Status != AsyncOperationStatus.Succeeded || locationsHandle.Result == null || locationsHandle.Result.Count == 0)
+ {
+ Addressables.Release(locationsHandle);
+ continue;
+ }
+
+ Addressables.Release(locationsHandle);
+
+ var handle = Addressables.LoadAssetAsync(key);
+ await handle.Task;
+
+ if (handle.Status == AsyncOperationStatus.Succeeded && handle.Result != null)
+ {
+ _loadedTextAssets[assetPath] = handle;
+ return handle.Result;
+ }
+
+ // If load failed, release and try next candidate.
+ if (handle.IsValid())
+ {
+ Addressables.Release(handle);
+ }
+ }
+
+ BMLogger.LogError($"AddressableManager: No Location found for TextAsset key='{assetPath}'. " +
+ $"Tried: {string.Join(", ", GetCandidateKeys(assetPath).Select(k => $"'{k}'"))}");
+ LogSimilarKeys(assetPath);
+ return null;
}
catch (Exception e)
{
- BMLogger.LogError(e.StackTrace);
+ BMLogger.LogError($"AddressableManager: Failed to load TextAsset '{assetPath}': {e}");
return null;
}
}
+ private static IEnumerable GetCandidateKeys(string assetPath)
+ {
+ if (string.IsNullOrWhiteSpace(assetPath))
+ {
+ yield break;
+ }
+
+ // Exact key (what caller asked for)
+ yield return assetPath;
+
+ // Common fallback used by this repo's Addressables settings: full asset path address.
+ // Example in `Assets/AddressableAssetsData/AssetGroups/configuration.asset`:
+ // m_Address: Assets/Addressable/elements.txt
+ if (!assetPath.Contains("/") && !assetPath.Contains("\\"))
+ {
+ yield return $"Assets/Addressable/{assetPath}";
+ }
+ }
+
+ private static void LogSimilarKeys(string needle)
+ {
+ // Helpful diagnostics in dev builds: show a few keys containing the substring.
+ try
+ {
+ var lower = needle?.ToLowerInvariant();
+ if (string.IsNullOrEmpty(lower))
+ {
+ return;
+ }
+
+ const int max = 20;
+ var matches = new List(max);
+
+ foreach (var locator in Addressables.ResourceLocators)
+ {
+ foreach (var keyObj in locator.Keys)
+ {
+ if (keyObj is not string keyStr)
+ {
+ continue;
+ }
+
+ if (!keyStr.ToLowerInvariant().Contains(lower))
+ {
+ continue;
+ }
+
+ matches.Add(keyStr);
+ if (matches.Count >= max)
+ {
+ goto Done;
+ }
+ }
+ }
+
+ Done:
+ if (matches.Count > 0)
+ {
+ BMLogger.LogWarning($"AddressableManager: Similar Addressables keys for '{needle}': {string.Join(", ", matches)}");
+ }
+ }
+ catch
+ {
+ // ignore diagnostics failures
+ }
+ }
+
///
/// Load an asset asynchronously. The address should look like this: "models/npcs/npc/魅灵首领/魅灵首领/魅灵首领.prefab"
///
diff --git a/Assets/PerfectWorld/Scripts/Common/DataProcess/elementdataman.cs b/Assets/PerfectWorld/Scripts/Common/DataProcess/elementdataman.cs
index 5e7e12c927..085a7974ea 100644
--- a/Assets/PerfectWorld/Scripts/Common/DataProcess/elementdataman.cs
+++ b/Assets/PerfectWorld/Scripts/Common/DataProcess/elementdataman.cs
@@ -321,7 +321,15 @@ namespace ModelRenderer.Scripts.GameData
// if (!File.Exists(pathname)) return -1;
- var dataFile = await AddressableManager.Instance.LoadTextAssetAsync("elements.data");
+ // Addressables key must match the configured "Address". This repo currently uses full asset paths
+ // (see `Assets/AddressableAssetsData/AssetGroups/configuration.asset`).
+ // `AddressableManager.LoadTextAssetAsync` also has fallbacks, so "elements.txt" will work too.
+ var dataFile = await AddressableManager.Instance.LoadTextAssetAsync("Assets/Addressable/elements.txt");
+ if (dataFile == null)
+ {
+ BMLogger.LogError("ElementDataMan: Failed to load Addressable TextAsset for elements data.");
+ return -1;
+ }
using (var file = new MemoryStream(dataFile.bytes))
{
diff --git a/Assets/PerfectWorld/Scripts/GameData/GShopLoader.cs b/Assets/PerfectWorld/Scripts/GameData/GShopLoader.cs
index 00f332c41d..00c3795227 100644
--- a/Assets/PerfectWorld/Scripts/GameData/GShopLoader.cs
+++ b/Assets/PerfectWorld/Scripts/GameData/GShopLoader.cs
@@ -2,108 +2,74 @@ using System;
using System.Collections.Generic;
using System.IO;
using BrewMonster;
+using BrewMonster.Scripts;
using Cysharp.Threading.Tasks;
using UnityEngine;
-using UnityEngine.Networking;
public class GShopLoader : MonoBehaviour
{
- [Header("File Paths")]
- public string gshopDataPath = "gshop.data";
- public string gshop1DataPath = "gshop1.data";
+ // Addressables-only: do NOT load gshop/gshop1 from file system paths.
+ // These must match the configured Addressables "Address" values in
+ // `Assets/AddressableAssetsData/AssetGroups/configuration.asset`.
+ private const string GSHOP_ADDRESS = "Assets/Addressable/gshop.txt";
+ private const string GSHOP1_ADDRESS = "Assets/Addressable/gshop1.txt";
[Header("Loaded Data")]
public GShopData primaryShop = new GShopData();
public GShopData secondaryShop = new GShopData();
-
-
async void Start()
{
- #if UNITY_ANDROID && !UNITY_EDITOR
- bool result = await MoveShopDataToPersistentPath();
- if (!result)
+ // Wait for AddressableManager to be initialized
+ while (!AddressableManager.Instance.IsInitialized())
{
- BMLogger.LogError($"ElementDataMan: Failed to move element file to persistent path");
- return;
+ await UniTask.DelayFrame(1);
}
- #endif
- LoadGShopData();
- }
-
- public async UniTask MoveShopDataToPersistentPath()
- {
- var destinationPath = Path.Combine(UnityEngine.Application.persistentDataPath, gshopDataPath);
- var sourcePath = Path.Combine(UnityEngine.Application.streamingAssetsPath, gshopDataPath);
-
-
- if (!File.Exists(destinationPath))
- {
- UnityWebRequest request = UnityWebRequest.Get(sourcePath);
- await request.SendWebRequest();
- if (request.result != UnityWebRequest.Result.Success)
- {
- BMLogger.LogError($"ElementDataMan: Failed to move element file to persistent path: {request.error}");
- return false;
- }
- File.WriteAllBytes(destinationPath, request.downloadHandler.data);
- }
-
- BMLogger.Log($"ElementDataMan: Successfully moved element file to persistent path: {destinationPath}");
-
- destinationPath = Path.Combine(UnityEngine.Application.persistentDataPath, gshop1DataPath);
- sourcePath = Path.Combine(UnityEngine.Application.streamingAssetsPath, gshop1DataPath);
-
- if (!File.Exists(destinationPath))
- {
- var request = UnityWebRequest.Get(sourcePath);
- await request.SendWebRequest();
- if (request.result != UnityWebRequest.Result.Success)
- {
- BMLogger.LogError($"ElementDataMan: Failed to move element file to persistent path: {request.error}");
- return false;
- }
- File.WriteAllBytes(destinationPath, request.downloadHandler.data);
- }
-
- BMLogger.Log($"ElementDataMan: Successfully moved element file to persistent path: {destinationPath}");
- return true;
+ await LoadGShopData();
}
- public void LoadGShopData()
+ public async UniTask LoadGShopData()
{
Debug.Log("=== Loading GShop Data ===");
// Load primary shop
- if (LoadShopData(gshopDataPath, primaryShop))
+ if (await LoadShopData(GSHOP_ADDRESS, primaryShop))
{
Debug.Log($"Primary shop loaded: {primaryShop.items.Count} items, {primaryShop.mainTypes.Count} categories");
//LogShopData("Primary Shop", primaryShop);
}
// Load secondary shop
- if (LoadShopData(gshop1DataPath, secondaryShop))
+ if (await LoadShopData(GSHOP1_ADDRESS, secondaryShop))
{
Debug.Log($"Secondary shop loaded: {secondaryShop.items.Count} items, {secondaryShop.mainTypes.Count} categories");
//LogShopData("Secondary Shop", secondaryShop);
}
}
- private bool LoadShopData(string filePath, GShopData shopData)
+ private async UniTask LoadShopData(string filePath, GShopData shopData)
{
try
{
- string fullPath = Path.Combine(Application.streamingAssetsPath, filePath);
+ // Load from Addressables
+ var textAsset = await AddressableManager.Instance.LoadTextAssetAsync(filePath);
- if (!File.Exists(fullPath))
+ if (textAsset == null)
{
- Debug.LogError($"GShop file not found: {fullPath}");
+ BMLogger.LogError($"GShopLoader: Failed to load {filePath} from Addressables. File not found or load failed.");
return false;
}
- using (FileStream fs = new FileStream(fullPath, FileMode.Open, FileAccess.Read))
- using (BinaryReader reader = new BinaryReader(fs))
+ if (textAsset.bytes == null || textAsset.bytes.Length == 0)
+ {
+ BMLogger.LogError($"GShopLoader: {filePath} loaded from Addressables but bytes array is null or empty.");
+ return false;
+ }
+
+ // Read binary data from TextAsset.bytes using MemoryStream
+ using (MemoryStream ms = new MemoryStream(textAsset.bytes))
+ using (BinaryReader reader = new BinaryReader(ms))
{
// Read timestamp
shopData.timestamp = reader.ReadUInt32();
@@ -133,7 +99,7 @@ public class GShopLoader : MonoBehaviour
}
catch (Exception e)
{
- Debug.LogError($"Error loading GShop data from {filePath}: {e.Message}");
+ BMLogger.LogError($"GShopLoader: Error loading GShop data from {filePath}: {e.Message}\nStackTrace: {e.StackTrace}");
return false;
}
}
diff --git a/Assets/Prefabs/UI/MallUI.prefab b/Assets/Prefabs/UI/MallUI.prefab
index da54c021e9..f33c2c6dcf 100644
--- a/Assets/Prefabs/UI/MallUI.prefab
+++ b/Assets/Prefabs/UI/MallUI.prefab
@@ -5290,8 +5290,6 @@ MonoBehaviour:
m_Script: {fileID: 11500000, guid: 20694866a3163b342953396044c25a4e, type: 3}
m_Name:
m_EditorClassIdentifier:
- gshopDataPath: gshop.data
- gshop1DataPath: gshop1.data
--- !u!1 &7409039696840300032
GameObject:
m_ObjectHideFlags: 0