Compare commits

..

12 Commits

Author SHA1 Message Date
795ca383d6 Remove GameItemsData.csv and update item loading path in Program.cs 2025-02-16 12:27:27 -03:00
77f4ada5f1 Update CI workflow to target ARM64 platform and clean up Dockerfile 2025-02-16 10:30:59 -03:00
a044faa163 Remove Docker installation steps from CI workflow 2025-02-15 22:27:22 -03:00
1cf5f07c80 Add CI workflow for Docker build and deployment; update Dockerfile and adjust health reduction logic in PetActionService; modify database connection string in appsettings.json 2025-02-15 22:20:19 -03:00
b84599b370 Implement base controller for shared functionality; update existing controllers to inherit from BaseController and adjust user ID handling. Add JWT authentication support and modify item retrieval methods in GameDataController. 2025-02-15 21:57:59 -03:00
6d81ff1564 Add GameDataController for item icon retrieval; update GameItemsRepository and GameItemService for new action effects 2025-02-12 21:22:43 -03:00
215d4ecb72 Add action gathering functionality: implement ActionGathered model and repository, update Pet model and services, and enhance GameItemsRepository with item retrieval methods. 2025-02-09 21:22:52 -03:00
653cc451d2 Refactor skill allocation to upgrade; implement skill requirements and resource checks; remove experience from Pet model; update README for skill tree progress 2025-02-08 22:46:19 -03:00
f553196ca0 Refactor inventory unequip logic to use item ID instead of equip target; update README for inventory and skill tree progress 2025-02-05 20:37:12 -03:00
5289910270 inventory working :D 2025-02-05 19:38:25 -03:00
7a2c3d2f67 not working inventory :c 2025-02-04 17:47:18 -03:00
f234b5d84d Add skill management system: implement Skill and PetSkill models, create SkillController, and update ApplicationDbContext for skills 2025-02-02 15:30:48 -03:00
45 changed files with 3836 additions and 687 deletions

58
.gitea/workflows/main.yml Normal file
View File

@@ -0,0 +1,58 @@
name: Main Build & Deploy
on: workflow_dispatch
jobs:
build:
name: Build and Push Docker Image (amd64 and arm64)
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Set up Docker Buildx
id: buildx
uses: docker/setup-buildx-action@v2
with:
config-inline: |
[registry."git.ivanch.me"]
- name: Login to Docker Hub
uses: https://github.com/docker/login-action@v3.3.0
with:
registry: git.ivanch.me
username: ${{ secrets.DOCKER_USERNAME }}
password: ${{ secrets.DOCKER_ACCESS_TOKEN }}
- name: Build Docker image and push
id: docker_build
uses: https://github.com/docker/build-push-action@v6.12.0
with:
context: ./
file: ./Dockerfile
push: true
tags: git.ivanch.me/ivanch/pet-companion/pet-companion-api:latest
platforms: linux/arm64
- name: Image digest
run: echo ${{ steps.docker_build.outputs.digest }}
deploy_live:
name: Deploy Live
runs-on: ubuntu-latest
needs: build
steps:
- name: Recreate container
uses: https://github.com/appleboy/ssh-action@v1.2.0
with:
host: ${{ secrets.LIVE_HOST }}
username: ${{ secrets.LIVE_USERNAME }}
key: ${{ secrets.LIVE_KEY }}
port: ${{ secrets.LIVE_PORT }}
script: |
cd ${{ secrets.LIVE_PROJECT_DIR }}
docker compose down
docker compose rm
docker compose pull
docker compose up -d

4
.gitignore vendored
View File

@@ -6,4 +6,6 @@ appsettings.Development.json
*.db *.db
*.db-shm *.db-shm
*.db-wal *.db-wal
*.csproj.user *.csproj.user
game-data

View File

@@ -0,0 +1,13 @@
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
namespace PetCompanion.Controllers
{
[Authorize]
[ApiController]
[Route("api/v1/[controller]")]
public class BaseController : Controller
{
protected string userId => User.Claims.FirstOrDefault(c => c.Type == "user_id").Value;
}
}

View File

@@ -0,0 +1,46 @@
using Microsoft.AspNetCore.Mvc;
using PetCompanion.Repositories;
namespace PetCompanion.Controllers
{
public class GameDataController : BaseController
{
private readonly GameItemsRepository gameItemsRepository;
private readonly ILogger<InventoryController> logger;
public GameDataController(
ILogger<InventoryController> logger,
GameItemsRepository gameItemsRepository)
{
this.logger = logger;
this.gameItemsRepository = gameItemsRepository;
}
[HttpGet("item/{itemId}")]
public IActionResult GetItemInfo(int itemId)
{
try
{
return Ok(gameItemsRepository.GetById(itemId));
}
catch (Exception ex)
{
return BadRequest(ex.Message);
}
}
[HttpGet("item/{itemId}/icon")]
public IActionResult GetItemIcon(int itemId)
{
try
{
var iconBytes = gameItemsRepository.GetItemIcon(itemId);
return File(iconBytes, "image/png");
}
catch (Exception ex)
{
return BadRequest(ex.Message);
}
}
}
}

View File

