Push and publish

This commit is contained in:
Samuel Bouchet 2026-03-18 18:56:40 +01:00
parent d635ab673c
commit 0a499d947e
3 changed files with 42 additions and 33 deletions

View file

@ -1115,28 +1115,44 @@ public sealed class WebGameHost
private async Task RenderFullLayout()
{
// Top row: Stats (30) | Resources (30) | Completion (60) — total 120
var topRow = new Table().NoBorder().HideHeaders().Expand();
topRow.AddColumn(new TableColumn("c1").Width(20).NoWrap());
topRow.AddColumn(new TableColumn("c2").Width(30).NoWrap());
topRow.AddColumn(new TableColumn("c3").NoWrap());
topRow.AddColumn(new TableColumn("c1").Width(30));
topRow.AddColumn(new TableColumn("c2").Width(30));
topRow.AddColumn(new TableColumn("c3").Width(60));
topRow.AddRow(
_renderContext.HasPortraitPanel
? PortraitPanel.Render(_state.Appearance, useColors: _renderContext.HasColors)
: new Panel("[dim]?[/]").Header("Portrait").Expand(),
_renderContext.HasStatsPanel
IRenderable statsPanel = _renderContext.HasStatsPanel
? StatsPanel.Render(_state, _loc)
: new Panel($"[dim italic]{Markup.Escape(_loc.Get("panel.locked.stats"))}[/]").Header("Stats").Expand(),
_renderContext.HasResourcePanel
? ResourcePanel.Render(_state, _loc)
: new Panel($"[dim italic]{Markup.Escape(_loc.Get("panel.locked.resources"))}[/]")
.Header(Markup.Escape(_loc.Get("resource.title"))).Expand());
: new Panel($"[dim italic]{Markup.Escape(_loc.Get("panel.locked.stats"))}[/]").Header("Stats").Expand();
IRenderable resourcePanel = _renderContext.HasResourcePanel
? ResourcePanel.Render(_state, _loc, barWidth: 8)
: new Panel($"[dim italic]{Markup.Escape(_loc.Get("panel.locked.resources"))}[/]")
.Header(Markup.Escape(_loc.Get("resource.title"))).Expand();
var completionItems = new List<IRenderable>();
if (_renderContext.HasCompletionTracker)
{
// Compact: single line with percent + hint joined
string completionLine = _loc.Get("ui.completion", _renderContext.CompletionPercent);
if (_renderContext.NextHints.Count > 0)
completionLine += " — " + _renderContext.NextHints[0];
completionItems.Add(new Markup($"[bold cyan]{Markup.Escape(completionLine)}[/]"));
// Additional hints on separate lines
for (int i = 1; i < _renderContext.NextHints.Count; i++)
completionItems.Add(new Markup($" [dim]{Markup.Escape(_renderContext.NextHints[i])}[/]"));
}
IRenderable completionPanel = completionItems.Count > 0
? new Rows(completionItems)
: new Text("");
topRow.AddRow(statsPanel, resourcePanel, completionPanel);
await _terminal.WriteRenderableAsync(topRow);
// Bottom row: Inventory (60) | Portrait + Crafting (60) — total 120
var botRow = new Table().NoBorder().HideHeaders().Expand();
botRow.AddColumn(new TableColumn("c1").Width(60).NoWrap());
botRow.AddColumn(new TableColumn("c2").NoWrap());
botRow.AddColumn(new TableColumn("c1").Width(60));
botRow.AddColumn(new TableColumn("c2").Width(60));
IRenderable leftPanel = _renderContext.HasInventoryPanel
? InventoryPanel.Render(_state, _registry, _loc, compact: true)
@ -1144,20 +1160,14 @@ public sealed class WebGameHost
.Header("Inventory").Expand();
var rightItems = new List<IRenderable>();
if (_renderContext.HasPortraitPanel)
rightItems.Add(PortraitPanel.Render(_state.Appearance, useColors: _renderContext.HasColors));
else
rightItems.Add(new Panel("[dim]?[/]").Header("Portrait").Expand());
if (_renderContext.HasCraftingPanel)
rightItems.Add(CraftingPanel.Render(_state, _registry, _loc));
if (_renderContext.HasCompletionTracker)
{
rightItems.Add(new Markup($"[bold cyan]{Markup.Escape(_loc.Get("ui.completion", _renderContext.CompletionPercent))}[/]"));
foreach (var hint in _renderContext.NextHints)
rightItems.Add(new Markup($" [dim]{Markup.Escape(hint)}[/]"));
}
IRenderable rightPanel = rightItems.Count > 0
? new Rows(rightItems)
: new Panel("[dim]???[/]").Header("???").Expand();
botRow.AddRow(leftPanel, rightPanel);
botRow.AddRow(leftPanel, new Rows(rightItems));
await _terminal.WriteRenderableAsync(botRow);
}

View file

@ -4,7 +4,7 @@
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Open The Box</title>
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@xterm/xterm@5.5.0/css/xterm.min.css" />
<link rel="stylesheet" href="lib/xterm/xterm.min.css" />
<link rel="stylesheet" href="css/terminal.css" />
</head>
<body>
@ -19,8 +19,8 @@
<div id="terminal"></div>
</div>
<script src="https://cdn.jsdelivr.net/npm/@xterm/xterm@5.5.0/lib/xterm.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/@xterm/addon-web-links@0.11.0/lib/addon-web-links.min.js"></script>
<script src="lib/xterm/xterm.min.js"></script>
<script src="lib/xterm/addon-web-links.min.js"></script>
<script src="js/terminal-interop.js"></script>
<!-- Blazor WASM -->

View file

@ -15,7 +15,7 @@ public static class ResourcePanel
/// Builds a renderable resource display from the current game state.
/// Only resources present in <see cref="GameState.VisibleResources"/> are shown.
/// </summary>
public static IRenderable Render(GameState state, LocalizationManager? loc = null)
public static IRenderable Render(GameState state, LocalizationManager? loc = null, int barWidth = 20)
{
var rows = new List<IRenderable>();
@ -29,7 +29,6 @@ public static class ResourcePanel
int max = resource.Max;
// Build a text-based bar: [####----] 40/100
int barWidth = 20;
int filled = max > 0 ? (int)Math.Round((double)current / max * barWidth) : 0;
filled = Math.Clamp(filled, 0, barWidth);
int empty = barWidth - filled;
@ -55,7 +54,7 @@ public static class ResourcePanel
private static string GetResourceColor(ResourceType type) => type switch
{
ResourceType.Gold => "gold1",
ResourceType.Blood => "red",
ResourceType.Ink => "red",
_ => "silver"
};
}