Skip to content

Commit

Permalink
refactor: simplify listener
Browse files Browse the repository at this point in the history
  • Loading branch information
reyronald committed Apr 6, 2024
1 parent 7bbc69d commit 1d36087
Show file tree
Hide file tree
Showing 4 changed files with 149 additions and 160 deletions.
13 changes: 1 addition & 12 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,18 +2,7 @@

A simple no-frills ACTWebSocket overlay for showing actions pressed in an overlay window.

Check it out online at: https://reyronald.github.io/SkillDisplay?HOST_PORT=ws://127.0.0.1:10501

## Installation

Make sure the 'Using BeforeLogLineRead' box is checked in ACTWebSocket then click the 'Add URL' button to add this URL:
`https://rawrington.github.io/SkillDisplay/`

## Troubleshooting

I have only tested and confirmed this working on the QT5.8.0 variant of OverlayProc with ACTWebSocket 1.3.3.9 so if you are having trouble please use these versions.

If you find any strange bugs, please report to me on here or find me on the ACT FFXIV discord.
Check it out online at: https://reyronald.github.io/SkillDisplay

## Preview

Expand Down
68 changes: 34 additions & 34 deletions src/ACTListener.ts
Original file line number Diff line number Diff line change
@@ -1,54 +1,54 @@
const getHost = () =>
/[?&]HOST_PORT=(wss?:\/\/[^&/]+)/.exec(window.location.search)

type Callback = (
...args: (string | { charID: number; charName: string })[]
) => void

type EventData = {
type: "broadcast"
msgtype: "Chat" | "SendCharName"
} & (
| {
msgtype: "ChangeZone"
msg: {
type: "ChangeZone"
zoneID: number
zoneName: string
}
}
| {
msgtype: "SendCharName"
msg: {
charID: number
charName: string
type: "ChangePrimaryPlayer"
}
}
| {
msgtype: "Chat"
msg: string
}
)

export default function listenToACT(callback: Callback) {
if (!getHost()) return listenOverlayPlugin(callback)
return listenActWebSocket(callback)
}
type Callback = (eventData: EventData) => void