@@ -0,0 +1,111 @@
using Microsoft.AspNetCore.Mvc;
using PetCompanion.Services;
namespace PetCompanion.Controllers
{
[ApiController]
[Route("api/v1/[controller]")]
public class InventoryController : BaseController
{
private readonly PetInventoryService inventoryService;
private readonly ILogger<InventoryController> logger;
public InventoryController(
ILogger<InventoryController> logger,
PetInventoryService inventoryService)
{
this.logger = logger;
this.inventoryService = inventoryService;
}
[HttpGet("{petId}")]
public IActionResult GetInventory(string petId)
{
try
{
var inventory = inventoryService.GetInventory(petId, userId.ToString());
return Ok(inventory);
}
catch (Exception ex)
{
return BadRequest(ex.Message);
}
}
[HttpPut("{petId}/{itemId}/use")]
public IActionResult UseItem(string petId, int itemId)
{
try
{
var updatedPet = 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}/{itemId}/unequip")]
public IActionResult UnequipItem(string petId, int itemId)
{
try
{
var updatedPet = inventoryService.UnequipItem(petId, userId.ToString(), itemId);
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;
}
}

View File

@@ -4,14 +4,11 @@ using PetCompanion.Services;
namespace PetCompanion.Controllers namespace PetCompanion.Controllers
{ {
[ApiController] public class PetController : BaseController
[Route("api/v1/[controller]")]
public class PetController : ControllerBase
{ {
private readonly PetService petService; private readonly PetService petService;
private readonly PetClassService petClassService; private readonly PetClassService petClassService;
private readonly ILogger<PetController> logger; private readonly ILogger<PetController> logger;
private Guid userId = Guid.Parse("f5f4b3b3-3b7b-4b7b-8b7b-7b7b7b7b7b7b");
public PetController( public PetController(
ILogger<PetController> logger, ILogger<PetController> logger,
@@ -69,7 +66,7 @@ namespace PetCompanion.Controllers
{ {
try try
{ {
var updatedPet = petService.UpdatePetResources(petId, userId.ToString()); var updatedPet = petService.CollectPetGathered(petId, userId.ToString());
return Ok(updatedPet); return Ok(updatedPet);
} }
catch (Exception ex) catch (Exception ex)

View File

@@ -0,0 +1,57 @@
using Microsoft.AspNetCore.Mvc;
using PetCompanion.Services;
namespace PetCompanion.Controllers
{
public class SkillController : BaseController
{
private readonly SkillService _skillService;
private readonly PetSkillService _petSkillService;
private readonly ILogger<SkillController> _logger;
public SkillController(
ILogger<SkillController> logger,
SkillService skillService,
PetSkillService petSkillService)
{
_logger = logger;
_skillService = skillService;
_petSkillService = petSkillService;
}
[HttpGet]
public IActionResult GetAvailableSkills()
{
var skills = _skillService.GetAvailableSkills();
return Ok(skills);
}
[HttpGet("{petId}/skills")]
public IActionResult GetPetSkills(string petId)
{
try
{
var skills = _petSkillService.GetPetSkills(petId, userId);
return Ok(skills);
}
catch (Exception ex)
{
return BadRequest(ex.Message);
}
}
[HttpPost("{petId}/allocate/{skillId}")]
public IActionResult UpgradeSkill(string petId, int skillId)
{
try
{
var result = _petSkillService.UpgradeSkill(petId, userId, skillId);
return Ok(result);
}
catch (Exception ex)
{
return BadRequest(ex.Message);
}
}
}
}

View File

@@ -12,6 +12,13 @@ namespace PetCompanion.Data
public DbSet<Pet> Pets { get; set; } public DbSet<Pet> Pets { get; set; }
public DbSet<PetStats> PetStats { get; set; } public DbSet<PetStats> PetStats { get; set; }
public DbSet<Resources> Resources { get; set; } public DbSet<Resources> Resources { get; set; }
public DbSet<Skill> Skills { get; set; }
public DbSet<SkillEffect> SkillEffects { get; set; }
public DbSet<PetSkill> PetSkills { get; set; }
public DbSet<GameItem> GameItems { get; set; }
public DbSet<Inventory> Inventories { get; set; }
public DbSet<EquippedItem> EquippedItems { get; set; }
public DbSet<ActionGathered> ActionGathered { get; set; }
protected override void OnModelCreating(ModelBuilder modelBuilder) protected override void OnModelCreating(ModelBuilder modelBuilder)
{ {
@@ -29,6 +36,56 @@ namespace PetCompanion.Data
.HasConversion( .HasConversion(
v => v != DateTime.MinValue ? v.ToUniversalTime() : v, v => v != DateTime.MinValue ? v.ToUniversalTime() : v,
v => v != DateTime.MinValue ? DateTime.SpecifyKind(v, DateTimeKind.Utc) : v); v => v != DateTime.MinValue ? DateTime.SpecifyKind(v, DateTimeKind.Utc) : v);
modelBuilder.Entity<PetSkill>()
.HasOne(ps => ps.Pet)
.WithMany(p => p.Skills)
.HasForeignKey(ps => ps.PetId);
modelBuilder.Entity<PetSkill>()
.HasOne(ps => ps.Skill)
.WithMany(s => s.PetSkills)
.HasForeignKey(ps => ps.SkillId);
modelBuilder.Entity<SkillEffect>()
.HasOne(se => se.Skill)
.WithMany(s => s.Effects)
.HasForeignKey(se => se.SkillId);
modelBuilder.Entity<SkillRequirement>()
.HasOne(se => se.Skill)
.WithMany(s => s.SkillRequirements)
.HasForeignKey(se => se.SkillId);
modelBuilder.Entity<EquippedItem>()
.HasOne(e => e.Pet)
.WithMany(p => p.EquippedItemsList)
.HasForeignKey(e => e.PetId);
modelBuilder.Entity<EquippedItem>()
.HasOne(e => e.GameItem)
.WithMany()
.HasForeignKey(e => e.GameItemId);
modelBuilder.Entity<ActionGathered>()
.HasOne(ag => ag.Pet)
.WithMany(p => p.ActionGathered)
.HasForeignKey(ag => ag.PetId)
.OnDelete(DeleteBehavior.Cascade);
modelBuilder.Entity<ActionGathered>()
.HasOne(ag => ag.GameItem)
.WithMany()
.HasForeignKey(ag => ag.ItemId);
// Seed initial data
var skills = SkillsData.GetInitialSkillsWithoutRelations();
var requirements = SkillsData.GetInitialSkillRequirements();
var effects = SkillsData.GetInitialSkillEffects();
modelBuilder.Entity<Skill>().HasData(skills);
modelBuilder.Entity<SkillRequirement>().HasData(requirements);
modelBuilder.Entity<SkillEffect>().HasData(effects);
} }
} }
} }

306
Data/SkillsData.cs Normal file
View File

@@ -0,0 +1,306 @@
using PetCompanion.Models;
namespace PetCompanion.Data
{
public static class SkillsData
{
public static IEnumerable<Skill> GetInitialSkillsWithoutRelations()
{
return new List<Skill>
{
new Skill
{
Id = 1,
Name = "Vitality Mastery",
Description = "Increases maximum health of your pet, making it more resilient.",
Type = SkillType.GROUND,
Icon = "❤",
SkillsIdRequired = null
},
new Skill
{
Id = 2,
Name = "Mind Enhancement",
Description = "Increases maximum intelligence of your pet, improving its learning capabilities.",
Type = SkillType.GROUND,
Icon = "🧠",
SkillsIdRequired = null
},
new Skill
{
Id = 3,
Name = "Strength Training",
Description = "Increases maximum strength of your pet, making it more powerful.",
Type = SkillType.GROUND,
Icon = "💪",
SkillsIdRequired = null
},
new Skill
{
Id = 4,
Name = "Charisma Boost",
Description = "Increases maximum charisma of your pet, making it more charming.",
Type = SkillType.GROUND,
Icon = "🎭",
SkillsIdRequired = null
},
new Skill
{
Id = 5,
Name = "Luck of the Draw",
Description = "Increases luck of your pet, making it more fortunate to find rare items.",
Type = SkillType.GROUND,
Icon = "🍀",
SkillsIdRequired = new List<int> { 4 }
},
new Skill
{
Id = 6,
Name = "Agility Training",
Description = "Increases agility of your pet, making it faster in combat.",
Type = SkillType.GROUND,
Icon = "🏃",
SkillsIdRequired = new List<int> { 3 }
},
new Skill
{
Id = 7,
Name = "Perception Boost",
Description = "Increases perception of your pet, making it more aware of its surroundings.",
Type = SkillType.GROUND,
Icon = "👀",
SkillsIdRequired = new List<int> { 2 }
},
new Skill
{
Id = 8,
Name = "Resourcefulness",
Description = "Increases the amount of resources gathered by your pet.",
Type = SkillType.GRAND,
Icon = "📦",
SkillsIdRequired = new List<int> { 5, 6, 7 }
}
};
}
public static IEnumerable<SkillRequirement> GetInitialSkillRequirements()
{
return new List<SkillRequirement>
{
new SkillRequirement { Id = 1, SkillId = 1, Resource = "Wisdom", Cost = 100 },
new SkillRequirement { Id = 2, SkillId = 1, Resource = "Food", Cost = 150 },
new SkillRequirement { Id = 3, SkillId = 2, Resource = "Wisdom", Cost = 150 },
new SkillRequirement { Id = 4, SkillId = 3, Resource = "Gold", Cost = 100 },
new SkillRequirement { Id = 5, SkillId = 3, Resource = "Food", Cost = 150 },
new SkillRequirement { Id = 6, SkillId = 4, Resource = "Wisdom", Cost = 200 },
new SkillRequirement { Id = 7, SkillId = 5, Resource = "Gold", Cost = 200 },
new SkillRequirement { Id = 8, SkillId = 6, Resource = "Gold", Cost = 200 },
new SkillRequirement { Id = 9, SkillId = 7, Resource = "Gold", Cost = 100 },
new SkillRequirement { Id = 10, SkillId = 7, Resource = "Junk", Cost = 100 },
new SkillRequirement { Id = 11, SkillId = 8, Resource = "Gold", Cost = 500 },
new SkillRequirement { Id = 12, SkillId = 8, Resource = "Junk", Cost = 500 },
new SkillRequirement { Id = 13, SkillId = 8, Resource = "Wisdom", Cost = 300 },
new SkillRequirement { Id = 14, SkillId = 8, Resource = "Food", Cost = 300 }
};
}
public static IEnumerable<SkillEffect> GetInitialSkillEffects()
{
return new List<SkillEffect>
{
new SkillEffect
{
Id = 1,
SkillId = 1,
Tier = SkillTier.I,
Effect = "MaxHealth",
Value = 25
},
new SkillEffect
{
Id = 2,
SkillId = 1,
Tier = SkillTier.II,
Effect = "MaxHealth",
Value = 50
},
new SkillEffect
{
Id = 3,
SkillId = 1,
Tier = SkillTier.III,
Effect = "MaxHealth",
Value = 100
},
new SkillEffect
{
Id = 4,
SkillId = 2,
Tier = SkillTier.I,
Effect = "MaxIntelligence",
Value = 5
},
new SkillEffect
{
Id = 5,
SkillId = 2,
Tier = SkillTier.II,
Effect = "MaxIntelligence",
Value = 10
},
new SkillEffect
{
Id = 6,
SkillId = 2,
Tier = SkillTier.III,
Effect = "MaxIntelligence",
Value = 20
},
new SkillEffect
{
Id = 7,
SkillId = 3,
Tier = SkillTier.I,
Effect = "MaxStrength",
Value = 5
},
new SkillEffect
{
Id = 8,
SkillId = 3,
Tier = SkillTier.II,
Effect = "MaxStrength",
Value = 10
},
new SkillEffect
{
Id = 9,
SkillId = 3,
Tier = SkillTier.III,
Effect = "MaxStrength",
Value = 20
},
new SkillEffect
{
Id = 10,
SkillId = 4,
Tier = SkillTier.I,
Effect = "MaxCharisma",
Value = 5
},
new SkillEffect
{
Id = 11,
SkillId = 4,
Tier = SkillTier.II,
Effect = "MaxCharisma",
Value = 10
},
new SkillEffect
{
Id = 12,
SkillId = 4,
Tier = SkillTier.III,
Effect = "MaxCharisma",
Value = 20
},
new SkillEffect
{
Id = 13,
SkillId = 5,
Tier = SkillTier.I,
Effect = "Luck",
Value = 1
},
new SkillEffect
{
Id = 14,
SkillId = 5,
Tier = SkillTier.II,
Effect = "Luck",
Value = 2
},
new SkillEffect
{
Id = 15,
SkillId = 5,
Tier = SkillTier.III,
Effect = "Luck",
Value = 3
},
new SkillEffect
{
Id = 16,
SkillId = 6,
Tier = SkillTier.I,
Effect = "Agility",
Value = 1
},
new SkillEffect
{
Id = 17,
SkillId = 6,
Tier = SkillTier.II,
Effect = "Agility",
Value = 2
},
new SkillEffect
{
Id = 18,
SkillId = 6,
Tier = SkillTier.III,
Effect = "Agility",
Value = 3
},
new SkillEffect
{
Id = 19,
SkillId = 7,
Tier = SkillTier.I,
Effect = "Perception",
Value = 1
},
new SkillEffect
{
Id = 20,
SkillId = 7,
Tier = SkillTier.II,
Effect = "Perception",
Value = 2
},
new SkillEffect
{
Id = 21,
SkillId = 7,
Tier = SkillTier.III,
Effect = "Perception",
Value = 3
},
new SkillEffect
{
Id = 22,
SkillId = 8,
Tier = SkillTier.I,
Effect = "Resourcefulness",
Value = 1
},
new SkillEffect
{
Id = 23,
SkillId = 8,
Tier = SkillTier.II,
Effect = "Resourcefulness",
Value = 2
},
new SkillEffect
{
Id = 24,
SkillId = 8,
Tier = SkillTier.III,
Effect = "Resourcefulness",
Value = 3
}
};
}
}
}

View File

@@ -1,13 +1,9 @@
# See https://aka.ms/customizecontainer to learn how to customize your debug container and how Visual Studio uses this Dockerfile to build your images for faster debugging.
# This stage is used when running from VS in fast mode (Default for Debug configuration)
FROM mcr.microsoft.com/dotnet/aspnet:8.0 AS base FROM mcr.microsoft.com/dotnet/aspnet:8.0 AS base
USER app USER app
WORKDIR /app WORKDIR /app
EXPOSE 8080 EXPOSE 8080
EXPOSE 8081 EXPOSE 8081
# This stage is used to build the service project # This stage is used to build the service project
FROM mcr.microsoft.com/dotnet/sdk:8.0 AS build FROM mcr.microsoft.com/dotnet/sdk:8.0 AS build
ARG BUILD_CONFIGURATION=Release ARG BUILD_CONFIGURATION=Release

View File

@@ -1,20 +0,0 @@
Item Name, Type, Rarity, Description
Basic Kibble,Consumable,Common,Adds +20 food resources
Superfood Smoothie,Consumable,Uncommon,Adds +30 food resources; Restores 5 Intelligence
Energy Drink,Consumable,Rare,Reduces Cooldown by 5 min
Golden Apple,Consumable,Legendary,Adds +20 Intelligence (Permanent); Adds +100 food resources
Healing Potion,Consumable,Uncommon,Adds +20 to Health; Adds +20 food resources
Charisma Cookie,Consumable,Rare,Adds +2 Charisma (Permanent)
XP Booster,Consumable,Rare,Award +10 XP
Sleeping Draught,Consumable,Common,Reduces Cooldown for resting by 10 min
Mystery Meat,Consumable,Uncommon,Randomly ±2 to one stat (Permanent)
Elixir of Vitality,Consumable,Legendary,Fully restores all stats and health; Adds +1 Level
Leather Hat,Equipment,Common,Helmet: +5 Max Health
Wizard Hat,Equipment,Rare,Helmet: +15 Max Intelligence
Knight's Armor,Equipment,Rare,Chest: +15 Max Strength
Golden Boots,Equipment,Uncommon,Legging: +10 Max Charisma
Laser Pointer,Equipment,Common,Weapon: +5 Max Strength
Celestial Crown,Equipment,Legendary,Helmet: +20 max to all stats
Dragon Scale Shield,Equipment,Legendary,Weapon: +50 Max Health
Feathers,Material,Common, Crafting material (coming soon)
Phoenix Feather,Material,Legendary, Crafting material (coming soon)
1 Item Name Type Rarity Description
2 Basic Kibble Consumable Common Adds +20 food resources
3 Superfood Smoothie Consumable Uncommon Adds +30 food resources; Restores 5 Intelligence
4 Energy Drink Consumable Rare Reduces Cooldown by 5 min
5 Golden Apple Consumable Legendary Adds +20 Intelligence (Permanent); Adds +100 food resources
6 Healing Potion Consumable Uncommon Adds +20 to Health; Adds +20 food resources
7 Charisma Cookie Consumable Rare Adds +2 Charisma (Permanent)
8 XP Booster Consumable Rare Award +10 XP
9 Sleeping Draught Consumable Common Reduces Cooldown for resting by 10 min
10 Mystery Meat Consumable Uncommon Randomly ±2 to one stat (Permanent)
11 Elixir of Vitality Consumable Legendary Fully restores all stats and health; Adds +1 Level
12 Leather Hat Equipment Common Helmet: +5 Max Health
13 Wizard Hat Equipment Rare Helmet: +15 Max Intelligence
14 Knight's Armor Equipment Rare Chest: +15 Max Strength
15 Golden Boots Equipment Uncommon Legging: +10 Max Charisma
16 Laser Pointer Equipment Common Weapon: +5 Max Strength
17 Celestial Crown Equipment Legendary Helmet: +20 max to all stats
18 Dragon Scale Shield Equipment Legendary Weapon: +50 Max Health
19 Feathers Material Common Crafting material (coming soon)
20 Phoenix Feather Material Legendary Crafting material (coming soon)

View File

@@ -1,141 +0,0 @@
// <auto-generated />
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("20250201173643_Initial")]
partial class Initial
{
/// <inheritdoc />
protected override void BuildTargetModel(ModelBuilder modelBuilder)
{
#pragma warning disable 612, 618
modelBuilder.HasAnnotation("ProductVersion", "9.0.1");
modelBuilder.Entity("PetCompanion.Models.Pet", b =>
{
b.Property<string>("Id")
.HasColumnType("TEXT");
b.Property<DateTime>("BasicActionCooldown")
.HasColumnType("TEXT");
b.Property<int>("Class")
.HasColumnType("INTEGER");
b.Property<DateTime>("GatherActionSince")
.HasColumnType("TEXT");
b.Property<bool>("IsDead")
.HasColumnType("INTEGER");
b.Property<int>("Level")
.HasColumnType("INTEGER");
b.Property<string>("Name")
.IsRequired()
.HasColumnType("TEXT");
b.Property<int>("PetBasicAction")
.HasColumnType("INTEGER");
b.Property<int>("PetGatherAction")
.HasColumnType("INTEGER");
b.Property<string>("UserId")
.IsRequired()
.HasColumnType("TEXT");
b.HasKey("Id");
b.ToTable("Pets");
});
modelBuilder.Entity("PetCompanion.Models.PetStats", b =>
{
b.Property<string>("PetId")
.HasColumnType("TEXT");
b.Property<int>("Charisma")
.HasColumnType("INTEGER");
b.Property<int>("Intelligence")
.HasColumnType("INTEGER");
b.Property<int>("MaxCharisma")
.HasColumnType("INTEGER");
b.Property<int>("MaxIntelligence")
.HasColumnType("INTEGER");
b.Property<int>("MaxStrength")
.HasColumnType("INTEGER");
b.Property<int>("Strength")
.HasColumnType("INTEGER");
b.HasKey("PetId");
b.ToTable("PetStats");
});
modelBuilder.Entity("PetCompanion.Models.Resources", b =>
{
b.Property<string>("PetId")
.HasColumnType("TEXT");
b.Property<int>("Food")
.HasColumnType("INTEGER");
b.Property<int>("Gold")
.HasColumnType("INTEGER");
b.Property<int>("Junk")
.HasColumnType("INTEGER");
b.Property<int>("Wisdom")
.HasColumnType("INTEGER");
b.HasKey("PetId");
b.ToTable("Resources");
});
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.Pet", b =>
{
b.Navigation("Resources")
.IsRequired();
b.Navigation("Stats")
.IsRequired();
});
#pragma warning restore 612, 618
}
}
}

View File

@@ -1,92 +0,0 @@
using System;
using Microsoft.EntityFrameworkCore.Migrations;
#nullable disable
namespace PetCompanion.Migrations
{
/// <inheritdoc />
public partial class Initial : Migration
{
/// <inheritdoc />
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.CreateTable(
name: "Pets",
columns: table => new
{
Id = table.Column<string>(type: "TEXT", nullable: false),
Name = table.Column<string>(type: "TEXT", nullable: false),
Class = table.Column<int>(type: "INTEGER", nullable: false),
Level = table.Column<int>(type: "INTEGER", nullable: false),
UserId = table.Column<string>(type: "TEXT", nullable: false),
IsDead = table.Column<bool>(type: "INTEGER", nullable: false),
PetGatherAction = table.Column<int>(type: "INTEGER", nullable: false),
GatherActionSince = table.Column<DateTime>(type: "TEXT", nullable: false),
PetBasicAction = table.Column<int>(type: "INTEGER", nullable: false),
BasicActionCooldown = table.Column<DateTime>(type: "TEXT", nullable: false)
},
constraints: table =>
{
table.PrimaryKey("PK_Pets", x => x.Id);
});
migrationBuilder.CreateTable(
name: "PetStats",
columns: table => new
{
PetId = table.Column<string>(type: "TEXT", nullable: false),
Intelligence = table.Column<int>(type: "INTEGER", nullable: false),
Strength = table.Column<int>(type: "INTEGER", nullable: false),
Charisma = table.Column<int>(type: "INTEGER", nullable: false),
MaxIntelligence = table.Column<int>(type: "INTEGER", nullable: false),
MaxStrength = table.Column<int>(type: "INTEGER", nullable: false),
MaxCharisma = table.Column<int>(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<string>(type: "TEXT", nullable: false),
Wisdom = table.Column<int>(type: "INTEGER", nullable: false),
Gold = table.Column<int>(type: "INTEGER", nullable: false),
Food = table.Column<int>(type: "INTEGER", nullable: false),
Junk = table.Column<int>(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);
});
}
/// <inheritdoc />
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropTable(
name: "PetStats");
migrationBuilder.DropTable(
name: "Resources");
migrationBuilder.DropTable(
name: "Pets");
}
}
}

View File

@@ -0,0 +1,834 @@
// <auto-generated />
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("20250209234852_InitialCreate")]
partial class InitialCreate
{
/// <inheritdoc />
protected override void BuildTargetModel(ModelBuilder modelBuilder)
{
#pragma warning disable 612, 618
modelBuilder.HasAnnotation("ProductVersion", "9.0.1");
modelBuilder.Entity("PetCompanion.Models.ActionGathered", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("INTEGER");
b.Property<int>("Amount")
.HasColumnType("INTEGER");
b.Property<int?>("ItemId")
.HasColumnType("INTEGER");
b.Property<string>("PetId")
.IsRequired()
.HasColumnType("TEXT");
b.Property<string>("Resource")
.HasColumnType("TEXT");
b.HasKey("Id");
b.HasIndex("ItemId");
b.HasIndex("PetId");
b.ToTable("ActionGathered");
});
modelBuilder.Entity("PetCompanion.Models.EquippedItem", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("INTEGER");
b.Property<int>("EquipTarget")
.HasColumnType("INTEGER");
b.Property<int>("GameItemId")
.HasColumnType("INTEGER");
b.Property<string>("PetId")
.IsRequired()
.HasColumnType("TEXT");
b.HasKey("Id");
b.HasIndex("GameItemId");
b.HasIndex("PetId");
b.ToTable("EquippedItems");
});
modelBuilder.Entity("PetCompanion.Models.GameItem", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("INTEGER");
b.Property<string>("Description")
.IsRequired()
.HasColumnType("TEXT");
b.Property<string>("Effect")
.IsRequired()
.HasColumnType("TEXT");
b.Property<int>("EquipTarget")
.HasColumnType("INTEGER");
b.Property<string>("Name")
.IsRequired()
.HasColumnType("TEXT");
b.Property<int>("Price")
.HasColumnType("INTEGER");
b.Property<int>("Rarity")
.HasColumnType("INTEGER");
b.Property<int>("Type")
.HasColumnType("INTEGER");
b.HasKey("Id");
b.ToTable("GameItems");
});
modelBuilder.Entity("PetCompanion.Models.Inventory", b =>
{
b.Property<string>("PetId")
.HasColumnType("TEXT");
b.Property<int>("Capacity")
.HasColumnType("INTEGER");
b.PrimitiveCollection<string>("Items")
.IsRequired()
.HasColumnType("TEXT");
b.HasKey("PetId");
b.ToTable("Inventories");
});
modelBuilder.Entity("PetCompanion.Models.Pet", b =>
{
b.Property<string>("Id")
.HasColumnType("TEXT");
b.Property<DateTime>("BasicActionCooldown")
.HasColumnType("TEXT");
b.Property<int>("Class")
.HasColumnType("INTEGER");
b.Property<DateTime>("GatherActionSince")
.HasColumnType("TEXT");
b.Property<int>("Health")
.HasColumnType("INTEGER");
b.Property<bool>("IsDead")
.HasColumnType("INTEGER");
b.Property<int>("Level")
.HasColumnType("INTEGER");
b.Property<int>("MaxHealth")
.HasColumnType("INTEGER");
b.Property<string>("Name")
.IsRequired()
.HasColumnType("TEXT");
b.Property<int>("PetBasicAction")
.HasColumnType("INTEGER");
b.Property<int>("PetGatherAction")
.HasColumnType("INTEGER");
b.Property<string>("UserId")
.IsRequired()
.HasColumnType("TEXT");
b.HasKey("Id");
b.ToTable("Pets");
});
modelBuilder.Entity("PetCompanion.Models.PetSkill", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("INTEGER");
b.Property<int>("CurrentTier")
.HasColumnType("INTEGER");
b.Property<string>("PetId")
.IsRequired()
.HasColumnType("TEXT");
b.Property<int>("SkillId")
.HasColumnType("INTEGER");
b.HasKey("Id");
b.HasIndex("PetId");
b.HasIndex("SkillId");
b.ToTable("PetSkills");
});
modelBuilder.Entity("PetCompanion.Models.PetStats", b =>
{
b.Property<string>("PetId")
.HasColumnType("TEXT");
b.Property<int>("Agility")
.HasColumnType("INTEGER");
b.Property<int>("Charisma")
.HasColumnType("INTEGER");
b.Property<int>("Intelligence")
.HasColumnType("INTEGER");
b.Property<int>("Luck")
.HasColumnType("INTEGER");
b.Property<int>("MaxCharisma")
.HasColumnType("INTEGER");
b.Property<int>("MaxIntelligence")
.HasColumnType("INTEGER");
b.Property<int>("MaxStrength")
.HasColumnType("INTEGER");
b.Property<int>("Perception")
.HasColumnType("INTEGER");
b.Property<int>("Strength")
.HasColumnType("INTEGER");
b.HasKey("PetId");
b.ToTable("PetStats");
});
modelBuilder.Entity("PetCompanion.Models.Resources", b =>
{
b.Property<string>("PetId")
.HasColumnType("TEXT");
b.Property<int>("Food")
.HasColumnType("INTEGER");
b.Property<int>("Gold")
.HasColumnType("INTEGER");
b.Property<int>("Junk")
.HasColumnType("INTEGER");
b.Property<int>("Wisdom")
.HasColumnType("INTEGER");
b.HasKey("PetId");
b.ToTable("Resources");
});
modelBuilder.Entity("PetCompanion.Models.Skill", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("INTEGER");
b.Property<string>("Description")
.IsRequired()
.HasColumnType("TEXT");
b.Property<string>("Icon")
.IsRequired()
.HasColumnType("TEXT");
b.Property<string>("Name")
.IsRequired()
.HasColumnType("TEXT");
b.PrimitiveCollection<string>("SkillsIdRequired")
.HasColumnType("TEXT");
b.Property<int>("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",
Type = 0
},
new
{
Id = 2,
Description = "Increases maximum intelligence of your pet, improving its learning capabilities.",
Icon = "🧠",
Name = "Mind Enhancement",
Type = 0
},
new
{
Id = 3,
Description = "Increases maximum strength of your pet, making it more powerful.",
Icon = "💪",
Name = "Strength Training",
Type = 0
},
new
{
Id = 4,
Description = "Increases maximum charisma of your pet, making it more charming.",
Icon = "🎭",
Name = "Charisma Boost",
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",
SkillsIdRequired = "[4]",
Type = 0
},
new
{
Id = 6,
Description = "Increases agility of your pet, making it faster in combat.",
Icon = "🏃",
Name = "Agility Training",
SkillsIdRequired = "[3]",
Type = 0
},
new
{
Id = 7,
Description = "Increases perception of your pet, making it more aware of its surroundings.",
Icon = "👀",
Name = "Perception Boost",
SkillsIdRequired = "[2]",
Type = 0
},
new
{
Id = 8,
Description = "Increases the amount of resources gathered by your pet.",
Icon = "📦",
Name = "Resourcefulness",
SkillsIdRequired = "[5,6,7]",
Type = 1
});
});
modelBuilder.Entity("PetCompanion.Models.SkillEffect", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("INTEGER");
b.Property<string>("Effect")
.IsRequired()
.HasColumnType("TEXT");
b.Property<int>("SkillId")
.HasColumnType("INTEGER");
b.Property<int>("Tier")
.HasColumnType("INTEGER");
b.Property<decimal>("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
},
new
{
Id = 22,
Effect = "Resourcefulness",
SkillId = 8,
Tier = 1,
Value = 1m
},
new
{
Id = 23,
Effect = "Resourcefulness",
SkillId = 8,
Tier = 2,
Value = 2m
},
new
{
Id = 24,
Effect = "Resourcefulness",
SkillId = 8,
Tier = 3,
Value = 3m
});
});
modelBuilder.Entity("PetCompanion.Models.SkillRequirement", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("INTEGER");
b.Property<int>("Cost")
.HasColumnType("INTEGER");
b.Property<string>("Resource")
.IsRequired()
.HasColumnType("TEXT");
b.Property<int>("SkillId")
.HasColumnType("INTEGER");
b.HasKey("Id");
b.HasIndex("SkillId");
b.ToTable("SkillRequirement");
b.HasData(
new
{
Id = 1,
Cost = 100,
Resource = "Wisdom",
SkillId = 1
},
new
{
Id = 2,
Cost = 150,
Resource = "Food",
SkillId = 1
},
new
{
Id = 3,
Cost = 150,
Resource = "Wisdom",
SkillId = 2
},
new
{
Id = 4,
Cost = 100,
Resource = "Gold",
SkillId = 3
},
new
{
Id = 5,
Cost = 150,
Resource = "Food",
SkillId = 3
},
new
{
Id = 6,
Cost = 200,
Resource = "Wisdom",
SkillId = 4
},
new
{
Id = 7,
Cost = 200,
Resource = "Gold",
SkillId = 5
},
new
{
Id = 8,
Cost = 200,
Resource = "Gold",
SkillId = 6
},
new
{
Id = 9,
Cost = 100,
Resource = "Gold",
SkillId = 7
},
new
{
Id = 10,
Cost = 100,
Resource = "Junk",
SkillId = 7
},
new
{
Id = 11,
Cost = 500,
Resource = "Gold",
SkillId = 8
},
new
{
Id = 12,
Cost = 500,
Resource = "Junk",
SkillId = 8
},
new
{
Id = 13,
Cost = 300,
Resource = "Wisdom",
SkillId = 8
},
new
{
Id = 14,
Cost = 300,
Resource = "Food",
SkillId = 8
});
});
modelBuilder.Entity("PetCompanion.Models.ActionGathered", b =>
{
b.HasOne("PetCompanion.Models.GameItem", "GameItem")
.WithMany()
.HasForeignKey("ItemId");
b.HasOne("PetCompanion.Models.Pet", "Pet")
.WithMany("ActionGathered")
.HasForeignKey("PetId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("GameItem");
b.Navigation("Pet");
});
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.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.SkillRequirement", b =>
{
b.HasOne("PetCompanion.Models.Skill", "Skill")
.WithMany("SkillRequirements")
.HasForeignKey("SkillId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("Skill");
});
modelBuilder.Entity("PetCompanion.Models.Pet", b =>
{
b.Navigation("ActionGathered");
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");
b.Navigation("SkillRequirements");
});
#pragma warning restore 612, 618
}
}
}

