adding resources

This commit is contained in:
hz
2026-05-18 15:05:55 -05:00
parent 32b953aa61
commit 6366ca46c6
11 changed files with 363 additions and 13 deletions
@@ -6,17 +6,19 @@ namespace LocationsApi.Services;
public class LocationService
{
private readonly IMongoCollection<Location> _locations;
private readonly ResourceService _resources;
private readonly int _homeMinDistance;
private readonly int _homeSearchRadius;
private readonly int _visibilityDepth;
public LocationService(IConfiguration cfg)
public LocationService(IConfiguration cfg, ResourceService resources)
{
var connectionString = cfg["MongoDB:ConnectionString"] ?? "mongodb://127.0.0.1:27017";
var databaseName = cfg["MongoDB:DatabaseName"] ?? "territory-autobattler";
var client = new MongoClient(connectionString);
var database = client.GetDatabase(databaseName);
_locations = database.GetCollection<Location>("Locations");
_resources = resources;
_homeMinDistance = int.TryParse(cfg["World:HomeMinDistance"], out var minDistance) ? Math.Max(1, minDistance) : 8;
_homeSearchRadius = int.TryParse(cfg["World:HomeSearchRadius"], out var searchRadius) ? Math.Max(_homeMinDistance, searchRadius) : 80;
_visibilityDepth = int.TryParse(cfg["World:VisibilityDepth"], out var visibilityDepth) ? Math.Max(0, visibilityDepth) : 3;
@@ -117,6 +119,7 @@ public class LocationService
var existingHome = await GetHomeAsync(username);
if (existingHome is not null)
{
await _resources.EnsureAsync(username);
return existingHome;
}
@@ -138,6 +141,7 @@ public class LocationService
var home = await TryCreateHomeAsync(username, candidate.q, candidate.r);
if (home is not null)
{
await _resources.EnsureAsync(username);
return home;
}
@@ -0,0 +1,89 @@
using LocationsApi.Models;
using MongoDB.Driver;
namespace LocationsApi.Services;
public class ResourceService
{
private readonly IMongoCollection<PlayerResources> _resources;
private readonly int _startingGold;
private readonly int _headquartersGoldPerMinute;
public ResourceService(IConfiguration cfg)
{
var connectionString = cfg["MongoDB:ConnectionString"] ?? "mongodb://127.0.0.1:27017";
var databaseName = cfg["MongoDB:DatabaseName"] ?? "territory-autobattler";
var client = new MongoClient(connectionString);
var database = client.GetDatabase(databaseName);
_resources = database.GetCollection<PlayerResources>("PlayerResources");
_startingGold = int.TryParse(cfg["Resources:StartingGold"], out var startingGold) ? Math.Max(0, startingGold) : 100;
_headquartersGoldPerMinute = int.TryParse(cfg["Resources:HeadquartersGoldPerMinute"], out var goldPerMinute)
? Math.Max(0, goldPerMinute)
: 10;
_resources.Indexes.CreateOne(new CreateIndexModel<PlayerResources>(
Builders<PlayerResources>.IndexKeys.Ascending(x => x.Username),
new CreateIndexOptions { Unique = true }));
}
public async Task<PlayerResources> EnsureAsync(string username)
{
var now = DateTime.UtcNow;
var update = Builders<PlayerResources>.Update
.SetOnInsert(x => x.Username, username)
.SetOnInsert(x => x.Gold, _startingGold)
.SetOnInsert(x => x.CreatedAtUtc, now)
.SetOnInsert(x => x.LastGoldGeneratedAtUtc, now)
.Set(x => x.GoldPerMinute, _headquartersGoldPerMinute)
.Set(x => x.UpdatedAtUtc, now);
var resources = await _resources.FindOneAndUpdateAsync(
x => x.Username == username,
update,
new FindOneAndUpdateOptions<PlayerResources>
{
IsUpsert = true,
ReturnDocument = ReturnDocument.After
});
return await ApplyGoldGenerationAsync(resources);
}
public async Task<PlayerResources> GetAsync(string username)
{
var resources = await EnsureAsync(username);
return await ApplyGoldGenerationAsync(resources);
}
private async Task<PlayerResources> ApplyGoldGenerationAsync(PlayerResources resources)
{
if (resources.GoldPerMinute <= 0)
{
return resources;
}
var now = DateTime.UtcNow;
var elapsed = now - resources.LastGoldGeneratedAtUtc;
var elapsedMinutes = (int)Math.Floor(elapsed.TotalMinutes);
if (elapsedMinutes <= 0)
{
return resources;
}
var generatedGold = elapsedMinutes * resources.GoldPerMinute;
var generationTimestamp = resources.LastGoldGeneratedAtUtc.AddMinutes(elapsedMinutes);
var update = Builders<PlayerResources>.Update
.Inc(x => x.Gold, generatedGold)
.Set(x => x.GoldPerMinute, _headquartersGoldPerMinute)
.Set(x => x.LastGoldGeneratedAtUtc, generationTimestamp)
.Set(x => x.UpdatedAtUtc, now);
return await _resources.FindOneAndUpdateAsync(
x => x.Username == resources.Username,
update,
new FindOneAndUpdateOptions<PlayerResources>
{
ReturnDocument = ReturnDocument.After
});
}
}