Rooms, items and some player stuff

This commit is contained in:
2021-11-04 20:58:37 +01:00
parent 36bb9264b3
commit a745ff299e
277 changed files with 14665 additions and 5 deletions

View File

@@ -0,0 +1,46 @@
import Item from '../item';
export default class ItemBuilder {
constructor() {
this.item = new Item();
}
withID(ID) {
this.item.id = ID;
return this;
}
withName(name) {
this.item.name = name;
return this;
}
withDescription(description) {
this.item.description = description;
return this;
}
isUsable(value) {
this.item.usable = value;
return this;
}
isTakeable(value) {
this.item.takeable = value;
return this;
}
withUseCallback(callback) {
this.item.useCallback = callback;
return this;
}
withTakeCallback(callback) {
this.item.takeCallback = callback;
return this;
}
create() {
return this.item;
}
}

View File

@@ -0,0 +1,66 @@
import Room from '../room';
export default class RoomBuilder {
constructor() {
this.room = new Room();
}
withID(ID) {
this.room.id = ID;
return this;
}
withTitle(title) {
this.room.title = title;
return this;
}
withFirstDescription(description) {
this.room.firstDescription = description;
return this;
}
withDescription(description) {
this.room.description = description;
return this;
}
withExit(direction, roomID) {
this.room.addExit(direction, roomID);
return this;
}
withItem(itemID) {
this.room.addItem(itemID);
return this;
}
withEnterCallback(callback) {
this.room.addEnterCallback(callback);
return this;
}
withExitCallback(callback) {
this.room.addExitCallback(callback);
return this;
}
withEnterLogic(func) {
this.room.addEnterLogic(func);
return this;
}
withExitLogic(func) {
this.room.addExitLogic(func);
return this;
}
withTick(func) {
this.room.addTickCallback(func);
return this;
}
create() {
return this.room;
}
}

43
src/engine/commands.js Normal file
View File

@@ -0,0 +1,43 @@
import LookCommand from "./commands/look";
import UseCommand from "./commands/use";
const defaultCommands = [
[["look", "l"], LookCommand],
[["use", "interact"], UseCommand]
];
export default class Commands {
constructor(context, commands) {
this.context = context;
this.commands = commands || new Map();
this.addDefaultCommands();
}
doCommand(str) {
const room = this.context.getRoom(this.context.player.currentRoom);
const split = str.split(" ");
if (this.commands.get(split[0])) {
this.commands.get(split[0])(split, this.context);
}
if (room.getExit(split[0])) {
this.context.move(room.getExit(split[0]));
}
}
addCommand(name, func) {
if (Array.isArray(name)) {
name.forEach((command) => this.commands.set(command, func));
} else {
this.commands.set(name, func);
}
}
addCommands(commands) {
commands.forEach((command) => {
this.addCommand(command[0], command[1]);
});
}
addDefaultCommands() {
this.addCommands(defaultCommands);
}
}

View File

@@ -0,0 +1,21 @@
export default function LookCommand(args, context) {
if (args.length == 0) {
context.examineRoom();
} else {
const room = context.getRoom(context.player.currentRoom);
const items = room.getItems();
let item = null;
for (let i of items) {
if (i.name.includes(args[1])) {
item = i;
break;
}
}
if (!item) {
context.output.say(`I could not find a ${args[1]}`);
} else {
context.output.say(item.name);
context.output.say(item.description);
}
}
}

View File

View File

@@ -0,0 +1,16 @@
export default async function UseCommand(args, context) {
const room = context.getRoom(context.player.currentRoom);
const items = room.getItems();
let item = null;
for (let i of items) {
if (i.name.includes(args[1])) {
item = i;
break;
}
}
if (!item) {
context.output.say(`I could not find a ${args[1]}`);
} else {
await item.onUse();
}
}

92
src/engine/index.js Normal file
View File

