From eaf4e3f26f16ff007d366be55c3ebeb86cf02d2f Mon Sep 17 00:00:00 2001 From: Mute Date: Sat, 12 Nov 2022 13:06:54 +0000 Subject: [PATCH] so refactor, much changes mostly improved syntax added exception handling for hooks hopefully fixed keydown interceptor --- mbchc-local.user.js | 232 +++++++++++++++++++------------------------- 1 file changed, 101 insertions(+), 131 deletions(-) diff --git a/mbchc-local.user.js b/mbchc-local.user.js index b8ca18b..1a183a5 100644 --- a/mbchc-local.user.js +++ b/mbchc-local.user.js @@ -368,11 +368,6 @@ if (cmd) cmd.AutoComplete = this.complete_fbc_pose }, gather_versions: function() { return(window.ChatRoomCharacter.filter(c => c.MBCHC).map(c => ({name: c.dn, cid: c.cid, version: c.MBCHC.VERSION}))) }, - need_load_hook: function(module, screen) { - if (!module || !screen) return(true) - if (("Character" === module) && ("Login" === screen)) return(true) - return(false) - }, find_timezone: function(char) { const timezones = this.settings("timezones") if (timezones && "number" === typeof timezones[char.cid]) return(timezones[char.cid]) @@ -526,7 +521,18 @@ window.ElementValue("InputChat", history[found]) window.ChatRoomLastMessageIndex = found }, - loader: function() { + focus_chat_whitelist(event) { + if (event.ctrlKey && "v" === event.key) return true // ctrl+V should paste + return false + }, + focus_chat(event) { // TODO: this is not ideal, but it will have to do for now + if (event.repeat) return // only unique presses please + if ("inline" !== document.getElementById("InputChat")?.style.display) return // input chat missing + if (["InputChat","bce-message-input"].includes(document.activeElement.id)) return // focus already set + if ([event.altKey, event.ctrlKey, event.metaKey].some(i => i) && !this.focus_chat_whitelist(event)) return // alt, ctrl and meta should all be false + window.ElementFocus("InputChat") + }, + loader() { if (this.remove_load_hook) { this.remove_load_hook() delete this.remove_load_hook @@ -573,135 +579,99 @@ this.calculate_maps() window.Player.MBCHC = {VERSION: this.VERSION} window.CommandCombine(COMMANDS) + + // Hooks + this.remove_fbc_hook = this.before("MainRun", () => window.bce_ActivityTriggers && this.patch_fbc()) + this.after("CharacterOnlineRefresh", char => this.update_char(char)) + this.after("ChatRoomReceiveSuitcaseMoney", () => { + if (this.AUTOHACK_ENABLED && this.LAST_HACKED) { + window.CurrentCharacter = this.cid2char(this.LAST_HACKED) + this.LAST_HACKED = null + window.ChatRoomTryToTakeSuitcase() + } + }) + this.before("ChatRoomSendChat", () => { + let input = window.ElementValue("InputChat") + if (!input.startsWith("@@@") && input.startsWith("@")) { + input = input.replace(this.RE_PREF_ACTIVITY, this.PREF_ACTIVITY) + input = input.replace(this.RE_PREF_ACTIVITY_ME, this.replace_me) + window.ElementValue("InputChat", input) + } + }) + this.after("ChatRoomSendChat", () => { + const history = window.ChatRoomLastMessage + if ((history.length > 1) && (history[history.length - 1] === history[history.length - 2])) {history.pop(); window.ChatRoomLastMessageIndex -= 1} + }) + this.before("ChatRoomDrawCharacterOverlay", (C, CharX, CharY, Zoom, Pos) => { + window.ChatRoomHideIconState < 1 && C.MBCHC && window.DrawRect(CharX + 175 * Zoom, CharY, 50 * Zoom, 50 * Zoom, C.MBCHC.VERSION === window.Player.MBCHC.VERSION ? this.RGB_POLLY : this.RGB_MUTE) + if (window.ChatRoomHideIconState < 1 && C.MBCHC_LOCAL && "number" === typeof C.MBCHC_LOCAL.TZ) { + const hours = new Date(window.CommonTime() + this.UTC_OFFSET + C.MBCHC_LOCAL.TZ * 60 * 60 * 1000).getHours() + window.DrawTextFit(hours < 10 ? "0" + hours.toString() : hours.toString(), CharX + 200 * Zoom, CharY + 25 * Zoom, 46 * Zoom, "white", "black") + } + }) + this.after("ElementValue", (ID, Value, cc = window.CurrentCharacter) => "bce_LayerPriority" === ID && cc?.FocusGroup && window.InventoryGet(cc, cc.FocusGroup.Name)?.Difficulty.toString() === Value && window.InventoryLocked(cc, cc.FocusGroup.Name, true) && window.ElementSetAttribute(ID, "disabled", true)) + this.after("ChatRoomCreateElement", () => this.COMP_HINT.parentElement || document.body.appendChild(this.COMP_HINT)) + this.before("ChatRoomClearAllElements", () => !void this.complete_hint_hide() && this.COMP_HINT.remove()) + this.before("ChatRoomClick", () => this.complete_hint_hide()) + this.after("ChatRoomResize", () => { + if (window.CharacterGetCurrent() == null && window.CurrentScreen == "ChatRoom" && document.getElementById("InputChat") && document.getElementById("TextAreaChatLog") && this.comp_hint_visible()) { // upstream + const fontsize = ChatRoomFontSize /* eslint-disable-line no-undef */ // window.ChatRoomFontSize is undefined + window.ElementPositionFix("TextAreaChatLog", fontsize, 1005, 66, 988, 630) + window.ElementPositionFix(this.COMP_HINT.id, fontsize, 1005, 701, 988, 200) + this.COMP_HINT.style.display = "flex" + } + }) + document.addEventListener("keydown", event => this.focus_chat(event)) + this.SDK.hookFunction("ChatRoomKeyDown", 0, (nextargs, next) => { // this fires on chat input events + let [event] = nextargs + window.MBCHC.complete_hint_hide() + if ((window.KeyPress == 33) || (window.KeyPress == 34)) { // better history + event.preventDefault() + return(window.MBCHC.history(window.KeyPress - 33)) + } + if (window.MBCHC.HISTORY_MODE) { + window.ChatRoomLastMessage.pop() + window.MBCHC.HISTORY_MODE = false + } + return(next(nextargs)) + }) + + // Chat room handlers + window.ChatRoomRegisterMessageHandler({ Priority: -220, Description: "MBCHC preprocessor", + Callback: (data, sender, msg, metadata) => { + data.MBCHC_ID = this.NEXT_MESSAGE + this.NEXT_MESSAGE += 1 + if (this.LOG_MESSAGES) console.debug({data, sender, msg, metadata}) + } + }) + window.ChatRoomRegisterMessageHandler({ Priority: -219, Description: "MBCHC room enter hook", + Callback: (data, sender, msg, metadata) => { if (("Action" === data.Type) && ("ServerEnter" === data.Content) && (data.Sender === window.Player.cid)) this.player_enters_room() } + }) + window.ChatRoomRegisterMessageHandler({ Priority: -219, Description: "MBCHC specific consumer", + Callback: (data, sender, msg, metadata) => { if (("Hidden" === data.Type) && ("MBCHC" === data.Content)) return this.receive(data) } + }) + window.ChatRoomRegisterMessageHandler({ Priority: -219, Description: "MBCHC autohack lookup", + Callback: (data, sender, msg, metadata) => { if (("Hidden" === data.Type) && ("ReceiveSuitcaseMoney" === data.Content)) this.LAST_HACKED = data.Sender } + }) + + // footer this.LOADED = true this.log("info", `loaded version ${this.VERSION}`) - if (window.GameVersion !== this.TARGET_VERSION) console.warn(`Game version doesn't match the target ("${this.TARGET_VERSION}"), beware of incompatibilities`) // TODO: check betas & cheat + if (window.GameVersion !== this.TARGET_VERSION) this.log("warn", `Game version doesn't match the target ("${this.TARGET_VERSION}"), beware of incompatibilities`) // TODO: betas are like R86Beta1; cheat? + if (("Online" === window.CurrentModule) && ("ChatRoom" === window.CurrentScreen)) { + window.ChatRoomCharacter.forEach(c => this.update_char(c)) + this.player_enters_room() + } + }, + preloader() { + this.SDK = window.bcModSdk.registerMod("MBCHC", this.VERSION) + this.before = (name, cb) => this.SDK.hookFunction(name, 0, (nextargs,next) => {try {cb?.(...nextargs)} catch (x) {console.error(x)} finally {return next(nextargs)}}) + this.after = (name, cb) => this.SDK.hookFunction(name, 0, (nextargs,next) => {const result = next(nextargs); try {cb?.(...nextargs)} catch (x) {console.error(x)} finally {return result}}) + if (window.CurrentModule && window.CurrentScreen && !("Character" === window.CurrentModule && "Login" === window.CurrentScreen)) return this.loader() + this.remove_load_hook = this.before("AsylumGGTSSAddItems", () => this.loader()) } } // MBCHC - // Hooks - window.MBCHC.sdk = window.bcModSdk.registerMod("MBCHC", window.MBCHC.VERSION) - window.MBCHC.sdk.hookFunction("CharacterOnlineRefresh", 0, (nextargs, next) => { - let result = next(nextargs) - window.MBCHC.update_char(nextargs[0]) - return(result) - }) - window.MBCHC.sdk.hookFunction("ChatRoomReceiveSuitcaseMoney", 0, (nextargs, next) => { - let result = next(nextargs) - if (window.MBCHC.AUTOHACK_ENABLED && window.MBCHC.LAST_HACKED) { - window.CurrentCharacter = window.MBCHC.cid2char(window.MBCHC.LAST_HACKED) - window.MBCHC.LAST_HACKED = null - window.ChatRoomTryToTakeSuitcase() - } - return(result) - }) - window.MBCHC.sdk.hookFunction("ChatRoomSendChat", 0, (nextargs, next) => { - let input = window.ElementValue("InputChat") - if (!input.startsWith("@@@") && input.startsWith("@")) { - input = input.replace(window.MBCHC.RE_PREF_ACTIVITY, window.MBCHC.PREF_ACTIVITY) - input = input.replace(window.MBCHC.RE_PREF_ACTIVITY_ME, window.MBCHC.replace_me) - window.ElementValue("InputChat", input) - } - let result = next(nextargs) - let history = window.ChatRoomLastMessage - if ((history.length > 1) && (history[history.length - 1] === history[history.length - 2])) {history.pop(); window.ChatRoomLastMessageIndex -= 1} - return(result) - }) - window.MBCHC.sdk.hookFunction("ChatRoomDrawCharacterOverlay", 0, (nextargs, next) => { - let [C, CharX, CharY, Zoom, Pos] = nextargs - if ((window.ChatRoomHideIconState < 1) && C.MBCHC) { - let colour = (C.MBCHC.VERSION === window.Player.MBCHC.VERSION) ? window.MBCHC.RGB_POLLY : window.MBCHC.RGB_MUTE - window.DrawRect(CharX + 175 * Zoom, CharY, 50 * Zoom, 50 * Zoom, colour) - } - if ((window.ChatRoomHideIconState < 1) && C.MBCHC_LOCAL && "number" === typeof C.MBCHC_LOCAL.TZ) { - let hours = new Date(window.CommonTime() + window.MBCHC.UTC_OFFSET + C.MBCHC_LOCAL.TZ * 60 * 60 * 1000).getHours() - let text = (hours < 10) ? "0" + hours.toString() : hours.toString() - window.DrawTextFit(text, CharX + 200 * Zoom, CharY + 25 * Zoom, 46 * Zoom, "white", "black") - } - return(next(nextargs)) - }) - window.MBCHC.sdk.hookFunction("ElementValue", 0, (nextargs, next) => { // TODO: layer priority will be locked too if it's the same as difficulty - let [ID, Value] = nextargs - let result = next(nextargs) - if (("bce_LayerPriority" === ID) && window.CurrentCharacter?.FocusGroup && (window.InventoryGet(window.CurrentCharacter, window.CurrentCharacter.FocusGroup.Name)?.Difficulty.toString() === Value) && window.InventoryLocked(window.CurrentCharacter, window.CurrentCharacter.FocusGroup.Name, true)) window.ElementSetAttribute(ID, "disabled", true) - return(result) - }) - window.MBCHC.sdk.hookFunction("ChatRoomCreateElement", 0, (nextargs, next) => { - let result = next(nextargs) - if (!window.MBCHC.COMP_HINT.parentElement) document.body.appendChild(window.MBCHC.COMP_HINT) - return(result) - }) - window.MBCHC.sdk.hookFunction("ChatRoomClearAllElements", 0, (nextargs, next) => { - window.MBCHC.complete_hint_hide() - window.MBCHC.COMP_HINT.remove() - return(next(nextargs)) - }) - window.MBCHC.sdk.hookFunction("ChatRoomResize", 0, (nextargs, next) => { - let result = next(nextargs) - if (window.CharacterGetCurrent() == null && window.CurrentScreen == "ChatRoom" && document.getElementById("InputChat") && document.getElementById("TextAreaChatLog") && window.MBCHC.comp_hint_visible()) { // upstream - let fontsize = ChatRoomFontSize /* eslint-disable-line no-undef */ // window.ChatRoomFontSize is undefined - window.ElementPositionFix("TextAreaChatLog", fontsize, 1005, 66, 988, 630) - window.ElementPositionFix(window.MBCHC.COMP_HINT.id, fontsize, 1005, 701, 988, 200) - window.MBCHC.COMP_HINT.style.display = "flex" - } - return(result) - }) - window.MBCHC.sdk.hookFunction("DocumentKeyDown", 0, (nextargs, next) => { - let [event] = nextargs - if ("InputChat" === document.activeElement.id || "bce-message-input" === document.activeElement.id) return(next(nextargs)) - if ("inline" === document.getElementById("InputChat")?.style.display && [event.altKey, event.ctrlKey, event.metaKey].every(i => !i)) window.ElementFocus("InputChat") // alt, ctrl and meta should all be false - // TODO: this is not ideal, but it will have to do for now - return(next(nextargs)) - }) - window.MBCHC.sdk.hookFunction("ChatRoomKeyDown", 0, (nextargs, next) => { - let [event] = nextargs - window.MBCHC.complete_hint_hide() - if ((window.KeyPress == 33) || (window.KeyPress == 34)) { // better history - event.preventDefault() - return(window.MBCHC.history(window.KeyPress - 33)) - } - if (window.MBCHC.HISTORY_MODE) { - window.ChatRoomLastMessage.pop() - window.MBCHC.HISTORY_MODE = false - } - return(next(nextargs)) - }) - window.MBCHC.sdk.hookFunction("ChatRoomClick", 0, (nextargs, next) => { - window.MBCHC.complete_hint_hide() - return(next(nextargs)) - }) - window.MBCHC.remove_fbc_hook = window.MBCHC.sdk.hookFunction("MainRun", 0, (nextargs, next) => { - if (window.bce_ActivityTriggers) window.MBCHC.patch_fbc() - return(next(nextargs)) - }) - - // Chat room handlers - window.ChatRoomRegisterMessageHandler({ Priority: -220, Description: "MBCHC preprocessor", - Callback: (data, sender, msg, metadata) => { - data.MBCHC_ID = window.MBCHC.NEXT_MESSAGE - window.MBCHC.NEXT_MESSAGE += 1 - if (window.MBCHC.LOG_MESSAGES) console.debug({data, sender, msg, metadata}) - } - }) - window.ChatRoomRegisterMessageHandler({ Priority: -219, Description: "MBCHC room enter hook", - Callback: (data, sender, msg, metadata) => { if (("Action" === data.Type) && ("ServerEnter" === data.Content) && (data.Sender === window.Player.cid)) window.MBCHC.player_enters_room() } - }) - window.ChatRoomRegisterMessageHandler({ Priority: -219, Description: "MBCHC specific consumer", - Callback: (data, sender, msg, metadata) => { if (("Hidden" === data.Type) && ("MBCHC" === data.Content)) return window.MBCHC.receive(data) } - }) - window.ChatRoomRegisterMessageHandler({ Priority: -219, Description: "MBCHC autohack lookup", - Callback: (data, sender, msg, metadata) => { if (("Hidden" === data.Type) && ("ReceiveSuitcaseMoney" === data.Content)) window.MBCHC.LAST_HACKED = data.Sender } - }) - - // MAIN SCREEN TURN ON - if (window.MBCHC.need_load_hook(window.CurrentModule, window.CurrentScreen)) { - window.MBCHC.remove_load_hook = window.MBCHC.sdk.hookFunction("AsylumGGTSSAddItems", 0, (nextargs, next) => {window.MBCHC.loader(); return(next(nextargs))}) - } else { - window.MBCHC.loader() - if (("Online" === window.CurrentModule) && ("ChatRoom" === window.CurrentScreen)) { - window.ChatRoomCharacter.forEach(c => window.MBCHC.update_char(c)) - window.MBCHC.player_enters_room() - } - } + window.MBCHC.preloader() })()