View File

@@ -0,0 +1,409 @@
using System;
using Microsoft.EntityFrameworkCore.Migrations;
#nullable disable
#pragma warning disable CA1814 // Prefer jagged arrays over multidimensional
namespace PetCompanion.Migrations
{
/// <inheritdoc />
public partial class InitialCreate : Migration
{
/// <inheritdoc />
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.CreateTable(
name: "GameItems",
columns: table => new
{
Id = table.Column<int>(type: "INTEGER", nullable: false)
.Annotation("Sqlite:Autoincrement", true),
Name = table.Column<string>(type: "TEXT", nullable: false),
Type = table.Column<int>(type: "INTEGER", nullable: false),
Rarity = table.Column<int>(type: "INTEGER", nullable: false),
Description = table.Column<string>(type: "TEXT", nullable: false),
Price = table.Column<int>(type: "INTEGER", nullable: false),
Effect = table.Column<string>(type: "TEXT", nullable: false),
EquipTarget = table.Column<int>(type: "INTEGER", nullable: false)
},
constraints: table =>
{
table.PrimaryKey("PK_GameItems", x => x.Id);
});
migrationBuilder.CreateTable(
name: "Pets",
columns: table => new
{
Id = table.Column<string>(type: "TEXT", nullable: false),
Name = table.Column<string>(type: "TEXT", nullable: false),
Class = table.Column<int>(type: "INTEGER", nullable: false),
Level = table.Column<int>(type: "INTEGER", nullable: false),
Health = table.Column<int>(type: "INTEGER", nullable: false),
MaxHealth = table.Column<int>(type: "INTEGER", nullable: false),
UserId = table.Column<string>(type: "TEXT", nullable: false),
IsDead = table.Column<bool>(type: "INTEGER", nullable: false),
PetGatherAction = table.Column<int>(type: "INTEGER", nullable: false),
GatherActionSince = table.Column<DateTime>(type: "TEXT", nullable: false),
PetBasicAction = table.Column<int>(type: "INTEGER", nullable: false),
BasicActionCooldown = table.Column<DateTime>(type: "TEXT", nullable: false)
},
constraints: table =>
{
table.PrimaryKey("PK_Pets", x => x.Id);
});
migrationBuilder.CreateTable(
name: "Skills",
columns: table => new
{
Id = table.Column<int>(type: "INTEGER", nullable: false)
.Annotation("Sqlite:Autoincrement", true),
Name = table.Column<string>(type: "TEXT", nullable: false),
Description = table.Column<string>(type: "TEXT", nullable: false),
Type = table.Column<int>(type: "INTEGER", nullable: false),
Icon = table.Column<string>(type: "TEXT", nullable: false),
SkillsIdRequired = table.Column<string>(type: "TEXT", nullable: true)
},
constraints: table =>
{
table.PrimaryKey("PK_Skills", x => x.Id);
});
migrationBuilder.CreateTable(
name: "ActionGathered",
columns: table => new
{
Id = table.Column<int>(type: "INTEGER", nullable: false)
.Annotation("Sqlite:Autoincrement", true),
PetId = table.Column<string>(type: "TEXT", nullable: false),
Resource = table.Column<string>(type: "TEXT", nullable: true),
ItemId = table.Column<int>(type: "INTEGER", nullable: true),
Amount = table.Column<int>(type: "INTEGER", nullable: false)
},
constraints: table =>
{
table.PrimaryKey("PK_ActionGathered", x => x.Id);
table.ForeignKey(
name: "FK_ActionGathered_GameItems_ItemId",
column: x => x.ItemId,
principalTable: "GameItems",
principalColumn: "Id");
table.ForeignKey(
name: "FK_ActionGathered_Pets_PetId",
column: x => x.PetId,
principalTable: "Pets",
principalColumn: "Id",
onDelete: ReferentialAction.Cascade);
});
migrationBuilder.CreateTable(
name: "EquippedItems",
columns: table => new
{
Id = table.Column<int>(type: "INTEGER", nullable: false)
.Annotation("Sqlite:Autoincrement", true),
PetId = table.Column<string>(type: "TEXT", nullable: false),
EquipTarget = table.Column<int>(type: "INTEGER", nullable: false),
GameItemId = table.Column<int>(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<string>(type: "TEXT", nullable: false),
Items = table.Column<string>(type: "TEXT", nullable: false),
Capacity = table.Column<int>(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<string>(type: "TEXT", nullable: false),
Intelligence = table.Column<int>(type: "INTEGER", nullable: false),
Strength = table.Column<int>(type: "INTEGER", nullable: false),
Charisma = table.Column<int>(type: "INTEGER", nullable: false),
Luck = table.Column<int>(type: "INTEGER", nullable: false),
Agility = table.Column<int>(type: "INTEGER", nullable: false),
Perception = table.Column<int>(type: "INTEGER", nullable: false),
MaxIntelligence = table.Column<int>(type: "INTEGER", nullable: false),
MaxStrength = table.Column<int>(type: "INTEGER", nullable: false),
MaxCharisma = table.Column<int>(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<string>(type: "TEXT", nullable: false),
Wisdom = table.Column<int>(type: "INTEGER", nullable: false),
Gold = table.Column<int>(type: "INTEGER", nullable: false),
Food = table.Column<int>(type: "INTEGER", nullable: false),
Junk = table.Column<int>(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<int>(type: "INTEGER", nullable: false)
.Annotation("Sqlite:Autoincrement", true),
PetId = table.Column<string>(type: "TEXT", nullable: false),
SkillId = table.Column<int>(type: "INTEGER", nullable: false),
CurrentTier = table.Column<int>(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<int>(type: "INTEGER", nullable: false)
.Annotation("Sqlite:Autoincrement", true),
SkillId = table.Column<int>(type: "INTEGER", nullable: false),
Tier = table.Column<int>(type: "INTEGER", nullable: false),
Effect = table.Column<string>(type: "TEXT", nullable: false),
Value = table.Column<decimal>(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: "SkillRequirement",
columns: table => new
{
Id = table.Column<int>(type: "INTEGER", nullable: false)
.Annotation("Sqlite:Autoincrement", true),
SkillId = table.Column<int>(type: "INTEGER", nullable: false),
Resource = table.Column<string>(type: "TEXT", nullable: false),
Cost = table.Column<int>(type: "INTEGER", nullable: false)
},
constraints: table =>
{
table.PrimaryKey("PK_SkillRequirement", x => x.Id);
table.ForeignKey(
name: "FK_SkillRequirement_Skills_SkillId",
column: x => x.SkillId,
principalTable: "Skills",
principalColumn: "Id",
onDelete: ReferentialAction.Cascade);
});
migrationBuilder.InsertData(
table: "Skills",
columns: new[] { "Id", "Description", "Icon", "Name", "SkillsIdRequired", "Type" },
values: new object[,]
{
{ 1, "Increases maximum health of your pet, making it more resilient.", "❤", "Vitality Mastery", null, 0 },
{ 2, "Increases maximum intelligence of your pet, improving its learning capabilities.", "🧠", "Mind Enhancement", null, 0 },
{ 3, "Increases maximum strength of your pet, making it more powerful.", "💪", "Strength Training", null, 0 },
{ 4, "Increases maximum charisma of your pet, making it more charming.", "🎭", "Charisma Boost", null, 0 },
{ 5, "Increases luck of your pet, making it more fortunate to find rare items.", "🍀", "Luck of the Draw", "[4]", 0 },
{ 6, "Increases agility of your pet, making it faster in combat.", "🏃", "Agility Training", "[3]", 0 },
{ 7, "Increases perception of your pet, making it more aware of its surroundings.", "👀", "Perception Boost", "[2]", 0 },
{ 8, "Increases the amount of resources gathered by your pet.", "📦", "Resourcefulness", "[5,6,7]", 1 }
});
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 },
{ 22, "Resourcefulness", 8, 1, 1m },
{ 23, "Resourcefulness", 8, 2, 2m },
{ 24, "Resourcefulness", 8, 3, 3m }
});
migrationBuilder.InsertData(
table: "SkillRequirement",
columns: new[] { "Id", "Cost", "Resource", "SkillId" },
values: new object[,]
{
{ 1, 100, "Wisdom", 1 },
{ 2, 150, "Food", 1 },
{ 3, 150, "Wisdom", 2 },
{ 4, 100, "Gold", 3 },
{ 5, 150, "Food", 3 },
{ 6, 200, "Wisdom", 4 },
{ 7, 200, "Gold", 5 },
{ 8, 200, "Gold", 6 },
{ 9, 100, "Gold", 7 },
{ 10, 100, "Junk", 7 },
{ 11, 500, "Gold", 8 },
{ 12, 500, "Junk", 8 },
{ 13, 300, "Wisdom", 8 },
{ 14, 300, "Food", 8 }
});
migrationBuilder.CreateIndex(
name: "IX_ActionGathered_ItemId",
table: "ActionGathered",
column: "ItemId");
migrationBuilder.CreateIndex(
name: "IX_ActionGathered_PetId",
table: "ActionGathered",
column: "PetId");
migrationBuilder.CreateIndex(
name: "IX_EquippedItems_GameItemId",
table: "EquippedItems",
column: "GameItemId");
migrationBuilder.CreateIndex(
name: "IX_EquippedItems_PetId",
table: "EquippedItems",
column: "PetId");
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");
migrationBuilder.CreateIndex(
name: "IX_SkillRequirement_SkillId",
table: "SkillRequirement",
column: "SkillId");
}
/// <inheritdoc />
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropTable(
name: "ActionGathered");
migrationBuilder.DropTable(
name: "EquippedItems");
migrationBuilder.DropTable(
name: "Inventories");
migrationBuilder.DropTable(
name: "PetSkills");
migrationBuilder.DropTable(
name: "PetStats");
migrationBuilder.DropTable(
name: "Resources");
migrationBuilder.DropTable(
name: "SkillEffects");
migrationBuilder.DropTable(
name: "SkillRequirement");
migrationBuilder.DropTable(
name: "GameItems");
migrationBuilder.DropTable(
name: "Pets");
migrationBuilder.DropTable(
name: "Skills");
}
}
}

View File

@@ -17,6 +17,111 @@ namespace PetCompanion.Migrations
#pragma warning disable 612, 618 #pragma warning disable 612, 618
modelBuilder.HasAnnotation("ProductVersion", "9.0.1"); modelBuilder.HasAnnotation("ProductVersion", "9.0.1");
modelBuilder.Entity("PetCompanion.Models.ActionGathered", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("INTEGER");
b.Property<int>("Amount")
.HasColumnType("INTEGER");
b.Property<int?>("ItemId")
.HasColumnType("INTEGER");
b.Property<string>("PetId")
.IsRequired()
.HasColumnType("TEXT");
b.Property<string>("Resource")
.HasColumnType("TEXT");
b.HasKey("Id");
b.HasIndex("ItemId");
b.HasIndex("PetId");
b.ToTable("ActionGathered");
});
modelBuilder.Entity("PetCompanion.Models.EquippedItem", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("INTEGER");
b.Property<int>("EquipTarget")
.HasColumnType("INTEGER");
b.Property<int>("GameItemId")
.HasColumnType("INTEGER");
b.Property<string>("PetId")
.IsRequired()
.HasColumnType("TEXT");
b.HasKey("Id");
b.HasIndex("GameItemId");
b.HasIndex("PetId");
b.ToTable("EquippedItems");
});
modelBuilder.Entity("PetCompanion.Models.GameItem", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("INTEGER");
b.Property<string>("Description")
.IsRequired()
.HasColumnType("TEXT");
b.Property<string>("Effect")
.IsRequired()
.HasColumnType("TEXT");
b.Property<int>("EquipTarget")
.HasColumnType("INTEGER");
b.Property<string>("Name")
.IsRequired()
.HasColumnType("TEXT");
b.Property<int>("Price")
.HasColumnType("INTEGER");
b.Property<int>("Rarity")
.HasColumnType("INTEGER");
b.Property<int>("Type")
.HasColumnType("INTEGER");
b.HasKey("Id");
b.ToTable("GameItems");
});
modelBuilder.Entity("PetCompanion.Models.Inventory", b =>
{
b.Property<string>("PetId")
.HasColumnType("TEXT");
b.Property<int>("Capacity")
.HasColumnType("INTEGER");
b.PrimitiveCollection<string>("Items")
.IsRequired()
.HasColumnType("TEXT");
b.HasKey("PetId");
b.ToTable("Inventories");
});
modelBuilder.Entity("PetCompanion.Models.Pet", b => modelBuilder.Entity("PetCompanion.Models.Pet", b =>
{ {
b.Property<string>("Id") b.Property<string>("Id")
@@ -31,12 +136,18 @@ namespace PetCompanion.Migrations
b.Property<DateTime>("GatherActionSince") b.Property<DateTime>("GatherActionSince")
.HasColumnType("TEXT"); .HasColumnType("TEXT");
b.Property<int>("Health")
.HasColumnType("INTEGER");
b.Property<bool>("IsDead") b.Property<bool>("IsDead")
.HasColumnType("INTEGER"); .HasColumnType("INTEGER");
b.Property<int>("Level") b.Property<int>("Level")
.HasColumnType("INTEGER"); .HasColumnType("INTEGER");
b.Property<int>("MaxHealth")
.HasColumnType("INTEGER");
b.Property<string>("Name") b.Property<string>("Name")
.IsRequired() .IsRequired()
.HasColumnType("TEXT"); .HasColumnType("TEXT");
@@ -56,17 +167,48 @@ namespace PetCompanion.Migrations
b.ToTable("Pets"); b.ToTable("Pets");
}); });
modelBuilder.Entity("PetCompanion.Models.PetSkill", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("INTEGER");
b.Property<int>("CurrentTier")
.HasColumnType("INTEGER");
b.Property<string>("PetId")
.IsRequired()
.HasColumnType("TEXT");
b.Property<int>("SkillId")
.HasColumnType("INTEGER");
b.HasKey("Id");
b.HasIndex("PetId");
b.HasIndex("SkillId");
b.ToTable("PetSkills");
});
modelBuilder.Entity("PetCompanion.Models.PetStats", b => modelBuilder.Entity("PetCompanion.Models.PetStats", b =>
{ {
b.Property<string>("PetId") b.Property<string>("PetId")
.HasColumnType("TEXT"); .HasColumnType("TEXT");
b.Property<int>("Agility")
.HasColumnType("INTEGER");
b.Property<int>("Charisma") b.Property<int>("Charisma")
.HasColumnType("INTEGER"); .HasColumnType("INTEGER");
b.Property<int>("Intelligence") b.Property<int>("Intelligence")
.HasColumnType("INTEGER"); .HasColumnType("INTEGER");
b.Property<int>("Luck")
.HasColumnType("INTEGER");
b.Property<int>("MaxCharisma") b.Property<int>("MaxCharisma")
.HasColumnType("INTEGER"); .HasColumnType("INTEGER");
@@ -76,6 +218,9 @@ namespace PetCompanion.Migrations
b.Property<int>("MaxStrength") b.Property<int>("MaxStrength")
.HasColumnType("INTEGER"); .HasColumnType("INTEGER");
b.Property<int>("Perception")
.HasColumnType("INTEGER");
b.Property<int>("Strength") b.Property<int>("Strength")
.HasColumnType("INTEGER"); .HasColumnType("INTEGER");
@@ -106,6 +251,514 @@ namespace PetCompanion.Migrations
b.ToTable("Resources"); b.ToTable("Resources");
}); });
modelBuilder.Entity("PetCompanion.Models.Skill", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("INTEGER");
b.Property<string>("Description")
.IsRequired()
.HasColumnType("TEXT");
b.Property<string>("Icon")
.IsRequired()
.HasColumnType("TEXT");
b.Property<string>("Name")
.IsRequired()
.HasColumnType("TEXT");
b.PrimitiveCollection<string>("SkillsIdRequired")
.HasColumnType("TEXT");
b.Property<int>("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",
Type = 0
},
new
{
Id = 2,
Description = "Increases maximum intelligence of your pet, improving its learning capabilities.",
Icon = "🧠",
Name = "Mind Enhancement",
Type = 0
},
new
{
Id = 3,
Description = "Increases maximum strength of your pet, making it more powerful.",
Icon = "💪",
Name = "Strength Training",
Type = 0
},
new
{
Id = 4,
Description = "Increases maximum charisma of your pet, making it more charming.",
Icon = "🎭",
Name = "Charisma Boost",
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",
SkillsIdRequired = "[4]",
Type = 0
},
new
{
Id = 6,
Description = "Increases agility of your pet, making it faster in combat.",
Icon = "🏃",
Name = "Agility Training",
SkillsIdRequired = "[3]",
Type = 0
},
new
{
Id = 7,
Description = "Increases perception of your pet, making it more aware of its surroundings.",
Icon = "👀",
Name = "Perception Boost",
SkillsIdRequired = "[2]",
Type = 0
},
new
{
Id = 8,
Description = "Increases the amount of resources gathered by your pet.",
Icon = "📦",
Name = "Resourcefulness",
SkillsIdRequired = "[5,6,7]",
Type = 1
});
});
modelBuilder.Entity("PetCompanion.Models.SkillEffect", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("INTEGER");
b.Property<string>("Effect")
.IsRequired()
.HasColumnType("TEXT");
b.Property<int>("SkillId")
.HasColumnType("INTEGER");
b.Property<int>("Tier")
.HasColumnType("INTEGER");
b.Property<decimal>("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
},
new
{
Id = 22,
Effect = "Resourcefulness",
SkillId = 8,
Tier = 1,
Value = 1m
},
new
{
Id = 23,
Effect = "Resourcefulness",
SkillId = 8,
Tier = 2,
Value = 2m
},
new
{
Id = 24,
Effect = "Resourcefulness",
SkillId = 8,
Tier = 3,
Value = 3m
});
});
modelBuilder.Entity("PetCompanion.Models.SkillRequirement", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("INTEGER");
b.Property<int>("Cost")
.HasColumnType("INTEGER");
b.Property<string>("Resource")
.IsRequired()
.HasColumnType("TEXT");
b.Property<int>("SkillId")
.HasColumnType("INTEGER");
b.HasKey("Id");
b.HasIndex("SkillId");
b.ToTable("SkillRequirement");
b.HasData(
new
{
Id = 1,
Cost = 100,
Resource = "Wisdom",
SkillId = 1
},
new
{
Id = 2,
Cost = 150,
Resource = "Food",
SkillId = 1
},
new
{
Id = 3,
Cost = 150,
Resource = "Wisdom",
SkillId = 2
},
new
{
Id = 4,
Cost = 100,
Resource = "Gold",
SkillId = 3
},
new
{
Id = 5,
Cost = 150,
Resource = "Food",
SkillId = 3
},
new
{
Id = 6,
Cost = 200,
Resource = "Wisdom",
SkillId = 4
},
new
{
Id = 7,
Cost = 200,
Resource = "Gold",
SkillId = 5
},
new
{
Id = 8,
Cost = 200,
Resource = "Gold",
SkillId = 6
},
new
{
Id = 9,
Cost = 100,
Resource = "Gold",
SkillId = 7
},
new
{
Id = 10,
Cost = 100,
Resource = "Junk",
SkillId = 7
},
new
{
Id = 11,
Cost = 500,
Resource = "Gold",
SkillId = 8
},
new
{
Id = 12,
Cost = 500,
Resource = "Junk",
SkillId = 8
},
new
{
Id = 13,
Cost = 300,
Resource = "Wisdom",
SkillId = 8
},
new
{
Id = 14,
Cost = 300,
Resource = "Food",
SkillId = 8
});
});
modelBuilder.Entity("PetCompanion.Models.ActionGathered", b =>
{
b.HasOne("PetCompanion.Models.GameItem", "GameItem")
.WithMany()
.HasForeignKey("ItemId");
b.HasOne("PetCompanion.Models.Pet", "Pet")
.WithMany("ActionGathered")
.HasForeignKey("PetId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("GameItem");
b.Navigation("Pet");
});
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.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 => modelBuilder.Entity("PetCompanion.Models.PetStats", b =>
{ {
b.HasOne("PetCompanion.Models.Pet", null) b.HasOne("PetCompanion.Models.Pet", null)
@@ -124,14 +777,54 @@ namespace PetCompanion.Migrations
.IsRequired(); .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.SkillRequirement", b =>
{
b.HasOne("PetCompanion.Models.Skill", "Skill")
.WithMany("SkillRequirements")
.HasForeignKey("SkillId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("Skill");
});
modelBuilder.Entity("PetCompanion.Models.Pet", b => modelBuilder.Entity("PetCompanion.Models.Pet", b =>
{ {
b.Navigation("ActionGathered");
b.Navigation("EquippedItemsList");
b.Navigation("Inventory")
.IsRequired();
b.Navigation("Resources") b.Navigation("Resources")
.IsRequired(); .IsRequired();
b.Navigation("Skills");
b.Navigation("Stats") b.Navigation("Stats")
.IsRequired(); .IsRequired();
}); });
modelBuilder.Entity("PetCompanion.Models.Skill", b =>
{
b.Navigation("Effects");
b.Navigation("PetSkills");
b.Navigation("SkillRequirements");
});
#pragma warning restore 612, 618 #pragma warning restore 612, 618
} }
} }