// https://github.com/OverlayPlugin/cactbot/blob/main/docs/LogGuide.md
function listenActWebSocket(callback: Callback) {
const host = getHost()
const wsUri = host && host[1] ? `${host[1]}/BeforeLogLineRead` : undefined
if (!wsUri) return () => undefined
export default function listenToACT(callback: Callback) {
const urlSearchParams = new URLSearchParams(window.location.search)
const HOST_PORT = urlSearchParams.get("HOST_PORT")
const hostPort = HOST_PORT || "ws://127.0.0.1:10501"

const wsUri = `${hostPort}/BeforeLogLineRead`

const ws = new WebSocket(wsUri)

ws.onerror = () => ws.close()

ws.onmessage = function (e) {
if (e.data === ".") return ws.send(".")

const obj: EventData = JSON.parse(e.data)
if (obj.msgtype === "SendCharName") {
return callback(obj.msg)
} else if (obj.msgtype === "Chat") {
return callback(...obj.msg.split("|"))
const eventData: EventData = JSON.parse(e.data)
if (eventData.msgtype === "SendCharName") {
return callback(eventData)
} else if (eventData.msgtype === "Chat") {
return callback(eventData)
}
}

return () => {
ws.close()
}
}

function listenOverlayPlugin(callback: Callback) {
// eslint-disable-next-line @typescript-eslint/no-explicit-any
const listener = (e: any) => {
callback(...e.detail)
}

document.addEventListener("onLogLine", listener)

return () => {
document.removeEventListener("onLogLine", listener)
}
}
222 changes: 111 additions & 111 deletions src/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ export default function App() {
let lastKey = 0
let timeoutId: number | undefined = undefined

const closeFn = listenToACT((...logSplit) => {
const closeFn = listenToACT((eventData) => {
const openNewEncounter = () => {
setEncounterList((encounterList) => {
if (
Expand All @@ -62,127 +62,127 @@ export default function App() {
})
}

if (
logSplit.length === 1 &&
typeof logSplit[0] !== "string" &&
logSplit[0].charID
) {
selfId = logSplit[0].charID
if (eventData.msgtype === "SendCharName") {
selfId = eventData.msg.charID
openNewEncounter()
return
}

function refineType(_arg: typeof logSplit): asserts _arg is string[] {}
refineType(logSplit)

const [
logCode,
logTimestamp,
logParameter1,
logParameter2,
logParameter3,
ability,
] = logSplit

if (!handleCodes.has(logCode as LogCode)) return

switch (logCode) {
case LINE_ID.LogLine:
if (logParameter1 === "0038" && logParameter3 === "end")
openNewEncounter()
return
case LINE_ID.ChangeZone:
currentZone = logParameter2
return
case LINE_ID.ChangePrimaryPlayer:
selfId = parseInt(logParameter1, 16)
openNewEncounter()
return
case LINE_ID.ActorControl:
if (logParameter2 === "40000012" || logParameter2 === "40000010")
if (eventData.msgtype === "Chat") {
const logSplit = eventData.msg.split("|")

const [
logCode,
logTimestamp,
logParameter1,
logParameter2,
logParameter3,
ability,
] = logSplit

if (!handleCodes.has(logCode as LogCode)) return

switch (logCode) {
case LINE_ID.LogLine:
if (logParameter1 === "0038" && logParameter3 === "end")
openNewEncounter()
return
case LINE_ID.ChangeZone:
currentZone = logParameter2
return
case LINE_ID.ChangePrimaryPlayer:
selfId = parseInt(logParameter1, 16)
openNewEncounter()
return
case LINE_ID.ActorControl:
if (logParameter2 === "40000012" || logParameter2 === "40000010")
openNewEncounter()
return
default:
break
}

if (selfId === undefined) return

if (parseInt(logParameter1, 16) !== selfId) return

const actionId = parseInt(logParameter3, 16)

const isCombatAction =
(actionId >= 9 && actionId <= 30000) || actionId === SPRINT_ACTION_ID
const isCraftingAction = actionId >= 100001 && actionId <= 100300
const isBugOrDuplicate =
logTimestamp === lastTimestamp && actionId === lastAction
const isItem = ability.startsWith("item_")

if (
(!isCombatAction && !isCraftingAction && !isItem) ||
isBugOrDuplicate
) {
return
default:
break
}

if (selfId === undefined) return

if (parseInt(logParameter1, 16) !== selfId) return

const actionId = parseInt(logParameter3, 16)

const isCombatAction =
(actionId >= 9 && actionId <= 30000) || actionId === SPRINT_ACTION_ID
const isCraftingAction = actionId >= 100001 && actionId <= 100300
const isBugOrDuplicate =
logTimestamp === lastTimestamp && actionId === lastAction
const isItem = ability.startsWith("item_")

if (
(!isCombatAction && !isCraftingAction && !isItem) ||
isBugOrDuplicate
) {
return
}

if (Date.now() - Date.parse(lastTimestamp) > 120000) openNewEncounter() //last action > 120s ago

lastTimestamp = logTimestamp
lastAction = actionId

let keyToRemove: number | null = null

// This is pretty silly but it's the neatest way to handle the updates going
// out at the same time, without finding some way to merge the action lists....
ReactDOM.unstable_batchedUpdates(() => {
setActionList((actionList) => {
const lastAction = actionList.at(-1)

keyToRemove = lastAction?.key ?? null

if (logCode === LINE_ID.NetworkCancelAbility) {
return actionList.slice(0, -1)
} else if (lastAction?.actionId === actionId && lastAction?.casting) {
const nextActionList = actionList.slice()
nextActionList[nextActionList.length - 1] = {
...lastAction,
casting: false,
}

if (Date.now() - Date.parse(lastTimestamp) > 120000) openNewEncounter() //last action > 120s ago

lastTimestamp = logTimestamp
lastAction = actionId

let keyToRemove: number | null = null

// This is pretty silly but it's the neatest way to handle the updates going
// out at the same time, without finding some way to merge the action lists....
ReactDOM.unstable_batchedUpdates(() => {
setActionList((actionList) => {
const lastAction = actionList.at(-1)

keyToRemove = lastAction?.key ?? null

if (logCode === LINE_ID.NetworkCancelAbility) {
return actionList.slice(0, -1)
} else if (
lastAction?.actionId === actionId &&
lastAction?.casting
) {
const nextActionList = actionList.slice()
nextActionList[nextActionList.length - 1] = {
...lastAction,
casting: false,
}
return nextActionList
} else {
const key = (lastKey % 256) + 1
lastKey = key
return actionList.concat({
actionId,
ability,
key,
casting: logCode === LINE_ID.NetworkStartsCasting,
})
}
return nextActionList
} else {
const key = (lastKey % 256) + 1
lastKey = key
return actionList.concat({
actionId,
ability,
key,
casting: logCode === LINE_ID.NetworkStartsCasting,
})
}
})
setEncounterList((encounterList) => {
if (logCode !== LINE_ID.NetworkAbility) return encounterList

if (!encounterList[0]) {
encounterList[0] = {
name: currentZone,
actionList: [],
})
setEncounterList((encounterList) => {
if (logCode !== LINE_ID.NetworkAbility) return encounterList

if (!encounterList[0]) {
encounterList[0] = {
name: currentZone,
actionList: [],
}
}
}

encounterList[0].actionList.push({ actionId, ability })
encounterList[0].actionList.push({ actionId, ability })

return encounterList
return encounterList
})
})
})

if (keyToRemove != null) {
timeoutId = window.setTimeout(() => {
setActionList((actionList) =>
actionList.filter((action) => action.key !== keyToRemove),
)
}, 10000)

if (keyToRemove != null) {
timeoutId = window.setTimeout(() => {
setActionList((actionList) =>
actionList.filter((action) => action.key !== keyToRemove),
)
}, 10000)
}
}
})

Expand Down
6 changes: 3 additions & 3 deletions vite.config.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import { defineConfig } from 'vite'
import react from '@vitejs/plugin-react'
import { defineConfig } from "vite"
import react from "@vitejs/plugin-react"

// https://vitejs.dev/config/
export default defineConfig({
plugins: [react()],
base: '/SkillDisplay/'
base: "/SkillDisplay",
})

0 comments on commit 1d36087

Please sign in to comment.