private BeatmapCharacteristicObject GetCharacteristicAsset(Characteristic characteristic)
        {
            //TODO: fix the lightshow and stuff
            if (characteristic == Characteristic.Lightshow || characteristic == Characteristic.Lawless)
            {
                return(null);
            }
            string name = MiscUtils.GetCharacteristicAssetName(characteristic);

            if (name == null)
            {
                name = "StandardBeatmapCharacteristic";
            }
            BeatmapCharacteristicObject charObj = null;

            if (!_characteristicCache.ContainsKey(name))
            {
                charObj = _assetsFile.Manager.MassFirstOrDefaultAsset <BeatmapCharacteristicObject>(x => x.Object.Name == name)?.Object;
                if (charObj == null)
                {
                    charObj = CreateCharacteristic(characteristic);
                }
                if (charObj == null)
                {
                    return(null);
                }
                _characteristicCache.Add(name, charObj);
            }
            else
            {
                charObj = _characteristicCache[name];
            }
            return(charObj);
        }
        private BeatmapCharacteristicObject CreateCharacteristic(Characteristic characteristic)
        {
            if (characteristic == Characteristic.Standard)
            {
                throw new Exception("Tried to create standard beatmap characteristic which means it's missing.  Assets are broken.");
            }

            BeatmapCharacteristicObject standardCharacteristic = GetCharacteristicAsset(Characteristic.Standard);

            if (standardCharacteristic == null)
            {
                Log.LogErr($"Unable to locate the standard beatmap characteristic while verifying characteristics!");
                throw new Exception("Could not locate standard beatmap characteristic!");
            }
            int count = _assetsFile.Manager.MassFindAssets <BeatmapCharacteristicObject>(x => true, false).Count();

            try
            {
                string characteristicName = $"LEVEL_{characteristic.ToString().ToUpper()}";
                string hintText           = $"{characteristicName}_HINT";
                string assetName          = MiscUtils.GetCharacteristicAssetName(characteristic);
                var    lightshowAsset     = (BeatmapCharacteristicObject)standardCharacteristic.ObjectInfo.Clone(standardCharacteristic.ObjectInfo.ParentFile);

                lightshowAsset.Name               = assetName;
                lightshowAsset.SerializedName     = characteristic.ToString();
                lightshowAsset.SortingOrder       = count;
                lightshowAsset.CompoundIdPartName = characteristic.ToString();
                //todo: text translation stuff
                //lightshowAsset.CharacteristicName = characteristicName;
                //lightshowAsset.HintText = hintText;
                var allChar = _assetsFile.Manager.MassFirstOrDefaultAsset <BeatmapCharacteristicCollectionObject>(x => true);
                if (allChar == null)
                {
                    throw new Exception("Unable to find AllBeatmapCharacteristics object!");
                }
                if (!allChar.Object.BeatmapCharacteristics.Any(x => x.Object.Name == lightshowAsset.Name))
                {
                    allChar.Object.BeatmapCharacteristics.Add(lightshowAsset.PtrFrom(allChar.Object));
                }
                try
                {
                    byte[] lightshowIcon = _config.EmbeddedResourcesFileProvider.Read($"{characteristic}.png");
                    if (lightshowIcon == null || lightshowIcon.Length < 1)
                    {
                        throw new Exception($"{characteristic}.png read was null or empty!");
                    }
                    var clonedSprite = (SpriteObject)standardCharacteristic.Icon.Object.ObjectInfo.Clone(standardCharacteristic.ObjectInfo.ParentFile);
                    var newTexture   = new Texture2DObject(standardCharacteristic.ObjectInfo.ParentFile)
                    {
                        Name = assetName
                    };
                    clonedSprite.RenderData.AtlasRectOffset.X = -1;
                    clonedSprite.RenderData.AtlasRectOffset.Y = -1;
                    clonedSprite.RenderData.TextureRect.X     = 0;
                    clonedSprite.RenderData.TextureRect.Y     = 0;
                    clonedSprite.RenderData.Texture           = newTexture.PtrFrom(clonedSprite);
                    clonedSprite.Name = assetName + "Icon";
                    ImageUtils.Instance.AssignImageToTexture(lightshowIcon, newTexture, 128, 128, Int32.MaxValue, TextureConversionFormat.Auto);
                    lightshowAsset.Icon = clonedSprite.PtrFrom(lightshowAsset);
                    standardCharacteristic.ObjectInfo.ParentFile.AddObject(clonedSprite);
                    standardCharacteristic.ObjectInfo.ParentFile.AddObject(newTexture);
                    standardCharacteristic.ObjectInfo.ParentFile.AddObject(lightshowAsset);
                }
                catch (Exception ex)
                {
                    Log.LogErr($"Failed to load {characteristic}'s png icon!", ex);
                    throw;
                }
                return(lightshowAsset);
            }
            catch (Exception ex)
            {
                Log.LogErr($"Exception trying to create {characteristic} characteristic!", ex);
                throw new Exception($"Error trying to create characteristic {characteristic}!", ex);
            }
        }