refactoring

This commit is contained in:
Kim Ravn Hansen
2025-10-21 15:53:44 +02:00
parent 15f648535c
commit ccd0f248fc
7 changed files with 85 additions and 63 deletions

View File

@@ -10,14 +10,11 @@ import { gGame } from "../../models/globals.js";
/** @property {Session} session */ /** @property {Session} session */
export class AuthenticationScene extends Scene { export class AuthenticationScene extends Scene {
introText = [
"= Welcome!", //
];
/** @type {Player} */ /** @type {Player} */
player; player;
onReady() { onReady() {
this.session.sendText("= Welcome");
this.show(UsernamePrompt); this.show(UsernamePrompt);
} }

View File

@@ -1,3 +1,4 @@
import { Prompt } from "../prompt.js";
import { Scene } from "../scene.js"; import { Scene } from "../scene.js";
/** /**
@@ -6,7 +7,38 @@ import { Scene } from "../scene.js";
* It's here we listen for player commands. * It's here we listen for player commands.
*/ */
export class GameScene extends Scene { export class GameScene extends Scene {
introText = ` onReady() {
//
// Find out which state the player and their characters are in
// Find out where we are
// Re-route to the relevant scene if necessary.
//
// IF player has stored state THEN
// restore it and resume [main flow]
// END
//
// IF player has no characters THEN
// go to createCharacterScene
// END
//
// set player's current location = Hovedstad
// display the welcome to Hovedstad stuff, and
// await the player's commands.
//
//
// IDEA:
// Does a player have a previous state?
// The state that was on the previous session?
//
// If player does not have a previous session
// then we start in the Adventurers Guild in the Hovedstad
//
this.show(GameScenePlaceholderPrompt);
}
}
class GameScenePlaceholderPrompt extends Prompt {
promptText = `
█▐▀▀▀▌▄ █▐▀▀▀▌▄
█ ▐▀▀▀▌▌▓▌ █ ▐▀▀▀▌▌▓▌
@@ -49,33 +81,6 @@ export class GameScene extends Scene {
= Welcome to Hovedstad = Welcome to Hovedstad
(( type :quit to quit ))
`; `;
onReady() {
//
// Find out which state the player and their characters are in
// Find out where we are
// Re-route to the relevant scene if necessary.
//
// IF player has stored state THEN
// restore it and resume [main flow]
// END
//
// IF player has no characters THEN
// go to createCharacterScene
// END
//
// set player's current location = Hovedstad
// display the welcome to Hovedstad stuff, and
// await the player's commands.
//
//
// IDEA:
// Does a player have a previous state?
// The state that was on the previous session?
//
// If player does not have a previous session
// then we start in the Adventurers Guild in the Hovedstad
//
}
} }

View File

@@ -5,7 +5,7 @@ import { Scene } from "../scene.js";
import { CreateUsernamePrompt } from "./createUsernamePrompt.js"; import { CreateUsernamePrompt } from "./createUsernamePrompt.js";
export class PlayerCreationScene extends Scene { export class PlayerCreationScene extends Scene {
introText = "= Create Player"; intro = "= Create Player";
/** @protected @type {Player} */ /** @protected @type {Player} */
player; player;

View File

@@ -5,7 +5,7 @@ import { Scene } from "../scene.js";
import { CreateUsernamePrompt } from "./createUsernamePrompt.js"; import { CreateUsernamePrompt } from "./createUsernamePrompt.js";
export class PlayerCreationScene extends Scene { export class PlayerCreationScene extends Scene {
introText = "= Create Player"; intro = "= Create Player";
/** @protected @type {Player} */ /** @protected @type {Player} */
player; player;

View File

@@ -43,7 +43,7 @@ export class Prompt {
/** @type {string|string[]} Default prompt text to send if we don't want to send something in the execute() call. */ /** @type {string|string[]} Default prompt text to send if we don't want to send something in the execute() call. */
promptText = [ promptText = [
"Please enter some very important info", // Stupid placeholder text "Please enter some very important info", // Silly placeholder text
"((or type :quit to run away))", // strings in double parentheses is rendered shaded/faintly "((or type :quit to run away))", // strings in double parentheses is rendered shaded/faintly
]; ];

View File

@@ -1,8 +1,10 @@
import { sprintf } from "sprintf-js"; import { sprintf } from "sprintf-js";
import { Prompt } from "./prompt.js";
/** @typedef {import("../utils/messages.js").WebsocketMessage} WebsocketMessage */ /** @typedef {import("../utils/messages.js").WebsocketMessage} WebsocketMessage */
/** @typedef {import("../models/session.js").Session} Session */ /** @typedef {import("../models/session.js").Session} Session */
/** @typedef {import("./prompt.js").Prompt } Prompt */ /** @typedef {import("./prompt.js").Prompt } Prompt */
/** @typedef {new (scene: Scene) => Prompt} PromptClassReference */
/** /**
* Scene - a class for showing one or more prompts in a row. * Scene - a class for showing one or more prompts in a row.
@@ -16,13 +18,8 @@ import { sprintf } from "sprintf-js";
* @abstract * @abstract
*/ */
export class Scene { export class Scene {
/** /** @constant @readonly @type {string|string[]|PromptClassReference} Text or prompt to show when this scene begins */
* @type {string|string[]} This text is shown when the scene begins intro;
*/
introText = "";
/** @constant @readonly @type {Prompt?} */
introPrompt;
/** @readonly @constant @protected @type {Session} */ /** @readonly @constant @protected @type {Session} */
#session; #session;
@@ -47,21 +44,15 @@ export class Scene {
/** @param {Session} session */ /** @param {Session} session */
execute(session) { execute(session) {
this.#session = session; this.#session = session;
this.onReady();
if (this.introText) {
this.session.sendText(this.introText);
}
if (this.introPrompt) {
this.showPrompt(this.introPrompt);
} else {
this.onReady();
}
} }
/** @abstract */
onReady() { onReady() {
throw new Error("Abstract method must be implemented by subclass"); if (!this.intro) {
return;
}
this.show(this.intro);
} }
/** @param {Prompt} prompt */ /** @param {Prompt} prompt */
@@ -70,9 +61,33 @@ export class Scene {
prompt.execute(); prompt.execute();
} }
/** @param {new (scene: Scene) => Prompt} promptClassReference */ /** @param {string|string[]} text */
show(promptClassReference) { showText(text) {
this.showPrompt(new promptClassReference(this)); this.session.sendText(text);
}
/** @param {PromptClassReference|string|string[]|Prompt} value */
show(value) {
if (value instanceof Prompt) {
this.showPrompt(value);
return;
}
if (typeof value === "string" || typeof value[0] === "string") {
this.showText(value);
return;
}
if (typeof value !== "function") {
throw new Error("Invalid type. Value must be string, string[], Prompt, or a class reference to Prompt");
}
const prompt = new value(this);
if (!(prompt instanceof Prompt)) {
throw new Error("Invalid class reference");
}
this.showPrompt(new value(this));
} }
/** /**
@@ -91,6 +106,11 @@ export class Scene {
message, message,
type: typeof message, type: typeof message,
}); });
if (!this.currentPrompt) {
throw new Error("LogicError: cannot get a reply when you have not prompted the player");
}
this.currentPrompt.onReply(message.text); this.currentPrompt.onReply(message.text);
} }
@@ -107,7 +127,7 @@ export class Scene {
* - call this method directly * - call this method directly
*/ */
onQuit() { onQuit() {
this.currentPrompt.onQuit(); this.currentPrompt?.onQuit();
} }
/** /**
@@ -127,7 +147,7 @@ export class Scene {
* @param {WebsocketMessage} message * @param {WebsocketMessage} message
*/ */
onHelp(message) { onHelp(message) {
this.currentPrompt.onHelp(message.text); this.currentPrompt?.onHelp(message.text);
} }
/** /**
@@ -185,7 +205,7 @@ export class Scene {
* @param {WebsocketMessage} message * @param {WebsocketMessage} message
*/ */
onColon(message) { onColon(message) {
const handledByPrompt = this.currentPrompt.onColon(message.command, message.args); const handledByPrompt = this.currentPrompt?.onColon(message.command, message.args);
if (!handledByPrompt) { if (!handledByPrompt) {
this.onColonFallback(message.command, message.args); this.onColonFallback(message.command, message.args);
@@ -203,7 +223,7 @@ export class Scene {
const n = Number(args[0]); const n = Number(args[0]);
this.session.sendText( this.session.sendText(
sprintf("%.2f centimeters is only %.2f inches. This is american wands are so short!", n, n / 2.54), sprintf("%.2f centimeters is only %.2f inches. This is why american wands are so short!", n, n / 2.54),
); );
} }

View File

@@ -22,4 +22,4 @@ class TestChild extends TestParent {
} }
} }
console.log(new TestChild()); console.log(Function.prototype.toString.call(TestChild));