diff --git a/Assets/Src/PowerUnit.cs b/Assets/Src/PowerUnit.cs index 4423ee7..6fa1dbf 100644 --- a/Assets/Src/PowerUnit.cs +++ b/Assets/Src/PowerUnit.cs @@ -32,14 +32,16 @@ public class PowerUnit { static float initialShieldMax = 5000f; float shieldCurrent = initialShieldMax; float shieldMax = initialShieldMax; - float shieldRegen = 10f; // * 100 ticks per second = 5s fully recharge + static float shieldBoostIncrease = 1000f; + static float shieldBoostAmount = 1000f; public float Shield => shieldCurrent; - public float ShieldMax => shieldMax; public string ShieldPct => $"{((shieldCurrent / shieldMax) * 100f):0}"; - float ShieldRegen => BoostActive.Count switch { - 0 => (shieldMax / 5f) * Time.fixedDeltaTime, - _ => 0f, + + bool UsingMovementBoost => BoostActive.Any(b => b.output != Output.Shield); + float ShieldRegen => UsingMovementBoost switch { + false => (shieldMax / 5f) * Time.fixedDeltaTime, + true => 0f, }; // Boost @@ -80,6 +82,8 @@ public class PowerUnit { if (boostAvailable < boostDurationSeconds) return; BoostActive.Add((output, Time.timeAsDouble + boostDurationSeconds)); boostAvailable -= boostDurationSeconds; + + if (output == Output.Shield) ShieldsBoost(); } public void Tick() { @@ -104,7 +108,7 @@ public class PowerUnit { boostProgress = Math.Max(0f, next); if (delta > 0f) boostAvailable = boostProgress; - shieldMax = initialShieldMax + BoostActive.Count(b => b.output == Output.Shield) * 1000f; + ShieldsSetMax(); shieldCurrent = Math.Min(shieldCurrent + ShieldRegen, shieldMax); } @@ -113,4 +117,13 @@ public class PowerUnit { shieldCurrent = shieldCurrent - amt; return shieldCurrent < 0f; } + + void ShieldsBoost() { + ShieldsSetMax(); + shieldCurrent = Math.Min(shieldCurrent + shieldBoostIncrease, shieldMax); + } + + void ShieldsSetMax() { + shieldMax = initialShieldMax + BoostActive.Count(b => b.output == Output.Shield) * shieldBoostAmount; + } } \ No newline at end of file diff --git a/Assets/Src/ShipControls.cs b/Assets/Src/ShipControls.cs index 96b3bef..e72320c 100755 --- a/Assets/Src/ShipControls.cs +++ b/Assets/Src/ShipControls.cs @@ -28,6 +28,8 @@ public class ShipControls : MonoBehaviour { public PowerUnit powerUnit = new(); + public float Speed => rigidBody.velocity.magnitude; + void Start() { Cursor.lockState = CursorLockMode.Locked; rigidBody = GetComponent(); @@ -160,10 +162,6 @@ public class ShipControls : MonoBehaviour { timing.StartTimer(); } - public float Speed() { - return rigidBody.velocity.magnitude; - } - public void Damage(float amt, string src) { Debug.Log($"Damage {amt} from {src}"); diff --git a/Assets/Src/UI/ControlsUI.cs b/Assets/Src/UI/ControlsUI.cs index 2c20050..0640ed5 100644 --- a/Assets/Src/UI/ControlsUI.cs +++ b/Assets/Src/UI/ControlsUI.cs @@ -93,7 +93,7 @@ public class ControlsUI : MonoBehaviour { return; } - speed.text = $"{ship.Speed():0}"; + speed.text = $"{ship.Speed:0}"; shield.detail = ship.powerUnit.ShieldPct switch { "100" => "", string pct => pct, diff --git a/Server/.env b/Server/.env new file mode 100644 index 0000000..c40525f --- /dev/null +++ b/Server/.env @@ -0,0 +1,3 @@ +POSTGRES_USER="spacerace" +POSTGRES_DB="spacerace" +POSTGRES_PASSWORD="zoomzoom" diff --git a/Server/.gitignore b/Server/.gitignore new file mode 100644 index 0000000..fa7d057 --- /dev/null +++ b/Server/.gitignore @@ -0,0 +1,50 @@ +db/ + +# unity ignores these +!*.csproj + +# ----------------- + +*.swp +*.*~ +project.lock.json +.DS_Store +*.pyc +nupkg/ + +# Visual Studio Code +.vscode/ + +# Rider +.idea/ + +# Visual Studio +.vs/ + +# Fleet +.fleet/ + +# Code Rush +.cr/ + +# User-specific files +*.suo +*.user +*.userosscache +*.sln.docstates + +# Build results +[Dd]ebug/ +[Dd]ebugPublic/ +[Rr]elease/ +[Rr]eleases/ +x64/ +x86/ +build/ +bld/ +[Bb]in/ +[Oo]bj/ +[Oo]ut/ +msbuild.log +msbuild.err +msbuild.wrn \ No newline at end of file diff --git a/Server/Controllers/CompletionController.cs b/Server/Controllers/CompletionController.cs new file mode 100644 index 0000000..831ed03 --- /dev/null +++ b/Server/Controllers/CompletionController.cs @@ -0,0 +1,43 @@ +using Microsoft.AspNetCore.Mvc; + +using Server.Models; + +namespace Server.Controllers; + +[ApiController] +[Route("[controller]")] +public class CompletionController : ControllerBase { + private readonly ILogger _logger; + private SpaceRaceDbContext _db; + + public CompletionController(ILogger logger, SpaceRaceDbContext db) { + _logger = logger; + _db = db; + } + + [HttpGet()] + public IEnumerable Get() { + return _db.Completions.Select(c => new CompletionDTO { + Id = c.Id, + UserId = c.UserId, + Map = c.Map, + Time = c.Time, + Date = c.Date, + }); + } + + [HttpPost()] + public async Task Post(CompletionDTO dto) { + Completion v = new Completion { + Id = Guid.NewGuid(), + UserId = Guid.NewGuid(), + Map = dto.Map, + Time = dto.Time, + Date = DateTimeOffset.UtcNow, + }; + + _db.Completions.Add(v); + await _db.SaveChangesAsync(); + return v; + } +} diff --git a/Server/Dockerfile b/Server/Dockerfile new file mode 100644 index 0000000..7e1e498 --- /dev/null +++ b/Server/Dockerfile @@ -0,0 +1,15 @@ +FROM mcr.microsoft.com/dotnet/sdk:7.0 AS build-env +WORKDIR /App + +# stops restore during build +COPY Server.csproj ./ +RUN dotnet restore + +COPY . ./ +RUN dotnet publish -c Release -o out + +# Build runtime image +FROM mcr.microsoft.com/dotnet/aspnet:7.0 +WORKDIR /App +COPY --from=build-env /App/out . +ENTRYPOINT ["dotnet", "Server.dll"] diff --git a/Server/Migrations/20230823032740_Beginninging.Designer.cs b/Server/Migrations/20230823032740_Beginninging.Designer.cs new file mode 100644 index 0000000..ffca26a --- /dev/null +++ b/Server/Migrations/20230823032740_Beginninging.Designer.cs @@ -0,0 +1,58 @@ +// +using System; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; +using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata; +using Server; + +#nullable disable + +namespace Server.Migrations +{ + [DbContext(typeof(SpaceRaceDbContext))] + [Migration("20230823032740_Beginninging")] + partial class Beginninging + { + /// + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasAnnotation("ProductVersion", "7.0.10") + .HasAnnotation("Relational:MaxIdentifierLength", 63); + + NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder); + + modelBuilder.Entity("Server.Completion", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("Date") + .HasColumnType("timestamp with time zone"); + + b.Property("Map") + .IsRequired() + .HasColumnType("text"); + + b.Property("Time") + .HasColumnType("double precision"); + + b.Property("UserId") + .HasColumnType("uuid"); + + b.HasKey("Id"); + + b.HasIndex("Map"); + + b.HasIndex("UserId"); + + b.ToTable("Completions"); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/Server/Migrations/20230823032740_Beginninging.cs b/Server/Migrations/20230823032740_Beginninging.cs new file mode 100644 index 0000000..f28929b --- /dev/null +++ b/Server/Migrations/20230823032740_Beginninging.cs @@ -0,0 +1,47 @@ +using System; +using Microsoft.EntityFrameworkCore.Migrations; + +#nullable disable + +namespace Server.Migrations +{ + /// + public partial class Beginninging : Migration + { + /// + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.CreateTable( + name: "Completions", + columns: table => new + { + Id = table.Column(type: "uuid", nullable: false), + Date = table.Column(type: "timestamp with time zone", nullable: false), + UserId = table.Column(type: "uuid", nullable: false), + Map = table.Column(type: "text", nullable: false), + Time = table.Column(type: "double precision", nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_Completions", x => x.Id); + }); + + migrationBuilder.CreateIndex( + name: "IX_Completions_Map", + table: "Completions", + column: "Map"); + + migrationBuilder.CreateIndex( + name: "IX_Completions_UserId", + table: "Completions", + column: "UserId"); + } + + /// + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropTable( + name: "Completions"); + } + } +} diff --git a/Server/Migrations/SpaceRaceDbContextModelSnapshot.cs b/Server/Migrations/SpaceRaceDbContextModelSnapshot.cs new file mode 100644 index 0000000..86cf5d3 --- /dev/null +++ b/Server/Migrations/SpaceRaceDbContextModelSnapshot.cs @@ -0,0 +1,55 @@ +// +using System; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; +using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata; +using Server; + +#nullable disable + +namespace Server.Migrations +{ + [DbContext(typeof(SpaceRaceDbContext))] + partial class SpaceRaceDbContextModelSnapshot : ModelSnapshot + { + protected override void BuildModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasAnnotation("ProductVersion", "7.0.10") + .HasAnnotation("Relational:MaxIdentifierLength", 63); + + NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder); + + modelBuilder.Entity("Server.Completion", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("Date") + .HasColumnType("timestamp with time zone"); + + b.Property("Map") + .IsRequired() + .HasColumnType("text"); + + b.Property("Time") + .HasColumnType("double precision"); + + b.Property("UserId") + .HasColumnType("uuid"); + + b.HasKey("Id"); + + b.HasIndex("Map"); + + b.HasIndex("UserId"); + + b.ToTable("Completions"); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/Server/Models/CompletionDTO.cs b/Server/Models/CompletionDTO.cs new file mode 100644 index 0000000..e47b25b --- /dev/null +++ b/Server/Models/CompletionDTO.cs @@ -0,0 +1,9 @@ +namespace Server.Models; + +public class CompletionDTO { + public DateTimeOffset Date { get; set; } + public Guid Id { get; set; } + public Guid UserId { get; set; } + public string Map { get; set; } + public double Time { get; set; } +} diff --git a/Server/Program.cs b/Server/Program.cs new file mode 100644 index 0000000..3cf1645 --- /dev/null +++ b/Server/Program.cs @@ -0,0 +1,34 @@ +using Microsoft.EntityFrameworkCore; + +using Server; + +var builder = WebApplication.CreateBuilder(args); + +builder.Services.AddControllers(); +builder.Services.AddDbContextPool(options => { + options.UseNpgsql( + builder.Configuration.GetConnectionString("SpaceRace"), + assembly => assembly.MigrationsAssembly(typeof(SpaceRaceDbContext).Assembly.FullName) + ); +}); + +var app = builder.Build(); + +UpdateDatabase(app); + +app.UseHttpsRedirection(); +app.UseAuthorization(); +app.MapControllers(); + +app.Run(); + +void UpdateDatabase(IApplicationBuilder app) { + try { + using var serviceScope = app.ApplicationServices.GetRequiredService().CreateScope(); + using var context = serviceScope.ServiceProvider.GetService(); + context?.Database.Migrate(); + } catch (Exception e) { + Console.Error.WriteLine("Error migrating db. {0}", e); + System.Environment.Exit(1); + } +} diff --git a/Server/Properties/launchSettings.json b/Server/Properties/launchSettings.json new file mode 100644 index 0000000..b26525b --- /dev/null +++ b/Server/Properties/launchSettings.json @@ -0,0 +1,41 @@ +{ + "$schema": "https://json.schemastore.org/launchsettings.json", + "iisSettings": { + "windowsAuthentication": false, + "anonymousAuthentication": true, + "iisExpress": { + "applicationUrl": "http://0.0.0.0:58932", + "sslPort": 44337 + } + }, + "profiles": { + "http": { + "commandName": "Project", + "dotnetRunMessages": true, + "launchBrowser": true, + "launchUrl": "", + "applicationUrl": "http://0.0.0.0:80", + "environmentVariables": { + "ASPNETCORE_ENVIRONMENT": "Development" + } + }, + "https": { + "commandName": "Project", + "dotnetRunMessages": true, + "launchBrowser": true, + "launchUrl": "", + "applicationUrl": "https://0.0.0.0:7246;http://0.0.0.0:5212", + "environmentVariables": { + "ASPNETCORE_ENVIRONMENT": "Development" + } + }, + "IIS Express": { + "commandName": "IISExpress", + "launchBrowser": true, + "launchUrl": "swagger", + "environmentVariables": { + "ASPNETCORE_ENVIRONMENT": "Development" + } + } + } +} diff --git a/Server/Repositories/SpaceRaceDbContext.cs b/Server/Repositories/SpaceRaceDbContext.cs new file mode 100644 index 0000000..c300c2f --- /dev/null +++ b/Server/Repositories/SpaceRaceDbContext.cs @@ -0,0 +1,19 @@ +using Microsoft.EntityFrameworkCore; +using System.ComponentModel.DataAnnotations; + +namespace Server; + +public class SpaceRaceDbContext : DbContext { + public DbSet Completions { get; set; } + public SpaceRaceDbContext(DbContextOptions options) : base(options) {} +} + +[Index(nameof(UserId))] +[Index(nameof(Map))] +public class Completion { + public DateTimeOffset Date { get; set; } + public Guid Id { get; set; } + public Guid UserId { get; set; } + [Required] public string Map { get; set; } + public double Time { get; set; } +} diff --git a/Server/Server.csproj b/Server/Server.csproj new file mode 100644 index 0000000..0c09921 --- /dev/null +++ b/Server/Server.csproj @@ -0,0 +1,19 @@ + + + + net7.0 + disable + enable + + + + + + runtime; build; native; contentfiles; analyzers; buildtransitive + all + + + + + + diff --git a/Server/appsettings.Development.json b/Server/appsettings.Development.json new file mode 100644 index 0000000..a32e316 --- /dev/null +++ b/Server/appsettings.Development.json @@ -0,0 +1,11 @@ +{ + "ConnectionStrings": { + "SpaceRace": "Server=localhost;Port=45432;Database=spacerace;User Id=spacerace;Password=zoomzoom", + }, + "Logging": { + "LogLevel": { + "Default": "Information", + "Microsoft.AspNetCore": "Warning" + } + } +} diff --git a/Server/appsettings.json b/Server/appsettings.json new file mode 100644 index 0000000..10f68b8 --- /dev/null +++ b/Server/appsettings.json @@ -0,0 +1,9 @@ +{ + "Logging": { + "LogLevel": { + "Default": "Information", + "Microsoft.AspNetCore": "Warning" + } + }, + "AllowedHosts": "*" +} diff --git a/Server/common.yaml b/Server/common.yaml new file mode 100644 index 0000000..3167d7c --- /dev/null +++ b/Server/common.yaml @@ -0,0 +1,9 @@ +services: + pg: + image: postgres:latest + environment: + POSTGRES_USER: '${POSTGRES_USER}' + POSTGRES_DB: '${POSTGRES_DB}' + POSTGRES_PASSWORD: '${POSTGRES_PASSWORD}' + ports: + - '45432:5432' diff --git a/Server/docker-compose.PROD.yaml b/Server/docker-compose.PROD.yaml new file mode 100644 index 0000000..c9d01fe --- /dev/null +++ b/Server/docker-compose.PROD.yaml @@ -0,0 +1,16 @@ +services: + pg: + extends: + file: common.yaml + service: pg + + server: + ports: + - '40080:80' + depends_on: + - 'pg' + environment: + CONNECTIONSTRINGS__SPACERACE: "Server=pg;Port=5432;Database=${POSTGRES_DB};User Id=${POSTGRES_USER};Password=${POSTGRES_PASSWORD}" + build: + context: . + dockerfile: ./Dockerfile diff --git a/Server/docker-compose.yaml b/Server/docker-compose.yaml new file mode 100644 index 0000000..a89d960 --- /dev/null +++ b/Server/docker-compose.yaml @@ -0,0 +1,19 @@ +services: + pg: + extends: + file: common.yaml + service: pg + + server: + image: mcr.microsoft.com/dotnet/sdk:7.0 + depends_on: + - 'pg' + ports: + - '40080:80' + environment: + CONNECTIONSTRINGS__SPACERACE: "Server=pg;Port=5432;Database=${POSTGRES_DB};User Id=${POSTGRES_USER};Password=${POSTGRES_PASSWORD}" + command: dotnet watch + working_dir: "/App" + volumes: + - "./:/App" + diff --git a/TODO.md b/TODO.md index 055b6db..fc68363 100644 --- a/TODO.md +++ b/TODO.md @@ -1,16 +1,15 @@ # SpaceRace! -- controls UI - - output boost indicators +- post times to server + - in theory yes + - rename completions to laps with migration - controls diagram - -- shield regen bug + - mouse / controller sens + - invert y - git lfs -- post times to server - - models - liquidator - cruise craft racing @@ -38,4 +37,8 @@ - pings ship - clears slowly to show most often used line +- track around star + +- track on rings of saturn + - whatever song opens tozzi's delayed mix is bgm \ No newline at end of file