Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions BlueprintStore.cs
Original file line number Diff line number Diff line change
Expand Up @@ -220,7 +220,7 @@ public static BlueprintFile Load(ICoreAPI api, string name)
var path = GetBlueprintPath(api, name);
if (!File.Exists(path))
{
throw new FileNotFoundException($"Blueprint not found: {path}");
throw new FileNotFoundException(FieldwrightLang.Get("error.blueprint-not-found", name));
}

var text = File.ReadAllText(path);
Expand Down Expand Up @@ -366,7 +366,7 @@ public static void Delete(ICoreAPI api, string name)

if (!mainExisted && !backupExisted)
{
throw new FileNotFoundException($"Blueprint not found: {name}");
throw new FileNotFoundException(FieldwrightLang.Get("error.blueprint-not-found", name));
}
if (mainExisted) File.Delete(main);
if (backupExisted) File.Delete(backup);
Expand Down
3 changes: 3 additions & 0 deletions Fieldwright.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,9 @@
<None Include="modinfo.json">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
<None Update="assets\**\*">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
</ItemGroup>

</Project>
65 changes: 65 additions & 0 deletions FieldwrightLang.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
using System;
using Vintagestory.API.Config;

namespace Fieldwright;

public static class FieldwrightLang
{
private const string Domain = "fieldwright";

public const string DirectionCodes = "up|down|north|south|east|west";
public const string MatchingModeCodes = "loose, medium, strict";

public static string Get(string key, params object[] args)
{
return Lang.Get($"{Domain}:{key}", args);
}

public static string Chat(string key, params object[] args)
{
return $"[Fieldwright] {Get(key, args)}";
}

public static string Facing(string? code)
{
return (code ?? string.Empty).ToLowerInvariant() switch
{
"north" => Get("face.north"),
"south" => Get("face.south"),
"east" => Get("face.east"),
"west" => Get("face.west"),
"up" => Get("face.up"),
"down" => Get("face.down"),
"-" => Get("face.none"),
"" => Get("face.none"),
_ => code ?? Get("face.none"),
};
}

public static string MatchingModeCode(MatchingMode mode)
{
return mode.ToString().ToLowerInvariant();
}

public static string MatchingModeLabel(MatchingMode mode)
{
return Get($"matching.mode.{MatchingModeCode(mode)}");
}

public static string MatchingModeDropdownLabel(MatchingMode mode)
{
return Get($"matching.dropdown.{MatchingModeCode(mode)}");
}

public static string MirrorState(MirrorAxis axis)
{
return axis switch
{
MirrorAxis.None => Get("mirror.off"),
MirrorAxis.X => Get("mirror.axis", "X"),
MirrorAxis.Y => Get("mirror.axis", "Y"),
MirrorAxis.Z => Get("mirror.axis", "Z"),
_ => Get("mirror.off"),
};
}
}
175 changes: 91 additions & 84 deletions FieldwrightModSystem.cs

Large diffs are not rendered by default.

8 changes: 4 additions & 4 deletions GhostChecklistDialog.cs
Original file line number Diff line number Diff line change
Expand Up @@ -92,15 +92,15 @@ private void Compose()

