mod should unload itself to avoid being visible; other changes are syntactic
This commit is contained in:
parent
1130b04947
commit
6cff644dc9
8
ambient.d.ts
vendored
8
ambient.d.ts
vendored
|
@ -1,15 +1,9 @@
|
||||||
/* eslint-disable no-unused-vars */
|
|
||||||
/* eslint-disable @typescript-eslint/consistent-type-definitions */
|
|
||||||
/* eslint-disable @typescript-eslint/member-delimiter-style */
|
|
||||||
/* eslint-disable @typescript-eslint/naming-convention */
|
|
||||||
/* eslint-disable @typescript-eslint/semi */
|
|
||||||
|
|
||||||
declare namespace LILY {
|
declare namespace LILY {
|
||||||
interface Utils {
|
interface Utils {
|
||||||
remove_hook: undefined | (() => void)
|
remove_hook: undefined | (() => void)
|
||||||
true(callback: () => unknown): true // stops elsint from complainting about constant bool expressions
|
true(callback: () => unknown): true // stops elsint from complainting about constant bool expressions
|
||||||
with<V, R>(value: V, callback: (v: V) => R): R // A silly helper to kinda curry values
|
with<V, R>(value: V, callback: (v: V) => R): R // A silly helper to kinda curry values
|
||||||
send(callback: () => unknown): boolean // updates the player if the function succeeds
|
send(callback: () => boolean): boolean // updates the player if the function succeeds
|
||||||
}
|
}
|
||||||
|
|
||||||
interface Box {
|
interface Box {
|
||||||
|
|
|
@ -13,6 +13,13 @@
|
||||||
],
|
],
|
||||||
"checkJs": true,
|
"checkJs": true,
|
||||||
"strict": true,
|
"strict": true,
|
||||||
"noImplicitOverride": true
|
"exactOptionalPropertyTypes": true,
|
||||||
|
"noFallthroughCasesInSwitch": true,
|
||||||
|
"noImplicitOverride": true,
|
||||||
|
"noImplicitReturns": true,
|
||||||
|
"noPropertyAccessFromIndexSignature": true,
|
||||||
|
"noUncheckedIndexedAccess": true,
|
||||||
|
"noUnusedLocals": true,
|
||||||
|
"noUnusedParameters": true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
64
lily.user.js
64
lily.user.js
|
@ -12,37 +12,26 @@
|
||||||
// @match https://www.bondage-europe.com/*
|
// @match https://www.bondage-europe.com/*
|
||||||
// @match http://localhost:*/*
|
// @match http://localhost:*/*
|
||||||
// ==/UserScript==
|
// ==/UserScript==
|
||||||
// checklist:
|
|
||||||
// [?] account filter, should only work on Lily 119643
|
|
||||||
// [?] voicebox
|
|
||||||
|
|
||||||
(function() {
|
(function() {
|
||||||
'use strict';
|
'use strict';
|
||||||
const W = /** @type {Window & typeof globalThis & {bcModSdk: import('bondage-club-mod-sdk').ModSDKGlobalAPI}} */ (window)
|
const W = /** @type {Window & typeof globalThis & {bcModSdk: import('bondage-club-mod-sdk').ModSDKGlobalAPI}} */ (window)
|
||||||
const SDK = W.bcModSdk.registerMod({name: GM_info.script.name, fullName: GM_info.script.description || '', version: GM_info.script.version, repository: 'finger://your.mom'})
|
const SDK = W.bcModSdk.registerMod({name: GM_info.script.name, fullName: GM_info.script.description ?? '', version: GM_info.script.version, repository: 'finger://your.mom'})
|
||||||
/** @type {LILY.Utils} */ const U = {remove_hook: undefined,
|
/** @type {LILY.Utils} */ const U = {remove_hook: undefined,
|
||||||
true(f) {f(); return true},
|
true(f) {f(); return true},
|
||||||
with: (v, f) => f(v),
|
with: (v, f) => f(v),
|
||||||
send: f => Boolean(f()) && !void W.ChatRoomCharacterUpdate(W.Player),
|
send: f => f() && U.true(() => void W.ChatRoomCharacterUpdate(W.Player)),
|
||||||
}
|
}
|
||||||
/** @type {LILY.Box} */ const Box = {
|
/** @type {LILY.Box} */ const Box = {
|
||||||
enable(item) { if (!item) return false
|
enable(item) { if (item === undefined) return false // TODO Okay, we need to be more clever here. The light should be above the box itself
|
||||||
const op = item.Property?.OverridePriority
|
return U.with(item.Property, ip => typeof ip?.OverridePriority === 'object' && (ip.OverridePriority['Light'] = 41) > 0)
|
||||||
if (op && typeof op === 'object') op.Light = 41 // todo Okay, we need to be more clever here. This should be above the box itself.
|
|
||||||
return true
|
|
||||||
},
|
|
||||||
disable(item) { if (!item) return false
|
|
||||||
item.Property ||= {}
|
|
||||||
const ip = item.Property
|
|
||||||
if (typeof ip.OverridePriority === 'number') ip.OverridePriority = {Lock: ip.OverridePriority, Unit: ip.OverridePriority}
|
|
||||||
ip.OverridePriority ||= {}
|
|
||||||
ip.OverridePriority.Light = 0
|
|
||||||
return true
|
|
||||||
},
|
},
|
||||||
|
disable(item) { return item === undefined ? false : U.with(item.Property ??= {}, ip => U.with(ip.OverridePriority ??= {}, op =>
|
||||||
|
typeof op === 'number' ? Boolean(ip.OverridePriority = {Lock: op, Unit: op}) : ((op['Light'] = 0) < 1)
|
||||||
|
))},
|
||||||
on: () => U.with(Box.item, i => U.send(() => Box.enable(i))),
|
on: () => U.with(Box.item, i => U.send(() => Box.enable(i))),
|
||||||
off: () => U.with(Box.item, i => U.send(() => Box.disable(i))),
|
off: () => U.with(Box.item, i => U.send(() => Box.disable(i))),
|
||||||
get item() {return U.with(W.InventoryGet(W.Player, 'ItemNeckAccessories'), item => item?.Craft?.Name === 'Lily\'s voicebox' ? item : undefined)},
|
get item() {return U.with(W.InventoryGet(W.Player, 'ItemNeckAccessories'), item => item?.Craft?.Name === 'Lily\'s voicebox' ? item : undefined)},
|
||||||
get enabled() {return U.with(Box.item, i => Boolean(i) && U.with(i?.Property?.OverridePriority, op => typeof op !== 'object' || !Object.hasOwn(op, 'Light') || op.Light > 0))}, // todo check if the light is above the box, the neck and the collar
|
get enabled() {return U.with(Box.item, i => i !== undefined && U.with(i?.Property?.OverridePriority, op => typeof op !== 'object' || !Object.hasOwn(op, 'Light') || (op['Light'] ?? 1) > 0))}, // TODO check if the light is above the box
|
||||||
}
|
}
|
||||||
/** @type {LILY.Eyes} */ const Eyes = {timeout: undefined, zones: ['ItemHead', 'Mask'],
|
/** @type {LILY.Eyes} */ const Eyes = {timeout: undefined, zones: ['ItemHead', 'Mask'],
|
||||||
rgb: [
|
rgb: [
|
||||||
|
@ -54,15 +43,15 @@
|
||||||
'#990099', '#99008a', '#99007a', '#99006b', '#99005c', '#99004d', '#99003d', '#99002e', '#99001f', '#99000f',
|
'#990099', '#99008a', '#99007a', '#99006b', '#99005c', '#99004d', '#99003d', '#99002e', '#99001f', '#99000f',
|
||||||
],
|
],
|
||||||
craft: {Item: 'AnimeLenses', Name: 'Akihabara souvenir', Description: 'you will never be the same uwu', Color: '#FFFFFF,Default,#FFFFFF,Default', Property: 'Thick', Lock: '', Private: true, ItemProperty: {}, Type: null, TypeRecord: null, MemberNumber: 71_240, MemberName: 'Mute'},
|
craft: {Item: 'AnimeLenses', Name: 'Akihabara souvenir', Description: 'you will never be the same uwu', Color: '#FFFFFF,Default,#FFFFFF,Default', Property: 'Thick', Lock: '', Private: true, ItemProperty: {}, Type: null, TypeRecord: null, MemberNumber: 71_240, MemberName: 'Mute'},
|
||||||
set_rgb: (item, n) => U.true(() => item.Color = [Eyes.rgb[n], 'Default', Eyes.rgb[n], 'Default']),
|
set_rgb: (item, n) => U.true(() => item.Color = [Eyes.rgb[n] ?? 'Default', 'Default', Eyes.rgb[n] ?? 'Default', 'Default']),
|
||||||
next_rgb: () => !Eyes.check('ItemHead') && U.with(Eyes.check('Mask'), i => i && U.with(Eyes.rgb.indexOf(i.Color?.[0] || Eyes.rgb[0]) + 1, n => Eyes.set_rgb(i, n))),
|
next_rgb: () => Eyes.check('ItemHead') !== undefined && U.with(Eyes.check('Mask'), i => i !== undefined && U.with(Eyes.rgb.indexOf(i.Color?.[0] ?? Eyes.rgb[0] ?? '') + 1, n => Eyes.set_rgb(i, n))),
|
||||||
roll_rgb: () => Eyes.next_rgb() && W.ChatRoomCharacterItemUpdate(W.Player, 'Mask'),
|
roll_rgb: () => Eyes.next_rgb() ?? void W.ChatRoomCharacterItemUpdate(W.Player, 'Mask'),
|
||||||
start: () => Boolean(Eyes.check('Mask')) && !Eyes.timeout && Boolean(Eyes.timeout = setInterval(Eyes.roll_rgb, 1000)),
|
start: () => Eyes.check('Mask') !== undefined && Eyes.timeout === undefined && Boolean(Eyes.timeout = setInterval(Eyes.roll_rgb, 1000)),
|
||||||
stop: () => Boolean(Eyes.check('Mask')) && Boolean(Eyes.timeout) && !(Eyes.timeout = void clearInterval(Eyes.timeout)),
|
stop: () => Eyes.check('Mask') !== undefined && Eyes.timeout !== undefined && U.true(() => Eyes.timeout = void clearInterval(Eyes.timeout)),
|
||||||
dim: () => U.send(() => !Eyes.check('ItemHead') && !void W.InventoryWear(W.Player, 'AnimeLenses', 'ItemHead', ['#FFFFFF', 'Default', '#FFFFFF', 'Default'], undefined, 71_240, Eyes.craft)),
|
dim: () => U.send(() => Eyes.check('ItemHead') === undefined && U.true(() => W.InventoryWear(W.Player, 'AnimeLenses', 'ItemHead', ['#FFFFFF', 'Default', '#FFFFFF', 'Default'], undefined, 71_240, Eyes.craft))),
|
||||||
clear: () => U.send(() => Boolean(Eyes.check('ItemHead')) && !void W.InventoryRemove(W.Player, 'ItemHead')),
|
clear: () => U.send(() => Eyes.check('ItemHead') !== undefined && U.true(() => void W.InventoryRemove(W.Player, 'ItemHead'))),
|
||||||
check: zone => U.with(Eyes.item, item => (item && item.Asset.Group.Name === zone) ? item : undefined),
|
check: zone => U.with(Eyes.item, item => item?.Asset.Group.Name === zone ? item : undefined),
|
||||||
get item() {return Eyes.zones.map(z => W.InventoryGet(W.Player, z)).find(item => item && item.Asset.Name === 'AnimeLenses') || undefined},
|
get item() {return Eyes.zones.map(z => W.InventoryGet(W.Player, z)).find(item => item?.Asset.Name === 'AnimeLenses') ?? undefined},
|
||||||
}
|
}
|
||||||
/** @type {LILY.Belt} */ const Belt = {users: [119_643, 154_662], admins: [71_240, 67_994],
|
/** @type {LILY.Belt} */ const Belt = {users: [119_643, 154_662], admins: [71_240, 67_994],
|
||||||
cli: {'#LILY': {
|
cli: {'#LILY': {
|
||||||
|
@ -72,23 +61,24 @@
|
||||||
}},
|
}},
|
||||||
/** @type {LILY.Belt['is_cb']} */ is_cb: s => typeof s === 'function',
|
/** @type {LILY.Belt['is_cb']} */ is_cb: s => typeof s === 'function',
|
||||||
run(tokens) { /** @type {string | undefined} */ let t, /** @type {LILY.Commands | LILY.CommandCB} */ cmd = Belt.cli
|
run(tokens) { /** @type {string | undefined} */ let t, /** @type {LILY.Commands | LILY.CommandCB} */ cmd = Belt.cli
|
||||||
while (t = tokens.shift()) if (U.with(cmd[t], next => !next || Belt.is_cb(cmd = next))) break // eslint-disable-line no-cond-assign
|
while ((t = tokens.shift()) !== undefined) if (U.with(cmd[t], next => next !== undefined && Belt.is_cb(cmd = next))) break // eslint-disable-line @typescript-eslint/no-loop-func
|
||||||
if (!Belt.is_cb(cmd)) return t ? `unknown token ${t}` : `subcommands: [${Object.keys(cmd).join(', ')}]`
|
if (!Belt.is_cb(cmd)) return t === undefined ? `subcommands: [${Object.keys(cmd).join(', ')}]` : `unknown token ${t}`
|
||||||
return U.with(cmd(...tokens), r => typeof r === 'boolean' ? (r ? 'success' : 'fail') : String(r))
|
return U.with(cmd(...tokens), r => typeof r === 'boolean' ? (r ? 'success' : 'fail') : String(r))
|
||||||
},
|
},
|
||||||
receive(data) { if (!data.Sender) return undefined
|
receive(data) { if (data.Sender === undefined) return undefined
|
||||||
W.ChatRoomSendLocal(`<span style="color: #666">${data.Content}</span>`)
|
W.ChatRoomSendLocal(`<span style="color: #666">${data.Content}</span>`)
|
||||||
return void W.ChatRoomSendWhisper(data.Sender, `LILY: ${Belt.admins.includes(data.Sender) ? Belt.run(data.Content.split(' ')) : 'access denied'}`)
|
return void W.ChatRoomSendWhisper(data.Sender, `LILY: ${Belt.admins.includes(data.Sender) ? Belt.run(data.Content.split(' ')) : 'access denied'}`)
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
/** @type {(text: string) => undefined} */ const unload = text => U.true(SDK.unload) && void console.debug(`LILY: ${text}, unloading the mod`)
|
||||||
const load_after_login = () => {
|
const load_after_login = () => {
|
||||||
if (U.remove_hook) {U.remove_hook?.(); U.remove_hook = undefined}
|
if (U.remove_hook !== undefined) {U.remove_hook?.(); U.remove_hook = undefined}
|
||||||
if (!W.Player.MemberNumber) return console.debug('LILY: member not identified')
|
if (W.Player.MemberNumber === undefined) return void unload('member not identified')
|
||||||
if (!Belt.users.includes(W.Player.MemberNumber)) return console.debug('LILY: member not eligible for loading')
|
if (!Belt.users.includes(W.Player.MemberNumber)) return void unload('member not eligible for loading')
|
||||||
SDK.hookFunction('SpeechTransformGagGarble', 0, ([text]) => text) // disable garbling
|
SDK.hookFunction('SpeechTransformGagGarble', 0, ([text]) => text) // disable garbling
|
||||||
SDK.hookFunction('ChatRoomSendChatMessage', 0, (na, n) => Box.enabled || na[0].startsWith('(') ? n(na) : Boolean(W.ChatRoomSendLocal('<span style="color: red">You try to talk, but nothing comes out.</span>')))
|
SDK.hookFunction('ChatRoomSendChatMessage', 0, (na, n) => Box.enabled || na[0].startsWith('(') ? n(na) : !U.true(() => void W.ChatRoomSendLocal('<span style="color: red">You try to talk, but nothing comes out.</span>')))
|
||||||
W.ChatRoomRegisterMessageHandler({Priority: -169, Description: 'LILY', Callback: data => data.Type === 'Whisper' && data.Content.startsWith('#LILY') && (Belt.receive(data) || true)})
|
W.ChatRoomRegisterMessageHandler({Priority: -169, Description: 'LILY', Callback: data => data.Type === 'Whisper' && data.Content.startsWith('#LILY') && U.true(() => void Belt.receive(data))})
|
||||||
console.debug(`LILY: eligible member detected, loaded version ${GM_info.script.version}`)
|
console.debug(`LILY: eligible member detected, loaded version ${GM_info.script.version}`)
|
||||||
}
|
}
|
||||||
U.remove_hook = SDK.hookFunction('AsylumGGTSSAddItems', 0, (na, n) => U.true(load_after_login) && n(na))
|
U.remove_hook = SDK.hookFunction('AsylumGGTSSAddItems', 0, (na, n) => U.true(load_after_login) && void n(na))
|
||||||
})()
|
})()
|
||||||
|
|
39
package.json
39
package.json
|
@ -10,13 +10,34 @@
|
||||||
"@types/tampermonkey": "^5.0.3"
|
"@types/tampermonkey": "^5.0.3"
|
||||||
},
|
},
|
||||||
"license": "SEE LICENSE IN LICENSE.",
|
"license": "SEE LICENSE IN LICENSE.",
|
||||||
"xo": {
|
"eslintConfig": {
|
||||||
"env": [
|
"root": true,
|
||||||
"browser",
|
"extends": [
|
||||||
"node"
|
"xo",
|
||||||
|
"xo-typescript"
|
||||||
],
|
],
|
||||||
"globals": ["GM", "GM_info"],
|
"parser": "@typescript-eslint/parser",
|
||||||
|
"parserOptions": { "project": ["./jsconfig.json"] },
|
||||||
|
"plugins": ["@typescript-eslint"],
|
||||||
|
"globals": {"GM": true, "GM_info": true},
|
||||||
"rules": {
|
"rules": {
|
||||||
|
"@typescript-eslint/brace-style": "off",
|
||||||
|
"@typescript-eslint/comma-dangle": ["error", "only-multiline"],
|
||||||
|
"@typescript-eslint/consistent-type-definitions": "off",
|
||||||
|
"@typescript-eslint/member-delimiter-style": "off",
|
||||||
|
"@typescript-eslint/naming-convention": "off",
|
||||||
|
"@typescript-eslint/no-confusing-void-expression": ["error", {
|
||||||
|
"ignoreVoidOperator": true
|
||||||
|
}],
|
||||||
|
"@typescript-eslint/no-meaningless-void-operator": "off",
|
||||||
|
"@typescript-eslint/padding-line-between-statements": "off",
|
||||||
|
"@typescript-eslint/semi": "off",
|
||||||
|
"@typescript-eslint/space-before-function-paren": "off",
|
||||||
|
"@typescript-eslint/strict-boolean-expressions": ["error", {
|
||||||
|
"allowString": false,
|
||||||
|
"allowNumber": false,
|
||||||
|
"allowNullableObject": false
|
||||||
|
}],
|
||||||
"array-element-newline": "off",
|
"array-element-newline": "off",
|
||||||
"brace-style": "off",
|
"brace-style": "off",
|
||||||
"camelcase": "off",
|
"camelcase": "off",
|
||||||
|
@ -44,6 +65,14 @@
|
||||||
"unicorn/prefer-module": "off",
|
"unicorn/prefer-module": "off",
|
||||||
"unicorn/prefer-top-level-await": "off",
|
"unicorn/prefer-top-level-await": "off",
|
||||||
"fake/fuck-commas": "off"
|
"fake/fuck-commas": "off"
|
||||||
|
},
|
||||||
|
"overrides": [
|
||||||
|
{
|
||||||
|
"files": ["*.d.ts"],
|
||||||
|
"rules": {
|
||||||
|
"no-unused-vars": "off"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue
Block a user