diff --git a/package-lock.json b/package-lock.json index 8ac2208..b78efef 100644 --- a/package-lock.json +++ b/package-lock.json @@ -5,6 +5,7 @@ "requires": true, "packages": { "": { + "name": "assassin-bug", "version": "1.0.0", "license": "ISC", "dependencies": { @@ -568,7 +569,6 @@ "dependencies": { "anymatch": "~3.1.2", "braces": "~3.0.2", - "fsevents": "~2.3.2", "glob-parent": "~5.1.2", "is-binary-path": "~2.1.0", "is-glob": "~4.0.1", diff --git a/src/engine/builders/item.js b/src/engine/builders/item.js index 5ef6ce7..c997668 100644 --- a/src/engine/builders/item.js +++ b/src/engine/builders/item.js @@ -1,56 +1,61 @@ -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.addUseCallback(callback); - return this; - } - - withTakeCallback(callback) { - this.item.addTakeCallback(callback); - return this; - } - - withDropCallback(callback) { - this.item.addDropCallback(callback); - return this; - } - - withTickCallback(callback) { - this.item.addTickCallback(callback); - return this; - } - - create() { - return this.item; - } +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; + } + + withState(key, value) { + this.item.setState(key, value); + return this; + } + + isUsable(value) { + this.item.usable = value; + return this; + } + + isTakeable(value) { + this.item.takeable = value; + return this; + } + + withUseCallback(callback) { + this.item.addUseCallback(callback); + return this; + } + + withTakeCallback(callback) { + this.item.addTakeCallback(callback); + return this; + } + + withDropCallback(callback) { + this.item.addDropCallback(callback); + return this; + } + + withTickCallback(callback) { + this.item.addTickCallback(callback); + return this; + } + + create() { + return this.item; + } } \ No newline at end of file diff --git a/src/engine/index.js b/src/engine/index.js index 1eb2073..ecff6ed 100644 --- a/src/engine/index.js +++ b/src/engine/index.js @@ -1,160 +1,160 @@ -import State from './state'; -import Room from './room'; -import Player from './player'; -import Output from './output'; -import Input from './input'; -import Commands from './commands'; -import Serialization from './serialization'; - -export default class Game { - constructor(newGame = true) { - this.newGame = newGame; - 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.output); - this.visitedRooms = new Map(); - this.interval = null; - this.Serialization = new Serialization(this); - } - - print(string) { - this.output.say(string); - } - - async tell(lines, time) { - for (let line of lines) { - this.print(line); - await this.wait(time); - } - } - - init(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 || State; - this.commandHandler.addCommands(data.commands); - this.player = new Player(); - this.player.context = this; - if (this.newGame) { - this.move(this.player.currentRoom); - } else { - this.Serialization.load(); - } - this.start(); - } - - advanceTick() { - this.items.forEach((item) => item.onTick()); - this.rooms.forEach((room) => room.onTick()); - } - - start() { - this.interval = setInterval(() => this.advanceTick(), 1000); - } - - stop() { - clearInterval(this.interval); - this.interval = null; - } - - 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(); - if (items.length < 1) return; - let itemDescription = `You see `; - items.forEach((item, index) => { - if (index < items.length - 2) { - itemDescription += `${item.name}, `; - } else if (index < items.length - 1) { - itemDescription += `${item.name} and `; - } else { - itemDescription += item.name - } - }); - this.output.say(itemDescription + "."); - } - - examineExits() { - const room = this.getRoom(this.player.currentRoom); - let exits = []; - let exitDescription = "You can go "; - const exitKeys = room.exits.keys(); - for (let exit of exitKeys) { - exits.push(exit); - } - exits.forEach((item, index) => { - if (index < exits.length - 2) { - exitDescription += `${item}, `; - } else if (index < exits.length - 1) { - exitDescription += `${item} and `; - } else { - exitDescription += item - } - }); - 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); - } - } - - enableCommandInput(value) { - this.commandHandler.enabled = value; - } - - setInputEcho(value) { - this.input.setEcho(value); - } - - save() { - this.Serialization.save(); - } - - load() { - this.Serialization.load(); - } +import State from './state'; +import Room from './room'; +import Player from './player'; +import Output from './output'; +import Input from './input'; +import Commands from './commands'; +import Serialization from './serialization'; + +export default class Game { + constructor(newGame = true) { + this.newGame = newGame; + this.player = new Player(); + this.state = new State(); + this.rooms = []; + this.items = []; + this.output = new Output(); + this.commandHandler = new Commands(this); + this.input = new Input(this.commandHandler, this.output); + this.visitedRooms = new Map(); + this.interval = null; + this.Serialization = new Serialization(this); + } + + print(string) { + this.output.say(string); + } + + async tell(lines, time) { + for (let line of lines) { + this.print(line); + await this.wait(time); + } + } + + init(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 || new State(); + this.commandHandler.addCommands(data.commands); + this.player = new Player(); + this.player.context = this; + if (this.newGame) { + this.move(this.player.currentRoom); + } else { + this.Serialization.load(); + } + this.start(); + } + + advanceTick() { + this.items.forEach((item) => item.onTick()); + this.rooms.forEach((room) => room.onTick()); + } + + start() { + this.interval = setInterval(() => this.advanceTick(), 1000); + } + + stop() { + clearInterval(this.interval); + this.interval = null; + } + + 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(); + if (items.length < 1) return; + let itemDescription = `You see `; + items.forEach((item, index) => { + if (index < items.length - 2) { + itemDescription += `${item.name}, `; + } else if (index < items.length - 1) { + itemDescription += `${item.name} and `; + } else { + itemDescription += item.name + } + }); + this.output.say(itemDescription + "."); + } + + examineExits() { + const room = this.getRoom(this.player.currentRoom); + let exits = []; + let exitDescription = "You can go "; + const exitKeys = room.exits.keys(); + for (let exit of exitKeys) { + exits.push(exit); + } + exits.forEach((item, index) => { + if (index < exits.length - 2) { + exitDescription += `${item}, `; + } else if (index < exits.length - 1) { + exitDescription += `${item} and `; + } else { + exitDescription += item + } + }); + 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); + } + } + + enableCommandInput(value) { + this.commandHandler.enabled = value; + } + + setInputEcho(value) { + this.input.setEcho(value); + } + + save() { + this.Serialization.save(); + } + + load() { + this.Serialization.load(); + } } \ No newline at end of file diff --git a/src/engine/item.js b/src/engine/item.js index e9c4a0d..46f4393 100644 --- a/src/engine/item.js +++ b/src/engine/item.js @@ -1,45 +1,56 @@ -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.dropCallback = null; - this.tickCallback = null; - this.context = null; - } - - async onUse() { - if (this.useCallback) return this.useCallback(this.context); - } - - async onTake() { - if (this.takeCallback) return this.takeCallback(this.context); - } - - async onDrop() { - if (this.dropCallback) return this.dropCallback(this.context); - } - async onTick() { - if (this.tickCallback) return this.tickCallback(this.context); - } - - addUseCallback(callback) { - this.useCallback = callback.bind(this); - } - - addTakeCallback(callback) { - this.takeCallback = callback.bind(this); - } - - addDropCallback(callback) { - this.dropCallback = callback.bind(this); - } - - addTickCallback(callback) { - this.tickCallback = callback.bind(this); - } +import State from "./state"; + +export default class Item { + constructor() { + this.id = "item"; + this.name = "An item"; + this.description = "You see nothing special about this item"; + this.state = new State(); + this.usable = true; + this.takeable = true; + this.useCallback = null; + this.takeCallback = null; + this.dropCallback = null; + this.tickCallback = null; + this.context = null; + } + + async onUse() { + if (this.useCallback) return this.useCallback(this.context); + } + + async onTake() { + if (this.takeCallback) return this.takeCallback(this.context); + } + + async onDrop() { + if (this.dropCallback) return this.dropCallback(this.context); + } + async onTick() { + if (this.tickCallback) return this.tickCallback(this.context); + } + + addUseCallback(callback) { + this.useCallback = callback.bind(this); + } + + addTakeCallback(callback) { + this.takeCallback = callback.bind(this); + } + + addDropCallback(callback) { + this.dropCallback = callback.bind(this); + } + + addTickCallback(callback) { + this.tickCallback = callback.bind(this); + } + + setState(key, value) { + return this.state.set(key, value); + } + + getState(key) { + return this.state.get(key); + } } \ No newline at end of file diff --git a/src/engine/serialization.js b/src/engine/serialization.js index d5250f7..07e657d 100644 --- a/src/engine/serialization.js +++ b/src/engine/serialization.js @@ -1,52 +1,67 @@ -export default class Serialization { - constructor(context) { - this.context = context; - } - - save() { - const saveobj = { - state: this.context.state.serialize(), - itemLocations: this.serializeItemLocations(), - player: { - currentRoom: this.context.player.currentRoom, - inventory: this.context.player.inventory - }, - volumes: { - music: this.context.output.sound.musicVolume, - sfx: this.context.output.sound.sfxVolume, - ambience: this.context.output.sound.ambienceVolume - } - }; - localStorage.setItem("save", JSON.stringify(saveobj)); - } - - load() { - const loadobj = JSON.parse(localStorage.getItem("save")); - this.context.state.deserialize(loadobj.state); - this.deserializeItemLocations(loadobj.itemLocations); - this.deserializePlayer(loadobj.player); - this.context.output.sound.setSFXVolume(loadobj.volumes.sfx); - this.context.output.sound.setMusicVolume(loadobj.volumes.music); - this.context.output.sound.setAmbienceVolume(loadobj.volumes.ambience); - } - - serializeItemLocations() { - return this.context.rooms.map((item) => { - return [item.id, - item.objects - ] - }); - } - - deserializeItemLocations(items) { - items.forEach((item) => { - const room = this.context.getRoom(item[0]); - room.objects = item[1]; - }) - } - - deserializePlayer(player) { - this.context.move(player.currentRoom); - this.context.player.inventory = player.inventory; - } +export default class Serialization { + constructor(context) { + this.context = context; + } + + save() { + const saveobj = { + state: this.context.state.serialize(), + itemLocations: this.serializeItemLocations(), + itemStates: this.serializeItemStates(), + player: { + currentRoom: this.context.player.currentRoom, + inventory: this.context.player.inventory + }, + volumes: { + music: this.context.output.sound.musicVolume, + sfx: this.context.output.sound.sfxVolume, + ambience: this.context.output.sound.ambienceVolume + } + }; + localStorage.setItem("save", JSON.stringify(saveobj)); + } + + load() { + const loadobj = JSON.parse(localStorage.getItem("save")); + this.context.state.deserialize(loadobj.state); + this.deserializeItemLocations(loadobj.itemLocations); + this.deserializeItemStates(loadobj.itemStates); + this.deserializePlayer(loadobj.player); + this.context.output.sound.setSFXVolume(loadobj.volumes.sfx); + this.context.output.sound.setMusicVolume(loadobj.volumes.music); + this.context.output.sound.setAmbienceVolume(loadobj.volumes.ambience); + } + + serializeItemLocations() { + return this.context.rooms.map((item) => { + return [item.id, + item.objects + ] + }); + } + + deserializeItemLocations(items) { + items.forEach((item) => { + const room = this.context.getRoom(item[0]); + room.objects = item[1]; + }) + } + + deserializeItemStates(items) { + items.forEach((item) => { + const obj = this.context.getItem(item[0]); + obj.state.deserialize(item[1]); + }) + } + + deserializePlayer(player) { + this.context.move(player.currentRoom); + this.context.player.inventory = player.inventory; + } + + serializeItemStates() { + return this.context.items.map((item) => { + return [item.id, item.state.serialize()] + }); + } } \ No newline at end of file diff --git a/src/engine/state.js b/src/engine/state.js index c8ddeb9..0061113 100644 --- a/src/engine/state.js +++ b/src/engine/state.js @@ -1,38 +1,36 @@ -class State { - constructor() { - this.states = new Map(); - } - - get(key, defaultValue = null) { - if (!this.states.has(key)) { - this.states.set(key, defaultValue); - return defaultValue; - } - return this.states.get(key); - } - - set(key, value) { - return this.states.set(key, value); - } - - change(key, amount = 1) { - let val = this.get(key, 0); - val += amount; - this.set(key, val); - } - - serialize() { - const entries = this.states.entries(); - const entrymap = []; - for (let state of entries) { - entrymap.push(state); - } - return entrymap; - } - - deserialize(data) { - this.states = new Map(data); - } -} - -export default new State(); \ No newline at end of file +export default class State { + constructor() { + this.states = new Map(); + } + + get(key, defaultValue = null) { + if (!this.states.has(key)) { + this.states.set(key, defaultValue); + return defaultValue; + } + return this.states.get(key); + } + + set(key, value) { + return this.states.set(key, value); + } + + change(key, amount = 1) { + let val = this.get(key, 0); + val += amount; + this.set(key, val); + } + + serialize() { + const entries = this.states.entries(); + const entrymap = []; + for (let state of entries) { + entrymap.push(state); + } + return entrymap; + } + + deserialize(data) { + this.states = new Map(data); + } +} \ No newline at end of file