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
20 changes: 12 additions & 8 deletions example/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ example/
│ │ ├── upgrades.tsx # themed workshop: styles, vars, cards with a face per stage, choices, and a hotspot
│ │ ├── lobby.tsx # full-screen main menu: paged worlds, a rename prompt, tooltips, and a ready switch
│ │ ├── lookout.tsx # horse-mode full-screen window with a signal bar
│ │ ├── storefront.tsx # horse-mode web-style store: tabs, live search, a scrolling grid and cart
│ │ ├── status_hud.tsx # the shader-relocated actionbar HUDs
│ │ └── clock_hud.ts # the clock HUD, written with the function-style raw API
│ ├── build/previews/ # preview PNGs of the windows and HUDs, rewritten by every build
Expand All @@ -27,13 +28,13 @@ example/

The Minestom server is the Gradle module `jvm/example`, which depends on `window-minestom`. `Main.kt` boots the server,
`Market.kt` and `Workshop.kt` are a throwaway domain model, `MyShop.kt` and `MyUpgrades.kt` implement the **generated**
`ShopView` and `UpgradesView`, and `MyLobby.kt` and `MyLookout.kt` the full-screen `LobbyFullscreen` and
`LookoutFullscreen`. `MyStatusHud.kt` implements the **generated** HUD views. The pack uses `target: "minestom"`, so a
window view takes the `Player` it is shown to: `Main.kt` opens the shop with `MyShop(player, market).open()`. Generated
HUD views take no player; the handwritten ones that need it take it themselves. `Main.kt` joins the status HUDs into one
action-bar `HudStack` and resends it with `player.sendHud(stack)` every tick, which keeps the wave bar moving smoothly,
re-renders the clocks, and stays ahead of the action bar fading out. The bindings live under `generated/`, produced by
the rpp plugin — committed, do not hand-edit.
`ShopView` and `UpgradesView`, and `MyLobby.kt`, `MyLookout.kt`, and `MyStorefront.kt` the full-screen
`LobbyFullscreen`, `LookoutFullscreen`, and `StorefrontFullscreen`. `MyStatusHud.kt` implements the **generated** HUD
views. The pack uses `target: "minestom"`, so a window view takes the `Player` it is shown to: `Main.kt` opens the shop
with `MyShop(player, market).open()`. Generated HUD views take no player; the handwritten ones that need it take it
themselves. `Main.kt` joins the status HUDs into one action-bar `HudStack` and resends it with `player.sendHud(stack)`
every tick, which keeps the wave bar moving smoothly, re-renders the clocks, and stays ahead of the action bar fading
out. The bindings live under `generated/`, produced by the rpp plugin — committed, do not hand-edit.

## Run it

Expand All @@ -58,7 +59,9 @@ until the server stops.
rename it in a native dialog, which returns to the lobby on Confirm or Cancel. The arrows or the scroll wheel move the
world list, a click selects a world, and right clicking anywhere toggles ready, which switches the line under the list
and retints the status. Play leaves once you are ready. `/lookout` opens a horse-mode window, which locks the view while
the cursor follows the mouse; Charge fills its signal bar.
the cursor follows the mouse; Charge fills its signal bar. `/store` opens a horse-mode storefront over the world: click
the search box and type to filter the grid as you go (Escape finishes), and the scroll wheel moves whichever of the grid
and the cart was clicked last. Right click flips the side pane between the details and the cart.

The actionbar-backed HUD demo is disabled by default so the inventory examples stay visually focused. Enable it with
`-Dwindow.hud.enabled=true`; use `-Dwindow.hud.spriteDebug=true` to print each HUD's static art to chat. The pack blanks
Expand All @@ -70,6 +73,7 @@ vanilla's experience bar, and one of the HUDs draws its wave bar there.
| `/upgrades` | opens the workshop, like the catalog's Workshop button |
| `/lobby` | opens the full-screen lobby |
| `/lookout` | opens the horse-mode lookout |
| `/store` | opens the horse-mode storefront |
| `/tone <ok\|warn\|danger\|auto>` | pins the tone the HUDs and newly opened windows draw in; `auto` unpins |
| `/bar <fraction\|auto>` | pins how full the wave bar and a newly opened shop's bar are |

