yeow-api 0.2.114 → 0.2.115

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "yeow-api",
3
- "version": "0.2.114",
3
+ "version": "0.2.115",
4
4
  "description": "Yeow API",
5
5
  "type": "module",
6
6
  "main": "./src/index.ts",
package/src/command.ts CHANGED
@@ -1,11 +1,16 @@
1
1
  import { call } from './task.js';
2
2
  import type { TaskOptions } from './task.js';
3
+ import { Player } from './player.js';
4
+ import type { Permission } from './permission.js';
5
+ import type { PermissionOptions } from './permission.js';
6
+ import { permissionPayload } from './permission.js';
3
7
 
4
- export interface CommandSender {
5
- readonly name: string;
6
- readonly uuid: string;
7
- readonly isPlayer: boolean;
8
- sendMessage(msg: string): void;
8
+ /** 命令发送者:玩家为真正的 `Player` 对象(异步 `sendMessage` 等全部方法);控制台为字符串 `'CONSOLE'`。 */
9
+ export type CommandSender = Player | 'CONSOLE';
10
+
11
+ /** 判断发送者是否为玩家(非 'CONSOLE' 即玩家)。 */
12
+ export function isPlayer(sender: CommandSender): sender is Player {
13
+ return sender !== 'CONSOLE';
9
14
  }
10
15
 
11
16
  export interface CommandPayload {
@@ -23,7 +28,12 @@ export interface ManualCompleter {
23
28
  export interface CommandOptions {
24
29
  description?: string;
25
30
  usage?: string;
26
- permission?: string;
31
+ /**
32
+ * 权限节点:字符串(兼容)或权限节点对象 `{ node, default }`(或 `registerPermission` 返回值)。
33
+ * 节点注册进 Bukkit 权限系统(权限插件/ permissions.yml 可管理);**执行时检查**——
34
+ * `permissionCheck` 事件结果优先,无处理时回退 Bukkit `hasPermission`。未声明则所有人可执行。
35
+ */
36
+ permission?: string | Permission | PermissionOptions;
27
37
  aliases?: string[];
28
38
  executor: (payload: CommandPayload) => void;
29
39
  completer?: CompleterFn | ManualCompleter;
@@ -34,21 +44,17 @@ export function registerCommand(name: string, options: CommandOptions, taskOptio
34
44
  const completer = options.completer;
35
45
  const pluginName = __plugin?.name || 'unknown';
36
46
 
37
- function decorateSender(sender: CommandSender): CommandSender {
38
- if (sender?.uuid && sender.isPlayer) {
39
- (sender as any).sendMessage = (msg: string) => {
40
- call('player.sendMessage', { uuid: sender.uuid, message: msg }, taskOptions);
41
- };
42
- } else {
43
- (sender as any).sendMessage = (msg: string) => {
44
- $send('log', { level: 'INFO', message: msg });
45
- };
47
+ /** 原始 sender({name, uuid, isPlayer})→ 真正的 Player 或 'CONSOLE'。 */
48
+ function adaptSender(raw: any): CommandSender {
49
+ if (raw?.isPlayer) {
50
+ const p = Player.getSync(raw.uuid);
51
+ if (p) return p;
46
52
  }
47
- return sender;
53
+ return 'CONSOLE';
48
54
  }
49
55
 
50
56
  const cbId = _registerCallback((payload: CommandPayload) => {
51
- (payload as any).sender = decorateSender(payload.sender);
57
+ (payload as any).sender = adaptSender(payload.sender);
52
58
  executor(payload);
53
59
  }, { persistent: true });
54
60
 
@@ -65,7 +71,7 @@ export function registerCommand(name: string, options: CommandOptions, taskOptio
65
71
 
66
72
  compCbId = _registerCallback((data: any) => {
67
73
  try {
68
- const sender = decorateSender(data.sender);
74
+ const sender = adaptSender(data.sender);
69
75
  if (manualRelease) {
70
76
  const complete = (result: string[]) => {
71
77
  $send('task', {
@@ -108,7 +114,7 @@ export function registerCommand(name: string, options: CommandOptions, taskOptio
108
114
  completerCbId: compCbId,
109
115
  description: options.description,
110
116
  usage: options.usage,
111
- permission: options.permission,
117
+ permission: options.permission ? permissionPayload(options.permission) : undefined,
112
118
  aliases: options.aliases,
113
119
  }, taskOptions);
114
120
  }
package/src/core.ts CHANGED
@@ -27,6 +27,7 @@ export type {
27
27
  BlockBreakEvent, BlockPlaceEvent, BlockFadeEvent, BlockGrowEvent, BlockSpreadEvent, BlockExplodeEvent,
28
28
  InventoryOpenEvent, InventoryCloseEvent, InventoryClickEvent,
29
29
  ServerPingEvent, ServerCommandEvent,
30
+ PermissionCheckEvent,
30
31
  PlayerResourcePackStatusEvent,
31
32
  } from './event.js';
32
33
  export { onInit, onLoad, onUnload } from './lifecycle.js';
@@ -94,5 +95,7 @@ export { log, Logger } from './log.js';
94
95
  export type { Message } from './message.js';
95
96
  export { getEnv } from './env.js';
96
97
  export type { EnvInfo } from './env.js';
98
+ export { registerPermission } from './permission.js';
99
+ export type { Permission, PermissionOptions, PermissionDefault } from './permission.js';
97
100
  export { createWorker, Worker, onMessage, postMessage } from './worker.js';
98
101
  export type { WorkerOptions } from './worker.js';
package/src/event.ts CHANGED
@@ -254,6 +254,27 @@ export interface ServerCommandEvent {
254
254
  sender: string;
255
255
  cancelled?: boolean;
256
256
  }
257
+
258
+ /**
259
+ * Yeow 生态权限检查(仅 `player.hasPermission` 任务与 Yeow 插件注册命令的执行检查触发;
260
+ * 其他 Java 插件的 hasPermission / 命令不会触发)。
261
+ *
262
+ * handler 返回 `{ allowed: <boolean> }` 决定结果;**不返回视为未处理**(回退 Bukkit hasPermission)。
263
+ * 多个 handler 都返回且结果冲突时,以**最后一个返回的为准**(不保证执行顺序)。
264
+ *
265
+ * ⚠ 普通插件不建议监听(每次权限检查都触发,影响性能)——专为 Yeow 生态权限管理插件设计。
266
+ * ⚠ handler 中调用 `hasPermission` 会再次触发本检查——**可能导致无限循环**,请避免。
267
+ */
268
+ export interface PermissionCheckEvent {
269
+ /** 检查对象:玩家 UUID 或 "CONSOLE"。 */
270
+ target: string;
271
+ /** 权限节点(如 "myplugin.home")。 */
272
+ node: string;
273
+ /** 权限对象(含节点默认值,`registerPermission` 或命令声明的权限)。 */
274
+ permission: { node: string; default?: string };
275
+ /** handler 返回 `{ allowed }` 决定结果。 */
276
+ allowed?: boolean;
277
+ }
257
278
  export interface InventoryClickEvent {
258
279
  player: Player;
259
280
  slot: number;
@@ -316,6 +337,7 @@ type EventMap = {
316
337
  inventoryClose: InventoryCloseEvent;
317
338
  serverPing: ServerPingEvent;
318
339
  serverCommand: ServerCommandEvent;
340
+ permissionCheck: PermissionCheckEvent;
319
341
  playerTeleport: PlayerTeleportEvent;
320
342
  playerItemConsume: PlayerItemConsumeEvent;
321
343
  inventoryClick: InventoryClickEvent;
@@ -0,0 +1,46 @@
1
+ import { call } from './task.js';
2
+ import type { TaskOptions } from './task.js';
3
+
4
+ /** 权限节点默认值:'all' = 所有人默认拥有;'op' = 仅 op(默认);'none' = 需授权。 */
5
+ export type PermissionDefault = 'all' | 'op' | 'none';
6
+
7
+ export interface PermissionOptions {
8
+ /** 权限节点(如 `myplugin.home`)。 */
9
+ node: string;
10
+ /** 默认值(默认 'op')。 */
11
+ default?: PermissionDefault;
12
+ }
13
+
14
+ /** 权限节点对象(注册后返回)。 */
15
+ export interface Permission {
16
+ node: string;
17
+ default: PermissionDefault;
18
+ }
19
+
20
+ let _registered: Record<string, Permission> = {};
21
+
22
+ /**
23
+ * 注册权限节点(幂等):节点注册进 Bukkit 权限系统——Paper 平台可通过
24
+ * `permissions.yml` 静态声明或 LuckPerms 等权限管理插件管理。
25
+ *
26
+ * 粒度较粗(只声明默认值);Yeow 生态内可由权限管理插件通过 `permissionCheck`
27
+ * 事件实现任意逻辑的权限管理。
28
+ */
29
+ export function registerPermission(options: PermissionOptions, taskOptions?: TaskOptions): Permission {
30
+ const node = options?.node;
31
+ if (!node || typeof node !== 'string' || node.trim() === '') {
32
+ throw new Error('registerPermission: node is required');
33
+ }
34
+ const def: PermissionDefault = options.default || 'op';
35
+ if (!_registered[node]) {
36
+ call('permission.register', { node, default: def }, taskOptions);
37
+ _registered[node] = { node, default: def };
38
+ }
39
+ return _registered[node];
40
+ }
41
+
42
+ /** 权限节点对象 → 请求载荷({ node, default });字符串包装为对象(default 默认 'op')——Java 侧不做兼容。 */
43
+ export function permissionPayload(perm: string | Permission | PermissionOptions): { node: string; default: PermissionDefault } {
44
+ if (typeof perm === 'string') return { node: perm, default: 'op' };
45
+ return { node: perm.node, default: perm.default || 'op' };
46
+ }
package/src/player.ts CHANGED
@@ -3,6 +3,7 @@ import type { TaskOptions } from './task.js';
3
3
  import { Location, LocationData } from './location.js';
4
4
  import type { ItemStack } from './item.js';
5
5
  import type { Message } from './message.js';
6
+ import type { Permission } from './permission.js';
6
7
 
7
8
  interface PlayerData {
8
9
  uuid: string;
@@ -135,11 +136,12 @@ export class Player {
135
136
  }
136
137
  giveExp(amount: number, options?: TaskOptions): Promise<void> { return post('player.giveExp', { uuid: this.uuid, amount }, options); }
137
138
  giveExpSync(amount: number, options?: TaskOptions): void { call('player.giveExp', { uuid: this.uuid, amount }, options); }
138
- hasPermission(node: string, options?: TaskOptions): Promise<boolean> {
139
- return post<boolean>('player.hasPermission', { uuid: this.uuid, permission: node }, options);
139
+ /** 检查权限(经 Yeow 权限检查:`permissionCheck` 事件优先,无处理时回退 Bukkit)。node 可为权限节点对象。 */
140
+ hasPermission(node: string | Permission, options?: TaskOptions): Promise<boolean> {
141
+ return post<boolean>('player.hasPermission', { uuid: this.uuid, permission: typeof node === 'string' ? node : { node: node.node } }, options);
140
142
  }
141
- hasPermissionSync(node: string, options?: TaskOptions): boolean {
142
- return call<boolean>('player.hasPermission', { uuid: this.uuid, permission: node }, options);
143
+ hasPermissionSync(node: string | Permission, options?: TaskOptions): boolean {
144
+ return call<boolean>('player.hasPermission', { uuid: this.uuid, permission: typeof node === 'string' ? node : { node: node.node } }, options);
143
145
  }
144
146
  /** 以玩家身份执行命令(**不含 `/` 前缀**,如 `say hi`;前缀会自动剥离;与服务器 `dispatchCommand`(控制台)相对)。 */
145
147
  performCommand(cmd: string, options?: TaskOptions): Promise<boolean> {