Skip to content

Pitfalls

Himxh edited this page Oct 4, 2026 · 1 revision

常见陷阱 / Common Pitfalls

说明 / Note

本章是速查汇总。每一条都能在前面找到详细解释。遇到问题时先在这里扫一眼。

This chapter is a lookup. Each entry is explained earlier. Scan here first when stuck.


语法陷阱 / Syntax Pitfalls

陷阱 正确写法
int a[];(无初始化无长度) int a[5]; 或 int a[] = {...};
struct S { ... } 后忘分号 struct S { ... };
enum E { A, B } 后忘分号 enum E { A, B };
if (x) stmt1; stmt2; 多条语句必须加 {}
Consumer<Player> c HimDSL 不支持泛型,用 var c
new Point() 用于 struct Point p;
Trap Fix
int a[]; int a[5]; or int a[] = {...};
Missing ; after struct S { ... } Add it
Missing ; after enum E { ... } Add it
if (x) stmt1; stmt2; Braces required for multiple statements
Consumer<Player> c No generics in HimDSL; use var c
new Point() for a struct Point p;

类型与运算 / Types and Operations

陷阱 说明
5 / 2 返回 2 整数除法截断;写 5.0 / 2 得 2.5
"" 在 if 里为真 空字符串不是假;用 s == "" 判断
int x = "hi"; 编译通过 类型检查是运行时的
toInt("abc") 返回 0 转换失败返回默认值,不报错
0.1 + 0.2 != 0.3 浮点精度问题;用 bigAdd
Trap Note
5 / 2 returns 2 Integer division; write 5.0 / 2
"" is truthy in if Compare with s == ""
int x = "hi"; compiles Type checks are runtime
toInt("abc") returns 0 Failed conversion yields default
0.1 + 0.2 != 0.3 Float precision; use bigAdd

字符串 / Strings

陷阱 说明
s.replace(a, b) 后 s 不变 字符串不可变,要赋回
"a.b".split(".") 返回空 . 是正则字符,用 "\\\\."
s.length(无括号) 方法必须带 ():s.length()
"a\\nb" 在聊天里不换行 Minecraft 聊天不渲染换行
Trap Note
s.replace(a, b) leaves s Strings are immutable; reassign
"a.b".split(".") returns empty . is regex; use "\\\\."
s.length (no parens) Method call needs ()
"a\\nb" does not wrap in chat Chat does not render newlines

容器 / Containers

陷阱 说明
list() 创建列表 用 vector()
map.size() Map 没有 size();用 isEmpty()
set.get(0) Set 无下标访问
stack.pop() on empty 空容器上 pop / poll / peek 报错
queue.push(x) 队列用 offer
list.remove(0) 和 list.remove(x) 同名不同行为;注意参数类型
Trap Note
list() to create a list Use vector()
map.size() No size() on maps; use isEmpty()
set.get(0) Sets have no indices
stack.pop() on empty pop / poll / peek on empty errors
queue.push(x) Queues use offer
list.remove(0) vs list.remove(x) Same name, different behavior

选择器 / Selectors

陷阱 说明
@a[...] @a 不支持过滤器
@s in main 返回 null;只在事件、GUI、lambda 里有效
@p[distance=..10] 无原点 在 main 里没有执行原点,不匹配
@e 不加过滤 遍历所有世界的实体,很重
@e[...] 返回 null 返回空列表,不是 null;用 size() == 0
Trap Note
@a[...] @a takes no filters
@s in main Returns null; only in events/GUI/lambdas
@p[distance=..10] without origin No origin in main
Unfiltered @e Very heavy
@e[...] returns null Returns an empty list; check size() == 0

占位符 / Placeholders

陷阱 说明
$player(p, naem)$ 拼错返回 null,不报错
$player(p, health)$ 用 hp,不是 health
$player(@p, name)$ 第一个参数是变量名,不能是选择器
papi("unknown") 返回空 PlaceholderAPI 未装或变量名错
Trap Note
$player(p, naem)$ Typo returns null, no error
$player(p, health)$ Use hp, not health
$player(@p, name)$ First argument is a variable name
papi("unknown") returns empty PAPI missing or wrong key

建议:能用引用(p.name)就别用占位符。引用拼错会报错。

Advice: prefer references (p.name) over placeholders. References error on typos.


事件与调度 / Events and Scheduling