22
Models/ActionGathered.cs Normal file
View File

@@ -0,0 +1,22 @@
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
using System.Text.Json.Serialization;
namespace PetCompanion.Models
{
public class ActionGathered
{
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
[Key]
public int Id { get; set; }
[ForeignKey("Pet")]
public string PetId { get; set; }
public string? Resource { get; set; }
[ForeignKey("GameItem")]
public int? ItemId { get; set; }
public int Amount { get; set; }
[JsonIgnore]
public virtual Pet Pet { get; set; }
public virtual GameItem? GameItem { get; set; }
}
}

View File

@@ -1,25 +0,0 @@
namespace PetCompanion.Models.Enums
{
public enum ItemType
{
Consumable,
Equipment,
Material
}
public enum ItemRarity
{
Common,
Uncommon,
Rare,
Legendary
}
public enum EquipmentSlot
{
Helmet,
Chest,
Leggings,
Weapon
}
}

20
Models/EquippedItem.cs Normal file
View File

@@ -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; }
}
}

41
Models/GameItem.cs Normal file
View File

@@ -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
}
}

View File

@@ -1,79 +0,0 @@
using PetCompanion.Models.Enums;
namespace PetCompanion.Models
{
public class MaterialItem : Item
{
public MaterialItem()
{
Type = ItemType.Material;
}
public override void Use(ref Pet pet)
{
// Materials cannot be used directly
}
}
public class StatBoostEquipment : EquipableItem
{
public Dictionary<string, int> StatBoosts { get; set; } = new();
public override void Equip(ref Pet pet)
{
base.Equip(ref pet);
if (IsEquipped)
{
foreach (var boost in StatBoosts)
{
switch (boost.Key.ToLower())
{
case "health":
pet.MaxHealth += boost.Value;
break;
case "intelligence":
pet.Stats.MaxIntelligence += boost.Value;
break;
case "strength":
pet.Stats.MaxStrength += boost.Value;
break;
case "charisma":
pet.Stats.MaxCharisma += boost.Value;
break;
}
}
}
}
public override void Unequip(ref Pet pet)
{
if (IsEquipped)
{
foreach (var boost in StatBoosts)
{
switch (boost.Key.ToLower())
{
case "health":
pet.MaxHealth -= boost.Value;
break;
case "intelligence":
pet.Stats.MaxIntelligence -= boost.Value;
break;
case "strength":
pet.Stats.MaxStrength -= boost.Value;
break;
case "charisma":
pet.Stats.MaxCharisma -= boost.Value;
break;
}
}
}
base.Unequip(ref pet);
}
public override void Use(ref Pet pet)
{
Equip(ref pet);
}
}
}

