Skip to content

Commit

Permalink
Fix Crossing Temple path display bug
Browse files Browse the repository at this point in the history
* Add sub alias to math/counter
* Print command in window it was executed in (ex shopwindow)

fixes #52
  • Loading branch information
joemcbride committed Sep 7, 2024
1 parent 176fd6a commit 6133643
Show file tree
Hide file tree
Showing 10 changed files with 251 additions and 10 deletions.
6 changes: 6 additions & 0 deletions app/src/Outlander.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,8 @@
7B3B9A1B2759DB200035D731 /* IconLoader.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7B3B9A192759DB200035D731 /* IconLoader.swift */; };
7B3B9A1D275B11390035D731 /* SubsCommandHandler.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7B3B9A1C275B11390035D731 /* SubsCommandHandler.swift */; };
7B3B9A1E275B11390035D731 /* SubsCommandHandler.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7B3B9A1C275B11390035D731 /* SubsCommandHandler.swift */; };
7B6820472C8BC856009833B3 /* EmulateTextCommandHandler.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7B6820462C8BC856009833B3 /* EmulateTextCommandHandler.swift */; };
7B6820482C8BC856009833B3 /* EmulateTextCommandHandler.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7B6820462C8BC856009833B3 /* EmulateTextCommandHandler.swift */; };
7B8F887327924B5200713BA7 /* AddProfileWindow.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7B8F887127924B5200713BA7 /* AddProfileWindow.swift */; };
7B8F887427924B5200713BA7 /* AddProfileWindow.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7B8F887127924B5200713BA7 /* AddProfileWindow.swift */; };
7B8F887527924B5200713BA7 /* AddProfileWindow.xib in Resources */ = {isa = PBXBuildFile; fileRef = 7B8F887227924B5200713BA7 /* AddProfileWindow.xib */; };
Expand Down Expand Up @@ -356,6 +358,7 @@
7B3B9A1827596F390035D731 /* TestPlayground.playground */ = {isa = PBXFileReference; lastKnownFileType = file.playground; path = TestPlayground.playground; sourceTree = "<group>"; xcLanguageSpecificationIdentifier = xcode.lang.swift; };
7B3B9A192759DB200035D731 /* IconLoader.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = IconLoader.swift; sourceTree = "<group>"; };
7B3B9A1C275B11390035D731 /* SubsCommandHandler.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SubsCommandHandler.swift; sourceTree = "<group>"; };
7B6820462C8BC856009833B3 /* EmulateTextCommandHandler.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EmulateTextCommandHandler.swift; sourceTree = "<group>"; };
7B8F887127924B5200713BA7 /* AddProfileWindow.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AddProfileWindow.swift; sourceTree = "<group>"; };
7B8F887227924B5200713BA7 /* AddProfileWindow.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = AddProfileWindow.xib; sourceTree = "<group>"; };
7B8F888D279FB1A500713BA7 /* Swen.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Swen.swift; sourceTree = "<group>"; };
Expand Down Expand Up @@ -782,6 +785,7 @@
F9CA204E245FC4B600A92736 /* CommandProcessor.swift */,
F9CA20452453AEBB00A92736 /* EchoCommandHandler.swift */,
7BBBC51D2772C4E800D1CF3E /* EditCommandHandler.swift */,
7B6820462C8BC856009833B3 /* EmulateTextCommandHandler.swift */,
7B917E4E276411A300887F95 /* EpediaCommandHandler.swift */,
7B10A693275FFA25000FEDE8 /* EvalCommandHandler.swift */,
7B10A690275FEA01000FEDE8 /* EvalMathCommandHandler.swift */,
Expand Down Expand Up @@ -1095,6 +1099,7 @@
F98B492C2471F38E000E2D92 /* Logger.swift in Sources */,
7B27C5B0274B23760095B9BF /* ScriptContext.swift in Sources */,
7B917E5227641B9E00887F95 /* PingCommandHandler.swift in Sources */,
7B6820472C8BC856009833B3 /* EmulateTextCommandHandler.swift in Sources */,
7B917E4C2763FF7E00887F95 /* PrintBoxCommandHandler.swift in Sources */,
7BCE4A2725C5011B00AF0444 /* MapLoader.swift in Sources */,
7B228B1D273871720052610B /* Pathfinder.swift in Sources */,
Expand Down Expand Up @@ -1169,6 +1174,7 @@
7B228B24273880320052610B /* GotoCommandHandler.swift in Sources */,
7B917E50276411A300887F95 /* EpediaCommandHandler.swift in Sources */,
7B8F888F279FB1A500713BA7 /* Swen.swift in Sources */,
7B6820482C8BC856009833B3 /* EmulateTextCommandHandler.swift in Sources */,
F9CA20792467849700A92736 /* ClassCommandHandler.swift in Sources */,
7B9C5A6D273F327700A17134 /* Variables.swift in Sources */,
F9CA204A245C9E2300A92736 /* WindowCommandHandler.swift in Sources */,
Expand Down
7 changes: 5 additions & 2 deletions app/src/Outlander/Handlers/CommandProcessor.swift
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ struct Command2 {
var isSystemCommand: Bool = false
var fileName: String = ""
var preset: String = ""
var window: String = ""
}

