diff --git a/src/engine/commands.js b/src/engine/commands.js index 25d5ce4..c5b86e3 100644 --- a/src/engine/commands.js +++ b/src/engine/commands.js @@ -3,13 +3,19 @@ import UseCommand from "./commands/use"; import TakeCommand from "./commands/take"; import DropCommand from "./commands/drop"; import EchoCommand from "./commands/echo"; +import SaveCommand from "./commands/save"; +import LoadCommand from "./commands/load"; +import VolumeCommand from "./commands/volume"; const defaultCommands = [ [["look", "l"], LookCommand], [["use", "interact"], UseCommand], [["take", "get"], TakeCommand], [["drop", "put"], DropCommand], - ["echo", EchoCommand] + ["echo", EchoCommand], + ["save", SaveCommand], + ["load", LoadCommand], + ["volume", VolumeCommand] ]; const directionMap = [ diff --git a/src/engine/commands/load.js b/src/engine/commands/load.js new file mode 100644 index 0000000..7d005e9 --- /dev/null +++ b/src/engine/commands/load.js @@ -0,0 +1,4 @@ +export default function LoadCommand(args, context) { + context.print(`Loading game...`); + context.load(); +} \ No newline at end of file diff --git a/src/engine/commands/save.js b/src/engine/commands/save.js new file mode 100644 index 0000000..e52ee9e --- /dev/null +++ b/src/engine/commands/save.js @@ -0,0 +1,4 @@ +export default function SaveCommand(args, context) { + context.print(`Saving game...`); + context.save(); +} \ No newline at end of file diff --git a/src/engine/commands/volume.js b/src/engine/commands/volume.js new file mode 100644 index 0000000..0fd3d0d --- /dev/null +++ b/src/engine/commands/volume.js @@ -0,0 +1,19 @@ +export default function VolumeCommand(args, context) { + if (args.length < 3) { + return context.print(`Usage: volume <0-100>`); + } + const value = parseInt(args[2]); + if (value > 100 || value < 1) { + return context.print(`No higher than 100 and no less than 1.`); + } + if (args[1] == "sfx") { + context.output.sound.setSFXVolume(value/100); + } else if (args[1] == "music") { + context.output.sound.setMusicVolume(value/100); + } else if (args[1] == "ambience") { + context.output.sound.setAmbienceVolume(value/100); + } else { + return context.print(`Invalid channel. Either ambience, sfx or music is allowed.`); + } + context.print(`${args[1]} volume set to ${value}%`) +} \ No newline at end of file diff --git a/src/engine/index.js b/src/engine/index.js index 983b9bb..c37e73d 100644 --- a/src/engine/index.js +++ b/src/engine/index.js @@ -4,7 +4,7 @@ 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() { @@ -17,6 +17,7 @@ export default class Game { this.input = new Input(this.commandHandler, this.output); this.visitedRooms = new Map(); this.interval = null; + this.Serialization = new Serialization(this); } print(string) { @@ -38,6 +39,7 @@ export default class Game { this.player.context = this; this.move(this.player.currentRoom); this.start(); + this.Serialization.save(); } advanceTick() { @@ -136,4 +138,12 @@ export default class Game { 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/serialization.js b/src/engine/serialization.js new file mode 100644 index 0000000..d5250f7 --- /dev/null +++ b/src/engine/serialization.js @@ -0,0 +1,52 @@ +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; + } +} \ No newline at end of file diff --git a/src/engine/sound.js b/src/engine/sound.js index 408e68a..8aea485 100644 --- a/src/engine/sound.js +++ b/src/engine/sound.js @@ -8,10 +8,14 @@ export default class Sound { this.music = null; this.previousAmbience = null; this.previousMusic = null; + this.ambienceVolume = 1; + this.musicVolume = 1; + this.sfxVolume = 1; } play(file) { const sound = this.res.loadImmediate(file); + sound.setVolume(this.sfxVolume); sound.play(); } @@ -24,6 +28,7 @@ export default class Sound { } if (!file) return; this.ambience = this.res.stream(file, 0); + this.ambience.setVolume(this.ambienceVolume); this.ambience.play(); this.ambience.loop(true); this.ambience.fadeIn(3); @@ -37,6 +42,7 @@ export default class Sound { } if (!file) return; this.music = this.res.stream(file, 1); + this.music.setVolume(this.musicVolume); this.music.play(); this.music.fadeIn(2); } @@ -44,4 +50,18 @@ export default class Sound { setImpulse(file) { this.res.setEnvironmentImpulse(file); } + + setMusicVolume(volume) { + this.musicVolume = volume; + if (this.music) this.music.setVolume(volume); + } + + setAmbienceVolume(volume) { + this.ambienceVolume = volume; + if (this.ambience) this.ambience.setVolume(volume); + } + + setSFXVolume(volume) { + this.sfxVolume = volume; + } } \ No newline at end of file diff --git a/src/engine/state.js b/src/engine/state.js index 04c3943..fa89ce2 100644 --- a/src/engine/state.js +++ b/src/engine/state.js @@ -13,6 +13,19 @@ class State { set(key, value) { return this.states.set(key, value); } + + 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