View File

@@ -1,28 +1,16 @@
namespace PetCompanion.Models using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
using System.Text.Json.Serialization;
namespace PetCompanion.Models
{ {
public class Inventory public class Inventory
{ {
public List<Item> Items { get; set; } = new(); [Key, ForeignKey("Pet")]
public int Capacity { get; set; } public string PetId { get; set; }
[JsonIgnore]
public bool AddItem(Item item) public virtual Pet Pet { get; set; }
{ public List<int> Items { get; set; } = new List<int>();
if (Items.Count < Capacity) public int Capacity { get; set; } = 20;
{
Items.Add(item);
return true;
}
return false;
}
public bool RemoveItem(Item item)
{
return Items.Remove(item);
}
public void TrashItem(Item item)
{
RemoveItem(item);
}
} }
} }

View File

@@ -1,50 +0,0 @@
using PetCompanion.Models.Enums;
namespace PetCompanion.Models
{
public abstract class Item
{
public string Id { get; set; }
public string Name { get; set; }
public string Description { get; set; }
public ItemType Type { get; set; }
public ItemRarity Rarity { get; set; }
public abstract void Use(ref Pet pet);
}
public abstract class EquipableItem : Item
{
public EquipmentSlot Slot { get; set; }
public bool IsEquipped { get; set; }
public virtual void Equip(ref Pet pet)
{
if (!IsEquipped)
{
pet.Equipment[Slot]?.Unequip(ref pet);
pet.Equipment[Slot] = this;
IsEquipped = true;
}
}
public virtual void Unequip(ref Pet pet)
{
if (IsEquipped)
{
pet.Equipment[Slot] = null;
IsEquipped = false;
}
}
}
public class ConsumableItem : Item
{
public Action<Pet> Effect { get; set; }
public override void Use(ref Pet pet)
{
Effect?.Invoke(pet);
}
}
}

View File

@@ -1,5 +1,5 @@
using System.ComponentModel.DataAnnotations; using System.ComponentModel.DataAnnotations;
using PetCompanion.Models.Enums; using System.ComponentModel.DataAnnotations.Schema;
namespace PetCompanion.Models namespace PetCompanion.Models
{ {
@@ -11,9 +11,7 @@ namespace PetCompanion.Models
public PetClass Class { get; set; } public PetClass Class { get; set; }
public PetStats Stats { get; set; } public PetStats Stats { get; set; }
public Resources Resources { get; set; } public Resources Resources { get; set; }
public Inventory Inventory { get; set; }
public int Level { get; set; } public int Level { get; set; }
public int Experience { get; set; }
public int Health { get; set; } public int Health { get; set; }
public int MaxHealth { get; set; } public int MaxHealth { get; set; }
public string UserId { get; set; } public string UserId { get; set; }
@@ -25,16 +23,29 @@ namespace PetCompanion.Models
public PetBasicAction PetBasicAction { get; set; } public PetBasicAction PetBasicAction { get; set; }
public DateTime BasicActionCooldown { get; set; } public DateTime BasicActionCooldown { get; set; }
public Dictionary<EquipmentSlot, EquipableItem> Equipment { get; set; } = new(); public virtual ICollection<PetSkill> Skills { get; set; } = new List<PetSkill>();
public virtual Inventory Inventory { get; set; }
public virtual ICollection<EquippedItem> EquippedItemsList { get; set; } = new List<EquippedItem>();
public Pet() public virtual ICollection<ActionGathered> ActionGathered { get; set; } = new List<ActionGathered>();
[NotMapped]
public Dictionary<ItemEquipTarget, int> EquippedItems
{ {
foreach (EquipmentSlot slot in Enum.GetValues(typeof(EquipmentSlot))) get => EquippedItemsList?.ToDictionary(e => e.EquipTarget, e => e.GameItemId) ?? new Dictionary<ItemEquipTarget, int>();
set
{ {
Equipment[slot] = null; EquippedItemsList = value.Select(kvp => new EquippedItem
{
PetId = Id,
EquipTarget = kvp.Key,
GameItemId = kvp.Value
}).ToList();
} }
} }
public Pet() { }
public void IncrementIntelligence(int amount) public void IncrementIntelligence(int amount)
{ {
var newValue = Stats.Intelligence + amount; var newValue = Stats.Intelligence + amount;

View File

@@ -14,5 +14,7 @@
GATHERING_WISDOM, GATHERING_WISDOM,
GATHERING_GOLD, GATHERING_GOLD,
GATHERING_FOOD, GATHERING_FOOD,
EXPLORE,
BATTLE
} }
} }

View File

@@ -1,5 +1,6 @@
using System.ComponentModel.DataAnnotations; using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema; using System.ComponentModel.DataAnnotations.Schema;
using System.Text.Json.Serialization;
namespace PetCompanion.Models namespace PetCompanion.Models
{ {
@@ -7,10 +8,20 @@ namespace PetCompanion.Models
{ {
[Key, ForeignKey("Pet")] [Key, ForeignKey("Pet")]
public string PetId { get; set; } public string PetId { get; set; }
// Display stats
public int Intelligence { get; set; } public int Intelligence { get; set; }
public int Strength { get; set; } public int Strength { get; set; }
public int Charisma { get; set; } public int Charisma { get; set; }
// Hidden stats (not displayed to the API)
[JsonIgnore]
public int Luck { get; set; } // used for rarity of item finds
[JsonIgnore]
public int Agility { get; set; } // used for combat
[JsonIgnore]
public int Perception { get; set; } // used for number of itens found
public int MaxIntelligence { get; set; } public int MaxIntelligence { get; set; }
public int MaxStrength { get; set; } public int MaxStrength { get; set; }
public int MaxCharisma { get; set; } public int MaxCharisma { get; set; }
@@ -67,6 +78,10 @@ namespace PetCompanion.Models
stats.MaxStrength = stats.Strength; stats.MaxStrength = stats.Strength;
stats.MaxCharisma = stats.Charisma; stats.MaxCharisma = stats.Charisma;
stats.Luck = 1;
stats.Agility = 1;
stats.Perception = 1;
return stats; return stats;
} }
} }