var composer = capi.Gui.CreateCompo(ComposerKey, dialogBounds)
.AddShadedDialogBG(bgBounds)
.AddDialogTitleBar($"Fieldwright: {blueprintName}", OnTitleBarClose)
.AddDialogTitleBar(FieldwrightLang.Get("ui.checklist.title", blueprintName), OnTitleBarClose)
.BeginChildElements(contentBounds)
.BeginClip(clipBounds)
.AddRichtext("", bodyFont, insideClipBounds, "body")
.EndClip()
.AddVerticalScrollbar(OnScroll, scrollbarBounds, "scroll")
.AddSmallButton("Copy to clipboard", OnCopyClicked, copyBtnBounds,
.AddSmallButton(FieldwrightLang.Get("ui.checklist.copy"), OnCopyClicked, copyBtnBounds,
EnumButtonStyle.Normal, "copyBtn")
.AddStaticText("Drag title to move", CairoFont.WhiteDetailText(),
.AddStaticText(FieldwrightLang.Get("ui.checklist.drag"), CairoFont.WhiteDetailText(),
hintBounds)
.EndChildElements()
.Compose();
Expand Down Expand Up @@ -160,7 +160,7 @@ private void OnTitleBarClose()
private bool OnCopyClicked()
{
var (_, plain) = GhostChecklistText.Build(tracker);
var header = $"Fieldwright: {blueprintName}\n";
var header = FieldwrightLang.Get("ui.checklist.title", blueprintName) + "\n";
capi.Forms.SetClipboardText(header + plain);
FieldwrightLogger.Info(capi, Component,
$"copied checklist for '{blueprintName}' to clipboard ({plain.Length} chars)");
Expand Down
2 changes: 1 addition & 1 deletion GhostChecklistHud.cs
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ private void Compose()
// Fully transparent backdrop, the player sees the world behind the HUD.
Composers[ComposerKey] = capi.Gui.CreateCompo(ComposerKey, bgBounds)
.BeginChildElements(dialogBounds)
.AddStaticText($"Fieldwright: {blueprintName}", titleFont,
.AddStaticText(FieldwrightLang.Get("ui.checklist.title", blueprintName), titleFont,
ElementBounds.Fixed(0, 0, 240, 20))
.AddRichtext("", bodyFont,
ElementBounds.Fixed(0, 24, 240, 256), "body")
Expand Down
18 changes: 10 additions & 8 deletions GhostChecklistText.cs
Original file line number Diff line number Diff line change
Expand Up @@ -19,16 +19,17 @@ public static (string vtml, string plain) Build(GhostMatchTracker tracker)
int totalCells = tracker.TotalBlockCells + tracker.TotalAirCells;
int doneCells = tracker.MatchedBlocks + (tracker.TotalAirCells - tracker.AirViolationCount);
float pct = totalCells > 0 ? (doneCells * 100f / totalCells) : 100f;
vtml.AppendLine($"<font color=\"#aaffaa\">Progress: {doneCells} / {totalCells} ({pct:F0}%)</font>");
plain.AppendLine($"Progress: {doneCells} / {totalCells} ({pct:F0}%)");
var progressLine = FieldwrightLang.Get("checklist.progress", doneCells, totalCells, pct);
vtml.AppendLine($"<font color=\"#aaffaa\">{progressLine}</font>");
plain.AppendLine(progressLine);

var needs = tracker.GetMaterialNeeds();
if (needs.Count > 0)
{
vtml.AppendLine();
vtml.AppendLine("<font color=\"#ffffff\">Materials needed:</font>");
vtml.AppendLine($"<font color=\"#ffffff\">{FieldwrightLang.Get("checklist.materials-needed")}</font>");
plain.AppendLine();
plain.AppendLine("Materials needed:");
plain.AppendLine(FieldwrightLang.Get("checklist.materials-needed"));

var sorted = new List<KeyValuePair<string, int>>(needs);
sorted.Sort((a, b) => string.Compare(a.Key, b.Key, System.StringComparison.Ordinal));
Expand All @@ -46,17 +47,18 @@ public static (string vtml, string plain) Build(GhostMatchTracker tracker)
if (tracker.BlocksToRemoveCount > 0)
{
vtml.AppendLine();
vtml.AppendLine($"<font color=\"#ff8888\">Blocks to remove: {tracker.BlocksToRemoveCount}</font>");
var removeLine = FieldwrightLang.Get("checklist.blocks-to-remove", tracker.BlocksToRemoveCount);
vtml.AppendLine($"<font color=\"#ff8888\">{removeLine}</font>");
plain.AppendLine();
plain.AppendLine($"Blocks to remove: {tracker.BlocksToRemoveCount}");
plain.AppendLine(removeLine);
}

if (tracker.IsComplete)
{
vtml.AppendLine();
vtml.AppendLine("<font color=\"#aaffaa\">Structure complete!</font>");
vtml.AppendLine($"<font color=\"#aaffaa\">{FieldwrightLang.Get("checklist.structure-complete")}</font>");
plain.AppendLine();
plain.AppendLine("Structure complete!");
plain.AppendLine(FieldwrightLang.Get("checklist.structure-complete"));
}

return (vtml.ToString(), plain.ToString());
Expand Down
27 changes: 14 additions & 13 deletions HotkeyHelpDialog.cs
Original file line number Diff line number Diff line change
Expand Up @@ -13,16 +13,16 @@ public class HotkeyHelpDialog : GuiDialog
private const int RowHeight = 26;
private const int TitleBarPad = 18;

private static readonly (string keys, string description)[] Hotkeys = new[]
private static readonly (string keys, string descriptionKey)[] Hotkeys = new[]
{
("Ctrl+Shift+B", "Set corner 1 (placement anchor + face)"),
("Ctrl+Shift+N", "Set corner 2 (opposite cuboid corner)"),
("Ctrl+Shift+P", "Place / unplace the active ghost"),
("Ctrl+Shift+M", "Cycle ghost mirror axis (None / X / Y / Z)"),
("Ctrl+Shift+X", "Cancel: dismiss active ghost + clear selection"),
("Ctrl+Shift+L", "Toggle the build checklist HUD"),
("Ctrl+Shift+K", "Open the blueprint library"),
("PgUp / PgDn", "Restore / peel layers off the top of the ghost"),
("Ctrl+Shift+B", "ui.hotkeys.desc.corner1"),
("Ctrl+Shift+N", "ui.hotkeys.desc.corner2"),
("Ctrl+Shift+P", "ui.hotkeys.desc.place"),
("Ctrl+Shift+M", "ui.hotkeys.desc.mirror"),
("Ctrl+Shift+X", "ui.hotkeys.desc.cancel"),
("Ctrl+Shift+L", "ui.hotkeys.desc.checklist"),
("Ctrl+Shift+K", "ui.hotkeys.desc.library"),
("PgUp / PgDn", "ui.hotkeys.desc.layers"),
};

public override string? ToggleKeyCombinationCode => null;
Expand Down Expand Up @@ -52,20 +52,21 @@ private void Compose()

var composer = capi.Gui.CreateCompo(ComposerKey, dialogBounds)
.AddShadedDialogBG(bgBounds)
.AddDialogTitleBar("Fieldwright, Hotkeys", () => TryClose())
.AddDialogTitleBar(FieldwrightLang.Get("ui.hotkeys.title"), () => TryClose())
.BeginChildElements(contentBounds);

composer.AddStaticText("Active anywhere in-world while Fieldwright is loaded:", headerFont,
composer.AddStaticText(FieldwrightLang.Get("ui.hotkeys.header"), headerFont,
ElementBounds.Fixed(0, TitleBarPad, DialogWidth, 24));

for (int i = 0; i < Hotkeys.Length; i++)
{
int rowY = TitleBarPad + 30 + i * RowHeight;
var (keys, desc) = Hotkeys[i];
var (keys, descKey) = Hotkeys[i];

composer
.AddStaticText(keys, keyFont, ElementBounds.Fixed(0, rowY, 160, 22))
.AddStaticText(desc, descFont, ElementBounds.Fixed(170, rowY, DialogWidth - 170, 22));
.AddStaticText(FieldwrightLang.Get(descKey), descFont,
ElementBounds.Fixed(170, rowY, DialogWidth - 170, 22));
}

composer.EndChildElements();
Expand Down
49 changes: 33 additions & 16 deletions SchematicLibraryDialog.cs
Original file line number Diff line number Diff line change
Expand Up @@ -100,20 +100,30 @@ private void Compose()

var composer = capi.Gui.CreateCompo(ComposerKey, dialogBounds)
.AddShadedDialogBG(bgBounds)
.AddDialogTitleBar("Fieldwright, Blueprint Library", OnTitleBarClose)
.AddDialogTitleBar(FieldwrightLang.Get("ui.library.title"), OnTitleBarClose)
.BeginChildElements(contentBounds)
.AddStaticText("Default matching mode:", titleFont, modeLabelBounds)
.AddStaticText(FieldwrightLang.Get("ui.library.default-matching-mode"), titleFont, modeLabelBounds)
.AddDropDown(
new[] { "loose", "medium", "strict" },
new[] { "Loose (family)", "Medium (variant-aware)", "Strict (exact)" },
new[]
{
FieldwrightLang.MatchingModeCode(MatchingMode.Loose),
FieldwrightLang.MatchingModeCode(MatchingMode.Medium),
FieldwrightLang.MatchingModeCode(MatchingMode.Strict)
},
new[]
{
FieldwrightLang.MatchingModeDropdownLabel(MatchingMode.Loose),
FieldwrightLang.MatchingModeDropdownLabel(MatchingMode.Medium),
FieldwrightLang.MatchingModeDropdownLabel(MatchingMode.Strict)
},
Math.Clamp((int)chosenMode, 0, 2),
OnMatchingModeChanged,
modeDropdownBounds,
"modeDropdown")
.AddStaticText(
entries.Count == 0
? "No blueprints saved yet."
: $"{entries.Count} saved",
? FieldwrightLang.Get("ui.library.empty")
: FieldwrightLang.Get("ui.library.saved-count", entries.Count),
rowFont, countLabelBounds);

// Per-row entries for the current page.
Expand All @@ -134,8 +144,15 @@ private void Compose()
var pasteBtnBounds = ElementBounds.Fixed(480, rowY + 8, 70, 32);
var deleteBtnBounds = ElementBounds.Fixed(560, rowY + 8, 70, 32);

string detailLine = $"{entry.SizeX}x{entry.SizeY}x{entry.SizeZ} · {entry.BlockCount} blocks · anchor {entry.AnchorFaceLabel}"
+ (entry.HasBackup ? " · has backup" : string.Empty);
string backupDetail = entry.HasBackup
? FieldwrightLang.Get("ui.library.has-backup")
: string.Empty;
string detailLine = FieldwrightLang.Get(
"ui.library.entry-detail",
entry.SizeX, entry.SizeY, entry.SizeZ,
entry.BlockCount,
FieldwrightLang.Facing(entry.AnchorFaceLabel),
backupDetail);
string dateLine = entry.ModifiedAt.ToString("yyyy-MM-dd HH:mm");

string capturedName = entry.Name;
Expand All @@ -146,7 +163,7 @@ private void Compose()
.AddStaticText(entry.Name, rowFont, nameBounds)
.AddStaticText(detailLine, dimFont, detailBounds)
.AddStaticText(dateLine, dimFont, dateBounds)
.AddSmallButton("Paste", () => OnPasteClicked(capturedName), pasteBtnBounds, EnumButtonStyle.Normal, "paste-" + rowKey);
.AddSmallButton(FieldwrightLang.Get("ui.library.paste"), () => OnPasteClicked(capturedName), pasteBtnBounds, EnumButtonStyle.Normal, "paste-" + rowKey);

if (isPendingDelete)
{
Expand All @@ -156,11 +173,11 @@ private void Compose()
var dangerFont = CairoFont.ButtonText()
.WithColor(new double[] { 1.0, 0.5, 0.5, 1.0 })
.WithFontSize(14);
composer.AddButton("Confirm?", () => OnDeleteClicked(capturedName, rowKey), deleteBtnBounds, dangerFont, EnumButtonStyle.Normal, "delete-" + rowKey);
composer.AddButton(FieldwrightLang.Get("ui.library.confirm-delete"), () => OnDeleteClicked(capturedName, rowKey), deleteBtnBounds, dangerFont, EnumButtonStyle.Normal, "delete-" + rowKey);
}
else
{
composer.AddSmallButton("Delete", () => OnDeleteClicked(capturedName, rowKey), deleteBtnBounds, EnumButtonStyle.Normal, "delete-" + rowKey);
composer.AddSmallButton(FieldwrightLang.Get("ui.library.delete"), () => OnDeleteClicked(capturedName, rowKey), deleteBtnBounds, EnumButtonStyle.Normal, "delete-" + rowKey);
}
}

Expand All @@ -173,11 +190,11 @@ private void Compose()
var reloadBtnBounds = ElementBounds.Fixed(540, footerY, 90, 32);

composer
.AddSmallButton("< Prev", OnPrevPage, prevBtnBounds, EnumButtonStyle.Small, "prevPage")
.AddStaticText($"Page {pageIndex + 1} / {PageCount}", rowFont, pageLabelBounds)
.AddSmallButton("Next >", OnNextPage, nextBtnBounds, EnumButtonStyle.Small, "nextPage")
.AddSmallButton("Hotkeys", OnHotkeysClicked, hotkeysBtnBounds, EnumButtonStyle.Small, "hotkeysBtn")
.AddSmallButton("Reload", OnReload, reloadBtnBounds, EnumButtonStyle.Small, "reloadBtn")
.AddSmallButton(FieldwrightLang.Get("ui.library.prev"), OnPrevPage, prevBtnBounds, EnumButtonStyle.Small, "prevPage")
.AddStaticText(FieldwrightLang.Get("ui.library.page", pageIndex + 1, PageCount), rowFont, pageLabelBounds)
.AddSmallButton(FieldwrightLang.Get("ui.library.next"), OnNextPage, nextBtnBounds, EnumButtonStyle.Small, "nextPage")
.AddSmallButton(FieldwrightLang.Get("ui.library.hotkeys"), OnHotkeysClicked, hotkeysBtnBounds, EnumButtonStyle.Small, "hotkeysBtn")
.AddSmallButton(FieldwrightLang.Get("ui.library.reload"), OnReload, reloadBtnBounds, EnumButtonStyle.Small, "reloadBtn")
.EndChildElements();

Composers[ComposerKey] = composer.Compose();
Expand Down
Loading