Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 1 addition & 2 deletions loader.ebc.user.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,11 @@
// @description:en PEX local-dev loader for EBC (loads the build from localhost:8000)
// @author PEX
// @supportURL https://github.com/Nice8923/BC-PEX
// @include /^https:\/\/(www\.)?bondage(projects\.elementfx|-(europe|asia))\.com\/.*/
// @include /^https?:\/\/(www\.)?(bondageprojects\.com|bondageprojects\.elementfx\.com|bondage-europe\.com|bondage-asia\.com)\/.*/
// @grant none
// @run-at document-end
// ==/UserScript==

window.PEX = window.PEX ?? {};
if (window.PEX) {
console.warn('⚗️[PEX] 已加载,跳过重复导入。');
} else {
Expand Down
5 changes: 2 additions & 3 deletions loader.embedded.user.js

Large diffs are not rendered by default.

3 changes: 1 addition & 2 deletions loader.local.user.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,11 @@
// @description:en PEX local-dev loader (loads the build from vite preview)
// @author PEX
// @supportURL https://github.com/Nice8923/BC-PEX
// @include /^https:\/\/(www\.)?bondage(projects\.elementfx|-(europe|asia))\.com\/.*/
// @include /^https?:\/\/(www\.)?(bondageprojects\.com|bondageprojects\.elementfx\.com|bondage-europe\.com|bondage-asia\.com)\/.*/
// @grant none
// @run-at document-end
// ==/UserScript==

window.PEX = window.PEX ?? {};
if (window.PEX) {
console.warn('⚗️[PEX] 已加载,跳过重复导入。');
} else {
Expand Down
3 changes: 1 addition & 2 deletions loader.template.user.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,11 @@
// @description:en Persona excretion gameplay: dizzy → excrete → blank → gel → feed-back recovery. Built-in sounds & expressions, /pex commands.
// @author PEX
// @supportURL https://github.com/Nice8923/BC-PEX
// @include /^https:\/\/(www\.)?bondage(projects\.elementfx|-(europe|asia))\.com\/.*/
// @include /^https?:\/\/(www\.)?(bondageprojects\.com|bondageprojects\.elementfx\.com|bondage-europe\.com|bondage-asia\.com)\/.*/
// @grant none
// @run-at document-end
// ==/UserScript==

window.PEX = window.PEX ?? {};
if (window.PEX) {
console.warn('⚗️[PEX] 已加载,跳过重复加载。');
} else {
Expand Down
3 changes: 1 addition & 2 deletions loader.user.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,13 +7,12 @@
// @description:en Persona excretion gameplay: dizzy → excrete → blank → gel → feed-back recovery. Supports /pex commands.
// @author PEX
// @supportURL https://github.com/Nice8923/BC-PEX
// @include /^https:\/\/(www\.)?bondage(projects\.elementfx|-(europe|asia))\.com\/.*/
// @include /^https?:\/\/(www\.)?(bondageprojects\.com|bondageprojects\.elementfx\.com|bondage-europe\.com|bondage-asia\.com)\/.*/
// @grant none
// @run-at document-end
// ==/UserScript==

// 薄加载器:从发布地址拉取构建产物(assets/main.js,GitHub Pages)。
window.PEX = window.PEX ?? {};
if (window.PEX) {
console.warn('⚗️[PEX] 已加载,跳过重复导入。');
} else {
Expand Down
5 changes: 4 additions & 1 deletion src/core/commands.js
Original file line number Diff line number Diff line change
Expand Up @@ -134,8 +134,11 @@ function tryRegisterCommand() {
return false;
}

// 策略3:keydown Enter 兜底
// 策略3:keydown Enter 兜底(单例守卫:core-init 顶层 hookChatInput 与进房后 registerCommandOnce 都会调它,避免重复挂监听导致 /pex 触发两次)
let _keyDownHooked = false;
function setupKeydownFallback() {
if (_keyDownHooked) return;
_keyDownHooked = true;
document.addEventListener('keydown', (e) => {
if (e.key !== 'Enter') return;
const input = document.getElementById('InputChat') || document.querySelector('textarea[id*="Chat"]');
Expand Down
35 changes: 35 additions & 0 deletions src/core/whitelist.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
// ════════════════════════════════════════
// 白名单代号解析
// 配置里的 whitelist 可填数字成员号,或代号:
// $owner —— 被授权方(目标本人)的主人
// $lover —— 被授权方(目标本人)的恋人
// 比较时 relativeTo 必须是【被授权方本人】的角色对象:
// 查看者端 = 被看的角色 C;接收端 = Player(接收方即被授权方)。
// 代号相对它解析。两条 BC 原生 API(Character 原型方法):
// IsOwnedByMemberNumber(n) / IsLoverOfMemberNumber(n)
// ════════════════════════════════════════

// candidate:要判断的成员号(查看者 / 发送者)。返回是否放行。
export function whitelistAllows(list, candidate, relativeTo) {
if (candidate == null) return false;
const c = Number(candidate);
if (!Number.isFinite(c) || c <= 0) return false;
for (const e of (list || [])) {
const s = String(e).trim();
if (/^\d+$/.test(s)) { if (Number(s) === c) return true; continue; }
try {
// 代号相对被授权方本人解析;各方法独立判断,缺哪个都不影响其它代号
if (s === '$owner') {
if (relativeTo && typeof relativeTo.IsOwnedByMemberNumber === 'function'
&& relativeTo.IsOwnedByMemberNumber(c)) return true;
} else if (s === '$lover' || s === '$lovers') {
if (relativeTo && typeof relativeTo.IsLoverOfMemberNumber === 'function'
&& relativeTo.IsLoverOfMemberNumber(c)) return true;
// 兜底:方法缺失时直接查 Lovership 数组
const lv = relativeTo && relativeTo.Lovership;
if (Array.isArray(lv) && lv.map(Number).includes(c)) return true;
}
} catch (e) {}
}
return false;
}
23 changes: 12 additions & 11 deletions src/ui/remote.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import { saveSettings, publishSharedSettings } from '../core/storage.js';
import { printChat } from '../core/commands.js';
import { ui } from '../expansion/i18n.js';
import { pexLog, characterNicknameSafe } from '../util/util.js';
import { whitelistAllows } from '../core/whitelist.js';

const BTN = { x: 1715, y: 175, w: 90, h: 90 }; // 资料页远程修改按钮
const PANEL_ID = 'pex-remote-panel';
Expand All @@ -27,20 +28,20 @@ const CATS = [
];

// 我方对目标是否有某类权限(对方公告快照兜底——实时回复到达前先用它)
function _viewerCanEdit(info, mode) {
// codeRef = 被授权方本人(被看的角色 C):白名单里的 $owner/$lover 相对它解析
function _viewerCanEdit(info, mode, codeRef) {
if (mode === 'any') return true;
if (mode === 'whitelist') {
const wl = Array.isArray(info?.wl) ? info.wl.map(Number) : [];
return wl.includes(Number(Player?.MemberNumber));
return whitelistAllows(info?.wl, Player?.MemberNumber, codeRef);
}
return false;
}
function _viewerPerms(info) {
function _viewerPerms(info, codeRef) {
const em = info?.editModes || {};
return {
time: _viewerCanEdit(info, em.time),
autoRevert: _viewerCanEdit(info, em.autoRevert),
timerVisibility: _viewerCanEdit(info, em.timerVisibility),
time: _viewerCanEdit(info, em.time, codeRef),
autoRevert: _viewerCanEdit(info, em.autoRevert, codeRef),
timerVisibility: _viewerCanEdit(info, em.timerVisibility, codeRef),
};
}
function _canEditAny(perms) {
Expand Down Expand Up @@ -68,7 +69,7 @@ function _ensurePerm(num) {
function _permFor(C, info) {
const pc = _permCache[C?.MemberNumber];
if (pc && Date.now() - pc.ts < PERM_TTL) return pc;
return { perms: _viewerPerms(info), values: null, ts: Date.now() };
return { perms: _viewerPerms(info, C), values: null, ts: Date.now() };
}

function targetInfo(C) {
Expand Down Expand Up @@ -221,7 +222,7 @@ function _doOpenRemoteSettings(C) {
}
R.target = C;
const pc = _permCache[num];
R.perms = pc ? pc.perms : _viewerPerms(targetInfo(C));
R.perms = pc ? pc.perms : _viewerPerms(targetInfo(C), C);
R.values = (pc && pc.values) ? pc.values : {};
showPanel();
}
Expand Down Expand Up @@ -281,8 +282,8 @@ function registerRemoteServer() {
const m = (CONFIG.editModes || {})[catKey] || 'off';
if (m === 'any') return true;
if (m === 'whitelist') {
const wl = (CONFIG.whitelist || []).map(String);
return wl.includes(String(sender));
// 白名单相对【被授权方本人】解析:这里是接收方自己(Player)
return whitelistAllows(CONFIG.whitelist || [], sender, Player);
}
return false;
};
Expand Down
10 changes: 8 additions & 2 deletions src/ui/settings.js
Original file line number Diff line number Diff line change
Expand Up @@ -247,7 +247,11 @@ const EXT = {
content.addEventListener('change', (e) => {
const t = e.target;
if (t.dataset.pexSelect) {
this._setPath(t.dataset.pexSelect, t.value);
// 数值型下拉(特效强度/失神视野)存数字而非字符串,保持类型一致;
// 纯数字值才转(其余如计时器可见性、表情名仍为字符串)
const raw = t.value;
const num = Number(raw);
this._setPath(t.dataset.pexSelect, (raw !== '' && /^\d+$/.test(raw) && !isNaN(num)) ? num : raw);
// 表情下拉 → 刷新预览(新结构:expressions.wait.N / expressions.excrete / blank)
const sel = t.dataset.pexSelect;
if (sel.startsWith('expressions.wait.')) {
Expand Down Expand Up @@ -336,7 +340,9 @@ const EXT = {
},
_sel(key, options, desc) {
const val = this._getPath(key);
return `<select class="pex-sel" data-pex-select="${key}" title="${esc(desc || '')}">${options.map(([v, l]) => `<option value="${v}" ${val === v ? 'selected' : ''}>${esc(l)}</option>`).join('')}</select>`;
// 用字符串比较判定选中:特效强度/失神视野等数值型下拉,
// 旧存档可能存成字符串 "3",与数字 3 严格比较会全部落空 → 下拉回退到第一项
return `<select class="pex-sel" data-pex-select="${key}" title="${esc(desc || '')}">${options.map(([v, l]) => `<option value="${v}" ${String(val) === String(v) ? 'selected' : ''}>${esc(l)}</option>`).join('')}</select>`;
},
_num(key, min, max, desc) {
return `<input type="number" class="pex-num" data-pex-number="${key}" min="${min}" max="${max}" value="${this._getPath(key)}" title="${esc(desc || '')}">`;
Expand Down
7 changes: 4 additions & 3 deletions src/ui/timer.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@

import { CONFIG, ES_KEY } from '../core/config.js';
import { getModApi } from '../core/config.js';
import { whitelistAllows } from '../core/whitelist.js';

// 读角色的 PEX 公告状态
function readState(C) {
Expand All @@ -27,11 +28,11 @@ function shouldDraw(C) {
if (vis === 'self') return isMe;
if (vis === 'others') return !isMe;
if (vis === 'whitelist') {
// 仅白名单:自己总能看到自己的;别人要看他在不在被观察者公告的白名单里
// 仅白名单:自己总能看到自己的;别人要看他在不在被观察者公告的白名单里。
// 白名单相对【被观察者本人】解析:$owner/$lover = 被观察者自己的主人/恋人
if (isMe) return true;
const wl = C?.OnlineSharedSettings?.[ES_KEY]?.wl || [];
const myNo = Player?.MemberNumber;
return wl.includes(String(myNo));
return whitelistAllows(wl, Player?.MemberNumber, C);
}
return false;
} catch (e) { return false; }
Expand Down