using System.Threading.Tasks; using System.Collections.Generic; using GameAuthApi.Models; using Microsoft.Extensions.Configuration; using MongoDB.Bson; using MongoDB.Driver; namespace GameAuthApi.Services; public class LocationService { private readonly IMongoCollection _locations; public LocationService(IConfiguration config) { var client = new MongoClient(config["MongoDB:ConnectionString"]); var db = client.GetDatabase(config["MongoDB:DatabaseName"]); _locations = db.GetCollection("Locations"); } public virtual async Task GetByIdAsync(string id) { if (!ObjectId.TryParse(id, out _)) return null; // prevent crash if id is invalid return await _locations.Find(x => x.Id == id).FirstOrDefaultAsync(); } public virtual async Task CreateAsync(Location loc) => await _locations.InsertOneAsync(loc); public virtual async Task DeleteAsync(string id) => await _locations.DeleteOneAsync(loc => loc.Id == id); public virtual async Task> GetByTypeAsync(string type) { return await _locations.Find(l => l.LocationType == type).ToListAsync(); } public virtual async Task DeleteByTypeAsync(string type) => await _locations.DeleteManyAsync(l => l.LocationType == type); public virtual async Task DeleteAllAsync() => await _locations.DeleteManyAsync(_ => true); public virtual async Task UpdateAsync(Location loc) => await _locations.ReplaceOneAsync(l => l.Id == loc.Id, loc); public virtual async Task AddPlayerToLocationAsync(string locationId, string playerId) { var update = Builders.Update.AddToSet(l => l.Players, playerId); await _locations.UpdateOneAsync(l => l.Id == locationId, update); } public virtual async Task GetByCoordinatesAsync(int x, int y, int z) { return await _locations.Find(loc => loc.X == x && loc.Y == y && loc.Z == z).FirstOrDefaultAsync(); } public virtual async Task GetSpawnLocationAsync() { return await _locations.Find(loc => loc.X == 0 && loc.Y == 0).FirstOrDefaultAsync(); } public virtual async Task RemovePlayerFromLocationAsync(string locationId, string playerId) { var update = Builders.Update.Pull(l => l.Players, playerId); await _locations.UpdateOneAsync(l => l.Id == locationId, update); } public virtual async Task AddItemToLocationAsync(string locationId, string itemId) { if (!ObjectId.TryParse(locationId, out _) || !ObjectId.TryParse(itemId, out _)) return; var idFilter = Builders.Filter.Eq(l => l.Id, locationId); // if the Content array is null, initialize it first // use a raw BsonDocument filter to avoid casting BsonNull to an ObjectId var nullFilter = idFilter & new BsonDocument("Content", BsonNull.Value); var initArray = Builders.Update.Set(l => l.Content, new List()); await _locations.UpdateOneAsync(nullFilter, initArray); var update = Builders.Update.Push(l => l.Content, itemId); await _locations.UpdateOneAsync(idFilter, update); } public virtual async Task RemoveItemFromLocationAsync(string locationId, string itemId) { if (!ObjectId.TryParse(locationId, out _) || !ObjectId.TryParse(itemId, out _)) return; // check that the Content array exists by using a raw BsonDocument filter var filter = Builders.Filter.Eq(l => l.Id, locationId) & new BsonDocument("Content", new BsonDocument("$ne", BsonNull.Value)); var update = Builders.Update.Pull(l => l.Content, itemId); await _locations.UpdateOneAsync(filter, update); } public virtual async Task ClearAllItemsAsync() { var update = Builders.Update.Set(l => l.Content, new List()); await _locations.UpdateManyAsync(_ => true, update); } }