@@ -0,0 +1,92 @@
import State from './state';
import Room from './room';
import Player from './player';
import Output from './output';
import Input from './input';
import Commands from './commands';
export default class Game {
constructor() {
this.player = new Player();
this.state = State;
this.rooms = [];
this.items = [];
this.output = new Output();
this.commandHandler = new Commands(this);
this.input = new Input(this.commandHandler);
this.visitedRooms = new Map();
}
print(string) {
this.output.say(string);
}
init(data) {
console.log(data);
this.rooms = data.rooms.map((room) => {
room.context = this;
return room;
});
this.items = data.items.map((item) => {
item.context = this;
return item;
});
this.state = data.state;
this.commandHandler.addCommands(data.commands);
this.player = new Player();
this.move(this.player.currentRoom);
}
examineRoom() {
const room = this.getRoom(this.player.currentRoom);
this.output.say(room.title);
if (!this.visitedRooms.get(this.player.currentRoom) && room.firstDescription != "") {
this.output.say(room.firstDescription);
} else {
this.output.say(room.description);
}
this.examineItems();
this.examineExits();
}
examineItems() {
const room = this.getRoom(this.player.currentRoom);
const items = room.getItems();
items.forEach((item) => this.output.say(item.name));
}
examineExits() {
const room = this.getRoom(this.player.currentRoom);
let exitDescription = "You can go ";
for (let exit of room.exits.keys()) {
exitDescription += " " + exit;
}
this.output.say(exitDescription);
}
getRoom(id) {
return this.rooms.find((room) => room.id == id);
}
getItem(id) {
return this.items.find((item) => item.id == id);
}
wait(ms) {
return new Promise((resolve, reject) => {
setTimeout(resolve, ms);
});
}
async move(roomID) {
const currentRoom = this.getRoom(this.player.currentRoom);
const newRoom = this.getRoom(roomID);
if (currentRoom.canExit() && newRoom.canEnter()) {
await currentRoom.onExit();
await newRoom.onEnter();
this.player.currentRoom = roomID;
this.examineRoom();
this.visitedRooms.set(roomID, true);
}
}
}

17
src/engine/input.js Normal file
View File

@@ -0,0 +1,17 @@
export default class Input {
constructor(commandHandler) {
this.handler = commandHandler;
this.inputField = document.getElementById("input-area");
this.init();
}
init() {
this.inputField.addEventListener("keydown", (e) => {
if (e.which == 13) {
const val = this.inputField.value;
this.inputField.value = "";
this.handler.doCommand(val);
}
})
}
}

20
src/engine/item.js Normal file
View File

@@ -0,0 +1,20 @@
export default class Item {
constructor() {
this.id = "item";
this.name = "An item";
this.description = "You see nothing special about this item";
this.usable = true;
this.takeable = true;
this.useCallback = null;
this.takeCallback = null;
this.context = null;
}
async onUse() {
if (this.useCallback) return this.useCallback(this.context);
}
async onTake() {
if (this.takeCallback) return this.takeCallback();
}
}

16
src/engine/output.js Normal file
View File

@@ -0,0 +1,16 @@
import { TTS } from '../framework/tts';
import { AriaOutput } from '../framework/tts/outputs/aria';
export default class Output {
constructor() {
this.tts = new TTS(new AriaOutput());
this.history = document.getElementById("output-area");
}
say(string) {
const node = document.createElement("p");
node.appendChild(document.createTextNode(string));
this.history.appendChild(node);
// this.tts.speak(string);
}
}

6
src/engine/player.js Normal file
View File

@@ -0,0 +1,6 @@
export default class Player {
constructor() {
this.inventory = [];
this.currentRoom = "start";
}
}

75
src/engine/room.js Normal file
View File

@@ -0,0 +1,75 @@
export default class Room {
constructor() {
this.id = "room";
this.title = "A room";
this.description = "You see nothing special";
this.firstDescription = "As you walk into the room, you notice nothing special";
this.objects = [];
this.exits = new Map();
this.enterCallback = null;
this.exitCallback = null;
this.canEnterLogic = null;
this.canExitLogic = null;
this.tickCallback = null;
this.context = null;
}
async onEnter() {
if (this.enterCallback) return this.enterCallback(this.context);
}
async onExit() {
if (this.exitCallback) return this.exitCallback(this.context);
}
canEnter() {
if (this.canEnterLogic) {
return this.canEnterLogic(this.context);
}
return true;
}
canExit() {
if (this.canExitLogic) {
return this.canExitLogic(this.context);
}
return true;
}
addExit(direction, roomID) {
this.exits.set(direction, roomID);
return this;
}
getExit(direction) {
return this.exits.get(direction);
}
addItem(item) {
this.objects.push(item);
}
addEnterCallback(callback) {
this.enterCallback = callback;
}
addExitCallback(callback) {
this.exitCallback = callback;
}
addEnterLogic(func) {
this.canEnterLogic = func;
}
addExitLogic(func) {
this.canExitLogic = func;
}
addTickCallback(callback) {
this.tickCallback = callback;
}
getItems() {
return this.objects.map((item) => this.context.getItem(item));
}
}

15
src/engine/state.js Normal file
View File

@@ -0,0 +1,15 @@
class State {
constructor() {
this.states = new Map();
}
get(key) {
return this.states.get(key);
}
set(key, value) {
return this.states.set(key, value);
}
}
export default new State();