class CommandProcesssor {
Expand Down Expand Up @@ -60,6 +61,8 @@ class CommandProcesssor {
handlers.append(TriggerCommandHandler(files))
handlers.append(EditCommandHandler(files))
handlers.append(MacroCommandHandler(files))
// for local testing only
// handlers.append(EmulateTextCommandHandler(files))

self.pluginManager = pluginManager
}
Expand Down Expand Up @@ -103,13 +106,13 @@ class CommandProcesssor {
var handled = false
for handler in handlers {
if handler.canHandle(cmd) {
handler.handle(cmd, with: context)
handled = true
handler.handle(cmd, with: context)
break
}
}
if !handled {
context.events2.sendGameCommand(Command2(command: cmd, isSystemCommand: command.isSystemCommand, fileName: command.fileName, preset: command.preset))
context.events2.sendGameCommand(Command2(command: cmd, isSystemCommand: command.isSystemCommand, fileName: command.fileName, preset: command.preset, window: command.window))
}
}
}
Expand Down
50 changes: 50 additions & 0 deletions app/src/Outlander/Handlers/EmulateTextCommandHandler.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
//
// EmulateTextCommandHandler.swift
// Outlander
//
// Created by Joe McBride on 9/6/24.
// Copyright © 2024 Joe McBride. All rights reserved.
//

import Foundation

class EmulateTextCommandHandler: ICommandHandler {
var command = "#emulate"

private let files: FileSystem
private let log = LogManager.getLog(String(describing: EmulateTextCommandHandler.self))
let queue = DispatchQueue(label: "swiftlee.concurrent.queue", qos: .background)

init(_ files: FileSystem) {
self.files = files
}

func handle(_ input: String, with: GameContext) {
let commands = input[command.count...].trimmingCharacters(in: .whitespacesAndNewlines).components(separatedBy: " ").filter { !$0.isEmpty }

if commands.isEmpty {
return
}

let fileName = commands[0]
let filePath = with.applicationSettings.paths.logs.appendingPathComponent(fileName)

if self.files.fileExists(filePath) {
guard let data = self.files.load(filePath) else {
return
}

guard let fileString = String(data: data, encoding: .utf8) else {
return
}

let lines = fileString.components(separatedBy: .newlines)

for line in lines {
queue.async {
with.events2.emulateGameText(line + "\r\n")
}
}
}
}
}
9 changes: 9 additions & 0 deletions app/src/Outlander/Infrastructure/Events.swift
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,10 @@ struct VariableChangedEvent: Event {
var value: String
}

struct EmulatedTextEvent: Event {
var data: String
}

