mirror of
https://github.com/Stone-Red-Code/TextLore.git
synced 2026-09-08 07:56:03 +02:00
Optimize code structure
This commit is contained in:
@@ -1,7 +1,9 @@
|
|||||||
@inherits LayoutComponentBase
|
@inherits LayoutComponentBase
|
||||||
|
|
||||||
<div class="fixed-top p-4">
|
<div class="fixed-top p-4">
|
||||||
<h1 class="text-white-50 mb-0">TextLore — Stone_Red</h1>
|
<a href="/" class="text-decoration-none">
|
||||||
|
<h1 class="text-white-50 mb-0">TextLore — Stone_Red</h1>
|
||||||
|
</a>
|
||||||
<div>
|
<div>
|
||||||
<a class="link-info" href="https://github.me.stone-red.net/TextLore">https://github.me.stone-red.net/TextLore</a>
|
<a class="link-info" href="https://github.me.stone-red.net/TextLore">https://github.me.stone-red.net/TextLore</a>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -1,18 +0,0 @@
|
|||||||
@page "/counter"
|
|
||||||
|
|
||||||
<PageTitle>Counter</PageTitle>
|
|
||||||
|
|
||||||
<h1>Counter</h1>
|
|
||||||
|
|
||||||
<p role="status">Current count: @currentCount</p>
|
|
||||||
|
|
||||||
<button class="btn btn-primary" @onclick="IncrementCount">Click me</button>
|
|
||||||
|
|
||||||
@code {
|
|
||||||
private int currentCount = 0;
|
|
||||||
|
|
||||||
private void IncrementCount()
|
|
||||||
{
|
|
||||||
currentCount++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
+12
-9
@@ -1,11 +1,11 @@
|
|||||||
using Microsoft.AspNetCore.Components;
|
using Microsoft.AspNetCore.Components;
|
||||||
|
|
||||||
using TextLore.Console;
|
using TextLore.Console;
|
||||||
using TextLore.Console.Commands;
|
using TextLore.Shared.Commands;
|
||||||
using TextLore.Games.Roguelike.Commands;
|
using TextLore.Shared.Logic;
|
||||||
using TextLore.Games.Roguelike.Models;
|
using TextLore.Shared.Models.Level;
|
||||||
|
|
||||||
namespace TextLore.Games.Roguelike;
|
namespace TextLore.Components.Pages.Games.Roguelike;
|
||||||
|
|
||||||
public partial class RoguelikePage
|
public partial class RoguelikePage
|
||||||
{
|
{
|
||||||
@@ -14,30 +14,33 @@ public partial class RoguelikePage
|
|||||||
// Short description how to play the game
|
// Short description how to play the game
|
||||||
private readonly string desctiption = "This is a roguelike game. Use commands to play the game.";
|
private readonly string desctiption = "This is a roguelike game. Use commands to play the game.";
|
||||||
|
|
||||||
private Components.Shared.Console console = null!;
|
private Shared.Console console = null!;
|
||||||
private HelpCommand? helpCommand;
|
private HelpCommand? helpCommand;
|
||||||
|
|
||||||
private Level? level;
|
private GameManager? gameManager = null;
|
||||||
|
|
||||||
[Parameter]
|
[Parameter]
|
||||||
public string Seed { get; set; } = string.Empty;
|
public string Seed { get; set; } = string.Empty;
|
||||||
|
|
||||||
public void OnLevelGenerated(Level level)
|
public async void OnLevelGenerated(Level level)
|
||||||
{
|
{
|
||||||
this.level = level;
|
gameManager = new GameManager(level);
|
||||||
|
|
||||||
|
StateHasChanged();
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override void OnInitialized()
|
protected override void OnInitialized()
|
||||||
{
|
{
|
||||||
helpCommand = new HelpCommand(commands);
|
helpCommand = new HelpCommand(commands);
|
||||||
commands.Add(helpCommand);
|
commands.Add(helpCommand);
|
||||||
|
commands.Add(new ExitCommand(NavigationManager));
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override async Task OnAfterRenderAsync(bool firstRender)
|
protected override async Task OnAfterRenderAsync(bool firstRender)
|
||||||
{
|
{
|
||||||
if (firstRender)
|
if (firstRender)
|
||||||
{
|
{
|
||||||
await console.Execute(new GenerateLevelCommand(DatabaseContext.Rooms, NavigationManager, OnLevelGenerated), Seed);
|
await console.Execute(new GenerateLevelCommand("roguelike", DatabaseContext.Rooms, NavigationManager, OnLevelGenerated), Seed);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
+1
-1
@@ -11,4 +11,4 @@
|
|||||||
@using TextLore.Components
|
@using TextLore.Components
|
||||||
@using TextLore.Components.Shared
|
@using TextLore.Components.Shared
|
||||||
@using TextLore.Console
|
@using TextLore.Console
|
||||||
@using TextLore.Console.Commands
|
@using TextLore.Shared.Commands
|
||||||
@@ -1,5 +1,7 @@
|
|||||||
@page "/"
|
@page "/"
|
||||||
|
|
||||||
|
@inject NavigationManager NavigationManager
|
||||||
|
|
||||||
<PageTitle>TextLore</PageTitle>
|
<PageTitle>TextLore</PageTitle>
|
||||||
|
|
||||||
<Console Name="Main Menu" Commands="commands" Description="@desctiption" HelpCommand="helpCommand" />
|
<Console Name="Main Menu" Commands="commands" Description="@desctiption" HelpCommand="helpCommand" />
|
||||||
@@ -16,5 +18,6 @@
|
|||||||
{
|
{
|
||||||
helpCommand = new HelpCommand(commands);
|
helpCommand = new HelpCommand(commands);
|
||||||
commands.Add(helpCommand);
|
commands.Add(helpCommand);
|
||||||
|
commands.Add(new PlayCommand(NavigationManager, "roguelike"));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,64 +0,0 @@
|
|||||||
@page "/weather"
|
|
||||||
@attribute [StreamRendering]
|
|
||||||
|
|
||||||
<PageTitle>Weather</PageTitle>
|
|
||||||
|
|
||||||
<h1>Weather</h1>
|
|
||||||
|
|
||||||
<p>This component demonstrates showing data.</p>
|
|
||||||
|
|
||||||
@if (forecasts == null)
|
|
||||||
{
|
|
||||||
<p><em>Loading...</em></p>
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
<table class="table">
|
|
||||||
<thead>
|
|
||||||
<tr>
|
|
||||||
<th>Date</th>
|
|
||||||
<th>Temp. (C)</th>
|
|
||||||
<th>Temp. (F)</th>
|
|
||||||
<th>Summary</th>
|
|
||||||
</tr>
|
|
||||||
</thead>
|
|
||||||
<tbody>
|
|
||||||
@foreach (var forecast in forecasts)
|
|
||||||
{
|
|
||||||
<tr>
|
|
||||||
<td>@forecast.Date.ToShortDateString()</td>
|
|
||||||
<td>@forecast.TemperatureC</td>
|
|
||||||
<td>@forecast.TemperatureF</td>
|
|
||||||
<td>@forecast.Summary</td>
|
|
||||||
</tr>
|
|
||||||
}
|
|
||||||
</tbody>
|
|
||||||
</table>
|
|
||||||
}
|
|
||||||
|
|
||||||
@code {
|
|
||||||
private WeatherForecast[]? forecasts;
|
|
||||||
|
|
||||||
protected override async Task OnInitializedAsync()
|
|
||||||
{
|
|
||||||
// Simulate asynchronous loading to demonstrate streaming rendering
|
|
||||||
await Task.Delay(500);
|
|
||||||
|
|
||||||
var startDate = DateOnly.FromDateTime(DateTime.Now);
|
|
||||||
var summaries = new[] { "Freezing", "Bracing", "Chilly", "Cool", "Mild", "Warm", "Balmy", "Hot", "Sweltering", "Scorching" };
|
|
||||||
forecasts = Enumerable.Range(1, 5).Select(index => new WeatherForecast
|
|
||||||
{
|
|
||||||
Date = startDate.AddDays(index),
|
|
||||||
TemperatureC = Random.Shared.Next(-20, 55),
|
|
||||||
Summary = summaries[Random.Shared.Next(summaries.Length)]
|
|
||||||
}).ToArray();
|
|
||||||
}
|
|
||||||
|
|
||||||
private class WeatherForecast
|
|
||||||
{
|
|
||||||
public DateOnly Date { get; set; }
|
|
||||||
public int TemperatureC { get; set; }
|
|
||||||
public string? Summary { get; set; }
|
|
||||||
public int TemperatureF => 32 + (int)(TemperatureC / 0.5556);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -56,7 +56,7 @@
|
|||||||
[Parameter]
|
[Parameter]
|
||||||
public Command? HelpCommand { get; set; }
|
public Command? HelpCommand { get; set; }
|
||||||
|
|
||||||
private string Placeholder => $"Enter a command{(HelpCommand is null ? "." : ", type 'help' for avaliable commands.")}";
|
private string Placeholder => disabled ? "Processing..." : $"Enter a command{(HelpCommand is null ? "." : ", type 'help' for avaliable commands.")}";
|
||||||
private ConsoleInput ConsoleInput { get; set; } = new();
|
private ConsoleInput ConsoleInput { get; set; } = new();
|
||||||
private List<ConsoleOutput> consoleOutputs = new();
|
private List<ConsoleOutput> consoleOutputs = new();
|
||||||
private ConsoleOutput? currentOutput;
|
private ConsoleOutput? currentOutput;
|
||||||
|
|||||||
@@ -10,4 +10,4 @@
|
|||||||
@using TextLore.Components
|
@using TextLore.Components
|
||||||
@using TextLore.Components.Shared
|
@using TextLore.Components.Shared
|
||||||
@using TextLore.Console
|
@using TextLore.Console
|
||||||
@using TextLore.Console.Commands
|
@using TextLore.Shared.Commands
|
||||||
@@ -1,8 +1,10 @@
|
|||||||
using Microsoft.EntityFrameworkCore;
|
using Microsoft.EntityFrameworkCore;
|
||||||
|
|
||||||
|
using TextLore.Shared.Models.Level;
|
||||||
|
|
||||||
namespace TextLore.Database;
|
namespace TextLore.Database;
|
||||||
|
|
||||||
public class GamesDatabaseContext(DbContextOptions<GamesDatabaseContext> options) : DbContext(options)
|
public class GamesDatabaseContext(DbContextOptions<GamesDatabaseContext> options) : DbContext(options)
|
||||||
{
|
{
|
||||||
public DbSet<Games.Roguelike.Models.RoomDefinition> Rooms { get; set; }
|
public DbSet<RoomDefinition> Rooms { get; set; }
|
||||||
}
|
}
|
||||||
@@ -2,6 +2,7 @@ using Microsoft.EntityFrameworkCore;
|
|||||||
|
|
||||||
using TextLore.Components;
|
using TextLore.Components;
|
||||||
using TextLore.Database;
|
using TextLore.Database;
|
||||||
|
using TextLore.Shared.Models.Level;
|
||||||
|
|
||||||
WebApplicationBuilder builder = WebApplication.CreateBuilder(args);
|
WebApplicationBuilder builder = WebApplication.CreateBuilder(args);
|
||||||
|
|
||||||
@@ -29,14 +30,14 @@ GamesDatabaseContext databaseContext = serviceScope.ServiceProvider.GetRequiredS
|
|||||||
if (await databaseContext.Database.EnsureCreatedAsync())
|
if (await databaseContext.Database.EnsureCreatedAsync())
|
||||||
{
|
{
|
||||||
databaseContext.Rooms.AddRange(
|
databaseContext.Rooms.AddRange(
|
||||||
new TextLore.Games.Roguelike.Models.RoomDefinition(1, TextLore.Games.Roguelike.Models.RoomTag.Start, "rogelike") { Name = "Start Room" },
|
new RoomDefinition(1, RoomTag.Start, "roguelike") { Name = "Start Room" },
|
||||||
new TextLore.Games.Roguelike.Models.RoomDefinition(1, TextLore.Games.Roguelike.Models.RoomTag.Unique, "rogelike") { Name = "Unique Room" },
|
new RoomDefinition(1, RoomTag.Unique, "roguelike") { Name = "Unique Room" },
|
||||||
new TextLore.Games.Roguelike.Models.RoomDefinition(2, TextLore.Games.Roguelike.Models.RoomTag.None, "rogelike") { Name = "Normal Room 1" },
|
new RoomDefinition(2, RoomTag.None, "roguelike") { Name = "Normal Room 1" },
|
||||||
new TextLore.Games.Roguelike.Models.RoomDefinition(3, TextLore.Games.Roguelike.Models.RoomTag.None, "rogelike") { Name = "Normal Room 2" },
|
new RoomDefinition(3, RoomTag.None, "roguelike") { Name = "Normal Room 2" },
|
||||||
new TextLore.Games.Roguelike.Models.RoomDefinition(4, TextLore.Games.Roguelike.Models.RoomTag.None, "rogelike") { Name = "Normal Room 3" },
|
new RoomDefinition(4, RoomTag.None, "roguelike") { Name = "Normal Room 3" },
|
||||||
new TextLore.Games.Roguelike.Models.RoomDefinition(5, TextLore.Games.Roguelike.Models.RoomTag.None, "rogelike") { Name = "Normal Room 4" },
|
new RoomDefinition(5, RoomTag.None, "roguelike") { Name = "Normal Room 4" },
|
||||||
new TextLore.Games.Roguelike.Models.RoomDefinition(6, TextLore.Games.Roguelike.Models.RoomTag.None, "rogelike") { Name = "Normal Room 5" },
|
new RoomDefinition(6, RoomTag.None, "roguelike") { Name = "Normal Room 5" },
|
||||||
new TextLore.Games.Roguelike.Models.RoomDefinition(1, TextLore.Games.Roguelike.Models.RoomTag.End, "rogelike") { Name = "End Room" }
|
new RoomDefinition(1, RoomTag.End, "roguelike") { Name = "End Room" }
|
||||||
);
|
);
|
||||||
|
|
||||||
_ = await databaseContext.SaveChangesAsync();
|
_ = await databaseContext.SaveChangesAsync();
|
||||||
|
|||||||
+3
-1
@@ -1,4 +1,6 @@
|
|||||||
namespace TextLore.Console.Commands;
|
using TextLore.Console;
|
||||||
|
|
||||||
|
namespace TextLore.Shared.Commands;
|
||||||
|
|
||||||
public class ClearCommand : Command
|
public class ClearCommand : Command
|
||||||
{
|
{
|
||||||
@@ -0,0 +1,17 @@
|
|||||||
|
using TextLore.Console;
|
||||||
|
|
||||||
|
namespace TextLore.Shared.Commands;
|
||||||
|
|
||||||
|
public class EchoCommand : Command
|
||||||
|
{
|
||||||
|
public override string Name => "echo";
|
||||||
|
|
||||||
|
public override string Description => "Echoes the input.";
|
||||||
|
|
||||||
|
public override Task<CommandResult> Execute(ConsoleWriter consoleOutput, string args)
|
||||||
|
{
|
||||||
|
consoleOutput.WriteLine(args);
|
||||||
|
|
||||||
|
return CommandResult.Success();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,21 @@
|
|||||||
|
using Microsoft.AspNetCore.Components;
|
||||||
|
|
||||||
|
using TextLore.Console;
|
||||||
|
|
||||||
|
namespace TextLore.Shared.Commands;
|
||||||
|
|
||||||
|
public class ExitCommand(NavigationManager navigationManager) : Command
|
||||||
|
{
|
||||||
|
public override string Name => "exit";
|
||||||
|
|
||||||
|
public override string Description => "Exits the game.";
|
||||||
|
|
||||||
|
public override Task<CommandResult> Execute(ConsoleWriter consoleOutput, string args)
|
||||||
|
{
|
||||||
|
consoleOutput.WriteLine("Exiting the game...");
|
||||||
|
|
||||||
|
navigationManager.NavigateTo("/");
|
||||||
|
|
||||||
|
return CommandResult.Success();
|
||||||
|
}
|
||||||
|
}
|
||||||
+9
-12
@@ -2,21 +2,18 @@
|
|||||||
using Microsoft.EntityFrameworkCore;
|
using Microsoft.EntityFrameworkCore;
|
||||||
|
|
||||||
using TextLore.Console;
|
using TextLore.Console;
|
||||||
using TextLore.Games.Roguelike.Logic;
|
using TextLore.Shared.Logic;
|
||||||
using TextLore.Games.Roguelike.Models;
|
using TextLore.Shared.Models;
|
||||||
using TextLore.Utilities.Logic;
|
using TextLore.Shared.Models.Level;
|
||||||
using TextLore.Utilities.Models;
|
|
||||||
|
|
||||||
namespace TextLore.Games.Roguelike.Commands;
|
namespace TextLore.Shared.Commands;
|
||||||
|
|
||||||
public class GenerateLevelCommand(IQueryable<RoomDefinition> roomDefinitions, NavigationManager navigationManager, Action<Level> levelGeneratedCallback) : Command
|
public class GenerateLevelCommand(string gameName, IQueryable<RoomDefinition> roomDefinitions, NavigationManager navigationManager, Action<Level> levelGeneratedCallback) : Command
|
||||||
{
|
{
|
||||||
private bool isGenerated = false;
|
private bool isGenerated = false;
|
||||||
public override string Name => "generatelevel";
|
public override string Name => "generatelevel";
|
||||||
public override string Description => "Generates a new level.";
|
public override string Description => "Generates a new level.";
|
||||||
|
|
||||||
public override string[] Aliases => ["genlevel"];
|
|
||||||
|
|
||||||
public override bool NoHistoryIfNoOutput => true;
|
public override bool NoHistoryIfNoOutput => true;
|
||||||
|
|
||||||
public override async Task<CommandResult> Execute(ConsoleWriter consoleOutput, string args)
|
public override async Task<CommandResult> Execute(ConsoleWriter consoleOutput, string args)
|
||||||
@@ -26,12 +23,12 @@ public class GenerateLevelCommand(IQueryable<RoomDefinition> roomDefinitions, Na
|
|||||||
consoleOutput.WriteLine("Invalid seed. Generating a new one...");
|
consoleOutput.WriteLine("Invalid seed. Generating a new one...");
|
||||||
seed = await GenerateSeed();
|
seed = await GenerateSeed();
|
||||||
|
|
||||||
navigationManager.NavigateTo($"/roguelike/{seed.ToBase64()}");
|
navigationManager.NavigateTo($"/{gameName}/{seed.ToBase64()}");
|
||||||
}
|
}
|
||||||
|
|
||||||
consoleOutput.WriteLine("Generating level...");
|
consoleOutput.WriteLine("Generating level...");
|
||||||
|
|
||||||
LevelGenerator levelGenerator = new LevelGenerator(seed, roomDefinitions);
|
LevelGenerator levelGenerator = new LevelGenerator(seed, roomDefinitions.Where(r => r.Game == gameName));
|
||||||
|
|
||||||
IProgress<PercentageProgress> progress = new Progress<PercentageProgress>(p => ReportProgress(p, consoleOutput));
|
IProgress<PercentageProgress> progress = new Progress<PercentageProgress>(p => ReportProgress(p, consoleOutput));
|
||||||
|
|
||||||
@@ -88,8 +85,8 @@ public class GenerateLevelCommand(IQueryable<RoomDefinition> roomDefinitions, Na
|
|||||||
private async Task<DeterministicRandom> GenerateSeed()
|
private async Task<DeterministicRandom> GenerateSeed()
|
||||||
{
|
{
|
||||||
int baseSeed = Guid.NewGuid().GetHashCode();
|
int baseSeed = Guid.NewGuid().GetHashCode();
|
||||||
int min = await roomDefinitions.MinAsync(r => r.Id);
|
int min = await roomDefinitions.Where(r => r.Game == gameName).MinAsync(r => r.Id);
|
||||||
int max = await roomDefinitions.MaxAsync(r => r.Id);
|
int max = await roomDefinitions.Where(r => r.Game == gameName).MaxAsync(r => r.Id);
|
||||||
|
|
||||||
return new DeterministicRandom(baseSeed, min, max);
|
return new DeterministicRandom(baseSeed, min, max);
|
||||||
}
|
}
|
||||||
+3
-1
@@ -1,4 +1,6 @@
|
|||||||
namespace TextLore.Console.Commands;
|
using TextLore.Console;
|
||||||
|
|
||||||
|
namespace TextLore.Shared.Commands;
|
||||||
|
|
||||||
public class HelpCommand(IEnumerable<Command> commands) : Command
|
public class HelpCommand(IEnumerable<Command> commands) : Command
|
||||||
{
|
{
|
||||||
@@ -0,0 +1,49 @@
|
|||||||
|
using Microsoft.AspNetCore.Components;
|
||||||
|
|
||||||
|
using TextLore.Console;
|
||||||
|
|
||||||
|
namespace TextLore.Shared.Commands;
|
||||||
|
|
||||||
|
public class PlayCommand(NavigationManager navigationManager, params string[] gameNames) : Command
|
||||||
|
{
|
||||||
|
public override string Name => "play";
|
||||||
|
|
||||||
|
public override string Description => "Starts a new game.";
|
||||||
|
|
||||||
|
public override string Usage => "play <game> (You only have to type the first few letters of the game name.)";
|
||||||
|
|
||||||
|
public override Task<CommandResult> Execute(ConsoleWriter consoleOutput, string args)
|
||||||
|
{
|
||||||
|
if (string.IsNullOrWhiteSpace(args))
|
||||||
|
{
|
||||||
|
consoleOutput.WriteLine("Available games:");
|
||||||
|
|
||||||
|
foreach (string availableGame in gameNames)
|
||||||
|
{
|
||||||
|
consoleOutput.WriteLine($"- {availableGame}");
|
||||||
|
}
|
||||||
|
|
||||||
|
return Task.FromResult(CommandResult.Failure("You need to specify a game to play."));
|
||||||
|
}
|
||||||
|
|
||||||
|
string? game = Array.Find(gameNames, g => g.StartsWith(args, StringComparison.CurrentCultureIgnoreCase));
|
||||||
|
|
||||||
|
if (game is null)
|
||||||
|
{
|
||||||
|
consoleOutput.WriteLine("Available games:");
|
||||||
|
|
||||||
|
foreach (string availableGame in gameNames)
|
||||||
|
{
|
||||||
|
consoleOutput.WriteLine($"- {availableGame}");
|
||||||
|
}
|
||||||
|
|
||||||
|
return Task.FromResult(CommandResult.Failure($"Game '{args}' not found."));
|
||||||
|
}
|
||||||
|
|
||||||
|
consoleOutput.WriteLine($"Starting game '{game}'...");
|
||||||
|
|
||||||
|
navigationManager.NavigateTo($"/{game}");
|
||||||
|
|
||||||
|
return Task.FromResult(CommandResult.Success());
|
||||||
|
}
|
||||||
|
}
|
||||||
+3
-1
@@ -1,4 +1,6 @@
|
|||||||
namespace TextLore.Console.Commands;
|
using TextLore.Console;
|
||||||
|
|
||||||
|
namespace TextLore.Shared.Commands;
|
||||||
|
|
||||||
public class TestCommand : Command
|
public class TestCommand : Command
|
||||||
{
|
{
|
||||||
+1
-1
@@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
using System.Diagnostics.CodeAnalysis;
|
using System.Diagnostics.CodeAnalysis;
|
||||||
|
|
||||||
namespace TextLore.Utilities.Logic;
|
namespace TextLore.Shared.Logic;
|
||||||
|
|
||||||
public class DeterministicRandom(int seed, int min, int max) : IParsable<DeterministicRandom>
|
public class DeterministicRandom(int seed, int min, int max) : IParsable<DeterministicRandom>
|
||||||
{
|
{
|
||||||
@@ -0,0 +1,63 @@
|
|||||||
|
using Microsoft.ClearScript;
|
||||||
|
using Microsoft.ClearScript.V8;
|
||||||
|
|
||||||
|
using TextLore.Console;
|
||||||
|
using TextLore.Shared.Models;
|
||||||
|
using TextLore.Shared.Models.Level;
|
||||||
|
using TextLore.Shared.Models.Player;
|
||||||
|
|
||||||
|
namespace TextLore.Shared.Logic;
|
||||||
|
|
||||||
|
public partial class GameManager
|
||||||
|
{
|
||||||
|
private readonly V8ScriptEngine scriptEngine = new V8ScriptEngine();
|
||||||
|
|
||||||
|
public PlayState PlayState { get; }
|
||||||
|
|
||||||
|
public GameManager(Level level)
|
||||||
|
{
|
||||||
|
PlayState = new(level, new());
|
||||||
|
|
||||||
|
ScriptContext currentScriptContext = new(() => PlayState.Player, () => PlayState.CurrentRoom?.Definition);
|
||||||
|
|
||||||
|
scriptEngine.AddHostObject("context", currentScriptContext);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void MovePlayer(Direction direction)
|
||||||
|
{
|
||||||
|
Position newPosition = PlayState.Player.Position + direction;
|
||||||
|
if (PlayState.Level.IsPositionInBounds(newPosition))
|
||||||
|
{
|
||||||
|
PlayState.Player.Position = newPosition;
|
||||||
|
|
||||||
|
SetScript(PlayState.CurrentRoom?.Definition.Script ?? string.Empty);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void ExecuteMethod(string method, ConsoleWriter consoleWriter)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
_ = scriptEngine.Invoke(method, consoleWriter);
|
||||||
|
}
|
||||||
|
catch (ScriptEngineException ex)
|
||||||
|
{
|
||||||
|
consoleWriter.WriteLine(ex.Message);
|
||||||
|
}
|
||||||
|
catch (ScriptInterruptedException ex)
|
||||||
|
{
|
||||||
|
consoleWriter.WriteLine(ex.Message);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void SetScript(string script)
|
||||||
|
{
|
||||||
|
scriptEngine.Execute(script);
|
||||||
|
}
|
||||||
|
|
||||||
|
public sealed class ScriptContext(Func<Player> player, Func<RoomDefinition?> room)
|
||||||
|
{
|
||||||
|
public Player Player => player();
|
||||||
|
public RoomDefinition? Room => room();
|
||||||
|
}
|
||||||
|
}
|
||||||
+3
-4
@@ -1,10 +1,9 @@
|
|||||||
using Microsoft.EntityFrameworkCore;
|
using Microsoft.EntityFrameworkCore;
|
||||||
|
|
||||||
using TextLore.Games.Roguelike.Models;
|
using TextLore.Shared.Models;
|
||||||
using TextLore.Utilities.Logic;
|
using TextLore.Shared.Models.Level;
|
||||||
using TextLore.Utilities.Models;
|
|
||||||
|
|
||||||
namespace TextLore.Games.Roguelike.Logic;
|
namespace TextLore.Shared.Logic;
|
||||||
|
|
||||||
public class LevelGenerator(DeterministicRandom seed, IQueryable<RoomDefinition> rooms)
|
public class LevelGenerator(DeterministicRandom seed, IQueryable<RoomDefinition> rooms)
|
||||||
{
|
{
|
||||||
@@ -0,0 +1,13 @@
|
|||||||
|
using TextLore.Shared.Models.Level;
|
||||||
|
using TextLore.Shared.Models.Player;
|
||||||
|
|
||||||
|
namespace TextLore.Shared.Logic;
|
||||||
|
|
||||||
|
public class PlayState(Level level, Player player)
|
||||||
|
{
|
||||||
|
public Level Level { get; } = level;
|
||||||
|
|
||||||
|
public Player Player { get; } = player;
|
||||||
|
|
||||||
|
public Room? CurrentRoom => Level.GetRoom(Player.Position);
|
||||||
|
}
|
||||||
+3
-3
@@ -1,4 +1,4 @@
|
|||||||
namespace TextLore.Utilities.Models;
|
namespace TextLore.Shared.Models;
|
||||||
|
|
||||||
public readonly struct Direction(int x, int y)
|
public readonly struct Direction(int x, int y)
|
||||||
{
|
{
|
||||||
@@ -10,6 +10,6 @@ public readonly struct Direction(int x, int y)
|
|||||||
public static Direction UpRight => new Direction(1, -1);
|
public static Direction UpRight => new Direction(1, -1);
|
||||||
public static Direction DownLeft => new Direction(-1, 1);
|
public static Direction DownLeft => new Direction(-1, 1);
|
||||||
public static Direction DownRight => new Direction(1, 1);
|
public static Direction DownRight => new Direction(1, 1);
|
||||||
public int X { get; } = x;
|
public int X => x;
|
||||||
public int Y { get; } = y;
|
public int Y => y;
|
||||||
}
|
}
|
||||||
+3
-3
@@ -1,7 +1,7 @@
|
|||||||
using TextLore.Utilities.Logic;
|
using TextLore.Shared.Logic;
|
||||||
using TextLore.Utilities.Models;
|
using TextLore.Shared.Models;
|
||||||
|
|
||||||
namespace TextLore.Games.Roguelike.Models;
|
namespace TextLore.Shared.Models.Level;
|
||||||
|
|
||||||
public class Level(Size size, DeterministicRandom seed)
|
public class Level(Size size, DeterministicRandom seed)
|
||||||
{
|
{
|
||||||
+2
-2
@@ -1,6 +1,6 @@
|
|||||||
using TextLore.Utilities.Models;
|
using TextLore.Shared.Models;
|
||||||
|
|
||||||
namespace TextLore.Games.Roguelike.Models;
|
namespace TextLore.Shared.Models.Level;
|
||||||
|
|
||||||
public class Room(Position position, RoomDefinition roomDefinition)
|
public class Room(Position position, RoomDefinition roomDefinition)
|
||||||
{
|
{
|
||||||
+1
-1
@@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
using System.ComponentModel.DataAnnotations.Schema;
|
using System.ComponentModel.DataAnnotations.Schema;
|
||||||
|
|
||||||
namespace TextLore.Games.Roguelike.Models;
|
namespace TextLore.Shared.Models.Level;
|
||||||
|
|
||||||
[PrimaryKey(nameof(Id), nameof(Tag), nameof(Game))]
|
[PrimaryKey(nameof(Id), nameof(Tag), nameof(Game))]
|
||||||
public class RoomDefinition(int id, RoomTag tag, string game)
|
public class RoomDefinition(int id, RoomTag tag, string game)
|
||||||
+1
-1
@@ -1,4 +1,4 @@
|
|||||||
namespace TextLore.Games.Roguelike.Models;
|
namespace TextLore.Shared.Models.Level;
|
||||||
|
|
||||||
public enum RoomTag
|
public enum RoomTag
|
||||||
{
|
{
|
||||||
@@ -0,0 +1,9 @@
|
|||||||
|
namespace TextLore.Shared.Models;
|
||||||
|
|
||||||
|
public readonly struct PercentageProgress(int current, int total)
|
||||||
|
{
|
||||||
|
public int Current => current;
|
||||||
|
public int Total => total;
|
||||||
|
public int Percentage => (int)((double)Current / Total * 100);
|
||||||
|
public bool IsComplete => Current >= Total;
|
||||||
|
}
|
||||||
@@ -0,0 +1,10 @@
|
|||||||
|
namespace TextLore.Shared.Models.Player;
|
||||||
|
|
||||||
|
public class InventoryItem(string name, string description, string tag)
|
||||||
|
{
|
||||||
|
public string Name { get; set; } = name;
|
||||||
|
|
||||||
|
public string Description { get; set; } = description;
|
||||||
|
|
||||||
|
public string Tag { get; set; } = tag;
|
||||||
|
}
|
||||||
@@ -0,0 +1,10 @@
|
|||||||
|
namespace TextLore.Shared.Models.Player;
|
||||||
|
|
||||||
|
public class Player
|
||||||
|
{
|
||||||
|
public int Health { get; set; } = 100;
|
||||||
|
|
||||||
|
public List<InventoryItem> Inventory { get; } = [];
|
||||||
|
|
||||||
|
public Position Position { get; set; } = new Position(0, 0);
|
||||||
|
}
|
||||||
@@ -1,9 +1,9 @@
|
|||||||
namespace TextLore.Utilities.Models;
|
namespace TextLore.Shared.Models;
|
||||||
|
|
||||||
public struct Position(int x, int y)
|
public readonly struct Position(int x, int y)
|
||||||
{
|
{
|
||||||
public int X { get; set; } = x;
|
public int X => x;
|
||||||
public int Y { get; set; } = y;
|
public int Y => y;
|
||||||
|
|
||||||
public static Position operator +(Position a, Position b)
|
public static Position operator +(Position a, Position b)
|
||||||
{
|
{
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
namespace TextLore.Shared.Models;
|
||||||
|
|
||||||
|
public readonly struct Size(int width, int height)
|
||||||
|
{
|
||||||
|
public int Width => width;
|
||||||
|
public int Height => height;
|
||||||
|
}
|
||||||
@@ -7,8 +7,11 @@
|
|||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
<PackageReference Include="Microsoft.ClearScript.V8" Version="7.4.4" />
|
||||||
|
<PackageReference Include="Microsoft.ClearScript.V8.Native.linux-x64" Version="7.4.4" />
|
||||||
|
<PackageReference Include="Microsoft.ClearScript.V8.Native.win-x64" Version="7.4.4" />
|
||||||
<PackageReference Include="Microsoft.EntityFrameworkCore.Sqlite" Version="8.0.1" />
|
<PackageReference Include="Microsoft.EntityFrameworkCore.Sqlite" Version="8.0.1" />
|
||||||
<PackageReference Include="Microsoft.IdentityModel.Tokens" Version="7.3.0" />
|
<PackageReference Include="Microsoft.IdentityModel.Tokens" Version="7.3.1" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
</Project>
|
</Project>
|
||||||
|
|||||||
@@ -1,9 +0,0 @@
|
|||||||
namespace TextLore.Utilities.Models;
|
|
||||||
|
|
||||||
public class PercentageProgress(int current, int total)
|
|
||||||
{
|
|
||||||
public int Current { get; set; } = current;
|
|
||||||
public int Total { get; set; } = total;
|
|
||||||
public int Percentage => (int)((double)Current / Total * 100);
|
|
||||||
public bool IsComplete => Current >= Total;
|
|
||||||
}
|
|
||||||
@@ -1,7 +0,0 @@
|
|||||||
namespace TextLore.Utilities.Models;
|
|
||||||
|
|
||||||
public readonly struct Size(int width, int height)
|
|
||||||
{
|
|
||||||
public int Width { get; } = width;
|
|
||||||
public int Height { get; } = height;
|
|
||||||
}
|
|
||||||
Binary file not shown.
Reference in New Issue
Block a user