/// <summary> /// Initializes the sounds for this entity type. /// </summary> /// <param name="assetManager"></param> public void InitSounds(IAssetManager assetManager) { if (Sounds != null) { foreach (var val in Sounds) { if (val.Value.Path.EndsWith("*")) { List <IAsset> assets = assetManager.GetMany("sounds/" + val.Value.Path.Substring(0, val.Value.Path.Length - 1), val.Value.Domain); AssetLocation[] sounds = new AssetLocation[assets.Count]; int i = 0; foreach (IAsset asset in assets) { sounds[i++] = asset.Location; } ResolvedSounds[val.Key] = sounds; } else { ResolvedSounds[val.Key] = new AssetLocation[] { val.Value.Clone().WithPathPrefix("sounds/") }; } } } }
/// <summary> /// Called when the savegame is loaded, parses building recipes from JSON assets. /// Recipes are loaded from "assets/recipes/buildingoverhaul/**.json". /// </summary> public void LoadFromAssets(IAssetManager manager, ILogger logger) { var count = 0; _byTool = new(); void LoadRecipe(AssetLocation location, JToken token) { var recipe = token.ToObject <Recipe>(location.Domain); if (!recipe.Enabled) { return; } recipe.Location = location; // TODO: Do some validation to make it easier to spot errors? // Ensure that every ingredient's AllowedVariants is sorted and distinct. // This is to make sure the array can be easily tested for equality. foreach (var ingredient in new [] { recipe.Tool, recipe.Material }.Append(recipe.Ingredients)) { ingredient.AllowedVariants = ingredient.AllowedVariants?.OrderBy(x => x)?.Distinct()?.ToArray(); } // Group recipes into separate lists by their tools. // For example all recipes with "game:hammer-*" end up in the same group. var groupedRecipes = _byTool.Find(list => (recipe.Tool == list[0].Tool)); if (groupedRecipes == null) { _byTool.Add(groupedRecipes = new()); } groupedRecipes.Add(recipe); count++; } var assets = manager.GetMany <JToken>(logger, $"recipes/{BuildingOverhaulSystem.MOD_ID}/"); foreach (var asset in assets) { switch (asset.Value) { case JObject obj: LoadRecipe(asset.Key, obj); break; case JArray arr: foreach (var token in arr) { LoadRecipe(asset.Key, token); } break; } } ResolveIngredients(); CachedMessage = new Message { _data = ToBytes() }; logger.Event("{0} building recipes loaded", count); }
/// <summary> /// Expands the Composite Texture to a texture atlas friendly version and populates the Baked field /// </summary> public void LoadAlternates(IAssetManager assetManager, ILogger logger) { if (Base.Path.EndsWith("*")) { List <IAsset> assets = assetManager.GetMany("shapes/" + Base.Path.Substring(0, Base.Path.Length - 1), Base.Domain); if (assets.Count == 0) { Base = new AssetLocation("block/basic/cube"); logger.Warning("Could not find any variants for shape {0}, will use standard cube shape.", Base.Path); } if (assets.Count == 1) { Base = assets[0].Location.CopyWithPath(assets[0].Location.Path.Substring("shapes/".Length)); Base.RemoveEnding(); } if (assets.Count > 1) { int origLength = (Alternates == null ? 0 : Alternates.Length); CompositeShape[] alternates = new CompositeShape[origLength + assets.Count]; if (Alternates != null) { Array.Copy(Alternates, alternates, Alternates.Length); } int i = 0; foreach (IAsset asset in assets) { AssetLocation newLocation = asset.Location.CopyWithPath(asset.Location.Path.Substring("shapes/".Length)); newLocation.RemoveEnding(); if (i == 0) { Base = newLocation.Clone(); } alternates[origLength + i] = new CompositeShape() { Base = newLocation, rotateX = rotateX, rotateY = rotateY, rotateZ = rotateZ }; i++; } Alternates = alternates; } } if (Alternates != null) { BakedAlternates = new CompositeShape[Alternates.Length + 1]; BakedAlternates[0] = this.Clone(); BakedAlternates[0].Alternates = null; for (int i = 0; i < Alternates.Length; i++) { BakedAlternates[i + 1] = Alternates[i].Clone(); if (BakedAlternates[i + 1].Base == null) { BakedAlternates[i + 1].Base = Base.Clone(); } if (BakedAlternates[i + 1].QuantityElements == null) { BakedAlternates[i + 1].QuantityElements = QuantityElements; } if (BakedAlternates[i + 1].SelectiveElements == null) { BakedAlternates[i + 1].SelectiveElements = SelectiveElements; } } } }
/// <summary> /// Expands a CompositeTexture to a texture atlas friendly version and populates the Baked field /// </summary> /// <param name="assetManager"></param> /// <param name="ct"></param> /// <returns></returns> static BakedCompositeTexture Bake(IAssetManager assetManager, CompositeTexture ct) { BakedCompositeTexture bct = new BakedCompositeTexture(); bct.BakedName = ct.Base.Clone(); if (ct.Base.EndsWithWildCard) { List <IAsset> assets = assetManager.GetMany("textures/" + bct.BakedName.Path.Substring(0, bct.BakedName.Path.Length - 1), bct.BakedName.Domain); if (assets.Count == 0) { ct.Base = bct.BakedName = new AssetLocation("unknown"); } else if (assets.Count == 1) { ct.Base = assets[0].Location.CloneWithoutPrefixAndEnding("textures/".Length); bct.BakedName = ct.Base.Clone(); } else if (assets.Count > 1) { int origLength = (ct.Alternates == null ? 0 : ct.Alternates.Length); CompositeTexture[] alternates = new CompositeTexture[origLength + assets.Count - 1]; if (ct.Alternates != null) { Array.Copy(ct.Alternates, alternates, ct.Alternates.Length); } for (int i = 0; i < assets.Count; i++) { IAsset asset = assets[i]; AssetLocation newLocation = asset.Location.CloneWithoutPrefixAndEnding("textures/".Length); if (i == 0) { ct.Base = newLocation; bct.BakedName = newLocation.Clone(); } else { var act = alternates[origLength + i - 1] = new CompositeTexture(newLocation); act.Rotation = ct.Rotation; act.Alpha = ct.Alpha; } } ct.Alternates = alternates; } } if (ct.Overlays != null) { bct.TextureFilenames = new AssetLocation[ct.Overlays.Length + 1]; bct.TextureFilenames[0] = ct.Base.Clone(); for (int i = 0; i < ct.Overlays.Length; i++) { bct.TextureFilenames[i + 1] = ct.Overlays[i].Clone(); bct.BakedName.Path += "++" + ct.Overlays[i].ToShortString(); } } else { bct.TextureFilenames = new AssetLocation[] { ct.Base.Clone() }; } if (ct.Rotation != 0) { if (ct.Rotation != 90 && ct.Rotation != 180 && ct.Rotation != 270) { throw new Exception("Texture definition " + ct.Base + " has a rotation thats not 0, 90, 180 or 270. These are the only allowed values!"); } bct.BakedName.Path += "@" + ct.Rotation; } if (ct.Alpha != 255) { if (ct.Alpha < 0 || ct.Alpha > 255) { throw new Exception("Texture definition " + ct.Base + " has a alpha value outside the 0..255 range."); } bct.BakedName.Path += "å" + ct.Alpha; } if (ct.Alternates != null) { bct.BakedVariants = new BakedCompositeTexture[ct.Alternates.Length + 1]; bct.BakedVariants[0] = bct; for (int i = 0; i < ct.Alternates.Length; i++) { bct.BakedVariants[i + 1] = Bake(assetManager, ct.Alternates[i]); } } return(bct); }
/// <summary> /// Expands a CompositeTexture to a texture atlas friendly version and populates the Baked field /// </summary> /// <param name="assetManager"></param> /// <param name="ct"></param> /// <returns></returns> static BakedCompositeTexture Bake(IAssetManager assetManager, CompositeTexture ct) { BakedCompositeTexture bct = new BakedCompositeTexture(); bct.BakedName = ct.Base.Clone(); if (ct.Base.Path.EndsWith("*")) { List <IAsset> assets = assetManager.GetMany("textures/" + bct.BakedName.Path.Substring(0, bct.BakedName.Path.Length - 1), bct.BakedName.Domain); if (assets.Count == 0) { ct.Base = bct.BakedName = new AssetLocation("unknown"); } if (assets.Count == 1) { ct.Base = assets[0].Location.Clone(); ct.Base.Path = assets[0].Location.Path.Substring("textures/".Length); ct.Base.RemoveEnding(); bct.BakedName = ct.Base.Clone(); } if (assets.Count > 1) { int origLength = (ct.Alternates == null ? 0 : ct.Alternates.Length); CompositeTexture[] alternates = new CompositeTexture[origLength + assets.Count - 1]; if (ct.Alternates != null) { Array.Copy(ct.Alternates, alternates, ct.Alternates.Length); } int i = 0; foreach (IAsset asset in assets) { AssetLocation newLocation = assets[0].Location.Clone(); newLocation.Path = asset.Location.Path.Substring("textures/".Length); newLocation.RemoveEnding(); if (i == 0) { ct.Base = newLocation; bct.BakedName = ct.Base; } else { alternates[origLength + i - 1] = new CompositeTexture(newLocation); } i++; } ct.Alternates = alternates; } } if (ct.Overlays != null) { bct.TextureFilenames = new AssetLocation[ct.Overlays.Length + 1]; bct.TextureFilenames[0] = ct.Base.Clone(); for (int i = 0; i < ct.Overlays.Length; i++) { bct.TextureFilenames[i + 1] = ct.Overlays[i].Clone(); bct.BakedName.Path += "++" + ct.Overlays[i].ToShortString(); } } else { bct.TextureFilenames = new AssetLocation[] { ct.Base.Clone() }; } if (ct.Rotation != 0) { if (ct.Rotation != 90 && ct.Rotation != 0 && ct.Rotation != 180 && ct.Rotation != 270) { throw new Exception("Texture definition " + ct.Base + " has a rotation thats not 0, 90, 180 or 270. These are the only allowed values!"); } bct.BakedName.Path += "@" + ct.Rotation; } if (ct.Alternates != null) { bct.BakedVariants = new BakedCompositeTexture[ct.Alternates.Length + 1]; bct.BakedVariants[0] = bct; for (int i = 0; i < ct.Alternates.Length; i++) { bct.BakedVariants[i + 1] = Bake(assetManager, ct.Alternates[i]); } } return(bct); }