extension Events2 {
func echoText(_ text: String, preset: String? = nil, color: String? = nil, mono: Bool = false) {
let data = EchoTextEvent(text: "\(text)\n".hexDecoededString(), preset: preset, color: color, mono: mono)
Expand Down Expand Up @@ -89,6 +93,11 @@ extension Events2 {
let evt = VariableChangedEvent(key: key, value: value)
post(evt)
}

func emulateGameText(_ data: String) {
let evt = EmulatedTextEvent(data: data)
post(evt)
}
}

class DummyEvent<T> where T: BaseEvent {}
Expand Down
4 changes: 4 additions & 0 deletions app/src/Outlander/Scripting/Script.swift
Original file line number Diff line number Diff line change
Expand Up @@ -929,6 +929,8 @@ class Script {

case "-":
fallthrough
case "sub":
fallthrough
case "subtract":
result = existingValue - numberValue

Expand Down Expand Up @@ -1575,6 +1577,8 @@ class Script {

case "-":
fallthrough
case "sub":
fallthrough
case "subtract":
result = existingValue - numberValue

Expand Down
12 changes: 11 additions & 1 deletion app/src/Outlander/Server/GameStream.swift
Original file line number Diff line number Diff line change
Expand Up @@ -240,6 +240,7 @@ class TagMode: IReaderMode {
let childContext = StreamContext([], text: context.text)

guard TextMode().read(childContext) != nil else {
context.text = childContext.text
return childContext.target
}

Expand Down Expand Up @@ -856,6 +857,11 @@ class GameStream {
let rawTag = TextTag.tagFor(data, window: "raw", mono: true)
streamCommands(.text([rawTag]))

// this currently gets sent in the Crossing Temple, a multi-line component
if data == "<compass></compass></component>\r\n" {
return
}

let tokens = tokenizer.read(data.replacingOccurrences(of: "\r\n", with: "\n"))

for token in tokens {
Expand Down Expand Up @@ -985,6 +991,10 @@ class GameStream {
let value = token.value("") ?? ""
context.globalVars[id] = value

if id == "roomexits" {
context.globalVars[id] = value.trimmingCharacters(in: .whitespacesAndNewlines)
}

if id == "roomobjs" {
let monsters = token.monsters(monsterCountIgnoreRegex)
context.globalVars["monsterlist"] = monsters.map { t in t.value() ?? "" }.joined(separator: "|")
Expand Down Expand Up @@ -1076,7 +1086,7 @@ class GameStream {
}

if lastToken?.name() == "preset", tag!.text.count > 0, tag!.text.hasPrefix(" You also see") {
tag?.preset = lastToken?.attr("id")
tag?.preset = lastToken?.attr("id")?.lowercased()
let text = "\n\(tag!.text.dropFirst(2))"
tag?.text = text
}
Expand Down
16 changes: 11 additions & 5 deletions app/src/Outlander/UI/GameViewController.swift
Original file line number Diff line number Diff line change
Expand Up @@ -184,12 +184,12 @@ class GameViewController: NSViewController, NSWindowDelegate {
}

case let .clearStream(name):
DispatchQueue.main.sync {
DispatchQueue.main.async {
self?.clearWindow(name)
}

case let .createWindow(name, title, closedTarget):
DispatchQueue.main.sync {
DispatchQueue.main.async {
self?.maybeCreateWindow(name, title: title, closedTarget: closedTarget)
}

Expand Down Expand Up @@ -249,14 +249,15 @@ class GameViewController: NSViewController, NSWindowDelegate {
let command = evt.command
let text = command.fileName.count > 0 ? "[\(command.fileName)]: \(command.command)\n" : "\(command.command)\n"
let mono = command.fileName.count > 0 ? true : false
let window = evt.command.window.isEmpty ? "main" : evt.command.window

var preset = command.fileName.count > 0 ? "scriptinput" : nil

if command.preset.count > 0 {
preset = command.preset
}

self.logText(text, preset: preset, mono: mono, playerCommand: !command.isSystemCommand)
self.logText(text, preset: preset, mono: mono, playerCommand: !command.isSystemCommand, window: window)
self.gameServer?.sendCommand(command.command)
}

Expand Down Expand Up @@ -302,6 +303,10 @@ class GameViewController: NSViewController, NSWindowDelegate {
self.handleRawStream(data: evt.text, streamData: false)
}

gameContext.events2.register(self) { (evt: EmulatedTextEvent) in
self.handleRawStream(data: evt.data, streamData: true)
}

vitalsBar.presetFor = { name in
guard self.vitalsBar.enabled == true else {
return (self.vitalsBar.disabledForegroundColor, self.vitalsBar.disabledBackgroundColor)
Expand Down Expand Up @@ -349,6 +354,7 @@ class GameViewController: NSViewController, NSWindowDelegate {
gameContext.events2.unregister(self, DummyEvent<ErrorEvent>())
gameContext.events2.unregister(self, DummyEvent<EchoTagEvent>())
gameContext.events2.unregister(self, DummyEvent<EchoTextEvent>())
gameContext.events2.unregister(self, DummyEvent<EmulatedTextEvent>())
gameContext.events2.unregister(self, DummyEvent<VariableChangedEvent>())
gameContext.events2.unregister(self, DummyEvent<WindowCommandEvent>())
}
Expand Down Expand Up @@ -963,8 +969,8 @@ class GameViewController: NSViewController, NSWindowDelegate {
}
}

func logText(_ text: String, preset: String? = nil, color: String? = nil, mono: Bool = false, playerCommand: Bool = false) {
logTag([TextTag.tagFor(text, window: "main", mono: mono, color: color, preset: preset, playerCommand: playerCommand)])
func logText(_ text: String, preset: String? = nil, color: String? = nil, mono: Bool = false, playerCommand: Bool = false, window: String = "main") {
logTag([TextTag.tagFor(text, window: window, mono: mono, color: color, preset: preset, playerCommand: playerCommand)])
}

func logError(_ text: String) {
Expand Down
4 changes: 2 additions & 2 deletions app/src/Outlander/UI/WindowViewController.swift
Original file line number Diff line number Diff line change
Expand Up @@ -203,7 +203,7 @@ class WindowViewController: NSViewController, NSUserInterfaceValidations, NSText
}

addMenu(title: "Close Window", action: #selector(closeWindow(sender:)))
// addMenu(title: "Show Settings", action: #selector(toggleSettingsAction(sender:)))
// addMenu(title: "Show Settings", action: #selector(toggleSettingsAction(sender:)))
addMenu(title: "Show Border", action: #selector(toggleShowBorder(sender:)))
addMenu(title: "Timestamp", action: #selector(toggleTimestamp(sender:)))
addMenu(title: "Auto Scroll", action: #selector(toggleAutoScroll(sender:)))
Expand Down Expand Up @@ -720,7 +720,7 @@ class WindowViewController: NSViewController, NSUserInterfaceValidations, NSText
if value.hasPrefix("command:") {
let cmd = value[8...]
if cmd.count > 0 {
gameContext?.events2.sendCommand(Command2(command: cmd, isSystemCommand: true))
gameContext?.events2.sendCommand(Command2(command: cmd, isSystemCommand: true, window: self.name))
}
} else {
guard let url = URL(string: value) else {
Expand Down
56 changes: 56 additions & 0 deletions app/src/OutlanderTests/GameStreamTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,24 @@ class GameStreamTests: XCTestCase {
}
}

func test_stream_room_exit_multi_tags() {
let context = GameContext()
let commands = streamCommands([
"<component id='room exits'>Obvious paths: clockwise, widdershins.\r\n",
"\r\n",
"<compass></compass></component>\r\n"
], context: context)

XCTAssertEqual(commands.count, 4)

switch commands[1] {
case .room:
XCTAssertEqual(context.globalVars["roomexits"], "Obvious paths: clockwise, widdershins.")
default:
XCTFail()
}
}

func testStreamRoomDescTags() {
let context = GameContext()
let commands = streamCommands([
Expand Down Expand Up @@ -160,6 +178,26 @@ class GameStreamTests: XCTestCase {
XCTAssertEqual(context.globalVars["monsterlist"], "a juvenile wyvern|a juvenile wyvern|a juvenile wyvern")
}

func test_stream_preset() {
let context = GameContext()
let commands = streamCommands([
"<preset id='roomDesc'>Fragrant smoke drifts from censers to carry periodic ripples of sound from the rooms beyond.</preset> You also see an iron-bound oak door set in the far wall.\r\n",
"<prompt time=\"1725664159\">&gt;</prompt>"
], context: context)

XCTAssertEqual(commands.count, 4)

switch commands[3] {
case let .text(tags):
XCTAssertEqual(tags[0].text, "Fragrant smoke drifts from censers to carry periodic ripples of sound from the rooms beyond.\nYou also see an iron-bound oak door set in the far wall.\n")
XCTAssertEqual(tags[0].preset, "roomdesc")
XCTAssertEqual(tags[1].text, ">")
XCTAssertEqual(tags[1].isPrompt, true)
default:
XCTFail()
}
}

func test_stream_hand_ids() {
let context = GameContext()
let commands = streamCommands([
Expand Down Expand Up @@ -581,4 +619,22 @@ class GameStreamTokenizerTests: XCTestCase {
XCTAssertTrue(token.hasAttr("cmd"))
XCTAssertEqual(token.attr("cmd"), "urchin guide Raven's Point, Town Square")
}

func test_invalid_component() {
let tokens = reader.read("<component id='room exits'>Obvious paths: clockwise, widdershins.\n")

XCTAssertEqual(tokens.count, 1)

let token = tokens[0]
XCTAssertEqual(token.children().count, 1)
}

func test_preset() {
let tokens = reader.read("<preset id='automapper'>Mapped exits: go oak door, go clockwise, go widdershins</preset>")

XCTAssertEqual(tokens.count, 1)

let token = tokens[0]
XCTAssertEqual(token.children().count, 1)
}
}
Loading

0 comments on commit 6133643

Please sign in to comment.