From 567c422f8cd42eba2437f9a8c2522716a1649be7 Mon Sep 17 00:00:00 2001 From: hazel Date: Mon, 26 Jan 2026 22:04:39 +0100 Subject: celesteia archive, last updated april 9th 2024 Signed-off-by: hazel --- source/resources/Resources.cs | 81 ++++++++ source/resources/collections/BaseCollection.cs | 207 +++++++++++++++++++++ source/resources/management/BlockManager.cs | 77 ++++++++ source/resources/management/EntityManager.cs | 46 +++++ source/resources/management/FontManager.cs | 43 +++++ source/resources/management/ItemManager.cs | 47 +++++ source/resources/management/RecipeManager.cs | 34 ++++ source/resources/management/SkyboxAssets.cs | 42 +++++ source/resources/sprites/BlockFrames.cs | 53 ++++++ source/resources/sprites/EntityFrames.cs | 32 ++++ source/resources/sprites/SkyboxPortionFrames.cs | 51 +++++ source/resources/types/BlockType.cs | 71 +++++++ source/resources/types/EntityType.cs | 20 ++ source/resources/types/ItemType.cs | 21 +++ source/resources/types/Recipe.cs | 48 +++++ source/resources/types/TileEntityType.cs | 27 +++ .../resources/types/builders/BlockTypeBuilder.cs | 82 ++++++++ source/resources/types/builders/ItemTypeBuilder.cs | 67 +++++++ 18 files changed, 1049 insertions(+) create mode 100644 source/resources/Resources.cs create mode 100644 source/resources/collections/BaseCollection.cs create mode 100644 source/resources/management/BlockManager.cs create mode 100644 source/resources/management/EntityManager.cs create mode 100644 source/resources/management/FontManager.cs create mode 100644 source/resources/management/ItemManager.cs create mode 100644 source/resources/management/RecipeManager.cs create mode 100644 source/resources/management/SkyboxAssets.cs create mode 100644 source/resources/sprites/BlockFrames.cs create mode 100644 source/resources/sprites/EntityFrames.cs create mode 100644 source/resources/sprites/SkyboxPortionFrames.cs create mode 100644 source/resources/types/BlockType.cs create mode 100644 source/resources/types/EntityType.cs create mode 100644 source/resources/types/ItemType.cs create mode 100644 source/resources/types/Recipe.cs create mode 100644 source/resources/types/TileEntityType.cs create mode 100644 source/resources/types/builders/BlockTypeBuilder.cs create mode 100644 source/resources/types/builders/ItemTypeBuilder.cs (limited to 'source/resources') diff --git a/source/resources/Resources.cs b/source/resources/Resources.cs new file mode 100644 index 0000000..d200764 --- /dev/null +++ b/source/resources/Resources.cs @@ -0,0 +1,81 @@ +using System.Collections.Generic; +using Celesteia.Resources.Management; +using Celesteia.Resources.Types; +using Microsoft.Xna.Framework.Content; + +namespace Celesteia.Resources { + public static class ResourceManager { + public static ItemManager Items = new ItemManager(); + public static BlockManager Blocks = new BlockManager(); + public static RecipeManager Recipes = new RecipeManager(); + public static EntityManager Entities = new EntityManager(); + public static FontTypes Fonts = new FontTypes(); + public static SkyboxAssets Skybox = new SkyboxAssets(); + + public const float SPRITE_SCALING = 0.125f; + public const int INVERSE_SPRITE_SCALING = 8; + + public static void AddCollection(IResourceCollection collection) { + Blocks.AddCollection(collection); + Items.AddCollection(collection); + Recipes.AddCollection(collection); + Entities.AddCollection(collection); + } + + public static void LoadContent(ContentManager content) { + Blocks.LoadContent(content); + Items.LoadContent(content); + Recipes.LoadContent(content); + Entities.LoadContent(content); + + Fonts.LoadContent(content); + Skybox.LoadContent(content); + } + } + + public struct NamespacedKey { + public readonly string Namespace; + public readonly string Index; + + public NamespacedKey(string ns, string index) { + Namespace = ns; + Index = index; + } + + public static NamespacedKey Base(string index) { + return new NamespacedKey("celesteia", index); + } + + public string Qualify() { + return $"{Namespace}:{Index}"; + } + + public override bool Equals(object obj) + { + return obj is NamespacedKey && ((NamespacedKey)obj).Namespace == Namespace && ((NamespacedKey)obj).Index == Index; + } + + public override int GetHashCode() + { + return base.GetHashCode(); + } + } + + public interface IResourceType { + public byte GetID(); + public void SetID(byte id); + } + + public interface IResourceManager { + public void AddCollection(IResourceCollection collection); + public IResourceType GetResource(NamespacedKey namespacedKey); + } + + public interface IResourceCollection { + public Dictionary GetBlocks(); + public Dictionary GetItems(); + public Dictionary GetRecipes(); + public Dictionary GetEntities(); + public NamespacedKey GetKey(string index); + } +} \ No newline at end of file diff --git a/source/resources/collections/BaseCollection.cs b/source/resources/collections/BaseCollection.cs new file mode 100644 index 0000000..2af029e --- /dev/null +++ b/source/resources/collections/BaseCollection.cs @@ -0,0 +1,207 @@ +using System.Collections.Generic; +using Celesteia.Game.Components; +using Celesteia.Game.ECS; +using Celesteia.Game.Items; +using Celesteia.Graphics.Lighting; +using Celesteia.Resources.Types; +using Celesteia.Resources.Types.Builders; +using Microsoft.Xna.Framework; +using Microsoft.Xna.Framework.Content; +using Microsoft.Xna.Framework.Graphics; +using MonoGame.Extended.TextureAtlases; + +/* + A collection of resources for the base game. +*/ +namespace Celesteia.Resources.Collections { + public class BaseCollection : IResourceCollection + { + public NamespacedKey GetKey(string index) => NamespacedKey.Base(index); + + private ContentManager _content; + public BaseCollection(ContentManager Content) { + _content = Content; + } + + + public Dictionary GetBlocks() => LoadBlocks(); + private Dictionary blocks; + private Dictionary LoadBlocks(int pixelSize = 8) { + if (blocks != null) return blocks; + + void AddBlock(string index, BlockType type) => blocks.Add(GetKey(index), type); + + TextureAtlas _atlas = TextureAtlas.Create("blocks", _content.Load("sprites/blocks"), pixelSize, pixelSize); + BlockTypeBuilder builder = new BlockTypeBuilder(_atlas); + + blocks = new Dictionary(); + AddBlock("air", builder.WithName("Air").Invisible().Get()); + AddBlock("grown_soil", builder.WithName("Grown Soil").Full().Frames(0).Properties( + strength: 5, + drop: GetKey("soil") + ).Get()); + AddBlock("soil", builder.WithName("Soil").Full().Frames(1).Properties( + strength: 5, + drop: GetKey("soil") + ).Get()); + AddBlock("stone", builder.WithName("Stone").Full().Frames(2).Properties( + strength: 7, + drop: GetKey("stone") + ).Get()); + AddBlock("deepstone", builder.WithName("Deepstone").Full().Frames(3).Properties( + strength: -1, + drop: GetKey("deepstone") + ).Get()); + AddBlock("log", builder.WithName("Wooden Log").Full().Frames(10).Properties( + strength: 2, + drop: GetKey("log") + ).Get()); + AddBlock("leaves", builder.WithName("Leaves").Walkthrough().Frames(11).Properties( + translucent: true, + strength: 1, + light: new BlockLightProperties(LightColor.black, 0, false) + ).Get()); + AddBlock("iron_ore", builder.WithName("Iron Ore").Full().Frames(8).Properties( + strength: 15, + drop: GetKey("iron_ore") + ).Get()); + AddBlock("copper_ore", builder.WithName("Copper Ore").Full().Frames(7).Properties( + strength: 10, + drop: GetKey("copper_ore") + ).Get()); + AddBlock("coal_ore", builder.WithName("Coal Ore").Full().Frames(14).Properties( + strength: 10, + drop: GetKey("coal") + ).Get()); + AddBlock("wooden_planks", builder.WithName("Wooden Planks").Full().Frames(4).Properties( + strength: 4, + drop: GetKey("wooden_planks") + ).Get()); + AddBlock("torch", builder.WithName("Torch").Walkthrough().Frames(9).Properties( + translucent: true, + strength: 1, + drop: GetKey("wooden_torch"), + light: new BlockLightProperties(LightColor.white, 6, false) + ).Get()); + AddBlock("stone_bricks", builder.WithName("Stone Bricks").Frames(6).Full().Properties( + strength: 7, + drop: GetKey("stone_bricks") + ).Get()); + AddBlock("unyx_bricks", builder.WithName("Unyx Bricks").Frames(12).Full().Properties( + strength: 10, + drop: GetKey("unyx_bricks") + ).Get()); + AddBlock("unyx_eyestone", builder.WithName("Unyx Eyestone").Frames(13).Full().Properties( + strength: 10, + drop: GetKey("unyx_eyestone"), + light: new BlockLightProperties(new LightColor(230f, 74f, 255f), 5, true) + ).Get()); + AddBlock("scorched_soil", builder.WithName("Scorched Soil").Frames(15).Full().Properties( + strength: -1 + ).Get()); + AddBlock("blue_flower", builder.WithName("Morning Stars").Frames(16).Walkthrough().Properties( + strength: 1, + drop: GetKey("blue_flower_bundle"), + light: new BlockLightProperties(LightColor.black, 0, false) + ).Get()); + AddBlock("red_flower", builder.WithName("Red Tears").Frames(17).Walkthrough().Properties( + strength: 1, + drop: GetKey("red_flower_bundle"), + light: new BlockLightProperties(LightColor.black, 0, false) + ).Get()); + AddBlock("violet_flower", builder.WithName("Colupria").Frames(18).Walkthrough().Properties( + strength: 1, + drop: GetKey("violet_flower_bundle"), + light: new BlockLightProperties(LightColor.black, 0, false) + ).Get()); + AddBlock("grass", builder.WithName("Grass").Frames(19).Walkthrough().Properties( + strength: 1, + light: new BlockLightProperties(LightColor.black, 0, false) + ).Get()); + AddBlock("crashed_capsule_base", builder.WithName("Crashed Capsule").UniqueFrames( + TextureAtlas.Create("cc", _content.Load("sprites/crashed_capsule"), pixelSize * 3, pixelSize * 3), 0, 1, + new Vector2(pixelSize * 1, pixelSize * 2) + ).Walkthrough().Properties( + translucent: true, + strength: -1, + light: new BlockLightProperties(LightColor.black, 0, false) + ).Get()); + AddBlock("crashed_capsule_frame", builder.WithName("Crashed Capsule").Invisible().Properties( + translucent: true, + strength: -1, + light: new BlockLightProperties(LightColor.black, 0, false) + ).Get()); + + return blocks; + } + + public Dictionary GetItems() => LoadItems(); + private Dictionary items; + private Dictionary LoadItems(int pixelSize = 16) { + if (items != null) return items; + + void AddItem(string index, ItemType type) => items.Add(GetKey(index), type); + + TextureAtlas _atlas = TextureAtlas.Create("items", _content.Load("sprites/items"), pixelSize, pixelSize); + ItemTypeBuilder builder = new ItemTypeBuilder(_atlas); + + items = new Dictionary(); + if (blocks != null) { + foreach (KeyValuePair pair in blocks) { + if (pair.Value.Frames == null) continue; + AddItem(pair.Key.Index, builder.WithName(pair.Value.Name).Block(pair.Key).Frame(pair.Value.Frames.GetFrame(0).GetRegion()).Get()); + } + } + + AddItem("iron_pickaxe", builder.WithName("Iron Pickaxe").Pickaxe(4).Frame(0).Get()); + AddItem("wooden_log", builder.WithName("Wooden Log").Frame(1).Block(NamespacedKey.Base("log")).Get()); + AddItem("coal", builder.WithName("Coal Lump").Frame(2).Get()); + AddItem("plank", builder.WithName("Plank").Frame(3).Get()); + AddItem("copper_ingot", builder.WithName("Copper Ingot").Frame(4).Get()); + AddItem("iron_ingot", builder.WithName("Iron Ingot").Frame(5).Get()); + AddItem("fuel_tank", builder.WithName("Fuel Tank").Frame(6).Upgrade(EntityAttribute.JumpFuel, 0.5f, 5f).Get()); + AddItem("wooden_torch", builder.WithName("Wooden Torch").Template(new ItemTypeTemplate(1000, true)) + .Frame(7).Actions(new TorchItemActions(NamespacedKey.Base("torch"))).Get()); + AddItem("blue_flower_bundle", builder.WithName("Morning Stars").Template(new ItemTypeTemplate(1000, true)) + .Frame(10).Actions(new FoliageItemActions(NamespacedKey.Base("blue_flower"))).Get()); + AddItem("red_flower_bundle", builder.WithName("Red Tears").Template(new ItemTypeTemplate(1000, true)) + .Frame(11).Actions(new FoliageItemActions(NamespacedKey.Base("red_flower"))).Get()); + AddItem("violet_flower_bundle", builder.WithName("Colupria").Template(new ItemTypeTemplate(1000, true)) + .Frame(12).Actions(new FoliageItemActions(NamespacedKey.Base("violet_flower"))).Get()); + + return items; + } + + public Dictionary GetRecipes() => LoadRecipes(); + private Dictionary recipes; + private Dictionary LoadRecipes() { + if (recipes != null) return recipes; + + void AddRecipe(string index, Recipe type) => recipes.Add(GetKey(index), type); + + recipes = new Dictionary(); + AddRecipe("plank_ingredient", new Recipe(new Part(GetKey("plank"), 4), new Part(GetKey("log"), 1))); + AddRecipe("plank_block", new Recipe(new Part(GetKey("wooden_planks"), 1), new Part(GetKey("plank"), 2))); + AddRecipe("copper_smelt", new Recipe(new Part(GetKey("copper_ingot"), 1), new Part(GetKey("copper_ore"), 1))); + AddRecipe("iron_smelt", new Recipe(new Part(GetKey("iron_ingot"), 1), new Part(GetKey("iron_ore"), 1))); + AddRecipe("fuel_tank", new Recipe(new Part(GetKey("fuel_tank"), 1), new Part(GetKey("iron_ingot"), 10), new Part(GetKey("copper_ingot"), 5))); + AddRecipe("torches", new Recipe(new Part(GetKey("wooden_torch"), 4), new Part(GetKey("plank"), 1), new Part(GetKey("coal"), 1))); + AddRecipe("stone_brick", new Recipe(new Part(GetKey("stone_bricks"), 4), new Part(GetKey("stone"), 4))); + + return recipes; + } + + public Dictionary GetEntities() => LoadEntities(); + private Dictionary entities; + private Dictionary LoadEntities() { + if (entities != null) return entities; + + void AddEntity(string index, EntityType type) => entities.Add(GetKey(index), type); + + entities = new Dictionary(); + AddEntity("player", new EntityType((e) => EntityFactory.BuildPlayer(e, _content.Load("sprites/entities/player/astronaut")))); + + return entities; + } + } +} \ No newline at end of file diff --git a/source/resources/management/BlockManager.cs b/source/resources/management/BlockManager.cs new file mode 100644 index 0000000..2271c0c --- /dev/null +++ b/source/resources/management/BlockManager.cs @@ -0,0 +1,77 @@ +using System; +using System.Collections.Generic; +using System.Diagnostics; +using Celesteia.Resources.Sprites; +using Celesteia.Resources.Types; +using Microsoft.Xna.Framework.Content; +using Microsoft.Xna.Framework.Graphics; +using MonoGame.Extended.TextureAtlases; + +namespace Celesteia.Resources.Management { + public abstract class BlockSpriteProperties { + public const int SIZE = 8; + } + + public class BlockManager : IResourceManager { + private List Types; + private BlockType[] BakedTypes; + private Dictionary keys = new Dictionary(); + + public BlockFrames BreakAnimation; + public BlockFrames Selection; + + private void LoadBreakingAnimation(ContentManager Content) { + Debug.WriteLine($"Loading block break animation..."); + BreakAnimation = new BlockFrames(TextureAtlas.Create("blockbreak", Content.Load("sprites/blockbreak"), + BlockSpriteProperties.SIZE, + BlockSpriteProperties.SIZE + ), 0, 3); + } + + private void LoadSelector(ContentManager Content) { + Debug.WriteLine($"Loading block selector..."); + Selection = new BlockFrames(TextureAtlas.Create("selection", Content.Load("sprites/blockselection"), + BlockSpriteProperties.SIZE, + BlockSpriteProperties.SIZE + ), 0, 1); + } + + private List _collections = new List(); + public void AddCollection(IResourceCollection collection) => _collections.Add(collection); + + public void LoadContent(ContentManager Content) { + LoadBreakingAnimation(Content); + LoadSelector(Content); + + Debug.WriteLine($"Loading block types..."); + + Types = new List(); + + foreach (IResourceCollection collection in _collections) + LoadCollection(collection); + + BakedTypes = Types.ToArray(); + } + + private void LoadCollection(IResourceCollection collection) { + foreach (NamespacedKey key in collection.GetBlocks().Keys) { + AddType(key, collection.GetBlocks()[key]); + } + } + + private byte next = 0; + private void AddType(NamespacedKey key, BlockType type) { + type.SetID(next++); + keys.Add(key.Qualify(), type.GetID()); + + Types.Add(type); + } + + public BlockType GetBlock(byte id) => BakedTypes[id]; + + public IResourceType GetResource(NamespacedKey key) { + if (!keys.ContainsKey(key.Qualify())) throw new NullReferenceException(); + return BakedTypes[keys[key.Qualify()]]; + } + } +} \ No newline at end of file diff --git a/source/resources/management/EntityManager.cs b/source/resources/management/EntityManager.cs new file mode 100644 index 0000000..74a4dbe --- /dev/null +++ b/source/resources/management/EntityManager.cs @@ -0,0 +1,46 @@ +using System; +using System.Collections.Generic; +using System.Diagnostics; +using Celesteia.Resources.Types; +using Microsoft.Xna.Framework.Content; + +namespace Celesteia.Resources.Management { + public class EntityManager : IResourceManager { + public List Types; + private EntityType[] BakedTypes; + private Dictionary keys = new Dictionary(); + + private List _collections = new List(); + public void AddCollection(IResourceCollection collection) => _collections.Add(collection); + + public void LoadContent(ContentManager Content) { + Debug.WriteLine($"Loading entity types..."); + + Types = new List(); + + foreach (IResourceCollection collection in _collections) + LoadCollection(collection); + + BakedTypes = Types.ToArray(); + } + + private void LoadCollection(IResourceCollection collection) { + foreach (NamespacedKey key in collection.GetEntities().Keys) { + AddType(key, collection.GetEntities()[key]); + } + } + + private byte next = 0; + private void AddType(NamespacedKey key, EntityType type) { + type.SetID(next++); + keys.Add(key.Qualify(), type.GetID()); + + Types.Add(type); + } + + public IResourceType GetResource(NamespacedKey key) { + if (!keys.ContainsKey(key.Qualify())) throw new NullReferenceException(); + return BakedTypes[keys[key.Qualify()]]; + } + } +} \ No newline at end of file diff --git a/source/resources/management/FontManager.cs b/source/resources/management/FontManager.cs new file mode 100644 index 0000000..482f25e --- /dev/null +++ b/source/resources/management/FontManager.cs @@ -0,0 +1,43 @@ +using System.Collections.Generic; +using System.Diagnostics; +using Microsoft.Xna.Framework.Content; +using Microsoft.Xna.Framework.Graphics; + +namespace Celesteia.Resources.Management { + public abstract class FontProperties { + public const int STANDARD_SIZE = 12; + } + + public class FontTypes { + public FontType DEFAULT { get; private set; } + private List Types; + + public void LoadContent(ContentManager Content) { + Debug.WriteLine($"Loading fonts..."); + + Types = new List(); + + Types.Add(DEFAULT = new FontType("Hobo", Content.Load("Hobo"))); + } + + public FontType GetFontType(string name) { + return Types.Find(x => x.Name == name); + } + } + + public class FontType { + public readonly string Name; + public readonly SpriteFont Font; + + public FontType(string name, SpriteFont font) { + Name = name; + Font = font; + + Debug.WriteLine($" Font '{name}' loaded."); + } + + public float Scale(float targetFontSize) { + return targetFontSize / FontProperties.STANDARD_SIZE; + } + } +} \ No newline at end of file diff --git a/source/resources/management/ItemManager.cs b/source/resources/management/ItemManager.cs new file mode 100644 index 0000000..3970d7d --- /dev/null +++ b/source/resources/management/ItemManager.cs @@ -0,0 +1,47 @@ +using System; +using System.Collections.Generic; +using System.Diagnostics; +using Celesteia.Resources.Types; +using Microsoft.Xna.Framework.Content; + +namespace Celesteia.Resources.Management { + + public class ItemManager : IResourceManager { + private List Types; + private ItemType[] BakedTypes; + private Dictionary keys = new Dictionary(); + + private List _collections = new List(); + public void AddCollection(IResourceCollection collection) => _collections.Add(collection); + + public void LoadContent(ContentManager Content) { + Debug.WriteLine($"Loading item types..."); + + Types = new List(); + + foreach (IResourceCollection collection in _collections) + LoadCollection(collection); + + BakedTypes = Types.ToArray(); + } + + private void LoadCollection(IResourceCollection collection) { + foreach (NamespacedKey key in collection.GetItems().Keys) { + AddType(key, collection.GetItems()[key]); + } + } + + private byte next = 0; + private void AddType(NamespacedKey key, ItemType type) { + type.SetID(next++); + keys.Add(key.Qualify(), type.GetID()); + + Types.Add(type); + } + + public IResourceType GetResource(NamespacedKey key) { + if (!keys.ContainsKey(key.Qualify())) throw new NullReferenceException(); + return BakedTypes[keys[key.Qualify()]]; + } + } +} \ No newline at end of file diff --git a/source/resources/management/RecipeManager.cs b/source/resources/management/RecipeManager.cs new file mode 100644 index 0000000..fb6df07 --- /dev/null +++ b/source/resources/management/RecipeManager.cs @@ -0,0 +1,34 @@ +using System.Collections.Generic; +using System.Diagnostics; +using Celesteia.Resources.Types; +using Microsoft.Xna.Framework.Content; + +namespace Celesteia.Resources.Management { + public class RecipeManager : IResourceManager { + public List Recipes; + + private List _collections = new List(); + public void AddCollection(IResourceCollection collection) => _collections.Add(collection); + + public void LoadContent(ContentManager Content) { + Debug.WriteLine($"Loading crafting recipes..."); + + Recipes = new List(); + + foreach (IResourceCollection collection in _collections) + LoadCollection(collection); + } + + private void LoadCollection(IResourceCollection collection) { + foreach (NamespacedKey key in collection.GetRecipes().Keys) { + AddType(collection.GetRecipes()[key]); + } + } + + private void AddType(Recipe recipe) { + Recipes.Add(recipe); + } + + public IResourceType GetResource(NamespacedKey namespacedKey) => null; + } +} \ No newline at end of file diff --git a/source/resources/management/SkyboxAssets.cs b/source/resources/management/SkyboxAssets.cs new file mode 100644 index 0000000..049c2a5 --- /dev/null +++ b/source/resources/management/SkyboxAssets.cs @@ -0,0 +1,42 @@ +using System.Collections.Generic; +using System.Diagnostics; +using Celesteia.Resources.Sprites; +using Microsoft.Xna.Framework.Content; +using Microsoft.Xna.Framework.Graphics; +using MonoGame.Extended.TextureAtlases; + +namespace Celesteia.Resources.Management { + public class SkyboxAssets { + private List Assets; + + public void LoadContent(ContentManager Content) { + Debug.WriteLine($"Loading skybox assets..."); + + Assets = new List(); + + Assets.Add(new SkyboxAsset(0, "stars", TextureAtlas.Create("stars", Content.Load("sprites/skybox/stars2"), 1024, 1024), 1024, 0)); + Assets.Add(new SkyboxAsset(1, "shadow", TextureAtlas.Create("shadow", Content.Load("sprites/skybox/shadow"), 1024, 1024), 1024, 0)); + Assets.Add(new SkyboxAsset(2, "nebula", TextureAtlas.Create("nebula", Content.Load("sprites/skybox/nebula"), 1024, 1024), 1024, 0)); + } + + public SkyboxAsset GetAsset(string name) { + return Assets.Find(x => x.Name == name); + } + } + + public class SkyboxAsset { + public readonly byte AssetID; + public readonly string Name; + public readonly SkyboxPortionFrames Frames; + + public SkyboxAsset(byte id, string name, TextureAtlas atlas, int size, int frameStart, int frameCount) { + AssetID = id; + Name = name; + Frames = new SkyboxPortionFrames(atlas, size, frameStart, frameCount); + + Debug.WriteLine($" Skybox asset '{name}' loaded."); + } + + public SkyboxAsset(byte id, string name, TextureAtlas atlas, int size, int frame) : this (id, name, atlas, size, frame, 1) {} + } +} \ No newline at end of file diff --git a/source/resources/sprites/BlockFrames.cs b/source/resources/sprites/BlockFrames.cs new file mode 100644 index 0000000..33db3e8 --- /dev/null +++ b/source/resources/sprites/BlockFrames.cs @@ -0,0 +1,53 @@ +using System; +using Microsoft.Xna.Framework; +using Microsoft.Xna.Framework.Graphics; +using MonoGame.Extended.TextureAtlases; + +namespace Celesteia.Resources.Sprites { + public class BlockFrames { + private readonly Vector2 _scaling; + + private BlockFrame[] _frames; + + private bool _doDraw; + public bool DoDraw => _doDraw; + + public BlockFrames(TextureAtlas atlas, int startIndex, int frameCount, Vector2? origin = null) { + _doDraw = frameCount > 0; + + _scaling = new Vector2(ResourceManager.SPRITE_SCALING); + + _frames = new BlockFrame[frameCount]; + for (int i = 0; i < frameCount; i++) { + _frames[i] = new BlockFrame(atlas.GetRegion(startIndex + i), _scaling, origin); + } + } + + public BlockFrame GetFrame(int index) { + if (!_doDraw) return null; + + return _frames[index % _frames.Length]; + } + + public BlockFrame GetProgressFrame(float progress) { + return GetFrame((int)MathF.Round(progress * (_frames.Length - 1))); + } + } + + public class BlockFrame { + private TextureRegion2D _region; + private Vector2 _scaling; + private Vector2 _origin; + + public BlockFrame(TextureRegion2D region, Vector2 scaling, Vector2? origin = null) { + _region = region; + _scaling = scaling; + _origin = origin.HasValue ? origin.Value : Vector2.Zero; + } + + public void Draw(int index, SpriteBatch spriteBatch, Vector2 position, Color color, float depth = 0f) + => spriteBatch.Draw(_region, position, color, 0f, _origin, _scaling, SpriteEffects.None, depth); + + public TextureRegion2D GetRegion() => _region; + } +} \ No newline at end of file diff --git a/source/resources/sprites/EntityFrames.cs b/source/resources/sprites/EntityFrames.cs new file mode 100644 index 0000000..65e31ee --- /dev/null +++ b/source/resources/sprites/EntityFrames.cs @@ -0,0 +1,32 @@ +using Microsoft.Xna.Framework; +using Microsoft.Xna.Framework.Graphics; +using MonoGame.Extended.TextureAtlases; + +namespace Celesteia.Resources.Sprites { + public class EntityFrames { + public SpriteEffects Effects; + + public int Frame; + + private readonly Vector2 _scaling; + + private TextureRegion2D[] _frames; + + public EntityFrames(TextureAtlas atlas, int startIndex, int frameCount, float scaling) { + _scaling = new Vector2(scaling); + + _frames = new TextureRegion2D[frameCount]; + for (int i = 0; i < frameCount; i++) { + _frames[i] = atlas.GetRegion(startIndex + i); + } + } + + private Vector2 GetOrigin(TextureRegion2D frame) { + return new Vector2(0.5f * frame.Width, 0.5f * frame.Height); + } + + public void Draw(int index, SpriteBatch spriteBatch, Vector2 position, Vector2 scale, Color color) { + spriteBatch.Draw(_frames[Frame % _frames.Length], position, color, 0f, GetOrigin(_frames[index % _frames.Length]), _scaling * scale, Effects, 0f, null); + } + } +} \ No newline at end of file diff --git a/source/resources/sprites/SkyboxPortionFrames.cs b/source/resources/sprites/SkyboxPortionFrames.cs new file mode 100644 index 0000000..dc26156 --- /dev/null +++ b/source/resources/sprites/SkyboxPortionFrames.cs @@ -0,0 +1,51 @@ +using Microsoft.Xna.Framework; +using Microsoft.Xna.Framework.Graphics; +using MonoGame.Extended.TextureAtlases; + +namespace Celesteia.Resources.Sprites { + public class SkyboxPortionFrames { + private readonly Vector2 _scaling; + + private TextureAtlas _atlas; + private int _start; + private int _count; + + private TextureRegion2D[] _frames; + private Color _color; + private float _depth; + + public SkyboxPortionFrames(TextureAtlas atlas, int size, int startIndex, int frameCount) { + _atlas = atlas; + _start = startIndex; + _count = frameCount; + _scaling = new Vector2(ResourceManager.SPRITE_SCALING) / 2f; + + _frames = new TextureRegion2D[frameCount]; + for (int i = 0; i < frameCount; i++) { + _frames[i] = atlas.GetRegion(startIndex + i); + } + } + + public SkyboxPortionFrames SetColor(Color color) { + _color = color; + return this; + } + + public SkyboxPortionFrames SetDepth(float depth) { + _depth = depth; + return this; + } + + private Vector2 GetOrigin(TextureRegion2D frame) { + return new Vector2(0.5f * frame.Width, 0.5f * frame.Height); + } + + public void Draw(int index, SpriteBatch spriteBatch, Vector2 position, float rotation, Vector2 scale) { + spriteBatch.Draw(_frames[index % _frames.Length], position, _color, rotation, GetOrigin(_frames[index % _frames.Length]), scale * _scaling, SpriteEffects.None, _depth, null); + } + + public SkyboxPortionFrames Clone() { + return new SkyboxPortionFrames(_atlas, 0, _start, _count).SetColor(_color).SetDepth(_depth); + } + } +} \ No newline at end of file diff --git a/source/resources/types/BlockType.cs b/source/resources/types/BlockType.cs new file mode 100644 index 0000000..d55e998 --- /dev/null +++ b/source/resources/types/BlockType.cs @@ -0,0 +1,71 @@ +using Celesteia.Graphics.Lighting; +using Celesteia.Resources.Sprites; +using MonoGame.Extended; +using MonoGame.Extended.TextureAtlases; + +namespace Celesteia.Resources.Types { + public class BlockType : IResourceType { + private byte id; + public readonly string Name; + public void SetID(byte value) => id = value; + public byte GetID() => id; + + public BlockType(string name) { + Name = name; + } + + public BlockFrames Frames = null; + public NamespacedKey? DropKey = null; + public RectangleF? BoundingBox = new RectangleF(0f, 0f, 1f, 1f); + public int Strength = 1; + public bool Translucent = false; + public BlockLightProperties Light = new BlockLightProperties(); + + + public BlockType MakeFrames(TextureAtlas atlas, int frameStart, int frameCount) { + Frames = new BlockFrames(atlas, frameStart, frameCount); + return this; + } + + public BlockType AddDrop(NamespacedKey dropKey) { + DropKey = dropKey; + return this; + } + + public BlockType SetBoundingBox(RectangleF boundingBox) { + BoundingBox = boundingBox; + return this; + } + + public BlockType SetStrength(int strength) { + Strength = strength; + return this; + } + + public BlockType SetLightProperties(BlockLightProperties properties) { + Light = properties; + if (Light == null) Light = new BlockLightProperties(); + return this; + } + + public BlockType SetTranslucent(bool translucent) { + Translucent = translucent; + return this; + } + } + + public class BlockLightProperties { + public readonly bool Emits = false; + public readonly bool Occludes = true; + public readonly int Propagation = 0; + public readonly LightColor Color = LightColor.black; + + public BlockLightProperties() {} + public BlockLightProperties(LightColor color, int propagation = 0, bool occludes = true) { + Emits = !color.Equals(LightColor.black); + Propagation = propagation; + Occludes = occludes; + Color = color; + } + } +} \ No newline at end of file diff --git a/source/resources/types/EntityType.cs b/source/resources/types/EntityType.cs new file mode 100644 index 0000000..4ecc20f --- /dev/null +++ b/source/resources/types/EntityType.cs @@ -0,0 +1,20 @@ +using System; +using MonoGame.Extended.Entities; + +namespace Celesteia.Resources.Types { + public class EntityType : IResourceType { + private byte id; + public byte GetID() => id; + public void SetID(byte value) => id = value; + + private Action InstantiateAction; + + public EntityType(Action instantiate) { + InstantiateAction = instantiate; + } + + public void Instantiate(Entity entity) { + InstantiateAction.Invoke(entity); + } + } +} \ No newline at end of file diff --git a/source/resources/types/ItemType.cs b/source/resources/types/ItemType.cs new file mode 100644 index 0000000..8b1da27 --- /dev/null +++ b/source/resources/types/ItemType.cs @@ -0,0 +1,21 @@ +using Celesteia.Game.Items; +using MonoGame.Extended.TextureAtlases; + +namespace Celesteia.Resources.Types { + public class ItemType : IResourceType { + private byte id; + public readonly string Name; + public byte GetID() => id; + public void SetID(byte value) => id = value; + + public ItemType(string name) { + Name = name; + } + + public string Lore = ""; + public TextureRegion2D Sprite = null; + public int MaxStackSize = 99; + public IItemActions Actions; + public bool ConsumeOnUse; + } +} \ No newline at end of file diff --git a/source/resources/types/Recipe.cs b/source/resources/types/Recipe.cs new file mode 100644 index 0000000..94dd9ba --- /dev/null +++ b/source/resources/types/Recipe.cs @@ -0,0 +1,48 @@ +using System.Collections.Generic; +using Celesteia.Game.Components.Items; + +namespace Celesteia.Resources.Types { + public class Recipe : IResourceType { + private byte id; + public readonly string Name; + public byte GetID() => id; + public void SetID(byte value) => id = value; + + public Part Result; + public List Ingredients; + + public Recipe(Part result, params Part[] ingredients) { + Result = result; + Ingredients = new List(ingredients); + } + + public bool Craftable(Inventory inventory) { + foreach (Part ingredient in Ingredients) + if (!inventory.ContainsAmount(ingredient.Key, ingredient.Amount)) return false; + + return true; + } + + public void Craft(Inventory inventory) { + if (!Craftable(inventory)) return; + + foreach (Part ingredient in Ingredients) + inventory.RemoveAmount(ingredient.Key, ingredient.Amount); + + inventory.AddItem(Result.Stack); + } + } + + public struct Part { + public NamespacedKey Key; + public int Amount; + + public Part(NamespacedKey key, int amount) { + Key = key; + Amount = amount; + } + + public ItemStack Stack => new ItemStack(Key, Amount); + public ItemType GetItemType() => ResourceManager.Items.GetResource(Key) as ItemType; + } +} \ No newline at end of file diff --git a/source/resources/types/TileEntityType.cs b/source/resources/types/TileEntityType.cs new file mode 100644 index 0000000..cd40514 --- /dev/null +++ b/source/resources/types/TileEntityType.cs @@ -0,0 +1,27 @@ +using System; +using Microsoft.Xna.Framework; +using MonoGame.Extended.Entities; + +namespace Celesteia.Resources.Types { + public class TileEntityType : IResourceType { + private byte id; + public byte GetID() => id; + public void SetID(byte value) => id = value; + + public readonly Point Bounds; + public readonly Point Origin; + public readonly NamespacedKey PartKey; + private Action InstantiateAction; + + public TileEntityType(NamespacedKey part, Action instantiate, int width, int height, int originX = 0, int originY = 0) { + PartKey = part; + InstantiateAction = instantiate; + Bounds = new Point(width, height); + Origin = new Point(originX, originY); + } + + public void Instantiate(Entity entity) { + InstantiateAction.Invoke(entity); + } + } +} \ No newline at end of file diff --git a/source/resources/types/builders/BlockTypeBuilder.cs b/source/resources/types/builders/BlockTypeBuilder.cs new file mode 100644 index 0000000..e08b1a1 --- /dev/null +++ b/source/resources/types/builders/BlockTypeBuilder.cs @@ -0,0 +1,82 @@ +using Microsoft.Xna.Framework; +using MonoGame.Extended; +using MonoGame.Extended.TextureAtlases; + +namespace Celesteia.Resources.Types.Builders { + public class BlockTypeBuilder { + private TextureAtlas _atlas; + public BlockTypeBuilder(TextureAtlas atlas) { + _atlas = atlas; + } + + private BlockType current; + public BlockTypeBuilder WithName(string name) { + current = new BlockType(name); + return this; + } + + public BlockTypeBuilder Full() => WithTemplate(BlockTypeTemplate.Full); + public BlockTypeBuilder Invisible() => WithTemplate(BlockTypeTemplate.Invisible); + public BlockTypeBuilder Walkthrough() => WithTemplate(BlockTypeTemplate.Walkthrough); + + public BlockTypeBuilder WithTemplate(BlockTypeTemplate template) { + current.Translucent = template.Translucent; + current.BoundingBox = template.BoundingBox; + current.DropKey = template.DropKey; + current.SetLightProperties(template.LightProperties); + current.Strength = template.Strength; + + return this; + } + + public BlockTypeBuilder Frames(int start, int count = 1) { + current.MakeFrames(_atlas, start, count); + return this; + } + + public BlockTypeBuilder UniqueFrames(TextureAtlas atlas, int start, int count = 1, Vector2? origin = null) { + current.Frames = new Sprites.BlockFrames(atlas, start, count, origin); + return this; + } + + public BlockTypeBuilder Properties(bool translucent = false, int strength = 1, NamespacedKey? drop = null, BlockLightProperties light = null) { + current.Translucent = translucent; + current.Strength = strength; + current.DropKey = drop; + current.SetLightProperties(light); + + return this; + } + + public BlockType Get() { + return current; + } + } + + public class BlockTypeTemplate + { + public static BlockTypeTemplate Invisible = new BlockTypeTemplate(null, null, 0, true); + public static BlockTypeTemplate Full = new BlockTypeTemplate(new RectangleF(0f, 0f, 1f, 1f), null, 1, false, null); + public static BlockTypeTemplate Walkthrough = new BlockTypeTemplate(null); + + public RectangleF? BoundingBox; + public NamespacedKey? DropKey; + public int Strength; + public bool Translucent; + public BlockLightProperties LightProperties; + + public BlockTypeTemplate( + RectangleF? boundingBox = null, + NamespacedKey? dropKey = null, + int strength = 1, + bool translucent = false, + BlockLightProperties lightProperties = null + ) { + BoundingBox = boundingBox; + DropKey = dropKey; + Strength = strength; + Translucent = translucent; + LightProperties = lightProperties; + } + } +} \ No newline at end of file diff --git a/source/resources/types/builders/ItemTypeBuilder.cs b/source/resources/types/builders/ItemTypeBuilder.cs new file mode 100644 index 0000000..cd9f61c --- /dev/null +++ b/source/resources/types/builders/ItemTypeBuilder.cs @@ -0,0 +1,67 @@ +using Celesteia.Game.Components; +using Celesteia.Game.Items; +using MonoGame.Extended.TextureAtlases; + +namespace Celesteia.Resources.Types.Builders { + public class ItemTypeBuilder { + private TextureAtlas _atlas; + public ItemTypeBuilder(TextureAtlas atlas) { + _atlas = atlas; + } + + private ItemType current; + public ItemTypeBuilder WithName(string name) { + current = new ItemType(name); + return this; + } + + public ItemTypeBuilder Block(NamespacedKey blockToPlace) + => Template(ItemTypeTemplate.Block).Actions(new BlockItemActions(blockToPlace)); + public ItemTypeBuilder Pickaxe(int power) + => Template(ItemTypeTemplate.Tool).Actions(new PickaxeItemActions(power)); + public ItemTypeBuilder Upgrade(EntityAttribute attribute, float increase, float max ) + => Template(ItemTypeTemplate.Tool).Actions(new UpgradeItemActions(attribute, increase, max)); + + public ItemTypeBuilder Template(ItemTypeTemplate template) { + current.MaxStackSize = template.MaxStackSize; + current.ConsumeOnUse = template.ConsumeOnUse; + return this; + } + + public ItemTypeBuilder Frame(int frame) { + return Frame(_atlas.GetRegion(frame)); + } + + public ItemTypeBuilder Frame(TextureRegion2D region) { + current.Sprite = region; + return this; + } + + public ItemTypeBuilder Actions(IItemActions actions) { + current.Actions = actions; + return this; + } + + public ItemType Get() { + return current; + } + } + + public class ItemTypeTemplate + { + public static ItemTypeTemplate Block = new ItemTypeTemplate(1000, true); + public static ItemTypeTemplate Tool = new ItemTypeTemplate(1, false); + public static ItemTypeTemplate Upgrade = new ItemTypeTemplate(1, false); + + public int MaxStackSize = 99; + public bool ConsumeOnUse = true; + + public ItemTypeTemplate( + int maxStackSize = 99, + bool consumeOnUse = true + ) { + MaxStackSize = maxStackSize; + ConsumeOnUse = consumeOnUse; + } + } +} \ No newline at end of file -- cgit v1.2.3