using DeluxeBackend.Controllers.Matchmaking; using DeluxeBackend.Models; using DeluxeBackend.Services; using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Mvc; using System.Net.NetworkInformation; using static DeluxeBackend.Controllers.Api.PlayerEventsController; using static DeluxeBackend.Enums; namespace DeluxeBackend.Controllers.Api { [Route("api/inventions")] [ApiController] [Authorize(Roles = "gameClient")] public class InventionsController(ILiteDbService db, IJwtService jwt, DiscordBotService discord) : ControllerBase { public class NewInventionRequestDTO { public required string name { get; set; } public required string description { get; set; } public required string imageName { get; set; } public int instantiationCost { get; set; } public int lightsCost { get; set; } public int chipsCost { get; set; } public int cloudVariablesCost { get; set; } public int aiCost { get; set; } public long creationRoomId { get; set; } = -1; public required string inventionDataFilename { get; set; } public required List referencedInventions { get; set; } public RoomRoleType creatorAccountRole { get; set; } } public class AddVersionInventionRequestDTO { public long inventionId { get; set; } public int instantiationCost { get; set; } public int lightsCost { get; set; } public int chipsCost { get; set; } public int cloudVariablesCost { get; set; } public int aiCost { get; set; } public long creationRoomId { get; set; } = -1; public string? inventionDataFilename { get; set; } public List? referencedInventions { get; set; } } [Token(Token = "0x200056D")] public enum FDOIOPFMNJL { [Token(Token = "0x4001262")] Success, [Token(Token = "0x4001263")] InvalidParameters, [Token(Token = "0x4001264")] PlayerCannotUpload, [Token(Token = "0x4001265")] DuplicateName, [Token(Token = "0x4001266")] NameTooShort, [Token(Token = "0x4001267")] NameTooLong, [Token(Token = "0x4001268")] NotCreator, [Token(Token = "0x4001269")] DoesNotExist, [Token(Token = "0x400126A")] ImageDoesNotExist, [Token(Token = "0x400126B")] InventionLimitReached, [Token(Token = "0x400126C")] DescriptionTooLong, [Token(Token = "0x400126D")] InnapropriateName, [Token(Token = "0x400126E")] InnapropriateDescription, [Token(Token = "0x400126F")] CannotBeModified, [Token(Token = "0x4001270")] PlayerCannotPublish, [Token(Token = "0x4001271")] AlreadyPublished, [Token(Token = "0x4001272")] AlreadyUnpublished, [Token(Token = "0x4001273")] InventionUnderModerationReview, [Token(Token = "0x4001274")] PlayerCannotDownload, [Token(Token = "0x4001275")] PlayerAlreadyOwns, [Token(Token = "0x4001276")] DescriptionTooShort, [Token(Token = "0x4001277")] DoesNotHavePermission, [Token(Token = "0x4001278")] PermissionLevelCannotBeChanged, [Token(Token = "0x4001279")] AlreadyCheered, [Token(Token = "0x400127A")] AlreadyRemovedCheer, [Token(Token = "0x400127B")] ModeratorRestrictedPublishing, [Token(Token = "0x400127C")] PlayerCannotSell, [Token(Token = "0x400127D")] InvalidPrice, [Token(Token = "0x400127E")] PriceCannotBeChanged, [Token(Token = "0x400127F")] InvalidPermissionForPaidInvention, [Token(Token = "0x4001280")] PurchaseFailed, [Token(Token = "0x4001281")] CannotDownloadPaidInvention, [Token(Token = "0x4001282")] CannotSellUnownedLineage, [Token(Token = "0x4001283")] DoesNotAllowTrial, [Token(Token = "0x4001284")] StillOnTrialCooldown, [Token(Token = "0x4001285")] PlayerCannotTrial, [Token(Token = "0x4001286")] PaidInventionPublishingDisabled, [Token(Token = "0x4001287")] PaidInventionPurchasingDisabled, [Token(Token = "0x4001288")] OperationIsDisabled, [Token(Token = "0x4001289")] PlayerRestrictedFromP2PSelling, [Token(Token = "0x400128A")] PlayerNotRecRoomPlusMember, [Token(Token = "0x400128B")] InvalidInstantiationCost, [Token(Token = "0x400128C")] FeaturedInventionNotPublished, [Token(Token = "0x400128D")] FeaturedInventionNotActive, [Token(Token = "0x400128E")] InventionContainsBlockedFiles, [Token(Token = "0x400128F")] PlayerRestrictedFromP2PBuying } [HttpGet("v2/mine")] public async Task Mine() { LoginWithInfoResult? login = await jwt.GetLoginWithInfo(User); if (login == null) return Unauthorized(); Account account = login.Account; var downloadedInventions = db.Inventions .Include(x => x.Creator) .Include(x => x.Room) .Find(x => x.DownloadIds.Contains(account.Id)) .Select(x => x.ToDictionary()) .ToList(); return Ok(downloadedInventions); } [HttpPost("v6/save")] public async Task Save([FromBody] NewInventionRequestDTO request) { LoginWithInfoResult? login = await jwt.GetLoginWithInfo(User); if (login == null) return Unauthorized(); Account account = login.Account; if (!account.DiscordId.HasValue) { return Ok(new { Status = (int)FDOIOPFMNJL.PlayerNotRecRoomPlusMember }); } if (!await discord.HasUserBoostedGuild(account.DiscordId.Value)) { return Ok(new { Status = (int)FDOIOPFMNJL.PlayerNotRecRoomPlusMember }); } Room? room = db.Rooms.FindById(request.creationRoomId); if (room == null) return NotFound(); InventionVersion inventionVersion = new() { Id = 1, ReplicationId = Guid.NewGuid(), InstantiationCost = request.instantiationCost, LightsCost = request.lightsCost, ChipsCost = request.chipsCost, CloudVariablesCost = request.cloudVariablesCost, BlobName = request.inventionDataFilename }; Invention invention = new() { ReplicationId = Guid.NewGuid(), Creator = account, Name = request.name, Description = request.description, ImageName = request.imageName, CurrentVersionNumber = 1, Accessibility = RoomAccessibility.Private, Room = room, Versions=[inventionVersion], DownloadIds = [account.Id] }; db.Inventions.Insert(invention); return Ok(new { Status= (int)FDOIOPFMNJL.Success, Invention=invention.ToDictionary(), InventionVersion=inventionVersion.ToDictionary(invention.Id) }); } [HttpGet("v1/versions")] public async Task Versions([FromQuery] long inventionId) { LoginWithInfoResult? login = await jwt.GetLoginWithInfo(User); if (login == null) return Unauthorized(); Account account = login.Account; Invention? invention = db.Inventions.FindById(inventionId); if (invention == null) { return NotFound(); } var versionList = invention.Versions.Select(v => v.ToDictionary(invention.Id)).ToList(); return Ok(versionList); } [HttpPatch("v4/addversion")] public async Task AddVersion([FromBody] AddVersionInventionRequestDTO request) { LoginWithInfoResult? login = await jwt.GetLoginWithInfo(User); if (login == null) return Unauthorized(); Account account = login.Account; Invention? invention = db.Inventions.Include(x => x.Creator).Include(x => x.Room).FindById(request.inventionId); if (invention == null) { return Ok(new { Status = (int)FDOIOPFMNJL.DoesNotExist }); } if (invention.Creator.Id != account.Id) { return Ok(new { Status = (int)FDOIOPFMNJL.NotCreator }); } if (string.IsNullOrEmpty(request.inventionDataFilename)) { return Ok(new { Status = (int)FDOIOPFMNJL.InvalidParameters }); } if (!account.DiscordId.HasValue) { return Ok(new { Status = (int)FDOIOPFMNJL.PlayerNotRecRoomPlusMember }); } if (!await discord.HasUserBoostedGuild(account.DiscordId.Value)) { return Ok(new { Status = (int)FDOIOPFMNJL.PlayerNotRecRoomPlusMember }); } int nextVersionNumber = invention.CurrentVersionNumber + 1; InventionVersion inventionVersion = new() { Id = nextVersionNumber, ReplicationId = Guid.NewGuid(), InstantiationCost = request.instantiationCost, LightsCost = request.lightsCost, ChipsCost = request.chipsCost, CloudVariablesCost = request.cloudVariablesCost, BlobName = request.inventionDataFilename }; invention.Versions.Add(inventionVersion); invention.CurrentVersionNumber = nextVersionNumber; invention.ModifiedAt = DateTime.UtcNow; db.Inventions.Update(invention); return Ok(new { Status = (int)FDOIOPFMNJL.Success, Invention = invention.ToDictionary(), InventionVersion = inventionVersion.ToDictionary(invention.Id) }); } [HttpGet("v2/batch")] [HttpPost("v2/batch")] public async Task Versions([FromQuery(Name = "id")] List? queryIds,[FromForm(Name = "id")] List? formIds) { List id = (queryIds != null && queryIds.Count > 0) ? queryIds : (formIds ?? new List()); LoginWithInfoResult? login = await jwt.GetLoginWithInfo(User); if (login == null) return Unauthorized(); Account account = login.Account; if (id.Count == 0) { return Ok(new List()); } var inventionsBatch = db.Inventions .Find(x => id.Contains(x.Id)) .Select(x => x.ToDictionary()) .ToList(); return Ok(inventionsBatch); } } }