101
Models/Skill.cs Normal file
View File

@@ -0,0 +1,101 @@
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
using System.Text.Json.Serialization;
namespace PetCompanion.Models
{
public enum SkillType
{
GROUND,
GRAND
}
public enum SkillTier
{
I = 1,
II = 2,
III = 3
}
public class Skill
{
[Key]
public int Id { get; set; }
public string Name { get; set; }
public string Description { get; set; }
public SkillType Type { get; set; }
public string Icon { get; set; }
public List<int>? SkillsIdRequired { get; set; }
public virtual ICollection<SkillRequirement> SkillRequirements { get; set; }
public virtual ICollection<SkillEffect> Effects { get; set; }
[JsonIgnore]
public virtual ICollection<PetSkill> PetSkills { get; set; }
}
public class SkillRequirement
{
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
[Key]
public int Id { get; set; }
public int SkillId { get; set; }
public string Resource { get; set; }
public int Cost { get; set; }
[JsonIgnore]
public virtual Skill Skill { get; set; }
}
public class SkillEffect
{
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
[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; }
public decimal Value { get; set; }
public void PetSkillUpgrade(ref Pet pet)
{
switch (Effect)
{
case "MaxHealth":
pet.MaxHealth += (int)Value;
break;
case "MaxIntelligence":
pet.Stats.MaxIntelligence += (int)Value;
break;
case "MaxStrength":
pet.Stats.MaxStrength += (int)Value;
break;
case "MaxCharisma":
pet.Stats.MaxCharisma += (int)Value;
break;
case "Luck":
pet.Stats.Luck += (int)Value;
break;
case "Agility":
pet.Stats.Agility += (int)Value;
break;
case "Perception":
pet.Stats.Perception += (int)Value;
break;
// Add more effects as needed
}
}
}
public class PetSkill
{
[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; }
public SkillTier CurrentTier { get; set; }
}
}

View File

@@ -1,4 +1,6 @@
using Microsoft.AspNetCore.Authentication.JwtBearer;
using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore;
using Microsoft.IdentityModel.Tokens;
using PetCompanion.Data; using PetCompanion.Data;
using PetCompanion.Repositories; using PetCompanion.Repositories;
using PetCompanion.Services; using PetCompanion.Services;
@@ -12,6 +14,10 @@ namespace PetCompanion
{ {
var builder = WebApplication.CreateBuilder(args); var builder = WebApplication.CreateBuilder(args);
// Read Firebase configuration from environment variables
var firebaseAppId = Environment.GetEnvironmentVariable("FIREBASE_APP_ID") ??
throw new InvalidOperationException("FIREBASE_APP_ID environment variable is not set");
// Add services to the container. // Add services to the container.
builder.Services.AddControllers() builder.Services.AddControllers()
.AddJsonOptions(options => .AddJsonOptions(options =>
@@ -24,12 +30,27 @@ namespace PetCompanion
// Configure Entity Framework Core // Configure Entity Framework Core
var connectionString = builder.Configuration.GetConnectionString("DefaultConnection"); var connectionString = builder.Configuration.GetConnectionString("DefaultConnection");
builder.Services.AddDbContext<ApplicationDbContext>(options => builder.Services.AddDbContext<ApplicationDbContext>(options =>
options.UseSqlite(connectionString)); {
options.UseSqlite(connectionString);
options.EnableSensitiveDataLogging();
});
builder.Services.AddScoped<PetClassRepository>(); builder.Services.AddScoped<PetClassRepository>();
builder.Services.AddScoped<PetClassService>(); builder.Services.AddScoped<PetClassService>();
builder.Services.AddScoped<PetActionService>();
builder.Services.AddScoped<SkillService>();
builder.Services.AddScoped<GameItemsRepository>();
builder.Services.AddScoped<GameItemService>();
builder.Services.AddScoped<PetRepository>(); builder.Services.AddScoped<PetRepository>();
builder.Services.AddScoped<PetService>(); builder.Services.AddScoped<PetService>();
builder.Services.AddScoped<PetSkillRepository>();
builder.Services.AddScoped<PetInventoryRepository>();
builder.Services.AddScoped<PetSkillService>();
builder.Services.AddScoped<PetInventoryService>();
builder.Services.AddScoped<ActionGatheredRepository>();
// Add the background service
builder.Services.AddHostedService<PetActionBackgroundService>();
// Add CORS policy // Add CORS policy
builder.Services.AddCors(options => builder.Services.AddCors(options =>
@@ -42,6 +63,21 @@ namespace PetCompanion
}); });
}); });
builder.Services
.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
.AddJwtBearer(options =>
{
options.Authority = $"https://securetoken.google.com/{firebaseAppId}";
options.TokenValidationParameters = new TokenValidationParameters
{
ValidateIssuer = true,
ValidIssuer = $"https://securetoken.google.com/{firebaseAppId}",
ValidateAudience = true,
ValidAudience = firebaseAppId,
ValidateLifetime = true
};
});
var app = builder.Build(); var app = builder.Build();
// Configure the HTTP request pipeline. // Configure the HTTP request pipeline.
@@ -52,8 +88,17 @@ namespace PetCompanion
} }
app.UseHttpsRedirection(); app.UseHttpsRedirection();
app.UseAuthentication();
app.UseAuthorization(); app.UseAuthorization();
// After app builder is created
using (var scope = app.Services.CreateScope())
{
var itemService = scope.ServiceProvider.GetRequiredService<GameItemService>();
itemService.LoadItemsFromCsv("game-data/GameItemsData.csv");
}
// Use CORS policy // Use CORS policy
app.UseCors("AllowAll"); app.UseCors("AllowAll");

View File

@@ -1,29 +1,39 @@
# Pet Companion # Pet Companion
## Todo: ## Todo (v1):
- [ ] Inventory system - [P] Inventory system
- [ ] Skill tree system - [P] Skill tree system
- [ ] Explore system - [ ] Explore system
- [ ] Battle system - [ ] Battle system
- [ ] Quest system
- [ ] User login/register system - [ ] User login/register system
- [ ] User profile/settings system - [ ] User profile/settings system
### V1.5:
- [ ] Icons and images optimization
### V2:
- [ ] Quest system
- [ ] Market system (internal)
- [ ] Front-End: 3D pet model - [ ] Front-End: 3D pet model
- [ ] Front-End: 3D pet animations - [ ] Front-End: 3D pet animations
- [ ] Front-End: 3D pet interactions - [ ] Front-End: 3D pet interactions
- [ ] Front-End: 3D pet environment (depending on the class) - [ ] Front-End: 3D pet environment (depending on the class)
### V3:
- [ ] Front-End: improved skill tree design
- [ ] Front-End: improved inventory design
## Inventory system ## Inventory system
- [ ] Inventory UI - [x] Inventory UI
- [ ] Inventory database - [x] Inventory database
- [ ] Inventory item database (items, consumables, equipment) - [x] Inventory item database (items, consumables, equipment)
- [ ] Inventory item interactions (use, equip, unequip, drop) - [x] Inventory item interactions (use, equip, unequip, drop)
- [ ] Inventory item stacking - [/] Inventory item stacking
- [ ] Inventory item sorting (UI) - [/] Inventory item sorting (UI)
## Skill tree system ## Skill tree system
- [ ] Skill tree UI - [x] Skill tree UI
- [ ] Skill tree database - [x] Skill tree database
- [ ] Skill tree interactions (learn, unlearn, upgrade) - [/] Skill tree interactions (learn, unlearn, upgrade)
- [ ] Skill tree requirements (level, skill points, other skills) - [/] Skill tree requirements (level, skill points, other skills)
- [ ] Skill tree effects (TBD) - [x] Skill tree effects (TBD)

View File

@@ -0,0 +1,47 @@
using PetCompanion.Data;
using PetCompanion.Models;
using Microsoft.EntityFrameworkCore;
namespace PetCompanion.Repositories
{
public class ActionGatheredRepository
{
private readonly ApplicationDbContext _context;
public ActionGatheredRepository(ApplicationDbContext context)
{
_context = context;
}
public IEnumerable<ActionGathered> GetAllActionGatheredByPetId(string petId)
{
return _context.ActionGathered
.Where(ag => ag.PetId == petId)
.Include(ag => ag.GameItem)
.ToList();
}
public ActionGathered CreateActionGathered(ActionGathered actionGathered)
{
var entry = _context.ActionGathered.Add(actionGathered);
_context.SaveChanges();
return entry.Entity;
}
public ActionGathered UpdateActionGathered(ActionGathered actionGathered)
{
var entry = _context.ActionGathered.Update(actionGathered);
_context.SaveChanges();
return entry.Entity;
}
public void DeleteAllActionGatheredByPetId(string petId)
{
var actionsToDelete = _context.ActionGathered
.Where(ag => ag.PetId == petId);
_context.ActionGathered.RemoveRange(actionsToDelete);
_context.SaveChanges();
}
}
}

View File

@@ -0,0 +1,47 @@
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 IEnumerable<GameItem> GetAll()
{
return _context.GameItems;
}
public byte[] GetItemIcon(int itemId)
{
if (_context.GameItems.Find(itemId) == null)
{
throw new Exception("Item not found");
}
return File.ReadAllBytes($"game-data/item/icons/{itemId}.png");
}
public void Add(GameItem item)
{
_context.GameItems.Add(item);
_context.SaveChanges();
}
public void Update(GameItem item)
{
_context.GameItems.Update(item);
_context.SaveChanges();
}
}
}

View File

@@ -1,176 +0,0 @@
using System.Text.RegularExpressions;
using PetCompanion.Models;
using PetCompanion.Models.Enums;
namespace PetCompanion.Repositories
{
public class ItemRepository
{
private readonly Dictionary<string, Item> _itemTemplates = new();
private readonly Dictionary<ItemRarity, List<string>> _itemsByRarity = new();
private readonly Random _random = new();
public ItemRepository()
{
foreach (ItemRarity rarity in Enum.GetValues(typeof(ItemRarity)))
{
_itemsByRarity[rarity] = new List<string>();
}
LoadItemsFromCsv();
}
private void LoadItemsFromCsv()
{
var lines = File.ReadAllLines("Items.csv").Skip(1); // Skip header
foreach (var line in lines)
{
var parts = line.Split(',');
var name = parts[0];
var type = Enum.Parse<ItemType>(parts[1]);
var rarity = Enum.Parse<ItemRarity>(parts[2]);
var description = parts[3];
Item item = type switch
{
ItemType.Consumable => CreateConsumableItem(name, description, rarity),
ItemType.Equipment => CreateEquipmentItem(name, description, rarity),
ItemType.Material => CreateMaterialItem(name, description, rarity),
_ => throw new ArgumentException($"Unknown item type: {type}")
};
_itemTemplates.Add(name, item);
_itemsByRarity[rarity].Add(name);
}
}
private Item CreateConsumableItem(string name, string description, ItemRarity rarity)
{
var item = new ConsumableItem
{
Id = Guid.NewGuid().ToString(),
Name = name,
Description = description,
Type = ItemType.Consumable,
Rarity = rarity
};
// Parse effects from description
if (description.Contains("food resources"))
{
var foodAmount = int.Parse(Regex.Match(description, @"\+(\d+) food").Groups[1].Value);
item.Effect = (pet) => pet.Resources.Food += foodAmount;
}
else if (description.Contains("Intelligence"))
{
var amount = int.Parse(Regex.Match(description, @"\+(\d+)").Groups[1].Value);
item.Effect = (pet) => pet.IncrementIntelligence(amount);
}
// Add more effect parsing as needed
return item;
}
private Item CreateEquipmentItem(string name, string description, ItemRarity rarity)
{
var equipment = new StatBoostEquipment
{
Id = Guid.NewGuid().ToString(),
Name = name,
Description = description,
Type = ItemType.Equipment,
Rarity = rarity
};
// Parse slot and stats from description
var slotMatch = Regex.Match(description, @"(Helmet|Chest|Legging|Weapon):");
if (slotMatch.Success)
{
equipment.Slot = Enum.Parse<EquipmentSlot>(slotMatch.Groups[1].Value);
}
var statMatch = Regex.Match(description, @"\+(\d+) Max (\w+)");
if (statMatch.Success)
{
var amount = int.Parse(statMatch.Groups[1].Value);
var stat = statMatch.Groups[2].Value;
equipment.StatBoosts.Add(stat, amount);
}
return equipment;
}
private Item CreateMaterialItem(string name, string description, ItemRarity rarity)
{
return new MaterialItem
{
Id = Guid.NewGuid().ToString(),
Name = name,
Description = description,
Type = ItemType.Material,
Rarity = rarity
};
}
public Item CreateItem(string itemName)
{
if (_itemTemplates.TryGetValue(itemName, out var template))
{
// Create a new instance with a new ID but same properties
var json = System.Text.Json.JsonSerializer.Serialize(template);
var newItem = System.Text.Json.JsonSerializer.Deserialize<Item>(json);
newItem.Id = Guid.NewGuid().ToString();
return newItem;
}
throw new KeyNotFoundException($"Item template not found: {itemName}");
}
/// Usage:
/* var rarityProbabilities = new Dictionary<ItemRarity, int>
{
{ ItemRarity.Common, 50 }, // 50% chance
{ ItemRarity.Uncommon, 30 }, // 30% chance
{ ItemRarity.Rare, 15 }, // 15% chance
{ ItemRarity.Legendary, 5 } // 5% chance
};
var itemRepo = new ItemRepository();
var randomItem = itemRepo.GenerateRandomItem(rarityProbabilities);
*/
public Item GenerateRandomItem(Dictionary<ItemRarity, int> rarityProbabilities)
{
// Validate probabilities
if (rarityProbabilities.Values.Sum() != 100)
{
throw new ArgumentException("Rarity probabilities must sum to 100");
}
// Generate random number between 0 and 100
var roll = _random.Next(1, 101);
var currentThreshold = 0;
// Determine which rarity we hit
ItemRarity selectedRarity = ItemRarity.Common;
foreach (var probability in rarityProbabilities)
{
currentThreshold += probability.Value;
if (roll <= currentThreshold)
{
selectedRarity = probability.Key;
break;
}
}
// Get random item from selected rarity
var possibleItems = _itemsByRarity[selectedRarity];
if (possibleItems.Count == 0)
{
// Fallback to common if no items of selected rarity
possibleItems = _itemsByRarity[ItemRarity.Common];
}
var randomItemName = possibleItems[_random.Next(possibleItems.Count)];
return CreateItem(randomItemName);
}
}
}

