From c76ad63d963a5bcc72e4d6ac3fc28fe4ca32b133 Mon Sep 17 00:00:00 2001 From: Mute Date: Wed, 20 Jul 2022 23:30:36 +0000 Subject: [PATCH] Update 'mbchc-dev.user.js' disallow /do in rooms with blocked activities; autocomplete improvements --- mbchc-dev.user.js | 45 +++++++++++++++++++++++++++------------------ 1 file changed, 27 insertions(+), 18 deletions(-) diff --git a/mbchc-dev.user.js b/mbchc-dev.user.js index 1a50903..5e56112 100644 --- a/mbchc-dev.user.js +++ b/mbchc-dev.user.js @@ -41,7 +41,6 @@ RE_TZ: /(?:GMT|UTC)([+-]\d\d?)/i, RE_ALL_LEFT: /^<+$/, RE_ALL_RIGHT: /^>+$/, - RE_CARET: /^\^/, RE_SPACES: /\s{2,}/g, RE_LAST_WORD: /(^|\s)([^\s]*)$/, RE_LAST_LETTER: /[\w]$/, @@ -218,6 +217,7 @@ if (options.dot && result.match(this.RE_LAST_LETTER)) result = `${result}.` return(result) }, + tokenise: function(text) { return text.replace(this.RE_SPACES, " ").split(" ") }, inform: function(html, timeout = 60000) { window.ChatRoomSendLocal(`
${html}
`, timeout) }, report: function(x) { this.inform(`Error: ${x.toString()}`) @@ -267,6 +267,13 @@ if (found.length > 1) throw `target "${input}": multiple matches (${found.map(c => `${c.cid}|${c.Name}|${c.Nickname || c.Name}`).join(",")})` return(found[0]) }, + char2targets: function(char) { + let [result, cid] = [new Set(), char.cid.toString()] + result.add(cid).add(`=${cid}`) + this.tokenise(char.Name).forEach(t => {result.add(t); result.add(`@${t}`)}) + if (char.Nickname) this.tokenise(char.Nickname).forEach(t => {result.add(t); result.add(`@${t}`)}) + return result + }, donate_data: function(target) { let char = this.target2char(target) if (char.IsPlayer()) throw "target must not be you" @@ -278,6 +285,7 @@ window.ChatRoomMessage({Sender: window.Player.cid, Type: "Action", Content: `You've bought data for $${cost} and sent it to ${char.dn}.`, Dictionary: [{Tag: "MISSING PLAYER DIALOG: ", Text: ""}]}) }, run_activity: function(char, ag, action) { try { + if (!window.ActivityAllowed()) throw "activities disabled in this room" if (!window.ServerChatRoomGetAllowItem(window.Player, char)) throw "no permissions" char.FocusGroup = this.ensure("invalid AssetGroup", () => window.AssetGroupGet(char.AssetFamily, ag)) let activity = this.ensure("invalid activity", () => window.ActivityAllowedForGroup(char, char.FocusGroup.Name, true).find(a => a.Name === action)) @@ -359,7 +367,7 @@ /* (["anim", "pose"]).forEach(tag => {let cmd = window.Commands.find(c => tag === c.Tag); if (cmd) cmd.AutoComplete = this[`complete_bce_${tag}`]}) */ // this line explodes, don't ask me why let cmd = window.Commands.find(c => "anim" === c.Tag) if (cmd) cmd.AutoComplete = this.complete_bce_anim - cmd = window.Commands.find(c => "pose" === c.Tag) + cmd = window.Commands.find(c => "pose" === c.Tag) if (cmd) cmd.AutoComplete = this.complete_bce_pose }, gather_versions: function() { return(window.ChatRoomCharacter.filter(c => c.MBCHC).map(c => ({name: c.dn, cid: c.cid, version: c.MBCHC.VERSION}))) }, @@ -448,23 +456,23 @@ comp_hint_visible: function() {return(this.COMP_HINT.parentElement && "flex" === this.COMP_HINT.style.display)}, complete_hint_hide: function(options) {if (!this.comp_hint_visible()) return; this.COMP_HINT.style.display = "none"; window.ChatRoomResize(false)}, complete_target: function(token, me2 = true, check_perms = false) { - let locase = token.toLocaleLowerCase() - let found = {} + let [locase, found] = [token.toLocaleLowerCase(), new Set()] for (let c of window.ChatRoomCharacter) { - let [n, nn, cid] = [c.Name.toLocaleLowerCase(), (c.Nickname || c.Name).toLocaleLowerCase(), c.cid.toString()] - if (!c.IsPlayer() || me2) [n, nn, cid, `@${n}`, `@${nn}`, `=${cid}`].forEach(s => {if (s.startsWith(locase) && (!check_perms || window.ServerChatRoomGetAllowItem(window.Player, c))) found[s] = true}) + if ((c.IsPlayer() && !me2) || (check_perms && !window.ServerChatRoomGetAllowItem(window.Player, c))) continue + this.char2targets(c).forEach(s => {if (s.toLocaleLowerCase().startsWith(locase)) found.add(s)}) } - this.complete(Object.keys(found)) + this.complete(Array.from(found)) }, complete_common: function() { let input = document.getElementById("InputChat").value - return([this, input, input.replace(this.RE_SPACES, " ").split(" ")]) + return([this, input, this.tokenise(input)]) }, complete_mbchc: function(args, locase, cmdline) { const [mbchc, input, tokens] = window.MBCHC.complete_common(); // `this` is command object if (tokens.length < 1) return if (tokens.length < 2) return(mbchc.complete([`${mbchc.CommandsKey}${this.Tag}`])) - if (tokens.length < 3) return(mbchc.complete(Object.keys(mbchc.SUBCOMMANDS_MBCHC).filter(c => c.startsWith(tokens[1])))) // complete subcommand name - let sub = mbchc.SUBCOMMANDS_MBCHC[tokens[1]] + let subname = tokens[1].toLocaleLowerCase() + if (tokens.length < 3) return(mbchc.complete(Object.keys(mbchc.SUBCOMMANDS_MBCHC).filter(c => c.startsWith(subname)))) // complete subcommand name + let sub = mbchc.SUBCOMMANDS_MBCHC[subname] if (sub && sub.args) { let argname = Object.keys(sub.args)[tokens.length - 3] if ("TARGET" === argname) return(mbchc.complete_target(tokens[tokens.length - 1], false)) @@ -481,25 +489,26 @@ if (tokens.length < 1) return if (tokens.length < 2) return(mbchc.complete([`${mbchc.CommandsKey}${this.Tag}`])) // now, we *could* run a filter to exclude impossible activities, but it isn't very useful, and also seems like a lot of CPU to iterate over every action on every zone of every char in the room - if (tokens.length < 3) return(mbchc.complete(Object.keys(mbchc.DO_DATA.verbs).filter(c => c.startsWith(tokens[1])))) // complete verb - let verb = tokens[1].toLocaleLowerCase() - let ags = mbchc.DO_DATA.verbs[verb] - if (!ags) return + let low = tokens[1].toLocaleLowerCase() + if (tokens.length < 3) return(mbchc.complete(Object.keys(mbchc.DO_DATA.verbs).filter(c => c.startsWith(low)))) // complete verb + let ags = mbchc.DO_DATA.verbs[low] + if (!ags) return(mbchc.bell()) + low = tokens[2].toLocaleLowerCase() if (tokens.length < 4) { // complete zone or target if (Object.keys(ags).length < 2) return(mbchc.complete_do_target(ags[Object.keys(ags)[0]], tokens[2])) // zone implied, complete target - let zones = Object.entries(mbchc.DO_DATA.zones).filter(([zone, ag]) => zone.startsWith(tokens[2]) && ags[ag]).map(([zone,ag]) => zone) + let zones = Object.entries(mbchc.DO_DATA.zones).filter(([zone, ag]) => zone.startsWith(low) && ags[ag]).map(([zone,ag]) => zone) return(mbchc.complete(zones)) } if (tokens.length < 5) { // complete target where it belongs if (Object.keys(ags).length < 2) return // zone implied, target already given - let zone = tokens[2].toLocaleLowerCase() - return(mbchc.complete_do_target(ags[mbchc.DO_DATA.zones[zone]], tokens[3])) + return(mbchc.complete_do_target(ags[mbchc.DO_DATA.zones[low]], tokens[3])) } + mbchc.bell() }, complete_bce_anim: function(args, locase, cmdline) { const [mbchc, input, tokens] = window.MBCHC.complete_common(); // `this` is command object if (tokens.length < 1) return if (tokens.length < 2) return(mbchc.complete([`${mbchc.CommandsKey}${this.Tag}`])) - if (tokens.length > 2) return + if (tokens.length > 2) return(mbchc.bell()) let anim = tokens[1].toLocaleLowerCase() return(mbchc.complete(Object.keys(window.bce_EventExpressions).filter(a => a.toLocaleLowerCase().startsWith(anim)))) },