编辑会话与历史
基本信息
| 属性 | 值 |
|---|---|
| 编辑会话类 | com.sk89q.worldedit.EditSession(EditSession.java:130,implements Extent) |
| 持有者 | com.sk89q.worldedit.LocalSession(每玩家一个) |
| 历史实现 | LocalSession 内的 List<EditSession> + historyPointer 游标 |
| 历史上限 | LocalSession.MAX_HISTORY_SIZE,字段初值 15(LocalSession.java:61) |
| 历史包 | com.sk89q.worldedit.history(UndoContext.java + change/ + changeset/) |
历史栈机制
LocalSession 用双字段模型:列表 history 与倒序游标 historyPointer(LocalSession.java:71)。
写入一次新操作时,LocalSession.remember(EditSession)(LocalSession.java:188)执行:
195 while (historyPointer < history.size()) { // 丢弃此撤销点之后的所有 redo 分支
196 history.remove(historyPointer);
197 }
198 history.add(editSession);
199 while (history.size() > MAX_HISTORY_SIZE) { // 超出上限时丢最老的
200 history.remove(0);
201 }
202 historyPointer = history.size();
因此先做新操作会清空 redo 分支(:195-197),历史超过上限时从头部淘汰(:199-201)。
undo 先把游标左移再取记录(LocalSession.java:225-227:--historyPointer; if (historyPointer >= 0) { EditSession editSession = history.get(historyPointer); …),越界时返回 null,命令层据此打印 “Undo successful.” 或不打印。
历史上限有硬下限 15
MAX_HISTORY_SIZE 由配置赋值(PropertiesConfiguration.java:111):
LocalSession.MAX_HISTORY_SIZE = Math.max(15, getInt("history-size", 15));
Math.max(15, …) 意味着把 history-size 配成 5、0 或任何小于 15 的值都无效,实际仍为 15。这与 LocalConfiguration 字段初值 15(LocalSession.java:61)一致。
同仓
YAMLConfiguration.java:100用的是Math.max(0, config.getInt("history.size", 15)),下限不同。YAML 配置在 1.7.10 Forge 版未被使用(Forge 侧只构造ForgeConfiguration),故不影响本条目所述行为——但这是上游两套配置实现的一处不一致,记录备查。
改动上限与 MaxChangedBlocksException
EditSession 逐次记录改动方块数(getBlockChangeCount(),EditSession.java:438)。写方块的核心入口有 3 个重载:
| 方法 | 行 |
|---|---|
setBlock(Vector, BaseBlock, Stage) |
EditSession.java:543 |
setBlock(Vector, BaseBlock) |
EditSession.java:587 |
setBlock(Vector, Pattern) |
EditSession.java:606 |
setBlockIfAir(Vector, BaseBlock) |
EditSession.java:654 |
超出 max-changed-blocks 时抛 MaxChangedBlocksException(配置默认 -1 = 不限)。会话级初始上限由 default-max-changed-blocks 决定,注入点为 SessionManager.java:159(session.setBlockChangeLimit(config.defaultChangeLimit))。
掩码
EditSession 持掩码,写入前逐方块判定。两个 setMask 重载(EditSession.java:338、:354)分别接受 com.sk89q.worldedit.masks.Mask 与另一套 Mask 接口。掩码可由单条命令设置(//gmask)或由刷子参数(/mask)设置,详见 工具与超级镐指令。
会话与玩家的绑定
- 取会话:
ForgeWorldEdit.getSession(EntityPlayerMP)(ForgeWorldEdit.java:312-317),内部WorldEdit.getInstance().getSessionManager().get(wrap(player)) - 每个玩家一个
LocalSession,选区、掩码、历史互不可见 - 会话本体落盘见 会话与存档
交互
- 一次
//undo撤销一整个命令(含该命令产生的所有方块改动),而非单个方块 //undo撤销他人会话需worldedit.history.undo.other权限(HistoryCommands.java:62)- 方块写入走队列模式:
EditSession.enableQueue()开启、disableQueue()关闭;disableQueue()在关闭前若队列仍启用则调用flushQueue()把待写方块落盘(EditSession.java:310-322)
相关条目
- 移动、历史与脚本指令 -
//undo///redo的命令面 - worldedit.properties 配置项 -
history-size、max-changed-blocks - 会话与存档 - 会话的持久化