View File

@@ -0,0 +1,71 @@
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 Inventory GetPetInventory(string petId)
{
return _context.Inventories
.FirstOrDefault(i => i.PetId == petId);
}
public Dictionary<ItemEquipTarget, int> GetEquippedItems(string petId)
{
var equippedItems = _context.EquippedItems
.Where(e => e.PetId == petId)
.ToDictionary(e => e.EquipTarget, e => e.GameItemId);
return equippedItems;
}
public void UpdateEquippedItems(string petId, Dictionary<ItemEquipTarget, int> equippedItems)
{
var existingItems = _context.EquippedItems
.Where(e => e.PetId == petId)
.ToList();
_context.EquippedItems.RemoveRange(existingItems);
var newEquippedItems = equippedItems.Select(kvp => new EquippedItem
{
PetId = petId,
EquipTarget = kvp.Key,
GameItemId = kvp.Value
});
_context.EquippedItems.AddRangeAsync(newEquippedItems);
_context.SaveChangesAsync();
}
public Inventory SavePetInventory(Inventory inventory)
{
if (_context.Inventories.Any(i => i.PetId == inventory.PetId))
{
_context.Inventories.Update(inventory);
}
else
{
_context.Inventories.Add(inventory);
}
_context.SaveChanges();
return inventory;
}
public Inventory UpdatePetInventory(Inventory inventory)
{
_context.Inventories.Update(inventory);
_context.SaveChanges();
return inventory;
}
}
}

View File

@@ -19,6 +19,20 @@ namespace PetCompanion.Repositories
.Where(p => p.UserId == userId) .Where(p => p.UserId == userId)
.Include(p => p.Stats) .Include(p => p.Stats)
.Include(p => p.Resources) .Include(p => p.Resources)
.Include(p => p.Inventory)
.Include(p => p.EquippedItemsList)
.Include(p => p.ActionGathered)
.ToList();
}
public IEnumerable<Pet> GetPetWithActions()
{
return context.Pets
.Where(predicate => predicate.PetGatherAction != PetActionGather.IDLE)
.Include(p => p.Stats)
.Include(p => p.Resources)
.Include(p => p.Inventory)
.Include(p => p.EquippedItemsList)
.ToList(); .ToList();
} }
@@ -28,6 +42,9 @@ namespace PetCompanion.Repositories
.Where(p => p.Id == petId && p.UserId == userId) .Where(p => p.Id == petId && p.UserId == userId)
.Include(p => p.Stats) .Include(p => p.Stats)
.Include(p => p.Resources) .Include(p => p.Resources)
.Include(p => p.Inventory)
.Include(p => p.EquippedItemsList)
.Include(p => p.ActionGathered)
.FirstOrDefault(); .FirstOrDefault();
} }
@@ -41,6 +58,12 @@ namespace PetCompanion.Repositories
public Pet UpdatePet(Pet pet) public Pet UpdatePet(Pet pet)
{ {
context.Pets.Update(pet); context.Pets.Update(pet);
if (pet.Inventory != null)
{
context.Inventories.Update(pet.Inventory);
}
context.SaveChanges(); context.SaveChanges();
return pet; return pet;
} }

View File

@@ -0,0 +1,55 @@
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 IEnumerable<Skill> GetAvailableSkills()
{
return _context.Skills
.Include(s => s.Effects)
.Include(s => s.SkillRequirements)
.ToList();
}
public Skill GetSkill(int id)
{
return _context.Skills
.Include(s => s.Effects)
.Include(s => s.SkillRequirements)
.FirstOrDefault(s => s.Id == id);
}
public IEnumerable<PetSkill> GetPetSkills(string petId)
{
return _context.PetSkills
.Include(ps => ps.Skill)
.ThenInclude(s => s.Effects)
.Where(ps => ps.PetId == petId)
.ToList();
}
public PetSkill SavePetSkill(PetSkill petSkill)
{
if (petSkill.Id == 0)
{
_context.PetSkills.Add(petSkill);
}
else
{
_context.PetSkills.Update(petSkill);
}
_context.SaveChanges();
return petSkill;
}
}
}

171
Services/GameItemService.cs Normal file
View File

@@ -0,0 +1,171 @@
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<GameItem>().ToList();
foreach (var item in items)
{
var existingItem = gameItemsRepository.GetById(item.Id);
if (existingItem == null)
{
gameItemsRepository.Add(item);
}
else
{
//gameItemsRepository.Update(item);
}
}
}
public GameItem GetRandomItem()
{
var items = gameItemsRepository.GetAll();
var random = new Random();
var index = random.Next(items.Count());
return items.ElementAt(index);
}
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":
pet.Resources.Food += value;
break;
case "ADD_INTELLIGENCE":
pet.IncrementIntelligence(value);
break;
case "REDUCE_COOLDOWN":
pet.BasicActionCooldown = pet.BasicActionCooldown.AddMinutes(-value);
break;
case "ADD_HEALTH":
pet.Health = Math.Min(pet.Health + value, pet.MaxHealth);
break;
case "ADD_CHARISMA":
pet.IncrementCharisma(value);
break;
case "ADD_STRENGTH":
pet.IncrementStrength(value);
break;
case "ADD_RANDOMSTAT":
var random = new Random();
var stat = random.Next(4);
switch (stat)
{
case 0: pet.IncrementStrength(value); break;
case 1: pet.IncrementIntelligence(value); break;
case 2: pet.IncrementCharisma(value); break;
case 3: pet.Health = Math.Min(pet.Health + value, pet.MaxHealth); break;
}
break;
case "RESTORE_STATS":
pet.Health = pet.MaxHealth;
pet.Stats.Intelligence = pet.Stats.MaxIntelligence;
pet.Stats.Strength = pet.Stats.MaxStrength;
pet.Stats.Charisma = pet.Stats.MaxCharisma;
break;
case "ADD_MAXHEALTH":
pet.MaxHealth += value;
break;
case "ADD_MAXINTELLIGENCE":
pet.Stats.MaxIntelligence += value;
break;
case "ADD_MAXSTRENGTH":
pet.Stats.MaxStrength += value;
break;
case "ADD_MAXCHARISMA":
pet.Stats.MaxCharisma += value;
break;
case "ADD_MAXALLSTATS":
pet.MaxHealth += value;
pet.Stats.MaxIntelligence += value;
pet.Stats.MaxStrength += value;
pet.Stats.MaxCharisma += value;
break;
}
}
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_MAXHEALTH":
pet.MaxHealth -= value;
pet.Health = Math.Min(pet.Health, pet.MaxHealth);
break;
case "ADD_MAXINTELLIGENCE":
pet.Stats.MaxIntelligence -= value;
pet.Stats.Intelligence = Math.Min(pet.Stats.Intelligence, pet.Stats.MaxIntelligence);
break;
case "ADD_MAXSTRENGTH":
pet.Stats.MaxStrength -= value;
pet.Stats.Strength = Math.Min(pet.Stats.Strength, pet.Stats.MaxStrength);
break;
case "ADD_MAXCHARISMA":
pet.Stats.MaxCharisma -= value;
pet.Stats.Charisma = Math.Min(pet.Stats.Charisma, pet.Stats.MaxCharisma);
break;
case "ADD_MAXALLSTATS":
pet.MaxHealth -= value;
pet.Stats.MaxIntelligence -= value;
pet.Stats.MaxStrength -= value;
pet.Stats.MaxCharisma -= value;
pet.Health = Math.Min(pet.Health, pet.MaxHealth);
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;
}
}
}
}

View File

@@ -0,0 +1,26 @@
namespace PetCompanion.Services
{
public class PetActionBackgroundService : BackgroundService
{
private readonly IServiceProvider _serviceProvider;
public PetActionBackgroundService(IServiceProvider serviceProvider)
{
_serviceProvider = serviceProvider;
}
protected override async Task ExecuteAsync(CancellationToken stoppingToken)
{
while (!stoppingToken.IsCancellationRequested)
{
using (var scope = _serviceProvider.CreateScope())
{
var petActionService = scope.ServiceProvider.GetRequiredService<PetActionService>();
petActionService.LoopPetActions();
}
await Task.Delay(TimeSpan.FromMinutes(1), stoppingToken);
}
}
}
}

View File

@@ -0,0 +1,153 @@
using PetCompanion.Models;
using PetCompanion.Repositories;
namespace PetCompanion.Services
{
public class PetActionService
{
private readonly ActionGatheredRepository actionGatheredRepository;
private readonly PetRepository petRepository;
private readonly GameItemService gameItemService;
public PetActionService(ActionGatheredRepository actionGatheredRepository, GameItemService gameItemService, PetRepository petRepository)
{
this.actionGatheredRepository = actionGatheredRepository;
this.gameItemService = gameItemService;
this.petRepository = petRepository;
}
public IEnumerable<ActionGathered> GetGatheredByPet(string petId)
{
return actionGatheredRepository.GetAllActionGatheredByPetId(petId);
}
public void DeleteAllActionGatheredByPetId(string petId)
{
actionGatheredRepository.DeleteAllActionGatheredByPetId(petId);
}
public void LoopPetActions()
{
var pets = petRepository.GetPetWithActions();
foreach (var pet in pets)
{
var gatheredResources = CalculateGatheredResources(pet);
if (gatheredResources != null)
{
var gatheredResourcesDb = actionGatheredRepository.GetAllActionGatheredByPetId(pet.Id);
foreach (var resource in gatheredResources)
{
if (gatheredResourcesDb.Any(ag => ag.Resource == resource.Resource))
{
var existingResource = gatheredResourcesDb.First(ag => ag.Resource == resource.Resource);
existingResource.Amount += resource.Amount;
actionGatheredRepository.UpdateActionGathered(existingResource);
}
else
{
actionGatheredRepository.CreateActionGathered(resource);
}
}
}
}
}
public ICollection<ActionGathered>? CalculateGatheredResources(Pet pet)
{
if (pet.PetGatherAction == PetActionGather.IDLE)
return null;
var timeElapsed = (DateTime.UtcNow - pet.GatherActionSince).TotalMinutes;
var gathered = new List<ActionGathered>();
var baseRate = (timeElapsed + pet.Level) / 10; // Base rate per hour
gathered.Add(new ActionGathered
{
Resource = "Junk",
Amount = (int)(baseRate * 0.2)
});
var random = new Random();
switch (pet.PetGatherAction)
{
case PetActionGather.GATHERING_WISDOM:
gathered.Add(new ActionGathered
{
Resource = "Wisdom",
Amount = (int)(baseRate * (pet.Stats.Intelligence * 0.5))
});
break;
case PetActionGather.GATHERING_GOLD:
gathered.Add(new ActionGathered
{
Resource = "Gold",
Amount = (int)(baseRate * (pet.Stats.Charisma * 0.5))
});
break;
case PetActionGather.GATHERING_FOOD:
gathered.Add(new ActionGathered
{
Resource = "Food",
Amount = (int)(baseRate * (pet.Stats.Strength * 0.5))
});
break;
case PetActionGather.EXPLORE:
gathered.Add(new ActionGathered
{
Resource = "Wisdom",
Amount = (int)(baseRate * (pet.Stats.Strength * 0.25))
});
if (random.Next(0, 100) < 5)
{
pet.Health -= 5;
}
if (random.Next(0, 100) < 2)
{
gathered.Add(new ActionGathered
{
ItemId = gameItemService.GetRandomItem().Id,
Amount = 1
});
}
break;
case PetActionGather.BATTLE:
gathered.Add(new ActionGathered
{
Resource = "Gold",
Amount = (int)(baseRate * (pet.Stats.Strength * 0.25))
});
if (random.Next(0, 100) < 5)
{
pet.Health -= random.Next(5, 10);
}
if (random.Next(0, 100) < 10)
{
gathered.Add(new ActionGathered
{
ItemId = gameItemService.GetRandomItem().Id,
Amount = 1
});
}
break;
}
for (int i = 0; i < gathered.Count; i++)
{
gathered[i].PetId = pet.Id;
}
return gathered;
}
}
}

View File

@@ -16,32 +16,5 @@ namespace PetCompanion.Services
{ {
return _petClassRepository.GetAllPetClassesInfo(); return _petClassRepository.GetAllPetClassesInfo();
} }
public Resources CalculateGatheredResources(PetStats stats, int petLevel, PetActionGather action, DateTime actionSince)
{
var timeElapsed = (DateTime.UtcNow - actionSince).TotalHours;
var resources = new Resources();
if (action == PetActionGather.IDLE)
return resources;
var baseRate = timeElapsed * 0.5 + petLevel; // Base rate per hour
resources.Junk = (int)(baseRate * 2);
switch (action)
{
case PetActionGather.GATHERING_WISDOM:
resources.Wisdom = (int)(baseRate * (stats.Intelligence * 2));
break;
case PetActionGather.GATHERING_GOLD:
resources.Gold = (int)(baseRate * (stats.Charisma * 2));
break;
case PetActionGather.GATHERING_FOOD:
resources.Food = (int)(baseRate * (stats.Strength * 1.5));
break;
}
return resources;
}
} }
} }

