From 7a2c3d2f67761a00ca6b675befcd094056d60166 Mon Sep 17 00:00:00 2001 From: Jose Henrique Date: Tue, 4 Feb 2025 17:47:18 -0300 Subject: [PATCH] not working inventory :c --- Controllers/InventoryController.cs | 113 +++ Controllers/SkillController.cs | 21 +- Data/ApplicationDbContext.cs | 39 +- Items.csv => GameItemsData.csv | 42 +- .../20250202234056_InitialCreate.Designer.cs | 677 ++++++++++++++++++ Migrations/20250202234056_InitialCreate.cs | 357 +++++++++ .../ApplicationDbContextModelSnapshot.cs | 674 +++++++++++++++++ Models/EquippedItem.cs | 20 + Models/GameItem.cs | 41 ++ Models/Inventory.cs | 26 + Models/Pet.cs | 24 +- Models/Skill.cs | 4 + Program.cs | 18 +- Repositories/GameItemsRepository.cs | 32 + Repositories/PetInventoryRepository.cs | 67 ++ Repositories/PetSkillRepository.cs | 39 + Services/GameItemService.cs | 121 ++++ Services/PetInventoryService.cs | 184 +++++ Services/PetService.cs | 169 ++++- Services/PetSkillService.cs | 63 ++ Services/SkillService.cs | 30 +- pet-companion-api.csproj | 1 + 22 files changed, 2713 insertions(+), 49 deletions(-) create mode 100644 Controllers/InventoryController.cs rename Items.csv => GameItemsData.csv (57%) create mode 100644 Migrations/20250202234056_InitialCreate.Designer.cs create mode 100644 Migrations/20250202234056_InitialCreate.cs create mode 100644 Migrations/ApplicationDbContextModelSnapshot.cs create mode 100644 Models/EquippedItem.cs create mode 100644 Models/GameItem.cs create mode 100644 Models/Inventory.cs create mode 100644 Repositories/GameItemsRepository.cs create mode 100644 Repositories/PetInventoryRepository.cs create mode 100644 Repositories/PetSkillRepository.cs create mode 100644 Services/GameItemService.cs create mode 100644 Services/PetInventoryService.cs create mode 100644 Services/PetSkillService.cs diff --git a/Controllers/InventoryController.cs b/Controllers/InventoryController.cs new file mode 100644 index 0000000..f507135 --- /dev/null +++ b/Controllers/InventoryController.cs @@ -0,0 +1,113 @@ +using Microsoft.AspNetCore.Mvc; +using PetCompanion.Models; +using PetCompanion.Services; + +namespace PetCompanion.Controllers +{ + [ApiController] + [Route("api/v1/[controller]")] + public class InventoryController : ControllerBase + { + private readonly PetInventoryService _inventoryService; + private readonly ILogger _logger; + private readonly Guid userId = Guid.Parse("f5f4b3b3-3b7b-4b7b-8b7b-7b7b7b7b7b7b"); + + public InventoryController( + ILogger logger, + PetInventoryService inventoryService) + { + _logger = logger; + _inventoryService = inventoryService; + } + + [HttpGet("{petId}")] + public async Task GetInventory(string petId) + { + try + { + var inventory = await _inventoryService.GetInventory(petId, userId.ToString()); + return Ok(inventory); + } + catch (Exception ex) + { + return BadRequest(ex.Message); + } + } + + [HttpPut("{petId}/{itemId}/use")] + public async Task UseItem(string petId, int itemId) + { + try + { + var updatedPet = await _inventoryService.UseItem(petId, userId.ToString(), itemId); + return Ok(updatedPet); + } + catch (Exception ex) + { + return BadRequest(ex.Message); + } + } + + [HttpPut("{petId}/{itemId}/equip")] + public IActionResult EquipItem(string petId, int itemId) + { + try + { + var updatedPet = _inventoryService.EquipItem(petId, userId.ToString(), itemId); + return Ok(updatedPet); + } + catch (Exception ex) + { + return BadRequest(ex.Message); + } + } + + [HttpPut("{petId}/{equipTarget}/unequip")] + public IActionResult UnequipItem(string petId, ItemEquipTarget equipTarget) + { + try + { + var updatedPet = _inventoryService.UnequipItem(petId, userId.ToString(), equipTarget); + return Ok(updatedPet); + } + catch (Exception ex) + { + return BadRequest(ex.Message); + } + } + + [HttpPut("{petId}/{itemId}/drop")] + public IActionResult DropItem(string petId, int itemId) + { + try + { + var updatedPet = _inventoryService.DropItem(petId, userId.ToString(), itemId); + return Ok(updatedPet); + } + catch (Exception ex) + { + return BadRequest(ex.Message); + } + } + + [HttpPost("{petId}/create")] + public IActionResult AddItem(string petId, [FromBody] AddItemRequest request) + { + try + { + var updatedPet = _inventoryService.AddItemToPet(petId, userId.ToString(), request.ItemId, request.Quantity); + return Ok(updatedPet); + } + catch (Exception ex) + { + return BadRequest(ex.Message); + } + } + } + + public class AddItemRequest + { + public int ItemId { get; set; } + public int Quantity { get; set; } = 1; + } +} diff --git a/Controllers/SkillController.cs b/Controllers/SkillController.cs index 8781a72..773dc73 100644 --- a/Controllers/SkillController.cs +++ b/Controllers/SkillController.cs @@ -8,15 +8,18 @@ namespace PetCompanion.Controllers public class SkillController : ControllerBase { private readonly SkillService _skillService; + private readonly PetSkillService _petSkillService; private readonly ILogger _logger; private Guid userId = Guid.Parse("f5f4b3b3-3b7b-4b7b-8b7b-7b7b7b7b7b7b"); public SkillController( ILogger logger, - SkillService skillService) + SkillService skillService, + PetSkillService petSkillService) { _logger = logger; _skillService = skillService; + _petSkillService = petSkillService; } [HttpGet] @@ -26,12 +29,26 @@ namespace PetCompanion.Controllers return Ok(skills); } + [HttpGet("{petId}/skills")] + public async Task GetPetSkills(string petId) + { + try + { + var skills = await _petSkillService.GetPetSkills(petId, userId.ToString()); + return Ok(skills); + } + catch (Exception ex) + { + return BadRequest(ex.Message); + } + } + [HttpPost("{petId}/allocate/{skillId}")] public async Task AllocateSkillPoint(string petId, int skillId) { try { - var result = await _skillService.AllocateSkillPoint(petId, userId.ToString(), skillId); + var result = await _petSkillService.AllocateSkillPoint(petId, userId.ToString(), skillId); return Ok(result); } catch (Exception ex) diff --git a/Data/ApplicationDbContext.cs b/Data/ApplicationDbContext.cs index 4c42c4a..255ea74 100644 --- a/Data/ApplicationDbContext.cs +++ b/Data/ApplicationDbContext.cs @@ -15,6 +15,10 @@ namespace PetCompanion.Data public DbSet Skills { get; set; } public DbSet SkillEffects { get; set; } public DbSet PetSkills { get; set; } + public DbSet GameItems { get; set; } + public DbSet Inventories { get; set; } + public DbSet InventoryItems { get; set; } + public DbSet EquippedItems { get; set; } protected override void OnModelCreating(ModelBuilder modelBuilder) { @@ -48,11 +52,44 @@ namespace PetCompanion.Data .WithMany(s => s.Effects) .HasForeignKey(se => se.SkillId); + modelBuilder.Entity() + .HasOne() + .WithMany(i => i.Items) + .HasForeignKey(ii => ii.InventoryId); + + modelBuilder.Entity() + .HasOne(ii => ii.GameItem); + + modelBuilder.Entity() + .HasOne(e => e.Pet) + .WithMany(p => p.EquippedItemsList) + .HasForeignKey(e => e.PetId); + + modelBuilder.Entity() + .HasOne(e => e.GameItem) + .WithMany() + .HasForeignKey(e => e.GameItemId); + // Seed initial skills var skills = SkillsData.GetInitialSkills(); - foreach (var skill in skills) + var skillWithoutEffects = SkillsData.GetInitialSkills().Select(s => new Skill + { + Id = s.Id, + Name = s.Name, + Type = s.Type, + Description = s.Description, + PointsCost = s.PointsCost, + Icon = s.Icon, + SkillsIdRequired = s.SkillsIdRequired + }).ToList(); + + foreach (var skill in skillWithoutEffects) { modelBuilder.Entity().HasData(skill); + } + + foreach (var skill in skills) + { foreach (var effect in skill.Effects) { modelBuilder.Entity().HasData(effect); diff --git a/Items.csv b/GameItemsData.csv similarity index 57% rename from Items.csv rename to GameItemsData.csv index 33f4160..2c58ec1 100644 --- a/Items.csv +++ b/GameItemsData.csv @@ -1,21 +1,21 @@ -ItemId,Item Name, Type, Rarity, Description,Price,Effect -0,Apple,Material,Common,Crafting material (coming soon),0,Nothing -1,Basic Kibble,Consumable,Common,Adds +20 food resources,0,ADD_FOOD_RESOURCES_20 -2,Superfood Smoothie,Consumable,Uncommon,Adds +30 food resources; Restores 5 Intelligence,0,ADD_FOOD_RESOURCES_30 -3,Energy Drink,Consumable,Rare,Reduces Cooldown by 5 min,0,REDUCE_COOLDOWN_5 -4,Golden Apple,Consumable,Legendary,Adds +20 Intelligence (Permanent); Adds +100 food resources,0,ADD_INTELLIGENCE_20 -5,Healing Potion,Consumable,Uncommon,Adds +20 to Health; Adds +20 food resources,0,ADD_HEALTH_20_AND_FOOD_20 -6,Charisma Cookie,Consumable,Rare,Adds +2 Charisma (Permanent),0,ADD_CHARISMA_2 -7,XP Booster,Consumable,Rare,Award +10 XP,0,ADD_XP_10 -8,Sleeping Draught,Consumable,Common,Reduces Cooldown for resting by 10 min,0,REDUCE_REST_COOLDOWN_10 -9,Mystery Meat,Consumable,Uncommon,Randomly Β±2 to one stat (Permanent),0,ADD_RANDOM_STAT_2 -10,Elixir of Vitality,Consumable,Legendary,Fully restores all stats and health; Adds +1 Level,0,RESTORE_STATS;ADD_LEVEL_1 -11,Leather Hat,Equipment,Common,Helmet: +5 Max Health,0,ADD_MAX_HEALTH_5 -12,Wizard Hat,Equipment,Rare,Helmet: +15 Max Intelligence,0,ADD_MAX_INTELLIGENCE_15 -13,Knight's Armor,Equipment,Rare,Chest: +15 Max Strength,0,ADD_MAX_STRENGTH_15 -14,Golden Boots,Equipment,Uncommon,Legging: +10 Max Charisma,0,ADD_MAX_CHARISMA_10 -15,Laser Pointer,Equipment,Common,Weapon: +5 Max Strength,0,ADD_MAX_STRENGTH_5 -16,Celestial Crown,Equipment,Legendary,Helmet: +20 max to all stats,0,ADD_MAX_ALL_STATS_20 -17,Dragon Scale Shield,Equipment,Legendary,Weapon: +50 Max Health,0,ADD_MAX_HEALTH_50 -18,Feathers,Material,Common,Crafting material (coming soon),0,Nothing -19,Phoenix Feather,Material,Legendary,Crafting material (coming soon),0,Nothing \ No newline at end of file +Id,Name,Type,Rarity,Description,Price,Effect,EquipTarget +1,Apple,Material,Common,Crafting material (coming soon),0,Nothing,None +2,Superfood Smoothie,Consumable,Uncommon,Adds +30 food resources; Restores 5 Intelligence,0,ADD_FOOD_RESOURCES_30,None +3,Energy Drink,Consumable,Rare,Reduces Cooldown by 5 min,0,REDUCE_COOLDOWN_5,None +4,Golden Apple,Consumable,Legendary,Adds +20 Intelligence (Permanent); Adds +100 food resources,0,ADD_INTELLIGENCE_20,None +5,Healing Potion,Consumable,Uncommon,Adds +20 to Health; Adds +20 food resources,0,ADD_HEALTH_20_AND_FOOD_20,None +6,Charisma Cookie,Consumable,Rare,Adds +2 Charisma (Permanent),0,ADD_CHARISMA_2,None +7,XP Booster,Consumable,Rare,Award +10 XP,0,ADD_XP_10,None +8,Sleeping Draught,Consumable,Common,Reduces Cooldown for resting by 10 min,0,REDUCE_REST_COOLDOWN_10,None +9,Mystery Meat,Consumable,Uncommon,Randomly Β±2 to one stat (Permanent),0,ADD_RANDOM_STAT_2,None +10,Elixir of Vitality,Consumable,Legendary,Fully restores all stats and health; Adds +1 Level,0,RESTORE_STATS;ADD_LEVEL_1,None +11,Leather Hat,Equipment,Common,Helmet: +5 Max Health,0,ADD_MAX_HEALTH_5,Head +12,Wizard Hat,Equipment,Rare,Helmet: +15 Max Intelligence,0,ADD_MAX_INTELLIGENCE_15,Head +13,Knight's Armor,Equipment,Rare,Chest: +15 Max Strength,0,ADD_MAX_STRENGTH_15,Body +14,Golden Boots,Equipment,Uncommon,Legging: +10 Max Charisma,0,ADD_MAX_CHARISMA_10,Legs +15,Laser Pointer,Equipment,Common,Weapon: +5 Max Strength,0,ADD_MAX_STRENGTH_5,Weapon +16,Celestial Crown,Equipment,Legendary,Helmet: +20 max to all stats,0,ADD_MAX_ALL_STATS_20,Head +17,Dragon Scale Shield,Equipment,Legendary,Weapon: +50 Max Health,0,ADD_MAX_HEALTH_50,Weapon +18,Feathers,Material,Common,Crafting material (coming soon),0,Nothing,None +19,Phoenix Feather,Material,Legendary,Crafting material (coming soon),0,Nothing,None +21,Basic Kibble,Consumable,Common,Adds +20 food resources,0,ADD_FOOD_RESOURCES_20,None \ No newline at end of file diff --git a/Migrations/20250202234056_InitialCreate.Designer.cs b/Migrations/20250202234056_InitialCreate.Designer.cs new file mode 100644 index 0000000..b0fe0b1 --- /dev/null +++ b/Migrations/20250202234056_InitialCreate.Designer.cs @@ -0,0 +1,677 @@ +ο»Ώ// +using System; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; +using PetCompanion.Data; + +#nullable disable + +namespace PetCompanion.Migrations +{ + [DbContext(typeof(ApplicationDbContext))] + [Migration("20250202234056_InitialCreate")] + partial class InitialCreate + { + /// + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder.HasAnnotation("ProductVersion", "9.0.1"); + + modelBuilder.Entity("PetCompanion.Models.EquippedItem", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("EquipTarget") + .HasColumnType("INTEGER"); + + b.Property("GameItemId") + .HasColumnType("INTEGER"); + + b.Property("PetId") + .IsRequired() + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("GameItemId"); + + b.HasIndex("PetId"); + + b.ToTable("EquippedItems"); + }); + + modelBuilder.Entity("PetCompanion.Models.GameItem", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Description") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("Effect") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("EquipTarget") + .HasColumnType("INTEGER"); + + b.Property("Name") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("Price") + .HasColumnType("INTEGER"); + + b.Property("Rarity") + .HasColumnType("INTEGER"); + + b.Property("Type") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.ToTable("GameItems"); + }); + + modelBuilder.Entity("PetCompanion.Models.Inventory", b => + { + b.Property("PetId") + .HasColumnType("TEXT"); + + b.Property("Capacity") + .HasColumnType("INTEGER"); + + b.HasKey("PetId"); + + b.ToTable("Inventories"); + }); + + modelBuilder.Entity("PetCompanion.Models.InventoryItem", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("GameItemId") + .HasColumnType("INTEGER"); + + b.Property("InventoryId") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("Quantity") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.HasIndex("GameItemId"); + + b.HasIndex("InventoryId"); + + b.ToTable("InventoryItems"); + }); + + modelBuilder.Entity("PetCompanion.Models.Pet", b => + { + b.Property("Id") + .HasColumnType("TEXT"); + + b.Property("BasicActionCooldown") + .HasColumnType("TEXT"); + + b.Property("Class") + .HasColumnType("INTEGER"); + + b.Property("Experience") + .HasColumnType("INTEGER"); + + b.Property("GatherActionSince") + .HasColumnType("TEXT"); + + b.Property("Health") + .HasColumnType("INTEGER"); + + b.Property("IsDead") + .HasColumnType("INTEGER"); + + b.Property("Level") + .HasColumnType("INTEGER"); + + b.Property("MaxHealth") + .HasColumnType("INTEGER"); + + b.Property("Name") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("PetBasicAction") + .HasColumnType("INTEGER"); + + b.Property("PetGatherAction") + .HasColumnType("INTEGER"); + + b.Property("SkillPoints") + .HasColumnType("INTEGER"); + + b.Property("UserId") + .IsRequired() + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.ToTable("Pets"); + }); + + modelBuilder.Entity("PetCompanion.Models.PetSkill", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("CurrentTier") + .HasColumnType("INTEGER"); + + b.Property("PetId") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("SkillId") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.HasIndex("PetId"); + + b.HasIndex("SkillId"); + + b.ToTable("PetSkills"); + }); + + modelBuilder.Entity("PetCompanion.Models.PetStats", b => + { + b.Property("PetId") + .HasColumnType("TEXT"); + + b.Property("Agility") + .HasColumnType("INTEGER"); + + b.Property("Charisma") + .HasColumnType("INTEGER"); + + b.Property("Intelligence") + .HasColumnType("INTEGER"); + + b.Property("Luck") + .HasColumnType("INTEGER"); + + b.Property("MaxCharisma") + .HasColumnType("INTEGER"); + + b.Property("MaxIntelligence") + .HasColumnType("INTEGER"); + + b.Property("MaxStrength") + .HasColumnType("INTEGER"); + + b.Property("Perception") + .HasColumnType("INTEGER"); + + b.Property("Strength") + .HasColumnType("INTEGER"); + + b.HasKey("PetId"); + + b.ToTable("PetStats"); + }); + + modelBuilder.Entity("PetCompanion.Models.Resources", b => + { + b.Property("PetId") + .HasColumnType("TEXT"); + + b.Property("Food") + .HasColumnType("INTEGER"); + + b.Property("Gold") + .HasColumnType("INTEGER"); + + b.Property("Junk") + .HasColumnType("INTEGER"); + + b.Property("Wisdom") + .HasColumnType("INTEGER"); + + b.HasKey("PetId"); + + b.ToTable("Resources"); + }); + + modelBuilder.Entity("PetCompanion.Models.Skill", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Description") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("Icon") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("Name") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("PointsCost") + .HasColumnType("INTEGER"); + + b.PrimitiveCollection("SkillsIdRequired") + .HasColumnType("TEXT"); + + b.Property("Type") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.ToTable("Skills"); + + b.HasData( + new + { + Id = 1, + Description = "Increases maximum health of your pet, making it more resilient.", + Icon = "❀", + Name = "Vitality Mastery", + PointsCost = 1, + Type = 0 + }, + new + { + Id = 2, + Description = "Increases maximum intelligence of your pet, improving its learning capabilities.", + Icon = "🧠", + Name = "Mind Enhancement", + PointsCost = 1, + Type = 0 + }, + new + { + Id = 3, + Description = "Increases maximum strength of your pet, making it more powerful.", + Icon = "πŸ’ͺ", + Name = "Strength Training", + PointsCost = 1, + Type = 0 + }, + new + { + Id = 4, + Description = "Increases maximum charisma of your pet, making it more charming.", + Icon = "🎭", + Name = "Charisma Boost", + PointsCost = 1, + Type = 0 + }, + new + { + Id = 5, + Description = "Increases luck of your pet, making it more fortunate to find rare items.", + Icon = "πŸ€", + Name = "Luck of the Draw", + PointsCost = 1, + SkillsIdRequired = "[4]", + Type = 0 + }, + new + { + Id = 6, + Description = "Increases agility of your pet, making it faster in combat.", + Icon = "πŸƒ", + Name = "Agility Training", + PointsCost = 1, + SkillsIdRequired = "[3]", + Type = 0 + }, + new + { + Id = 7, + Description = "Increases perception of your pet, making it more aware of its surroundings.", + Icon = "πŸ‘€", + Name = "Perception Boost", + PointsCost = 1, + SkillsIdRequired = "[2]", + Type = 0 + }); + }); + + modelBuilder.Entity("PetCompanion.Models.SkillEffect", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Effect") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("SkillId") + .HasColumnType("INTEGER"); + + b.Property("Tier") + .HasColumnType("INTEGER"); + + b.Property("Value") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("SkillId"); + + b.ToTable("SkillEffects"); + + b.HasData( + new + { + Id = 1, + Effect = "MaxHealth", + SkillId = 1, + Tier = 1, + Value = 25m + }, + new + { + Id = 2, + Effect = "MaxHealth", + SkillId = 1, + Tier = 2, + Value = 50m + }, + new + { + Id = 3, + Effect = "MaxHealth", + SkillId = 1, + Tier = 3, + Value = 100m + }, + new + { + Id = 4, + Effect = "MaxIntelligence", + SkillId = 2, + Tier = 1, + Value = 5m + }, + new + { + Id = 5, + Effect = "MaxIntelligence", + SkillId = 2, + Tier = 2, + Value = 10m + }, + new + { + Id = 6, + Effect = "MaxIntelligence", + SkillId = 2, + Tier = 3, + Value = 20m + }, + new + { + Id = 7, + Effect = "MaxStrength", + SkillId = 3, + Tier = 1, + Value = 5m + }, + new + { + Id = 8, + Effect = "MaxStrength", + SkillId = 3, + Tier = 2, + Value = 10m + }, + new + { + Id = 9, + Effect = "MaxStrength", + SkillId = 3, + Tier = 3, + Value = 20m + }, + new + { + Id = 10, + Effect = "MaxCharisma", + SkillId = 4, + Tier = 1, + Value = 5m + }, + new + { + Id = 11, + Effect = "MaxCharisma", + SkillId = 4, + Tier = 2, + Value = 10m + }, + new + { + Id = 12, + Effect = "MaxCharisma", + SkillId = 4, + Tier = 3, + Value = 20m + }, + new + { + Id = 13, + Effect = "Luck", + SkillId = 5, + Tier = 1, + Value = 1m + }, + new + { + Id = 14, + Effect = "Luck", + SkillId = 5, + Tier = 2, + Value = 2m + }, + new + { + Id = 15, + Effect = "Luck", + SkillId = 5, + Tier = 3, + Value = 3m + }, + new + { + Id = 16, + Effect = "Agility", + SkillId = 6, + Tier = 1, + Value = 1m + }, + new + { + Id = 17, + Effect = "Agility", + SkillId = 6, + Tier = 2, + Value = 2m + }, + new + { + Id = 18, + Effect = "Agility", + SkillId = 6, + Tier = 3, + Value = 3m + }, + new + { + Id = 19, + Effect = "Perception", + SkillId = 7, + Tier = 1, + Value = 1m + }, + new + { + Id = 20, + Effect = "Perception", + SkillId = 7, + Tier = 2, + Value = 2m + }, + new + { + Id = 21, + Effect = "Perception", + SkillId = 7, + Tier = 3, + Value = 3m + }); + }); + + modelBuilder.Entity("PetCompanion.Models.EquippedItem", b => + { + b.HasOne("PetCompanion.Models.GameItem", "GameItem") + .WithMany() + .HasForeignKey("GameItemId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("PetCompanion.Models.Pet", "Pet") + .WithMany("EquippedItemsList") + .HasForeignKey("PetId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("GameItem"); + + b.Navigation("Pet"); + }); + + modelBuilder.Entity("PetCompanion.Models.Inventory", b => + { + b.HasOne("PetCompanion.Models.Pet", "Pet") + .WithOne("Inventory") + .HasForeignKey("PetCompanion.Models.Inventory", "PetId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Pet"); + }); + + modelBuilder.Entity("PetCompanion.Models.InventoryItem", b => + { + b.HasOne("PetCompanion.Models.GameItem", "GameItem") + .WithMany() + .HasForeignKey("GameItemId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("PetCompanion.Models.Inventory", null) + .WithMany("Items") + .HasForeignKey("InventoryId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("GameItem"); + }); + + modelBuilder.Entity("PetCompanion.Models.PetSkill", b => + { + b.HasOne("PetCompanion.Models.Pet", "Pet") + .WithMany("Skills") + .HasForeignKey("PetId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("PetCompanion.Models.Skill", "Skill") + .WithMany("PetSkills") + .HasForeignKey("SkillId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Pet"); + + b.Navigation("Skill"); + }); + + modelBuilder.Entity("PetCompanion.Models.PetStats", b => + { + b.HasOne("PetCompanion.Models.Pet", null) + .WithOne("Stats") + .HasForeignKey("PetCompanion.Models.PetStats", "PetId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("PetCompanion.Models.Resources", b => + { + b.HasOne("PetCompanion.Models.Pet", null) + .WithOne("Resources") + .HasForeignKey("PetCompanion.Models.Resources", "PetId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("PetCompanion.Models.SkillEffect", b => + { + b.HasOne("PetCompanion.Models.Skill", "Skill") + .WithMany("Effects") + .HasForeignKey("SkillId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Skill"); + }); + + modelBuilder.Entity("PetCompanion.Models.Inventory", b => + { + b.Navigation("Items"); + }); + + modelBuilder.Entity("PetCompanion.Models.Pet", b => + { + b.Navigation("EquippedItemsList"); + + b.Navigation("Inventory") + .IsRequired(); + + b.Navigation("Resources") + .IsRequired(); + + b.Navigation("Skills"); + + b.Navigation("Stats") + .IsRequired(); + }); + + modelBuilder.Entity("PetCompanion.Models.Skill", b => + { + b.Navigation("Effects"); + + b.Navigation("PetSkills"); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/Migrations/20250202234056_InitialCreate.cs b/Migrations/20250202234056_InitialCreate.cs new file mode 100644 index 0000000..b1a9838 --- /dev/null +++ b/Migrations/20250202234056_InitialCreate.cs @@ -0,0 +1,357 @@ +ο»Ώusing System; +using Microsoft.EntityFrameworkCore.Migrations; + +#nullable disable + +#pragma warning disable CA1814 // Prefer jagged arrays over multidimensional + +namespace PetCompanion.Migrations +{ + /// + public partial class InitialCreate : Migration + { + /// + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.CreateTable( + name: "GameItems", + columns: table => new + { + Id = table.Column(type: "INTEGER", nullable: false) + .Annotation("Sqlite:Autoincrement", true), + Name = table.Column(type: "TEXT", nullable: false), + Type = table.Column(type: "INTEGER", nullable: false), + Rarity = table.Column(type: "INTEGER", nullable: false), + Description = table.Column(type: "TEXT", nullable: false), + Price = table.Column(type: "INTEGER", nullable: false), + Effect = table.Column(type: "TEXT", nullable: false), + EquipTarget = table.Column(type: "INTEGER", nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_GameItems", x => x.Id); + }); + + migrationBuilder.CreateTable( + name: "Pets", + columns: table => new + { + Id = table.Column(type: "TEXT", nullable: false), + Name = table.Column(type: "TEXT", nullable: false), + Class = table.Column(type: "INTEGER", nullable: false), + Level = table.Column(type: "INTEGER", nullable: false), + Experience = table.Column(type: "INTEGER", nullable: false), + Health = table.Column(type: "INTEGER", nullable: false), + MaxHealth = table.Column(type: "INTEGER", nullable: false), + UserId = table.Column(type: "TEXT", nullable: false), + IsDead = table.Column(type: "INTEGER", nullable: false), + PetGatherAction = table.Column(type: "INTEGER", nullable: false), + GatherActionSince = table.Column(type: "TEXT", nullable: false), + PetBasicAction = table.Column(type: "INTEGER", nullable: false), + BasicActionCooldown = table.Column(type: "TEXT", nullable: false), + SkillPoints = table.Column(type: "INTEGER", nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_Pets", x => x.Id); + }); + + migrationBuilder.CreateTable( + name: "Skills", + columns: table => new + { + Id = table.Column(type: "INTEGER", nullable: false) + .Annotation("Sqlite:Autoincrement", true), + Name = table.Column(type: "TEXT", nullable: false), + Description = table.Column(type: "TEXT", nullable: false), + Type = table.Column(type: "INTEGER", nullable: false), + PointsCost = table.Column(type: "INTEGER", nullable: false), + Icon = table.Column(type: "TEXT", nullable: false), + SkillsIdRequired = table.Column(type: "TEXT", nullable: true) + }, + constraints: table => + { + table.PrimaryKey("PK_Skills", x => x.Id); + }); + + migrationBuilder.CreateTable( + name: "EquippedItems", + columns: table => new + { + Id = table.Column(type: "INTEGER", nullable: false) + .Annotation("Sqlite:Autoincrement", true), + PetId = table.Column(type: "TEXT", nullable: false), + EquipTarget = table.Column(type: "INTEGER", nullable: false), + GameItemId = table.Column(type: "INTEGER", nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_EquippedItems", x => x.Id); + table.ForeignKey( + name: "FK_EquippedItems_GameItems_GameItemId", + column: x => x.GameItemId, + principalTable: "GameItems", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + table.ForeignKey( + name: "FK_EquippedItems_Pets_PetId", + column: x => x.PetId, + principalTable: "Pets", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + }); + + migrationBuilder.CreateTable( + name: "Inventories", + columns: table => new + { + PetId = table.Column(type: "TEXT", nullable: false), + Capacity = table.Column(type: "INTEGER", nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_Inventories", x => x.PetId); + table.ForeignKey( + name: "FK_Inventories_Pets_PetId", + column: x => x.PetId, + principalTable: "Pets", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + }); + + migrationBuilder.CreateTable( + name: "PetStats", + columns: table => new + { + PetId = table.Column(type: "TEXT", nullable: false), + Intelligence = table.Column(type: "INTEGER", nullable: false), + Strength = table.Column(type: "INTEGER", nullable: false), + Charisma = table.Column(type: "INTEGER", nullable: false), + Luck = table.Column(type: "INTEGER", nullable: false), + Agility = table.Column(type: "INTEGER", nullable: false), + Perception = table.Column(type: "INTEGER", nullable: false), + MaxIntelligence = table.Column(type: "INTEGER", nullable: false), + MaxStrength = table.Column(type: "INTEGER", nullable: false), + MaxCharisma = table.Column(type: "INTEGER", nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_PetStats", x => x.PetId); + table.ForeignKey( + name: "FK_PetStats_Pets_PetId", + column: x => x.PetId, + principalTable: "Pets", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + }); + + migrationBuilder.CreateTable( + name: "Resources", + columns: table => new + { + PetId = table.Column(type: "TEXT", nullable: false), + Wisdom = table.Column(type: "INTEGER", nullable: false), + Gold = table.Column(type: "INTEGER", nullable: false), + Food = table.Column(type: "INTEGER", nullable: false), + Junk = table.Column(type: "INTEGER", nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_Resources", x => x.PetId); + table.ForeignKey( + name: "FK_Resources_Pets_PetId", + column: x => x.PetId, + principalTable: "Pets", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + }); + + migrationBuilder.CreateTable( + name: "PetSkills", + columns: table => new + { + Id = table.Column(type: "INTEGER", nullable: false) + .Annotation("Sqlite:Autoincrement", true), + PetId = table.Column(type: "TEXT", nullable: false), + SkillId = table.Column(type: "INTEGER", nullable: false), + CurrentTier = table.Column(type: "INTEGER", nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_PetSkills", x => x.Id); + table.ForeignKey( + name: "FK_PetSkills_Pets_PetId", + column: x => x.PetId, + principalTable: "Pets", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + table.ForeignKey( + name: "FK_PetSkills_Skills_SkillId", + column: x => x.SkillId, + principalTable: "Skills", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + }); + + migrationBuilder.CreateTable( + name: "SkillEffects", + columns: table => new + { + Id = table.Column(type: "INTEGER", nullable: false) + .Annotation("Sqlite:Autoincrement", true), + SkillId = table.Column(type: "INTEGER", nullable: false), + Tier = table.Column(type: "INTEGER", nullable: false), + Effect = table.Column(type: "TEXT", nullable: false), + Value = table.Column(type: "TEXT", nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_SkillEffects", x => x.Id); + table.ForeignKey( + name: "FK_SkillEffects_Skills_SkillId", + column: x => x.SkillId, + principalTable: "Skills", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + }); + + migrationBuilder.CreateTable( + name: "InventoryItems", + columns: table => new + { + Id = table.Column(type: "INTEGER", nullable: false) + .Annotation("Sqlite:Autoincrement", true), + InventoryId = table.Column(type: "TEXT", nullable: false), + GameItemId = table.Column(type: "INTEGER", nullable: false), + Quantity = table.Column(type: "INTEGER", nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_InventoryItems", x => x.Id); + table.ForeignKey( + name: "FK_InventoryItems_GameItems_GameItemId", + column: x => x.GameItemId, + principalTable: "GameItems", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + table.ForeignKey( + name: "FK_InventoryItems_Inventories_InventoryId", + column: x => x.InventoryId, + principalTable: "Inventories", + principalColumn: "PetId", + onDelete: ReferentialAction.Cascade); + }); + + migrationBuilder.InsertData( + table: "Skills", + columns: new[] { "Id", "Description", "Icon", "Name", "PointsCost", "SkillsIdRequired", "Type" }, + values: new object[,] + { + { 1, "Increases maximum health of your pet, making it more resilient.", "❀", "Vitality Mastery", 1, null, 0 }, + { 2, "Increases maximum intelligence of your pet, improving its learning capabilities.", "🧠", "Mind Enhancement", 1, null, 0 }, + { 3, "Increases maximum strength of your pet, making it more powerful.", "πŸ’ͺ", "Strength Training", 1, null, 0 }, + { 4, "Increases maximum charisma of your pet, making it more charming.", "🎭", "Charisma Boost", 1, null, 0 }, + { 5, "Increases luck of your pet, making it more fortunate to find rare items.", "πŸ€", "Luck of the Draw", 1, "[4]", 0 }, + { 6, "Increases agility of your pet, making it faster in combat.", "πŸƒ", "Agility Training", 1, "[3]", 0 }, + { 7, "Increases perception of your pet, making it more aware of its surroundings.", "πŸ‘€", "Perception Boost", 1, "[2]", 0 } + }); + + migrationBuilder.InsertData( + table: "SkillEffects", + columns: new[] { "Id", "Effect", "SkillId", "Tier", "Value" }, + values: new object[,] + { + { 1, "MaxHealth", 1, 1, 25m }, + { 2, "MaxHealth", 1, 2, 50m }, + { 3, "MaxHealth", 1, 3, 100m }, + { 4, "MaxIntelligence", 2, 1, 5m }, + { 5, "MaxIntelligence", 2, 2, 10m }, + { 6, "MaxIntelligence", 2, 3, 20m }, + { 7, "MaxStrength", 3, 1, 5m }, + { 8, "MaxStrength", 3, 2, 10m }, + { 9, "MaxStrength", 3, 3, 20m }, + { 10, "MaxCharisma", 4, 1, 5m }, + { 11, "MaxCharisma", 4, 2, 10m }, + { 12, "MaxCharisma", 4, 3, 20m }, + { 13, "Luck", 5, 1, 1m }, + { 14, "Luck", 5, 2, 2m }, + { 15, "Luck", 5, 3, 3m }, + { 16, "Agility", 6, 1, 1m }, + { 17, "Agility", 6, 2, 2m }, + { 18, "Agility", 6, 3, 3m }, + { 19, "Perception", 7, 1, 1m }, + { 20, "Perception", 7, 2, 2m }, + { 21, "Perception", 7, 3, 3m } + }); + + migrationBuilder.CreateIndex( + name: "IX_EquippedItems_GameItemId", + table: "EquippedItems", + column: "GameItemId"); + + migrationBuilder.CreateIndex( + name: "IX_EquippedItems_PetId", + table: "EquippedItems", + column: "PetId"); + + migrationBuilder.CreateIndex( + name: "IX_InventoryItems_GameItemId", + table: "InventoryItems", + column: "GameItemId"); + + migrationBuilder.CreateIndex( + name: "IX_InventoryItems_InventoryId", + table: "InventoryItems", + column: "InventoryId"); + + migrationBuilder.CreateIndex( + name: "IX_PetSkills_PetId", + table: "PetSkills", + column: "PetId"); + + migrationBuilder.CreateIndex( + name: "IX_PetSkills_SkillId", + table: "PetSkills", + column: "SkillId"); + + migrationBuilder.CreateIndex( + name: "IX_SkillEffects_SkillId", + table: "SkillEffects", + column: "SkillId"); + } + + /// + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropTable( + name: "EquippedItems"); + + migrationBuilder.DropTable( + name: "InventoryItems"); + + migrationBuilder.DropTable( + name: "PetSkills"); + + migrationBuilder.DropTable( + name: "PetStats"); + + migrationBuilder.DropTable( + name: "Resources"); + + migrationBuilder.DropTable( + name: "SkillEffects"); + + migrationBuilder.DropTable( + name: "GameItems"); + + migrationBuilder.DropTable( + name: "Inventories"); + + migrationBuilder.DropTable( + name: "Skills"); + + migrationBuilder.DropTable( + name: "Pets"); + } + } +} diff --git a/Migrations/ApplicationDbContextModelSnapshot.cs b/Migrations/ApplicationDbContextModelSnapshot.cs new file mode 100644 index 0000000..3d4af2e --- /dev/null +++ b/Migrations/ApplicationDbContextModelSnapshot.cs @@ -0,0 +1,674 @@ +ο»Ώ// +using System; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; +using PetCompanion.Data; + +#nullable disable + +namespace PetCompanion.Migrations +{ + [DbContext(typeof(ApplicationDbContext))] + partial class ApplicationDbContextModelSnapshot : ModelSnapshot + { + protected override void BuildModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder.HasAnnotation("ProductVersion", "9.0.1"); + + modelBuilder.Entity("PetCompanion.Models.EquippedItem", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("EquipTarget") + .HasColumnType("INTEGER"); + + b.Property("GameItemId") + .HasColumnType("INTEGER"); + + b.Property("PetId") + .IsRequired() + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("GameItemId"); + + b.HasIndex("PetId"); + + b.ToTable("EquippedItems"); + }); + + modelBuilder.Entity("PetCompanion.Models.GameItem", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Description") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("Effect") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("EquipTarget") + .HasColumnType("INTEGER"); + + b.Property("Name") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("Price") + .HasColumnType("INTEGER"); + + b.Property("Rarity") + .HasColumnType("INTEGER"); + + b.Property("Type") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.ToTable("GameItems"); + }); + + modelBuilder.Entity("PetCompanion.Models.Inventory", b => + { + b.Property("PetId") + .HasColumnType("TEXT"); + + b.Property("Capacity") + .HasColumnType("INTEGER"); + + b.HasKey("PetId"); + + b.ToTable("Inventories"); + }); + + modelBuilder.Entity("PetCompanion.Models.InventoryItem", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("GameItemId") + .HasColumnType("INTEGER"); + + b.Property("InventoryId") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("Quantity") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.HasIndex("GameItemId"); + + b.HasIndex("InventoryId"); + + b.ToTable("InventoryItems"); + }); + + modelBuilder.Entity("PetCompanion.Models.Pet", b => + { + b.Property("Id") + .HasColumnType("TEXT"); + + b.Property("BasicActionCooldown") + .HasColumnType("TEXT"); + + b.Property("Class") + .HasColumnType("INTEGER"); + + b.Property("Experience") + .HasColumnType("INTEGER"); + + b.Property("GatherActionSince") + .HasColumnType("TEXT"); + + b.Property("Health") + .HasColumnType("INTEGER"); + + b.Property("IsDead") + .HasColumnType("INTEGER"); + + b.Property("Level") + .HasColumnType("INTEGER"); + + b.Property("MaxHealth") + .HasColumnType("INTEGER"); + + b.Property("Name") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("PetBasicAction") + .HasColumnType("INTEGER"); + + b.Property("PetGatherAction") + .HasColumnType("INTEGER"); + + b.Property("SkillPoints") + .HasColumnType("INTEGER"); + + b.Property("UserId") + .IsRequired() + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.ToTable("Pets"); + }); + + modelBuilder.Entity("PetCompanion.Models.PetSkill", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("CurrentTier") + .HasColumnType("INTEGER"); + + b.Property("PetId") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("SkillId") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.HasIndex("PetId"); + + b.HasIndex("SkillId"); + + b.ToTable("PetSkills"); + }); + + modelBuilder.Entity("PetCompanion.Models.PetStats", b => + { + b.Property("PetId") + .HasColumnType("TEXT"); + + b.Property("Agility") + .HasColumnType("INTEGER"); + + b.Property("Charisma") + .HasColumnType("INTEGER"); + + b.Property("Intelligence") + .HasColumnType("INTEGER"); + + b.Property("Luck") + .HasColumnType("INTEGER"); + + b.Property("MaxCharisma") + .HasColumnType("INTEGER"); + + b.Property("MaxIntelligence") + .HasColumnType("INTEGER"); + + b.Property("MaxStrength") + .HasColumnType("INTEGER"); + + b.Property("Perception") + .HasColumnType("INTEGER"); + + b.Property("Strength") + .HasColumnType("INTEGER"); + + b.HasKey("PetId"); + + b.ToTable("PetStats"); + }); + + modelBuilder.Entity("PetCompanion.Models.Resources", b => + { + b.Property("PetId") + .HasColumnType("TEXT"); + + b.Property("Food") + .HasColumnType("INTEGER"); + + b.Property("Gold") + .HasColumnType("INTEGER"); + + b.Property("Junk") + .HasColumnType("INTEGER"); + + b.Property("Wisdom") + .HasColumnType("INTEGER"); + + b.HasKey("PetId"); + + b.ToTable("Resources"); + }); + + modelBuilder.Entity("PetCompanion.Models.Skill", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Description") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("Icon") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("Name") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("PointsCost") + .HasColumnType("INTEGER"); + + b.PrimitiveCollection("SkillsIdRequired") + .HasColumnType("TEXT"); + + b.Property("Type") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.ToTable("Skills"); + + b.HasData( + new + { + Id = 1, + Description = "Increases maximum health of your pet, making it more resilient.", + Icon = "❀", + Name = "Vitality Mastery", + PointsCost = 1, + Type = 0 + }, + new + { + Id = 2, + Description = "Increases maximum intelligence of your pet, improving its learning capabilities.", + Icon = "🧠", + Name = "Mind Enhancement", + PointsCost = 1, + Type = 0 + }, + new + { + Id = 3, + Description = "Increases maximum strength of your pet, making it more powerful.", + Icon = "πŸ’ͺ", + Name = "Strength Training", + PointsCost = 1, + Type = 0 + }, + new + { + Id = 4, + Description = "Increases maximum charisma of your pet, making it more charming.", + Icon = "🎭", + Name = "Charisma Boost", + PointsCost = 1, + Type = 0 + }, + new + { + Id = 5, + Description = "Increases luck of your pet, making it more fortunate to find rare items.", + Icon = "πŸ€", + Name = "Luck of the Draw", + PointsCost = 1, + SkillsIdRequired = "[4]", + Type = 0 + }, + new + { + Id = 6, + Description = "Increases agility of your pet, making it faster in combat.", + Icon = "πŸƒ", + Name = "Agility Training", + PointsCost = 1, + SkillsIdRequired = "[3]", + Type = 0 + }, + new + { + Id = 7, + Description = "Increases perception of your pet, making it more aware of its surroundings.", + Icon = "πŸ‘€", + Name = "Perception Boost", + PointsCost = 1, + SkillsIdRequired = "[2]", + Type = 0 + }); + }); + + modelBuilder.Entity("PetCompanion.Models.SkillEffect", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Effect") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("SkillId") + .HasColumnType("INTEGER"); + + b.Property("Tier") + .HasColumnType("INTEGER"); + + b.Property("Value") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("SkillId"); + + b.ToTable("SkillEffects"); + + b.HasData( + new + { + Id = 1, + Effect = "MaxHealth", + SkillId = 1, + Tier = 1, + Value = 25m + }, + new + { + Id = 2, + Effect = "MaxHealth", + SkillId = 1, + Tier = 2, + Value = 50m + }, + new + { + Id = 3, + Effect = "MaxHealth", + SkillId = 1, + Tier = 3, + Value = 100m + }, + new + { + Id = 4, + Effect = "MaxIntelligence", + SkillId = 2, + Tier = 1, + Value = 5m + }, + new + { + Id = 5, + Effect = "MaxIntelligence", + SkillId = 2, + Tier = 2, + Value = 10m + }, + new + { + Id = 6, + Effect = "MaxIntelligence", + SkillId = 2, + Tier = 3, + Value = 20m + }, + new + { + Id = 7, + Effect = "MaxStrength", + SkillId = 3, + Tier = 1, + Value = 5m + }, + new + { + Id = 8, + Effect = "MaxStrength", + SkillId = 3, + Tier = 2, + Value = 10m + }, + new + { + Id = 9, + Effect = "MaxStrength", + SkillId = 3, + Tier = 3, + Value = 20m + }, + new + { + Id = 10, + Effect = "MaxCharisma", + SkillId = 4, + Tier = 1, + Value = 5m + }, + new + { + Id = 11, + Effect = "MaxCharisma", + SkillId = 4, + Tier = 2, + Value = 10m + }, + new + { + Id = 12, + Effect = "MaxCharisma", + SkillId = 4, + Tier = 3, + Value = 20m + }, + new + { + Id = 13, + Effect = "Luck", + SkillId = 5, + Tier = 1, + Value = 1m + }, + new + { + Id = 14, + Effect = "Luck", + SkillId = 5, + Tier = 2, + Value = 2m + }, + new + { + Id = 15, + Effect = "Luck", + SkillId = 5, + Tier = 3, + Value = 3m + }, + new + { + Id = 16, + Effect = "Agility", + SkillId = 6, + Tier = 1, + Value = 1m + }, + new + { + Id = 17, + Effect = "Agility", + SkillId = 6, + Tier = 2, + Value = 2m + }, + new + { + Id = 18, + Effect = "Agility", + SkillId = 6, + Tier = 3, + Value = 3m + }, + new + { + Id = 19, + Effect = "Perception", + SkillId = 7, + Tier = 1, + Value = 1m + }, + new + { + Id = 20, + Effect = "Perception", + SkillId = 7, + Tier = 2, + Value = 2m + }, + new + { + Id = 21, + Effect = "Perception", + SkillId = 7, + Tier = 3, + Value = 3m + }); + }); + + modelBuilder.Entity("PetCompanion.Models.EquippedItem", b => + { + b.HasOne("PetCompanion.Models.GameItem", "GameItem") + .WithMany() + .HasForeignKey("GameItemId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("PetCompanion.Models.Pet", "Pet") + .WithMany("EquippedItemsList") + .HasForeignKey("PetId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("GameItem"); + + b.Navigation("Pet"); + }); + + modelBuilder.Entity("PetCompanion.Models.Inventory", b => + { + b.HasOne("PetCompanion.Models.Pet", "Pet") + .WithOne("Inventory") + .HasForeignKey("PetCompanion.Models.Inventory", "PetId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Pet"); + }); + + modelBuilder.Entity("PetCompanion.Models.InventoryItem", b => + { + b.HasOne("PetCompanion.Models.GameItem", "GameItem") + .WithMany() + .HasForeignKey("GameItemId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("PetCompanion.Models.Inventory", null) + .WithMany("Items") + .HasForeignKey("InventoryId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("GameItem"); + }); + + modelBuilder.Entity("PetCompanion.Models.PetSkill", b => + { + b.HasOne("PetCompanion.Models.Pet", "Pet") + .WithMany("Skills") + .HasForeignKey("PetId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("PetCompanion.Models.Skill", "Skill") + .WithMany("PetSkills") + .HasForeignKey("SkillId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Pet"); + + b.Navigation("Skill"); + }); + + modelBuilder.Entity("PetCompanion.Models.PetStats", b => + { + b.HasOne("PetCompanion.Models.Pet", null) + .WithOne("Stats") + .HasForeignKey("PetCompanion.Models.PetStats", "PetId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("PetCompanion.Models.Resources", b => + { + b.HasOne("PetCompanion.Models.Pet", null) + .WithOne("Resources") + .HasForeignKey("PetCompanion.Models.Resources", "PetId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("PetCompanion.Models.SkillEffect", b => + { + b.HasOne("PetCompanion.Models.Skill", "Skill") + .WithMany("Effects") + .HasForeignKey("SkillId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Skill"); + }); + + modelBuilder.Entity("PetCompanion.Models.Inventory", b => + { + b.Navigation("Items"); + }); + + modelBuilder.Entity("PetCompanion.Models.Pet", b => + { + b.Navigation("EquippedItemsList"); + + b.Navigation("Inventory") + .IsRequired(); + + b.Navigation("Resources") + .IsRequired(); + + b.Navigation("Skills"); + + b.Navigation("Stats") + .IsRequired(); + }); + + modelBuilder.Entity("PetCompanion.Models.Skill", b => + { + b.Navigation("Effects"); + + b.Navigation("PetSkills"); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/Models/EquippedItem.cs b/Models/EquippedItem.cs new file mode 100644 index 0000000..7557f11 --- /dev/null +++ b/Models/EquippedItem.cs @@ -0,0 +1,20 @@ +using System.ComponentModel.DataAnnotations; +using System.ComponentModel.DataAnnotations.Schema; + +namespace PetCompanion.Models +{ + public class EquippedItem + { + [Key] + public int Id { get; set; } + + public string PetId { get; set; } + [ForeignKey("PetId")] + public virtual Pet Pet { get; set; } + + public ItemEquipTarget EquipTarget { get; set; } + public int GameItemId { get; set; } + [ForeignKey("GameItemId")] + public virtual GameItem GameItem { get; set; } + } +} diff --git a/Models/GameItem.cs b/Models/GameItem.cs new file mode 100644 index 0000000..8bed33c --- /dev/null +++ b/Models/GameItem.cs @@ -0,0 +1,41 @@ +using System.ComponentModel.DataAnnotations; + +namespace PetCompanion.Models +{ + public class GameItem + { + [Key] + public int Id { get; set; } + public string Name { get; set; } + public ItemType Type { get; set; } + public ItemRarity Rarity { get; set; } + public string Description { get; set; } + public int Price { get; set; } + public string Effect { get; set; } + public ItemEquipTarget EquipTarget { get; set; } + } + + public enum ItemType + { + Material, + Consumable, + Equipment + } + + public enum ItemRarity + { + Common, + Uncommon, + Rare, + Legendary + } + + public enum ItemEquipTarget + { + None, + Head, + Body, + Legs, + Weapon + } +} diff --git a/Models/Inventory.cs b/Models/Inventory.cs new file mode 100644 index 0000000..6d6b7b9 --- /dev/null +++ b/Models/Inventory.cs @@ -0,0 +1,26 @@ +using System.ComponentModel.DataAnnotations; +using System.ComponentModel.DataAnnotations.Schema; +using System.Text.Json.Serialization; + +namespace PetCompanion.Models +{ + public class Inventory + { + [Key, ForeignKey("Pet")] + public string PetId { get; set; } + [JsonIgnore] + public virtual Pet Pet { get; set; } + public virtual ICollection Items { get; set; } = new List(); + public int Capacity { get; set; } = 20; + } + + public class InventoryItem + { + [Key] + public int Id { get; set; } + public string InventoryId { get; set; } + public int GameItemId { get; set; } + public virtual GameItem GameItem { get; set; } + public int Quantity { get; set; } + } +} diff --git a/Models/Pet.cs b/Models/Pet.cs index 14430b3..1759118 100644 --- a/Models/Pet.cs +++ b/Models/Pet.cs @@ -1,5 +1,5 @@ ο»Ώusing System.ComponentModel.DataAnnotations; -using PetCompanion.Models.Enums; +using System.ComponentModel.DataAnnotations.Schema; namespace PetCompanion.Models { @@ -11,7 +11,6 @@ namespace PetCompanion.Models public PetClass Class { get; set; } public PetStats Stats { get; set; } public Resources Resources { get; set; } - public Inventory Inventory { get; set; } public int Level { get; set; } public int Experience { get; set; } public int Health { get; set; } @@ -25,19 +24,30 @@ namespace PetCompanion.Models public PetBasicAction PetBasicAction { get; set; } public DateTime BasicActionCooldown { get; set; } - public Dictionary Equipment { get; set; } = new(); - public int SkillPoints { get; set; } = 2; public virtual ICollection Skills { get; set; } = new List(); - public Pet() + public virtual Inventory Inventory { get; set; } + + [NotMapped] + public Dictionary EquippedItems { - foreach (EquipmentSlot slot in Enum.GetValues(typeof(EquipmentSlot))) + get => EquippedItemsList?.ToDictionary(e => e.EquipTarget, e => e.GameItemId) ?? new Dictionary(); + set { - Equipment[slot] = null; + EquippedItemsList = value.Select(kvp => new EquippedItem + { + PetId = Id, + EquipTarget = kvp.Key, + GameItemId = kvp.Value + }).ToList(); } } + public virtual ICollection EquippedItemsList { get; set; } = new List(); + + public Pet() { } + public void IncrementIntelligence(int amount) { var newValue = Stats.Intelligence + amount; diff --git a/Models/Skill.cs b/Models/Skill.cs index f7f79c4..f044927 100644 --- a/Models/Skill.cs +++ b/Models/Skill.cs @@ -1,4 +1,5 @@ using System.ComponentModel.DataAnnotations; +using System.Text.Json.Serialization; namespace PetCompanion.Models { @@ -26,6 +27,7 @@ namespace PetCompanion.Models public string Icon { get; set; } public List? SkillsIdRequired { get; set; } public virtual ICollection Effects { get; set; } + [JsonIgnore] public virtual ICollection PetSkills { get; set; } } @@ -34,6 +36,7 @@ namespace PetCompanion.Models [Key] public int Id { get; set; } public int SkillId { get; set; } + [JsonIgnore] public virtual Skill Skill { get; set; } public SkillTier Tier { get; set; } public string Effect { get; set; } @@ -74,6 +77,7 @@ namespace PetCompanion.Models [Key] public int Id { get; set; } public string PetId { get; set; } + [JsonIgnore] public virtual Pet Pet { get; set; } public int SkillId { get; set; } public virtual Skill Skill { get; set; } diff --git a/Program.cs b/Program.cs index 3d9b3e7..85b2cf7 100644 --- a/Program.cs +++ b/Program.cs @@ -24,13 +24,22 @@ namespace PetCompanion // Configure Entity Framework Core var connectionString = builder.Configuration.GetConnectionString("DefaultConnection"); builder.Services.AddDbContext(options => - options.UseSqlite(connectionString)); + { + options.UseSqlite(connectionString); + options.EnableSensitiveDataLogging(); + }); builder.Services.AddScoped(); builder.Services.AddScoped(); builder.Services.AddScoped(); + builder.Services.AddScoped(); + builder.Services.AddScoped(); builder.Services.AddScoped(); builder.Services.AddScoped(); + builder.Services.AddScoped(); + builder.Services.AddScoped(); + builder.Services.AddScoped(); + builder.Services.AddScoped(); // Add CORS policy builder.Services.AddCors(options => @@ -55,6 +64,13 @@ namespace PetCompanion app.UseHttpsRedirection(); app.UseAuthorization(); + // After app builder is created + using (var scope = app.Services.CreateScope()) + { + var itemService = scope.ServiceProvider.GetRequiredService(); + itemService.LoadItemsFromCsv("GameItemsData.csv"); + } + // Use CORS policy app.UseCors("AllowAll"); diff --git a/Repositories/GameItemsRepository.cs b/Repositories/GameItemsRepository.cs new file mode 100644 index 0000000..d727be7 --- /dev/null +++ b/Repositories/GameItemsRepository.cs @@ -0,0 +1,32 @@ +using PetCompanion.Data; +using PetCompanion.Models; + +namespace PetCompanion.Repositories +{ + public class GameItemsRepository + { + private readonly ApplicationDbContext _context; + + public GameItemsRepository(ApplicationDbContext context) + { + _context = context; + } + + public GameItem GetById(int id) + { + return _context.GameItems.Find(id); + } + + public void Add(GameItem item) + { + _context.GameItems.Add(item); + _context.SaveChanges(); + } + + public void Update(GameItem item) + { + _context.GameItems.Update(item); + _context.SaveChanges(); + } + } +} diff --git a/Repositories/PetInventoryRepository.cs b/Repositories/PetInventoryRepository.cs new file mode 100644 index 0000000..e8c089d --- /dev/null +++ b/Repositories/PetInventoryRepository.cs @@ -0,0 +1,67 @@ +using Microsoft.EntityFrameworkCore; +using PetCompanion.Data; +using PetCompanion.Models; + +namespace PetCompanion.Repositories +{ + public class PetInventoryRepository + { + private readonly ApplicationDbContext _context; + + public PetInventoryRepository(ApplicationDbContext context) + { + _context = context; + } + + public async Task GetPetInventory(string petId) + { + return await _context.Inventories + .Include(i => i.Items) + .ThenInclude(ii => ii.GameItem) + .FirstOrDefaultAsync(i => i.PetId == petId); + } + + public async Task> GetEquippedItems(string petId) + { + var equippedItems = await _context.EquippedItems + .Where(e => e.PetId == petId) + .ToDictionaryAsync(e => e.EquipTarget, e => e.GameItemId); + + return equippedItems; + } + + public async Task SaveInventory(Inventory inventory) + { + var existingInventory = await _context.Inventories + .Include(i => i.Items) + .FirstOrDefaultAsync(i => i.PetId == inventory.PetId); + + if (existingInventory == null) + { + _context.Inventories.Add(inventory); + } + else + { + // Clear existing items + _context.InventoryItems.RemoveRange(existingInventory.Items); + + // Update inventory properties + // existingInventory.Capacity = inventory.Capacity; + + // Add new items + foreach (var item in inventory.Items) + { + existingInventory.Items.Add(new InventoryItem + { + InventoryId = existingInventory.PetId, + GameItemId = item.GameItemId, + Quantity = item.Quantity, + GameItem = item.GameItem + }); + } + } + + await _context.SaveChangesAsync(); + } + } +} diff --git a/Repositories/PetSkillRepository.cs b/Repositories/PetSkillRepository.cs new file mode 100644 index 0000000..17fcd94 --- /dev/null +++ b/Repositories/PetSkillRepository.cs @@ -0,0 +1,39 @@ +using Microsoft.EntityFrameworkCore; +using PetCompanion.Data; +using PetCompanion.Models; + +namespace PetCompanion.Repositories +{ + public class PetSkillRepository + { + private readonly ApplicationDbContext _context; + + public PetSkillRepository(ApplicationDbContext context) + { + _context = context; + } + + public async Task> GetPetSkills(string petId) + { + return await _context.PetSkills + .Include(ps => ps.Skill) + .ThenInclude(s => s.Effects) + .Where(ps => ps.PetId == petId) + .ToListAsync(); + } + + public async Task SavePetSkill(PetSkill petSkill) + { + if (petSkill.Id == 0) + { + _context.PetSkills.Add(petSkill); + } + else + { + _context.PetSkills.Update(petSkill); + } + await _context.SaveChangesAsync(); + return petSkill; + } + } +} diff --git a/Services/GameItemService.cs b/Services/GameItemService.cs new file mode 100644 index 0000000..c564d8f --- /dev/null +++ b/Services/GameItemService.cs @@ -0,0 +1,121 @@ +using CsvHelper; +using System.Globalization; +using PetCompanion.Models; +using PetCompanion.Repositories; + +namespace PetCompanion.Services +{ + public class GameItemService + { + private readonly GameItemsRepository gameItemsRepository; + + public GameItemService(GameItemsRepository gameItemsRepository) + { + this.gameItemsRepository = gameItemsRepository; + } + + public void LoadItemsFromCsv(string filePath) + { + using var reader = new StreamReader(filePath); + using var csv = new CsvReader(reader, CultureInfo.InvariantCulture); + + var items = csv.GetRecords().ToList(); + + foreach (var item in items) + { + var existingItem = gameItemsRepository.GetById(item.Id); + if (existingItem == null) + { + gameItemsRepository.Add(item); + } + else + { + //gameItemsRepository.Update(item); + } + } + } + + public void ApplyItemEffect(Pet pet, GameItem item) + { + var effects = item.Effect.Split(';'); + foreach (var effect in effects) + { + ApplySingleEffect(pet, effect.Trim()); + } + } + + public void RemoveItemEffect(Pet pet, GameItem item) + { + var effects = item.Effect.Split(';'); + foreach (var effect in effects) + { + RemoveSingleEffect(pet, effect.Trim()); + } + } + + private void ApplySingleEffect(Pet pet, string effect) + { + if (effect == "Nothing") return; + + var parts = effect.Split('_'); + var action = parts[0]; + var target = parts[1]; + var value = parts.Length > 2 ? int.Parse(parts[2]) : 0; + + switch ($"{action}_{target}") + { + case "ADD_FOOD_RESOURCES": + pet.Resources.Food += value; + break; + case "ADD_INTELLIGENCE": + pet.Stats.Intelligence += value; + break; + case "ADD_HEALTH": + pet.Health = Math.Min(pet.Health + value, pet.MaxHealth); + break; + case "ADD_MAX_HEALTH": + pet.MaxHealth += value; + break; + // Add more effect handlers as needed + } + } + + private void RemoveSingleEffect(Pet pet, string effect) + { + if (effect == "Nothing") return; + + var parts = effect.Split('_'); + var action = parts[0]; + var target = parts[1]; + var value = parts.Length > 2 ? int.Parse(parts[2]) : 0; + + switch ($"{action}_{target}") + { + case "ADD_MAX_HEALTH": + pet.MaxHealth -= value; + pet.Health = Math.Min(pet.Health, pet.MaxHealth); + break; + case "ADD_MAX_INTELLIGENCE": + pet.Stats.MaxIntelligence -= value; + pet.Stats.Intelligence = Math.Min(pet.Stats.Intelligence, pet.Stats.MaxIntelligence); + break; + case "ADD_MAX_STRENGTH": + pet.Stats.MaxStrength -= value; + pet.Stats.Strength = Math.Min(pet.Stats.Strength, pet.Stats.MaxStrength); + break; + case "ADD_MAX_CHARISMA": + pet.Stats.MaxCharisma -= value; + pet.Stats.Charisma = Math.Min(pet.Stats.Charisma, pet.Stats.MaxCharisma); + break; + case "ADD_MAX_ALL_STATS": + pet.Stats.MaxIntelligence -= value; + pet.Stats.MaxStrength -= value; + pet.Stats.MaxCharisma -= value; + pet.Stats.Intelligence = Math.Min(pet.Stats.Intelligence, pet.Stats.MaxIntelligence); + pet.Stats.Strength = Math.Min(pet.Stats.Strength, pet.Stats.MaxStrength); + pet.Stats.Charisma = Math.Min(pet.Stats.Charisma, pet.Stats.MaxCharisma); + break; + } + } + } +} diff --git a/Services/PetInventoryService.cs b/Services/PetInventoryService.cs new file mode 100644 index 0000000..b76edbd --- /dev/null +++ b/Services/PetInventoryService.cs @@ -0,0 +1,184 @@ +using PetCompanion.Models; +using PetCompanion.Repositories; + +namespace PetCompanion.Services +{ + public class PetInventoryService + { + private readonly PetInventoryRepository _inventoryRepository; + private readonly PetRepository _petRepository; + private readonly GameItemsRepository _gameItemsRepository; + + public PetInventoryService( + PetInventoryRepository inventoryRepository, + PetRepository petRepository, + GameItemsRepository gameItemsRepository) + { + _inventoryRepository = inventoryRepository; + _petRepository = petRepository; + _gameItemsRepository = gameItemsRepository; + } + + public async Task GetInventory(string petId, string userId) + { + var pet = _petRepository.GetPetById(petId, userId); + if (pet == null) + throw new Exception("Pet not found"); + + return await _inventoryRepository.GetPetInventory(petId); + } + + public async Task CreateInventory(string petId) + { + var inventory = new Inventory + { + PetId = petId, + Capacity = 20, + Items = new List() + }; + + await _inventoryRepository.SaveInventory(inventory); + return inventory; + } + + public async Task UseItem(string petId, string userId, int itemId) + { + var pet = _petRepository.GetPetById(petId, userId); + if (pet == null) + throw new Exception("Pet not found"); + + var inventory = await _inventoryRepository.GetPetInventory(petId); + var item = inventory.Items.FirstOrDefault(i => i.GameItemId == itemId); + + if (item == null || item.Quantity <= 0) + throw new Exception("Item not found in inventory"); + + item.Quantity--; + if (item.Quantity <= 0) + inventory.Items.Remove(item); + + await _inventoryRepository.SaveInventory(inventory); + return _petRepository.UpdatePet(pet); + } + + public async Task EquipItem(string petId, string userId, int itemId) + { + var pet = _petRepository.GetPetById(petId, userId); + if (pet == null) + throw new Exception("Pet not found"); + + var inventory = await _inventoryRepository.GetPetInventory(petId); + var item = inventory.Items.FirstOrDefault(i => i.GameItemId == itemId); + + if (item == null || item.Quantity <= 0) + throw new Exception("Item not found in inventory"); + + if (item.GameItem.Type != ItemType.Equipment) + throw new Exception("Item is not equipment"); + + var equippedItems = await _inventoryRepository.GetEquippedItems(petId); + if (equippedItems.ContainsKey(item.GameItem.EquipTarget)) + { + await UnequipItem(petId, userId, item.GameItem.EquipTarget); + } + + item.Quantity--; + if (item.Quantity <= 0) + inventory.Items.Remove(item); + + await _inventoryRepository.SaveInventory(inventory); + return _petRepository.UpdatePet(pet); + } + + public async Task UnequipItem(string petId, string userId, ItemEquipTarget equipTarget) + { + var pet = _petRepository.GetPetById(petId, userId); + if (pet == null) + throw new Exception("Pet not found"); + + var equippedItems = await _inventoryRepository.GetEquippedItems(petId); + if (!equippedItems.ContainsKey(equipTarget)) + return pet; + + var itemId = equippedItems[equipTarget]; + var item = _gameItemsRepository.GetById(itemId); + + if (item != null) + { + var inventory = await _inventoryRepository.GetPetInventory(petId); + var inventoryItem = inventory.Items.FirstOrDefault(i => i.GameItemId == itemId); + + if (inventoryItem != null) + inventoryItem.Quantity++; + else + inventory.Items.Add(new InventoryItem + { + GameItemId = itemId, + Quantity = 1, + GameItem = item, + InventoryId = pet.Id + }); + + await _inventoryRepository.SaveInventory(inventory); + } + + return _petRepository.UpdatePet(pet); + } + + public async Task DropItem(string petId, string userId, int itemId) + { + var pet = _petRepository.GetPetById(petId, userId); + if (pet == null) + throw new Exception("Pet not found"); + + var inventory = await _inventoryRepository.GetPetInventory(petId); + if (inventory == null) + throw new Exception("Inventory not found"); + + var item = inventory.Items.FirstOrDefault(i => i.GameItemId == itemId); + if (item == null || item.Quantity <= 0) + throw new Exception("Item not found in inventory"); + + item.Quantity--; + if (item.Quantity <= 0) + inventory.Items.Remove(item); + + await _inventoryRepository.SaveInventory(inventory); + return pet; + } + + public async Task AddItemToPet(string petId, string userId, int itemId, int quantity) + { + var pet = _petRepository.GetPetById(petId, userId); + if (pet == null) + throw new Exception("Pet not found"); + + var gameItem = _gameItemsRepository.GetById(itemId); + if (gameItem == null) + throw new Exception("Item not found"); + + var inventory = await _inventoryRepository.GetPetInventory(petId); + if (inventory == null) + throw new Exception("Inventory not found"); + + var existingItem = inventory.Items.FirstOrDefault(i => i.GameItemId == itemId); + if (existingItem != null) + { + existingItem.Quantity += quantity; + } + else + { + inventory.Items.Add(new InventoryItem + { + GameItemId = itemId, + Quantity = quantity, + GameItem = gameItem, + InventoryId = inventory.PetId + }); + } + + await _inventoryRepository.SaveInventory(inventory); + return pet; + } + } +} diff --git a/Services/PetService.cs b/Services/PetService.cs index 1af9bd1..6c86540 100644 --- a/Services/PetService.cs +++ b/Services/PetService.cs @@ -6,12 +6,23 @@ namespace PetCompanion.Services public class PetService { private readonly PetRepository petRepository; - private readonly PetClassService _petClassService; + private readonly PetClassService petClassService; + private readonly GameItemService gameItemService; + private readonly GameItemsRepository gameItemsRepository; + private readonly PetInventoryService petInventoryService; - public PetService(PetRepository petRepository, PetClassService petClassService) + public PetService( + PetRepository petRepository, + PetClassService petClassService, + GameItemService gameItemService, + GameItemsRepository gameItemsRepository, + PetInventoryService petInventoryService) { this.petRepository = petRepository; - _petClassService = petClassService; + this.petClassService = petClassService; + this.gameItemService = gameItemService; + this.gameItemsRepository = gameItemsRepository; + this.petInventoryService = petInventoryService; } public IEnumerable GetAllPets(Guid userId) @@ -39,7 +50,11 @@ namespace PetCompanion.Services IsDead = false }; - return petRepository.CreatePet(pet); + var createdPet = petRepository.CreatePet(pet); + + var inventory = petInventoryService.CreateInventory(petId).Result; + + return createdPet; } public Pet UpdatePetAction(string petId, string userId, PetUpdateActionRequest actionRequest) @@ -118,7 +133,7 @@ namespace PetCompanion.Services throw new Exception("Pet not found"); } - return _petClassService.CalculateGatheredResources(pet.Stats, pet.Level, pet.PetGatherAction, pet.GatherActionSince); + return petClassService.CalculateGatheredResources(pet.Stats, pet.Level, pet.PetGatherAction, pet.GatherActionSince); } public Pet UpdatePetResources(string petId, string userId) @@ -129,7 +144,7 @@ namespace PetCompanion.Services throw new Exception("Pet not found"); } - var gatheredResources = _petClassService.CalculateGatheredResources(pet.Stats, pet.Level, pet.PetGatherAction, pet.GatherActionSince); + var gatheredResources = petClassService.CalculateGatheredResources(pet.Stats, pet.Level, pet.PetGatherAction, pet.GatherActionSince); pet.Resources.Wisdom += gatheredResources.Wisdom; pet.Resources.Gold += gatheredResources.Gold; @@ -139,5 +154,147 @@ namespace PetCompanion.Services return petRepository.UpdatePetResources(pet); } + + public Pet UseItem(string petId, string userId, int itemId) + { + var pet = petRepository.GetPetById(petId, userId); + if (pet == null) + throw new Exception("Pet not found"); + + var inventoryItem = pet.Inventory.Items.FirstOrDefault(i => i.GameItemId == itemId); + if (inventoryItem == null || inventoryItem.Quantity <= 0) + throw new Exception("Item not found in inventory"); + + gameItemService.ApplyItemEffect(pet, inventoryItem.GameItem); + + inventoryItem.Quantity--; + if (inventoryItem.Quantity <= 0) + pet.Inventory.Items.Remove(inventoryItem); + + return petRepository.UpdatePet(pet); + } + + public Pet EquipItem(string petId, string userId, int itemId) + { + var pet = petRepository.GetPetById(petId, userId); + if (pet == null) + throw new Exception("Pet not found"); + + var inventoryItem = pet.Inventory.Items.FirstOrDefault(i => i.GameItemId == itemId); + if (inventoryItem == null || inventoryItem.Quantity <= 0) + throw new Exception("Item not found in inventory"); + + if (inventoryItem.GameItem.Type != ItemType.Equipment) + throw new Exception("Item is not equipment"); + + // If there's already an item equipped in that slot, unequip it first + if (pet.EquippedItems.ContainsKey(inventoryItem.GameItem.EquipTarget)) + { + UnequipItem(pet, inventoryItem.GameItem.EquipTarget); + } + + // Apply equipment effects + gameItemService.ApplyItemEffect(pet, inventoryItem.GameItem); + + // Mark item as equipped + pet.EquippedItems[inventoryItem.GameItem.EquipTarget] = itemId; + + // Remove from inventory + inventoryItem.Quantity--; + if (inventoryItem.Quantity <= 0) + pet.Inventory.Items.Remove(inventoryItem); + + return petRepository.UpdatePet(pet); + } + + public Pet UnequipItem(string petId, string userId, ItemEquipTarget equipTarget) + { + var pet = petRepository.GetPetById(petId, userId); + if (pet == null) + throw new Exception("Pet not found"); + + UnequipItem(pet, equipTarget); + return petRepository.UpdatePet(pet); + } + + private void UnequipItem(Pet pet, ItemEquipTarget equipTarget) + { + if (!pet.EquippedItems.ContainsKey(equipTarget)) + return; + + var equippedItemId = pet.EquippedItems[equipTarget]; + var equippedItem = gameItemsRepository.GetById(equippedItemId); + + if (equippedItem != null) + { + // Remove equipment effects + gameItemService.RemoveItemEffect(pet, equippedItem); + + // Add item back to inventory + var inventoryItem = pet.Inventory.Items.FirstOrDefault(i => i.GameItemId == equippedItemId); + if (inventoryItem != null) + inventoryItem.Quantity++; + else + pet.Inventory.Items.Add(new InventoryItem + { + GameItemId = equippedItemId, + Quantity = 1, + GameItem = equippedItem, + InventoryId = pet.Id + }); + } + + pet.EquippedItems.Remove(equipTarget); + } + + public Pet GetPet(string petId, string userId) + { + var pet = petRepository.GetPetById(petId, userId); + if (pet == null) + throw new Exception("Pet not found"); + return pet; + } + + public Pet DropItem(string petId, string userId, int itemId) + { + var pet = GetPet(petId, userId); + + var inventoryItem = pet.Inventory.Items.FirstOrDefault(i => i.GameItemId == itemId); + if (inventoryItem == null || inventoryItem.Quantity <= 0) + throw new Exception("Item not found in inventory"); + + inventoryItem.Quantity--; + if (inventoryItem.Quantity <= 0) + pet.Inventory.Items.Remove(inventoryItem); + + return petRepository.UpdatePet(pet); + } + + public Pet AddItemToPet(string petId, string userId, int itemId, int quantity) + { + var pet = GetPet(petId, userId); + var gameItem = gameItemsRepository.GetById(itemId); + + if (gameItem == null) + throw new Exception("Item not found"); + + var inventoryItem = pet.Inventory.Items.FirstOrDefault(i => i.GameItemId == itemId); + if (inventoryItem != null) + { + inventoryItem.Quantity += quantity; + } + else + { + pet.Inventory.Items.Add(new InventoryItem + { + GameItemId = itemId, + Quantity = quantity, + GameItem = gameItem, + InventoryId = pet.Id + }); + } + + return petRepository.UpdatePet(pet); + } } } diff --git a/Services/PetSkillService.cs b/Services/PetSkillService.cs new file mode 100644 index 0000000..842c5e0 --- /dev/null +++ b/Services/PetSkillService.cs @@ -0,0 +1,63 @@ +using PetCompanion.Models; +using PetCompanion.Repositories; + +namespace PetCompanion.Services +{ + public class PetSkillService + { + private readonly PetSkillRepository _petSkillRepository; + private readonly PetRepository _petRepository; + + public PetSkillService(PetSkillRepository petSkillRepository, PetRepository petRepository) + { + _petSkillRepository = petSkillRepository; + _petRepository = petRepository; + } + + public async Task> GetPetSkills(string petId, string userId) + { + var pet = _petRepository.GetPetById(petId, userId); + if (pet == null) + throw new Exception("Pet not found"); + + return await _petSkillRepository.GetPetSkills(petId); + } + + public async Task AllocateSkillPoint(string petId, string userId, int skillId) + { + var pet = _petRepository.GetPetById(petId, userId); + if (pet == null) + throw new Exception("Pet not found"); + + if (pet.SkillPoints <= 0) + throw new Exception("No skill points available"); + + var skills = await _petSkillRepository.GetPetSkills(petId); + var existingSkill = skills.FirstOrDefault(s => s.SkillId == skillId); + + if (existingSkill != null) + { + if (existingSkill.CurrentTier == SkillTier.III) + throw new Exception("Skill already at maximum tier"); + + existingSkill.CurrentTier++; + await _petSkillRepository.SavePetSkill(existingSkill); + } + else + { + existingSkill = new PetSkill + { + PetId = petId, + SkillId = skillId, + CurrentTier = SkillTier.I + }; + await _petSkillRepository.SavePetSkill(existingSkill); + } + + pet.SkillPoints--; + _petRepository.UpdatePet(pet); + + return existingSkill; + } + } +} diff --git a/Services/SkillService.cs b/Services/SkillService.cs index cc88eaa..96ea143 100644 --- a/Services/SkillService.cs +++ b/Services/SkillService.cs @@ -7,18 +7,23 @@ namespace PetCompanion.Services { public class SkillService { - private readonly ApplicationDbContext context; - private readonly PetRepository petRepository; + private readonly ApplicationDbContext _context; + private readonly PetRepository _petRepository; + private readonly PetSkillRepository _petSkillRepository; - public SkillService(ApplicationDbContext context, PetRepository petRepository) + public SkillService( + ApplicationDbContext context, + PetRepository petRepository, + PetSkillRepository petSkillRepository) { - this.context = context; - this.petRepository = petRepository; + _context = context; + _petRepository = petRepository; + _petSkillRepository = petSkillRepository; } public async Task AllocateSkillPoint(string petId, string userId, int skillId) { - var pet = await context.Pets + var pet = await _context.Pets .Include(p => p.Skills) .FirstOrDefaultAsync(p => p.Id == petId && p.UserId == userId); @@ -28,7 +33,7 @@ namespace PetCompanion.Services if (pet.SkillPoints <= 0) throw new Exception("No skill points available"); - var skill = await context.Skills + var skill = await _context.Skills .Include(s => s.Effects) .FirstOrDefaultAsync(s => s.Id == skillId); @@ -45,6 +50,8 @@ namespace PetCompanion.Services var effect = skill.Effects.FirstOrDefault(e => e.Tier == existingSkill.CurrentTier); if (effect != null) effect.PetSkillUpgrade(ref pet); + + await _petSkillRepository.SavePetSkill(existingSkill); } else { @@ -54,21 +61,22 @@ namespace PetCompanion.Services SkillId = skillId, CurrentTier = SkillTier.I }; - pet.Skills.Add(newSkill); + await _petSkillRepository.SavePetSkill(newSkill); + var effect = skill.Effects.FirstOrDefault(e => e.Tier == SkillTier.I); if (effect != null) effect.PetSkillUpgrade(ref pet); } pet.SkillPoints--; - await context.SaveChangesAsync(); + await _context.SaveChangesAsync(); - return pet.Skills.First(ps => ps.SkillId == skillId); + return (await _petSkillRepository.GetPetSkills(petId)).First(ps => ps.SkillId == skillId); } public async Task> GetAvailableSkills() { - return await context.Skills + return await _context.Skills .Include(s => s.Effects) .ToListAsync(); } diff --git a/pet-companion-api.csproj b/pet-companion-api.csproj index dee5e3c..da20927 100644 --- a/pet-companion-api.csproj +++ b/pet-companion-api.csproj @@ -11,6 +11,7 @@ + all