陷阱 说明
写了 @EventHandler 但没反应 必须 start("函数名")
start 已在运行的任务 报错;先 stop
事件函数重载 start 无法分辨,避免
@BukkitRunnable 不带 sche 异步执行,不能直接操作游戏
sleep 在 main 里 阻塞主线程,卡服
sleep 在 @BukkitRunnable 同上
Trap Note
@EventHandler has no effect Must start("name")
start on running task Errors; stop first
Overloaded event functions start cannot resolve; avoid
@BukkitRunnable without sche Async; cannot touch game directly
sleep in main Blocks main thread
sleep in scheduled task Same

GUI

陷阱 说明
填了槽位但界面空 open 前要 updateAll
修改 slot.name 后没变化 手动 update
slot.lore[0] = "x" 无效;读-改-写回
点击回调里用 @p 用 @s(点击者)
Shift 点击无反应 未注册 onShiftLeftClick,不回退
onClose 里打开同一 GUI 死循环
Trap Note
Slots filled, GUI empty updateAll before open
slot.name changed, no visible effect Manually update
slot.lore[0] = "x" Read-modify-reassign
@p inside a click callback Use @s (the clicker)
Shift-click does nothing Register onShiftLeftClick; no fallback
Reopening same GUI in onClose Infinite loop

文件与命令 / Files and Commands

陷阱 说明
fwritelines 当追加 覆盖;追加用 fopen(..., "a")
相对路径 ../x 不能逃逸插件目录
fopen 后忘记 fclose 文件保持打开
runcmd 命令带斜杠 不带前导 /
runcmd 玩家名拼错 静默丢弃
Trap Note
fwritelines as append Overwrites; use fopen(..., "a")
../x path Cannot escape
Missing fclose File stays open
runcmd with slash No leading /
runcmd misspelled player Silently dropped

结构化提示 / Structuring Advice

除了具体陷阱,下面的习惯能让脚本更好维护:

Besides specific traps, these habits improve maintainability:

用引用字段代替占位符

string name = p.name;               // ✓
string name = $player(p, name)$;    // 也可以,但拼错不报错

用方法形式代替函数形式

int n = list.size();                // ✓
int n = size(list);                 // 兼容但不推荐

用具名函数代替内联 lambda

// 单处使用
slot.onLeftClick = () -> { doWork(); };     // ✓

// 多处使用
void doWork() { ... }                       // ✓ 具名函数
slot1.onLeftClick = () -> { doWork(); };
slot2.onLeftClick = () -> { doWork(); };

lambda 只在"一次性回调"里用。多处复用时,具名函数更清楚。

Lambda for one-shot callbacks. For repeated use, named functions are clearer.

用返回值代替全局变量

// ✗
int result;
void compute() { result = 42; }

// ✓
int compute() { return 42; }

一个脚本做一件事

不要把所有逻辑塞进一个文件。按功能拆分:welcome.himdsl、shop.himdsl、autosave.himdsl。

Do not cram everything into one file. Split by function: welcome.himdsl, shop.himdsl, autosave.himdsl.


小结 / Summary

  • 本章是所有陷阱的速查表。

  • 引用 > 占位符;方法形式 > 函数形式;具名函数 > 内联 lambda。

  • 返回值 > 全局变量。

  • 一个脚本做一件事。

  • A cheat sheet of all traps.

  • References > placeholders; method > function form; named > inline lambda.

  • Return values > globals.

  • One script, one purpose.


进阶部分回顾 / Advanced Review

进阶部分到此结束。五章覆盖了:类解析、枚举解析、作用域与闭包、调试、常见陷阱。

The Advanced section ends here. Five chapters: class resolution, enum resolution, scopes and closures, debugging, and pitfalls.

日常脚本不需要深究这些机制。它们存在的意义是:当你遇到"为什么这样不生效"的时候,有个地方能查到。

Daily scripts ignore these internals. They exist so that, when "why doesn't this work" strikes, there is a place to look.


下一步 / Next Steps

下一部分进入扩展 API。第十章 HimDSLAPI 讲如何从其他 Java 插件调用 HimDSL。

The next part covers the Extension API. Chapter HimDSLAPI shows how other Java plugins call HimDSL.


HimDSL 文档 / Documentation

入门 / Getting Started

语言基础 / Language Basics

控制流 / Control Flow

函数 / Functions

数据结构 / Data Structures

自定义类型 / Custom Types

Minecraft 集成 / Minecraft Integration

事件与调度 / Events & Scheduling

GUI 系统 / GUI System

内置函数参考 / Built-ins Reference

进阶 / Advanced

扩展 API / Extension API

你真的需要 API 吗?/ Do you really need the API?

Clone this wiki locally