View File

@@ -0,0 +1,163 @@
using PetCompanion.Models;
using PetCompanion.Repositories;
namespace PetCompanion.Services
{
public class PetInventoryService
{
private readonly PetInventoryRepository petInventoryRepository;
private readonly PetRepository petRepository;
private readonly GameItemsRepository gameItemsRepository;
private readonly GameItemService gameItemService;
public PetInventoryService(
PetInventoryRepository petInventoryRepository,
PetRepository petRepository,
GameItemsRepository gameItemsRepository,
GameItemService gameItemService)
{
this.petInventoryRepository = petInventoryRepository;
this.petRepository = petRepository;
this.gameItemsRepository = gameItemsRepository;
this.gameItemService = gameItemService;
}
public Inventory GetInventory(string petId, string userId)
{
var pet = petRepository.GetPetById(petId, userId);
if (pet == null)
throw new Exception("Pet not found");
return petInventoryRepository.GetPetInventory(petId);
}
public Inventory CreateInventory(string petId)
{
var inventory = new Inventory
{
PetId = petId,
Capacity = 20,
Items = new List<int>()
};
petInventoryRepository.SavePetInventory(inventory);
return inventory;
}
public Pet UseItem(string petId, string userId, int itemId)
{
var pet = petRepository.GetPetById(petId, userId);
if (pet == null)
throw new Exception("Pet not found");
if (!pet.Inventory.Items.Any(i => i == itemId))
throw new Exception("Item not found in inventory");
var gameItem = gameItemsRepository.GetById(itemId);
gameItemService.ApplyItemEffect(pet, gameItem);
pet.Inventory.Items.Remove(itemId);
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");
if (!pet.Inventory.Items.Any(i => i == itemId))
throw new Exception("Item not found in inventory");
var gameItem = gameItemsRepository.GetById(itemId);
if (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(gameItem.EquipTarget))
{
var equippedItemId = pet.EquippedItems[gameItem.EquipTarget];
UnequipItem(petId, userId, equippedItemId);
}
// Apply equipment effects
gameItemService.ApplyItemEffect(pet, gameItem);
// Mark item as equipped
pet.EquippedItems[gameItem.EquipTarget] = itemId;
// Remove from inventory
pet.Inventory.Items.Remove(itemId);
petInventoryRepository.UpdateEquippedItems(petId, pet.EquippedItems);
return petRepository.UpdatePet(pet);
}
public Pet UnequipItem(string petId, string userId, int itemId)
{
var pet = petRepository.GetPetById(petId, userId);
if (pet == null)
throw new Exception("Pet not found");
var equipTarget = pet.EquippedItems.FirstOrDefault(kvp => kvp.Value == itemId).Key;
if (equipTarget == ItemEquipTarget.None)
throw new Exception("No item equipped in that slot");
var equippedItem = gameItemsRepository.GetById(itemId);
if (equippedItem != null)
{
// Remove equipment effects
gameItemService.RemoveItemEffect(pet, equippedItem);
// Add item back to inventory
pet.Inventory.Items.Add(itemId);
}
pet.EquippedItems.Remove(equipTarget);
return petRepository.UpdatePet(pet);
}
public Pet DropItem(string petId, string userId, int itemId)
{
var pet = petRepository.GetPetById(petId, userId);
if (!pet.Inventory.Items.Any(i => i == itemId))
throw new Exception("Item not found in inventory");
var gameItem = gameItemsRepository.GetById(itemId);
pet.Inventory.Items.Remove(itemId);
return petRepository.UpdatePet(pet);
}
public Pet AddItemToPet(string petId, string userId, int itemId, int quantity)
{
var pet = petRepository.GetPetById(petId, userId);
var gameItem = gameItemsRepository.GetById(itemId);
if (gameItem == null)
throw new Exception("Item not found");
if (pet == null)
throw new Exception("Pet not found");
if (pet.Inventory.Items.Count + quantity > pet.Inventory.Capacity)
throw new Exception("Not enough space in inventory");
for (int i = 0; i < quantity; i++)
{
pet.Inventory.Items.Add(itemId);
}
return petRepository.UpdatePet(pet);
}
}
}

View File

@@ -1,4 +1,5 @@
using PetCompanion.Models; using Microsoft.EntityFrameworkCore.Query;
using PetCompanion.Models;
using PetCompanion.Repositories; using PetCompanion.Repositories;
namespace PetCompanion.Services namespace PetCompanion.Services
@@ -6,32 +7,45 @@ namespace PetCompanion.Services
public class PetService public class PetService
{ {
private readonly PetRepository petRepository; private readonly PetRepository petRepository;
private readonly PetClassService _petClassService; private readonly PetClassService petClassService;
private readonly GameItemService gameItemService;
private readonly GameItemsRepository gameItemsRepository;
private readonly PetInventoryService petInventoryService;
private readonly PetActionService petActionService;
public PetService(PetRepository petRepository, PetClassService petClassService) public PetService(
PetRepository petRepository,
PetClassService petClassService,
GameItemService gameItemService,
GameItemsRepository gameItemsRepository,
PetInventoryService petInventoryService,
PetActionService petActionService)
{ {
this.petRepository = petRepository; this.petRepository = petRepository;
_petClassService = petClassService; this.petClassService = petClassService;
this.gameItemService = gameItemService;
this.gameItemsRepository = gameItemsRepository;
this.petInventoryService = petInventoryService;
this.petActionService = petActionService;
} }
public IEnumerable<Pet> GetAllPets(Guid userId) public IEnumerable<Pet> GetAllPets(string userId)
{ {
return petRepository.GetPetsByUserId(userId.ToString()); return petRepository.GetPetsByUserId(userId);
} }
public Pet CreatePet(Guid userId, PetCreationRequest petRequest) public Pet CreatePet(string userId, PetCreationRequest petRequest)
{ {
var petId = Guid.NewGuid().ToString(); var petId = Guid.NewGuid().ToString();
var pet = new Pet var pet = new Pet
{ {
Id = petId, Id = petId,
UserId = userId.ToString(), UserId = userId,
Name = petRequest.Name, Name = petRequest.Name,
Class = petRequest.Class, Class = petRequest.Class,
Health = 100, Health = 100,
MaxHealth = 100, MaxHealth = 100,
Level = 1, Level = 1,
Experience = 0,
Stats = PetStats.BuildFromClass(petRequest.Class), Stats = PetStats.BuildFromClass(petRequest.Class),
Resources = new Resources(), Resources = new Resources(),
GatherActionSince = DateTime.UtcNow, GatherActionSince = DateTime.UtcNow,
@@ -39,7 +53,11 @@ namespace PetCompanion.Services
IsDead = false IsDead = false
}; };
return petRepository.CreatePet(pet); var createdPet = petRepository.CreatePet(pet);
var inventory = petInventoryService.CreateInventory(petId);
return createdPet;
} }
public Pet UpdatePetAction(string petId, string userId, PetUpdateActionRequest actionRequest) public Pet UpdatePetAction(string petId, string userId, PetUpdateActionRequest actionRequest)
@@ -109,7 +127,7 @@ namespace PetCompanion.Services
} }
} }
public Resources GetGatheredResources(string petId, string userId) public IEnumerable<ActionGathered> GetGatheredResources(string petId, string userId)
{ {
var pet = petRepository.GetPetById(petId, userId); var pet = petRepository.GetPetById(petId, userId);
@@ -118,10 +136,10 @@ namespace PetCompanion.Services
throw new Exception("Pet not found"); throw new Exception("Pet not found");
} }
return _petClassService.CalculateGatheredResources(pet.Stats, pet.Level, pet.PetGatherAction, pet.GatherActionSince); return petActionService.GetGatheredByPet(petId);
} }
public Pet UpdatePetResources(string petId, string userId) public Pet CollectPetGathered(string petId, string userId)
{ {
var pet = petRepository.GetPetById(petId, userId); var pet = petRepository.GetPetById(petId, userId);
if (pet == null) if (pet == null)
@@ -129,15 +147,51 @@ namespace PetCompanion.Services
throw new Exception("Pet not found"); throw new Exception("Pet not found");
} }
var gatheredResources = _petClassService.CalculateGatheredResources(pet.Stats, pet.Level, pet.PetGatherAction, pet.GatherActionSince); var petGathered = petActionService.GetGatheredByPet(petId);
pet.Resources.Wisdom += gatheredResources.Wisdom; if (petGathered == null)
pet.Resources.Gold += gatheredResources.Gold; {
pet.Resources.Food += gatheredResources.Food; throw new Exception("No resources to collect");
pet.Resources.Junk += gatheredResources.Junk; }
pet.GatherActionSince = DateTime.UtcNow;
return petRepository.UpdatePetResources(pet); foreach (var resource in petGathered)
{
if (resource.Resource != null && resource.Resource != string.Empty)
{
switch (resource.Resource)
{
case "Junk":
pet.Resources.Junk += resource.Amount;
break;
case "Food":
pet.Resources.Food += resource.Amount;
break;
case "Gold":
pet.Resources.Gold += resource.Amount;
break;
case "Wisdom":
pet.Resources.Wisdom += resource.Amount;
break;
}
}
else if (resource.ItemId != null && resource.ItemId > 0)
{
petInventoryService.AddItemToPet(petId, userId, resource.ItemId ?? 1, resource.Amount);
}
}
var updatedPet = petRepository.UpdatePet(pet);
petActionService.DeleteAllActionGatheredByPetId(petId);
return updatedPet;
}
public Pet GetPet(string petId, string userId)
{
var pet = petRepository.GetPetById(petId, userId);
if (pet == null)
throw new Exception("Pet not found");
return pet;
} }
} }
} }

View File

@@ -0,0 +1,89 @@
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 IEnumerable<PetSkill> GetPetSkills(string petId, string userId)
{
var pet = _petRepository.GetPetById(petId, userId);
if (pet == null)
throw new Exception("Pet not found");
return _petSkillRepository.GetPetSkills(petId);
}
public PetSkill UpgradeSkill(string petId, string userId, int skillId)
{
var pet = _petRepository.GetPetById(petId, userId);
if (pet == null)
throw new Exception("Pet not found");
var skill = _petSkillRepository.GetSkill(skillId);
if (skill == null)
throw new Exception("Skill not found");
foreach (var req in skill.SkillRequirements)
{
if (req.Resource.ToLower() == "wisdom" && pet.Resources.Wisdom < req.Cost)
throw new Exception("Insufficient resources");
if (req.Resource.ToLower() == "food" && pet.Resources.Food < req.Cost)
throw new Exception("Insufficient resources");
if (req.Resource.ToLower() == "gold" && pet.Resources.Gold < req.Cost)
throw new Exception("Insufficient resources");
if (req.Resource.ToLower() == "junk" && pet.Resources.Junk < req.Cost)
throw new Exception("Insufficient resources");
}
var skills = _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++;
_petSkillRepository.SavePetSkill(existingSkill);
}
else
{
if (!skill.SkillsIdRequired?.TrueForAll(ni => pet.Skills.Any(s => s.SkillId == ni)) ?? false)
{
throw new Exception("Missing required skill");
}
existingSkill = new PetSkill
{
PetId = petId,
SkillId = skillId,
CurrentTier = SkillTier.I
};
_petSkillRepository.SavePetSkill(existingSkill);
}
foreach (var req in skill.SkillRequirements)
{
if (req.Resource.ToLower() == "wisdom") pet.Resources.Wisdom -= req.Cost;
if (req.Resource.ToLower() == "food") pet.Resources.Food -= req.Cost;
if (req.Resource.ToLower() == "gold") pet.Resources.Gold -= req.Cost;
if (req.Resource.ToLower() == "junk") pet.Resources.Junk -= req.Cost;
}
_petRepository.UpdatePet(pet);
return existingSkill;
}
}
}

24
Services/SkillService.cs Normal file
View File

@@ -0,0 +1,24 @@
using PetCompanion.Models;
using PetCompanion.Repositories;
namespace PetCompanion.Services
{
public class SkillService
{
private readonly PetRepository _petRepository;
private readonly PetSkillRepository _petSkillRepository;
public SkillService(
PetRepository petRepository,
PetSkillRepository petSkillRepository)
{
_petRepository = petRepository;
_petSkillRepository = petSkillRepository;
}
public IEnumerable<Skill> GetAvailableSkills()
{
return _petSkillRepository.GetAvailableSkills();
}
}
}

View File

@@ -7,6 +7,6 @@
}, },
"AllowedHosts": "*", "AllowedHosts": "*",
"ConnectionStrings": { "ConnectionStrings": {
"DefaultConnection": "Data Source=petcompanion.db" "DefaultConnection": "Data Source=game-data/petcompanion.db"
} }
} }

View File

@@ -11,6 +11,8 @@
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>
<PackageReference Include="CsvHelper" Version="33.0.1" />
<PackageReference Include="Microsoft.AspNetCore.Authentication.JwtBearer" Version="8.0.13" />
<PackageReference Include="Microsoft.Data.Sqlite" Version="9.0.1" /> <PackageReference Include="Microsoft.Data.Sqlite" Version="9.0.1" />
<PackageReference Include="Microsoft.EntityFrameworkCore.Design" Version="9.0.1"> <PackageReference Include="Microsoft.EntityFrameworkCore.Design" Version="9.0.1">
<PrivateAssets>all</PrivateAssets> <PrivateAssets>all</PrivateAssets>