115 lines
No EOL
4.2 KiB
TypeScript
115 lines
No EOL
4.2 KiB
TypeScript
import EventEmitter from "eventemitter3"
|
|
import type { GameEvent } from "../shared/gameEvents"
|
|
import type { Interaction, InteractionQueueItem } from "../shared/script/types"
|
|
import { script } from "../shared/script"
|
|
import { findMatchingCombination, getInteractionQueueItemId } from "../shared/util"
|
|
|
|
interface Events {
|
|
"game-event": [GameEvent]
|
|
}
|
|
|
|
export class Game extends EventEmitter<Events> {
|
|
private currentRoomId: string = script.roomsById.values().next()!.value!.id
|
|
private interactionQueue: Map<string, InteractionQueueItem> = new Map()
|
|
private visibleObjectIds = new Set<string>()
|
|
|
|
constructor() {
|
|
super()
|
|
this.switchRoom(this.currentRoomId)
|
|
}
|
|
|
|
getInitialStateEvents(): GameEvent[] {
|
|
const events: GameEvent[] = []
|
|
|
|
events.push({ type: "room-changed", roomId: this.currentRoomId })
|
|
|
|
this.interactionQueue.forEach(item => events.push({ type: "interaction-queued", item }))
|
|
script.roomsById.get(this.currentRoomId)!.initialObjects.forEach(o => {
|
|
if (!this.visibleObjectIds.has(o.id)) events.push({ type: "object-visibility-changed", id: o.id, isVisible: false })
|
|
})
|
|
|
|
script.roomsById.get(this.currentRoomId)!.hiddenObjects.forEach(o => {
|
|
if (this.visibleObjectIds.has(o.id)) events.push({ type: "object-visibility-changed", id: o.id, isVisible: true })
|
|
})
|
|
|
|
return events
|
|
}
|
|
|
|
addInteractionVote(interaction: Interaction) {
|
|
const id = getInteractionQueueItemId(interaction)
|
|
const existingItem = this.interactionQueue.get(id)
|
|
if (existingItem === undefined) {
|
|
const item = {
|
|
id,
|
|
votes: 1,
|
|
interaction
|
|
}
|
|
|
|
this.interactionQueue.set(item.id, item)
|
|
this.emit("game-event", { type: "interaction-queued", item })
|
|
} else {
|
|
existingItem.votes += 1
|
|
this.emit("game-event", { type: "interaction-votes-changed", id: existingItem.id, votes: existingItem.votes })
|
|
}
|
|
}
|
|
|
|
removeInteractionVote(id: string) {
|
|
const item = this.interactionQueue.get(id)
|
|
if (item !== undefined) {
|
|
item.votes -= 1
|
|
this.emit("game-event", { type: "interaction-votes-changed", id: item.id, votes: item.votes })
|
|
|
|
if (item.votes <= 0) this.interactionQueue.delete(id)
|
|
}
|
|
}
|
|
|
|
switchRoom(roomId: string) {
|
|
this.currentRoomId = roomId
|
|
this.interactionQueue.clear()
|
|
this.visibleObjectIds.clear()
|
|
script.roomsById.get(this.currentRoomId)!.initialObjects.forEach(o => this.visibleObjectIds.add(o.id))
|
|
this.emit("game-event", { type: "room-changed", roomId })
|
|
}
|
|
|
|
activateInteractionQueueItem(id: string) {
|
|
const item = this.interactionQueue.get(id)
|
|
if (item === undefined) return
|
|
this.interactionQueue.delete(id)
|
|
this.emit("game-event", { type: "interaction-votes-changed", id, votes: 0 })
|
|
switch (item.interaction.type) {
|
|
case "use":
|
|
this.setObjectVisibility(item.interaction.objectId, false)
|
|
break
|
|
|
|
case "combine":
|
|
const matchingCombination = findMatchingCombination(script.roomsById.get(this.currentRoomId)!.combinations, item.interaction.objectIds)
|
|
|
|
if (matchingCombination !== undefined) {
|
|
matchingCombination.inputs.forEach(input => {
|
|
if (input.isConsumed) this.setObjectVisibility(input.objectId, false)
|
|
})
|
|
|
|
matchingCombination.outputIds.forEach(outputId => {
|
|
this.setObjectVisibility(outputId, true)
|
|
})
|
|
}
|
|
|
|
break
|
|
}
|
|
}
|
|
|
|
removeInteractionQueueItem(id: string) {
|
|
if (!this.interactionQueue.has(id)) return
|
|
this.emit("game-event", { type: "interaction-votes-changed", id, votes: 0 })
|
|
this.interactionQueue.delete(id)
|
|
}
|
|
|
|
setObjectVisibility(id: string, isVisible: boolean) {
|
|
if (isVisible) this.visibleObjectIds.add(id)
|
|
else this.visibleObjectIds.delete(id)
|
|
|
|
this.emit("game-event", { type: "object-visibility-changed", id, isVisible })
|
|
}
|
|
}
|
|
|
|
export const game = new Game() |