Expand Down
2 changes: 1 addition & 1 deletion example/pack/rpp.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ export default defineConfig({
namespace: "window",
coreShaders: { hud: true, hover: true },
vanilla: { anvil: { field: "search_field" }, hud: { experience: false }, slotHighlight: false },
size: { report: true, budget: 1_150_000 },
size: { report: true, budget: 3_000_000 },
previews: { output: "build/previews" },
kotlin: {
package: "com.chunkzero.window.example.generated",
Expand Down
13 changes: 13 additions & 0 deletions example/pack/src/window/art.ts
Original file line number Diff line number Diff line change
Expand Up @@ -85,3 +85,16 @@ export const icons = {
clear: texture("window/icons/clear.png"),
check: texture("window/icons/check.png"),
};

/** White translucent glass, nine-sliced over its box; a `tint` colors it and the world shows through. */
export const glass = texture("window/icons/store/glass.png", { insets: 2 });

/** A storefront product's 16x16 art by `STORE_ICONS` id; as a frame, it stretches over its box. */
export const productIcon = (id: string) => texture(`window/icons/store/products/${id}.png`, { insets: 0 });

export const storeIcons = {
arrowUp: texture("window/icons/store/arrow_up.png"),
arrowDown: texture("window/icons/store/arrow_down.png"),
magnifier: texture("window/icons/store/magnifier.png"),
cart: texture("window/icons/store/cart.png"),
};
107 changes: 107 additions & 0 deletions example/pack/src/window/handles.ts
Original file line number Diff line number Diff line change
Expand Up @@ -88,3 +88,110 @@ export const play = action("play");
/** How far the lookout's signal has charged. */
export const signal = fraction("signal");
export const charge = action("charge");

// Storefront, a full-screen window; `tone` is shared
/** The product art a card or the detail pane shows; `none` shows nothing. */
export const STORE_ICONS = [
"none",
"diamond",
"emerald",
"gold",
"iron",
"copper",
"redstone",
"lapis",
"coal",
"quartz",
"amethyst",
"ender_pearl",
"blaze_rod",
"ghast_tear",
"prismarine",
"heart",
"nether_star",
"totem",
"trident",
"elytra",
"rocket",
"golden_apple",
"experience",
"book",
"spyglass",
"compass",
"clock",
"name_tag",
"saddle",
"shell",
"echo",
] as const;

export const storeCategory = selection("store_category", ["all", "gear", "magic", "deals"]);
export const storePane = selection("store_pane", ["details", "cart"]);
export const storeSearch = text("store_search");
export const storeHasSearch = flag("store_has_search");
export const storeFind = action("store_find");
export const storeClearSearch = action("store_clear_search");
export const storeCartCount = text("store_cart_count");
export const openDetails = action("open_details");
export const openCart = action("open_cart");

export const STORE_CARDS = 9;
const storeCards = { shape: [STORE_CARDS] } as const;
export const cardName = text("card_name", storeCards);
export const cardPrice = text("card_price", storeCards);
export const cardIcon = value("card_icon", STORE_ICONS, storeCards);
export const cardFilled = flag("card_filled", storeCards);
export const cardFeatured = flag("card_featured", storeCards);
export const cardSelected = flag("card_selected", storeCards);
export const pickCard = action("pick_card", storeCards);
export const storeResults = text("store_results");
export const storeSortLabel = text("store_sort_label");
export const storeSort = action("store_sort");
/** Which pane the scroll wheel moves. */
export const catalogFocused = flag("catalog_focused");

/** Segments of a scrollbar track; each is lit while its stretch of the list is in view. */
export const CATALOG_TRACK = 8;
export const catalogThumb = flag("catalog_thumb", { shape: [CATALOG_TRACK] });
export const catalogUp = action("catalog_up");
export const catalogDown = action("catalog_down");

export const detailIcon = value("detail_icon", STORE_ICONS);
export const detailName = text("detail_name");
export const detailTier = tint("detail_tier", {
common: "#ffffff",
rare: "#55ffff",
epic: "#ff77ff",
legendary: "#ffb20b",
});
export const detailKind = text("detail_kind");
export const detailPrice = text("detail_price");
export const detailBlurb = text("detail_blurb");
export const detailInCart = text("detail_in_cart");
export const quantity = text("quantity");
export const canLess = flag("can_less");
export const canMore = flag("can_more");
export const less = action("less");
export const more = action("more");
export const addToCart = action("add_to_cart");
export const buyNow = action("buy_now");
export const canBuyNow = flag("can_buy_now");
export const buyNowLabel = text("buy_now_label");

export const CART_ROWS = 5;
const cartRows = { shape: [CART_ROWS] } as const;
export const cartName = text("cart_name", cartRows);
export const cartQuantity = text("cart_quantity", cartRows);
export const cartPrice = text("cart_price", cartRows);
export const removeLine = action("remove_line", cartRows);
export const cartThumb = flag("cart_thumb", { shape: [CART_ROWS] });
export const cartUp = action("cart_up");
export const cartDown = action("cart_down");
export const cartEmpty = flag("cart_empty");
export const cartTotal = text("cart_total");
export const checkout = action("checkout");
export const canCheckout = flag("can_checkout");
export const clearCart = action("clear_cart");

export const storeBalance = text("store_balance");
export const storeToast = text("store_toast");
Binary file added example/pack/src/window/icons/store/arrow_down.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added example/pack/src/window/icons/store/arrow_up.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added example/pack/src/window/icons/store/cart.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added example/pack/src/window/icons/store/glass.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added example/pack/src/window/icons/store/magnifier.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
58 changes: 57 additions & 1 deletion example/pack/src/window/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import lookout from "./lookout.tsx";
import search from "./search.tsx";
import shop from "./shop.tsx";
import statusHuds, { bottomCenter, coins, hint, power, rate, topLeft, waveBar, waveCharge } from "./status_hud.tsx";
import storefront from "./storefront.tsx";
import upgrades from "./upgrades.tsx";

/** A preview of the workshop with one card in each stage. */
Expand All @@ -31,11 +32,64 @@ const upgradesPreview = (options: PreviewOptions) =>
options,
);

/** The storefront browsing Gear, with a card selected and two lines in the cart. */
const storefrontState = (pane: "details" | "cart") =>
[
[handles.storeCategory, "gear"],
[handles.storePane, pane],
[handles.storeSearch, "ing_"],
[handles.storeHasSearch, true],
[handles.storeCartCount, "3"],
[handles.storeResults, "Gear: 14 items"],
[handles.storeSortLabel, "Sort: Price"],
[handles.catalogFocused, pane === "details"],
[
handles.cardName,
[
"Gilded Ingot",
"Tempered Iron",
"Copper Bundle",
"Tide Trident",
"Sky Wings",
"Rocket Crate",
"Scout Spyglass",
"Explorer Compass",
"Chrono Dial",
],
],
[handles.cardPrice, ["180", "95", "75", "860", "1150", "155", "165", "205", "260"]],
[handles.cardIcon, ["gold", "iron", "copper", "trident", "elytra", "rocket", "spyglass", "compass", "clock"]],
[handles.cardFilled, [true, true, true, true, true, true, true, true, true]],
[handles.cardFeatured, [false, false, false, true, true]],
[handles.cardSelected, [false, false, false, true]],
[handles.catalogThumb, [false, false, true, true, true, true, false, false]],
[handles.detailIcon, "trident"],
[handles.detailName, "Tide Trident"],
[handles.detailTier, "legendary"],
[handles.detailKind, "Legendary gear"],
[handles.detailPrice, "860"],
[handles.detailBlurb, "Forged in the drowned halls. Returns to your hand and calls lightning in a storm."],
[handles.detailInCart, "1 already in your cart"],
[handles.quantity, "2"],
[handles.canLess, true],
[handles.canMore, true],
[handles.canBuyNow, true],
[handles.buyNowLabel, "Buy 1720"],
[handles.cartName, ["Tide Trident", "Copper Bundle", "Rocket Crate"]],
[handles.cartQuantity, ["x1", "x1", "x1"]],
[handles.cartPrice, ["860", "75", "155"]],
[handles.cartThumb, [true, true, true, true, true]],
[handles.cartTotal, "1090"],
[handles.canCheckout, true],
[handles.storeBalance, "2500"],
[handles.storeToast, "Added Tide Trident to your cart"],
] as const;

export default defineWindows({
sprites: { searchField: art.inputField, ...ranks },
windows: [shop, search, upgrades],
huds: statusHuds,
fullscreens: [lobby, lookout],
fullscreens: [lobby, lookout, storefront],
// `rpp build` writes these to build/previews/, one PNG per preview.
previews: [
preview(shop, [
Expand Down Expand Up @@ -85,5 +139,7 @@ export default defineWindows({
[handles.worldName, ["Ironvale", "Emberly", "Ashmoor"]],
[handles.ready, true],
]),
preview(storefront, storefrontState("details")),
preview(storefront, storefrontState("cart"), { name: "storefront_cart" }),
],
});
Loading
Loading