Skip to content
Merged
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
17 changes: 15 additions & 2 deletions desktop/src/EggPicker.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,11 @@ interface TemplateMeta {
/// `id` (e.g. "mars" in "mars.drakon") when rendering the "by
/// <author>" chip in the picker row.
author?: AuthorBlock;
/// Display ordering hint for the egg-picker UI. Lower = shown earlier.
/// Builtin difficulty ladder: unicorn=1, sun=2, kingkong=3.
/// Templates without an explicit value (user-imported community ones)
/// sort AFTER explicit-order templates, by name alphabetically.
display_order?: number;
}

/// Disambiguator label for the egg-picker row. Two templates with the
Expand Down Expand Up @@ -134,11 +139,19 @@ export function EggPicker({ onConfirm, onCancel, onImport }: Props) {
const loadTemplates = useCallback(async (): Promise<TemplateInfo[] | null> => {
try {
const rows = await invoke<TemplateInfo[]>("template_list");
const order = (s: string) =>
const sourceRank = (s: string) =>
s === "builtin" ? 0 : s === "community" ? 1 : 2;
// Templates without `display_order` sort AFTER explicit ones —
// builtin difficulty ladder (unicorn=1, sun=2, kingkong=3) wins,
// community/custom imports fall back to name alphabetic at the
// tail. Using +Infinity keeps the comparator stable and avoids
// mixing "unordered" templates into the middle of the ladder.
const orderRank = (m: TemplateMeta) =>
m.display_order ?? Number.POSITIVE_INFINITY;
rows.sort(
(a, b) =>
order(a.source) - order(b.source) ||
sourceRank(a.source) - sourceRank(b.source) ||
orderRank(a.template.meta) - orderRank(b.template.meta) ||
a.template.meta.name.localeCompare(b.template.meta.name),
);
setTemplates(rows);
Expand Down
2 changes: 2 additions & 0 deletions src/template/registry.rs
Original file line number Diff line number Diff line change
Expand Up @@ -545,6 +545,7 @@ mod tests {
// picker / pet creation would silently break.
assert!(BUILTIN.get_dir("sun").is_some());
assert!(BUILTIN.get_dir("unicorn").is_some());
assert!(BUILTIN.get_dir("kingkong").is_some());
}

fn stage_at(idx: u32, trigger: Trigger) -> Stage {
Expand Down Expand Up @@ -618,6 +619,7 @@ mod tests {
license: None,
description: None,
source_url: None,
display_order: None,
},
species: TemplateSpecies {
name: "Test".into(),
Expand Down
6 changes: 6 additions & 0 deletions src/template/types.rs
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,12 @@ pub struct TemplateMeta {
pub description: Option<String>,
#[serde(default)]
pub source_url: Option<String>,
/// Display ordering hint for the egg-picker UI. Lower = shown
/// earlier. Templates without an explicit value (e.g. user-imported
/// community ones) sort after explicit-order templates, alphabetically.
/// Builtin difficulty ladder: unicorn=1, sun=2, kingkong=3.
#[serde(default)]
pub display_order: Option<i32>,
}

/// Author shape on disk. Templates in the wild use either:
Expand Down
23 changes: 23 additions & 0 deletions src/xp/engine.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1005,6 +1005,29 @@ mod tests {
assert_eq!(pet.name, "Sparkle");
}

#[tokio::test]
async fn pick_template_kingkong_loads_and_creates_pet() {
// KingKong is the 3rd builtin (hard mode, ~2.5× Sun). Same
// load-canary as the unicorn test: silently broken levels /
// stages / rules in this template would drop it from the
// picker without anything red-flagging.
let _g = env_test_lock();
let dir = tempfile::tempdir().expect("tempdir");
std::env::set_var("PETPET_HOME", dir.path());
let db = crate::db::DbHandle::open(&dir.path().join("test.db"))
.await
.expect("open db");
let engine = XPEngine::open(db.clone()).await.expect("open engine");

let pet = engine
.pick_template("kingkong", Some("Konga".into()))
.await
.expect("kingkong should load and snapshot");

assert_eq!(pet.template_id, "kingkong");
assert_eq!(pet.name, "Konga");
}

#[tokio::test]
async fn pick_template_unknown_errors() {
let _g = env_test_lock();
Expand Down
Loading
Loading