using System.Collections.Generic; using System.Linq; using Cysharp.Threading.Tasks; using Newtonsoft.Json.Linq; using SLZ.Serialize; using UnityEngine; #if UNITY_EDITOR using UnityEditor; #endif namespace SLZ.Marrow.Warehouse { public interface IReadOnlyScannable { Barcode Barcode { get; } string Title { get; } string Description { get; } } public interface IScannable : IReadOnlyScannable, IPackable, IPackedAssets { bool Unlockable { get; } bool Redacted { get; } void GenerateBarcode(bool forceGeneration = false); void GenerateBarcodeInternal(bool forceGeneration = false); } public interface IPackedAssets { public List PackedAssets { get; } void ImportPackedAssets(Dictionary packedAssets); List ExportPackedAssets(); #if UNITY_EDITOR void GeneratePackedAssets(bool saveAsset = true); #endif } public abstract class Scannable : ScriptableObject, IScannable { [SerializeField] private Barcode _barcode; public Barcode Barcode { get { return _barcode; } set { _barcode = value; } } [SerializeField] [Delayed] private string _title; public string Title { get { return _title; } set { _title = value; } } [SerializeField] [Delayed] private string _description = ""; public string Description { get { return _description; } set { _description = value; } } [SerializeField] [Tooltip("Locks the crate from the user until it is unlocked")] private bool _unlockable = false; public bool Unlockable { get { return _unlockable; } set { _unlockable = value; } } [SerializeField] [Tooltip("Hides the crate from Menus")] private bool _redacted = false; public bool Redacted { get { return _redacted; } set { _redacted = value; } } public void GenerateBarcode(bool forceGeneration = false) { if (Barcode == null || !Barcode.IsValid()) { Barcode = new Barcode(); } GenerateBarcodeInternal(forceGeneration); } public abstract void GenerateBarcodeInternal(bool forceGeneration = false); private List _packedAssets = new List(); public List PackedAssets { get => _packedAssets; } public virtual void ImportPackedAssets(Dictionary packedAssets) { PackedAssets.Clear(); foreach (var kvp in packedAssets) { PackedAssets.Add(kvp.Value); } } public virtual List ExportPackedAssets() { PackedAssets.Clear(); return PackedAssets; } public virtual void Pack(ObjectStore store, JObject json) { json.Add("barcode", Barcode.ID); json.Add("title", Title); json.Add("description", Description); json.Add("unlockable", Unlockable); json.Add("redacted", Redacted); PackJsonPackedAssets(json); } public virtual void Unpack(ObjectStore store, string objectId) { if (store.TryGetJSON("barcode", objectId, out JToken barcodeValue)) { Barcode = new Barcode(barcodeValue.ToObject()); } if (store.TryGetJSON("title", objectId, out JToken titleValue)) { name = titleValue.ToObject(); Title = titleValue.ToObject(); } if (store.TryGetJSON("description", objectId, out JToken descValue)) { Description = descValue.ToObject(); } if (store.TryGetJSON("unlockable", objectId, out JToken unlockValue)) { Unlockable = unlockValue.ToObject(); } if (store.TryGetJSON("redacted", objectId, out JToken redaValue)) { Redacted = redaValue.ToObject(); } UnpackJsonPackedAssets(store, objectId); } public void PackJsonPackedAssets(JObject json) { ExportPackedAssets(); var packedAssetsArray = new JArray(); foreach (var packedAsset in PackedAssets) { var packedAssetJObject = new JObject { { "title", packedAsset.title }, }; if (packedAsset.marrowAsset != null) { packedAssetJObject.Add(new JProperty("guid", packedAsset.marrowAsset.AssetGUID)); } if (packedAsset.HasSubAssets()) { packedAssetJObject.Add(new JProperty("subAssets", new JArray(packedAsset.subAssets.Select(p => p.subAsset.AssetGUID)))); } if (packedAsset.marrowAsset != null || packedAsset.subAssets.Count > 0) packedAssetsArray.Add(packedAssetJObject); } json.Add(new JProperty("packedAssets", packedAssetsArray)); } public void UnpackJsonPackedAssets(ObjectStore store, string objectId) { if (store.TryGetJSON("packedAssets", objectId, out JToken packedAssetsValue)) { var packedAssets = new Dictionary(); foreach (var arrayToken in (JArray)packedAssetsValue) { if (((JObject)arrayToken).TryGetValue("title", out var titleToken)) { var packedAsset = new PackedAsset(); packedAsset.title = titleToken.ToObject(); if (((JObject)arrayToken).TryGetValue("guid", out var guidToken)) { packedAsset.marrowAsset = new MarrowAsset(guidToken.ToObject()); packedAsset.assetType = typeof(UnityEngine.Object); } if (((JObject)arrayToken).TryGetValue("subAssets", out var subAssetsToken)) { List subAssets = new List(); for (var i = 0; i < ((JArray)subAssetsToken).Count; i++) { var subAssetToken = ((JArray)subAssetsToken)[i]; subAssets.Add(new PackedSubAsset($"{i}", new MarrowAsset(subAssetToken.ToObject()))); } packedAsset.subAssets = subAssets; } if ((packedAsset.marrowAsset != null || packedAsset.HasSubAssets()) && !packedAssets.ContainsKey(packedAsset.title)) { packedAssets[packedAsset.title] = packedAsset; } } } ImportPackedAssets(packedAssets); } } #if UNITY_EDITOR public virtual void GeneratePackedAssets(bool saveAsset = true) { } [ContextMenu("Generate Barcode")] private void GenerateBarcodeMenuButton() { GenerateBarcode(true); EditorUtility.SetDirty(this); AssetDatabase.SaveAssetIfDirty(this); } public virtual string GetAssetFilename() { return $"{GetAssetFilenameTitle()}.{GetFullAssetExtension()}"; } public virtual string GetAssetFilenameTitle() { return Title.Replace(".", ""); } public virtual string GetAssetExtension() { string typeNameShort = string.Empty; foreach (var c in GetType().Name) { if (char.IsUpper(c)) typeNameShort += c; } typeNameShort = typeNameShort.ToLower(); return typeNameShort; } public string GetFullAssetExtension() { return $"{GetAssetExtension()}.asset"; } public string GetNameNoExtension() { return name.Replace($".{GetAssetExtension()}", ""); } #endif } }