Repository navigation
Added
- On startup, and again on every
/ul reload, this module now checks your ownconfig/worlds.yml
for the eight keys this version no longer reads (the entries under Removed) and logs one warning per
leftover, naming the module, the file and the key, and saying where the text comes from. Deleting
a key from the module stops a fresh file being written with it but does nothing to the file you
already have, so without this warning an edited value would go on meaning nothing, silently. Delete
the keys from the file to silence it (part of #38). - 本模块现在会在启动时、以及每次
/ul reload时检查你自己的config/worlds.yml中是否仍存在本版本不再读取的
八个配置键(见下方 Removed 中的条目),并为每个残留键各记一条警告,点明模块、文件与键名,并说明文本来自哪里。
从模块中删除一个键,只会让新生成的文件里不再有它,对你已有的文件没有任何影响,因此若没有这条警告,被改过的值
会继续悄无声息地不起作用。把这些键从文件中删除即可不再提示(#38 的一部分)。
Changed
-
Requires UltiTools 6.3.0.
plugin.ymlraisesapi-versionfrom620in released 1.0.0 to630.
UltiTools 6.2.x refuses to load this module because of thatapi-version. -
需要 UltiTools 6.3.0。
plugin.yml的api-version从已发布的 1.0.0 中的620提升到630。
UltiTools 6.2.x 会因该api-version拒绝加载本模块。 -
The empty-world check now runs on the framework's own config-bound scheduling, bound to
auto_unload.check_interval(UltiTools 6.3.0, UltiKits/UltiTools-Reborn#531), instead of a one-second tick
inside this module. The first check comes one interval after the module loads./ul reloadapplies a changed
value keeping the check's place in its cycle; a value outside 1 to 107374182 seconds refuses the module at
start, and at/ul reloadis not applied: the running interval is kept, a warning names the key, and the
reload is reported as partial. The minimum drops from 10 seconds to 1 second; at least 10 seconds is
recommended. Yourconfig/worlds.ymlis not rewritten; only a newly written file, or a key the framework newly inserts,
carries the new comment. -
空世界检查现在由框架自身的配置绑定调度执行,绑定到
auto_unload.check_interval(UltiTools 6.3.0,
UltiKits/UltiTools-Reborn#531),不再使用模块内部的每秒计数。首次检查在模块加载一个间隔之后进行。/ul reload
会应用修改后的值,并保持检查在其周期中的位置;超出 1 到 107374182 秒的值会在启动时令模块被拒绝加载,在/ul reload
时不会生效:保留正在运行的间隔,一条警告点明该键,且重载被报告为部分完成。最小值从 10 秒降为 1 秒;建议至少 10 秒。
不会改写你的config/worlds.yml;只有新生成的文件、或由框架新插入的键,才带有新的注释。 -
plugin.ymlnow declaresidentify-string: ultiworlds, the identifier the UltiKits catalogue lists this
module under. With it the framework's update check at start and/upm updateinclude this module; without
it they skipped it. A module jar published before this change carries no identifier and cannot be an update
source for this version. -
plugin.yml现声明identify-string: ultiworlds,即 UltiKits 模块目录中本模块的标识。有了它,框架启动时的更新检查与
/upm update会包含本模块;此前会跳过它。此前发布、不带该标识的模块 jar 不能作为本版本的更新来源。 -
/world delete <name>now asks before it deletes. After the checks it always made (permission,
a world by that name exists, not the default world, not inprotected_worlds), it opens a
confirmation window titled "Confirm Delete: " instead of deleting on the spot; the world is
deleted only when you click the window's greenOKbutton. The redCancelbutton, or closing
the window any other way, deletes nothing. ClickingOKchecks the permission, the default world
andprotected_worldsagain, because they can change while the window is open, and a window
deletes at most once, never after it has been closed, and only for a click on its ownOKbutton
(not for a click at the same slot in your own inventory). The window is valid for 30 seconds, the
same limit and clock as the console's confirmation:OKafter that deletes nothing and asks you
to run the command again. If this module deletes that world for another request while your window
is open -- or starts to and fails part-way -- yourOKdeletes nothing either. The chat lines change with it: the old "Deleting world , please
wait..." / "World has been deleted!" / "Failed to delete the world!" lines
(world.delete.deleting,world.delete.success,world.delete.failed) are no longer sent to a
player; the window sends "World has been deleted" or "Failed to delete world "
(command.delete.success,command.delete.failed), and "Delete operation cancelled"
(command.delete.cancelled) forCancel. If you customised those three old lines for players, carry
your text over to the new keys in a custom language file, not in the officiallang/*.yml: copy the
official file in the samelang/folder to a name that starts with its language code and a hyphen
(for examplelang/en-myserver.yml) and setlanguage: en-myserverinplugins/UltiTools/config.yml.
An earlier edit made in an official file is not kept: the first start after the upgrade restores the
file and keeps your previous file as.bak, where your old text is (UltiKits/UltiTools-Reborn#616). The
old lines are now the console's (next entry) (#19). -
The server console can now delete a world, behind a typed confirmation. Until now the whole
/worldcommand was player-only, so the console could not run/world deleteat all. It now
can, and it never deletes on the first request:/world delete <name>from the console makes the
same checks as for a player (a world by that name exists, it is not the default world, it is not
inprotected_worlds), deletes nothing, and asks you to run the same command again within 30
seconds. Only that repeat -- same world name, spelled and cased exactly the same, within 30
seconds -- deletes, and it makes every check again first; it then prints "Deleting world ,
please wait..." followed by "World has been deleted!" or "Failed to delete the world!". A
repeat after 30 seconds deletes nothing and starts a new 30-second wait; a repeat made after this
module has deleted (or started deleting) a world by that name for another request deletes nothing, says so, and counts
as a new request; a check that refuses the
request or the repeat cancels the pending request; each request allows one deletion. A pending
request lives in memory only and is lost on restart, and the 30 seconds are measured on a clock
that changes to the system time do not affect. Command blocks and other non-player,
non-console senders are refused, and so is RCON (the remote console protocol used by tools such
asmcrconand many chat bridges): it cannot delete a world. Every other/worldsubcommand stays player-only, as before;
/world helpfrom the console now lists only/world delete(#19). -
Every command that runs as the server console counts as the console, and they all share one
identity: each reports the nameCONSOLE, so there is one pending confirmation per world name
for all of them together, and any one of them confirms a request made by any other. That
includes UltiPanel remote commands, post-teleport commands added with/world postcmd add, and
console commands run by other modules or plugins (for example scheduled commands, menu actions,
kit commands and mail commands).- UltiPanel. A panel user can delete a world by sending
world delete <name>twice within 30
seconds. When the server accepts the command dispatch,command_result'sdata.outputreads
"Command dispatched to the server console. Its output appears in the server log stream."
This acknowledges dispatch, not deletion: the command runs as the server console, and its prompt,
outcome and any refusal go to the server log, not todata.output. Read those lines in the
server log (or in the panel's log view, if log streaming is on). - Post-teleport commands. A
world delete <name>stored as a post-teleport command runs every
time any player teleports into that world with/world tpor the world list. Any two such
teleports within 30 seconds, by the same player or by different players, delete the named world;
so do one such teleport plus the same command from the console, the panel or any other
console-run command within 30 seconds. Stored asworld delete {world}, it targets whichever
world is teleported into. The prompt goes to the console, so the teleporting players are never
told. Do not add one. Adding post-teleport commands requiresultiworlds.admin.settings, so that
permission is in effect enough to delete any unprotected world (#19).
- UltiPanel. A panel user can delete a world by sending
-
Known limitation. A delete confirmation, from a player or from the console, does not try to
recognise "the same world": it is bound to its 30 seconds and to this module's own deletions. A
world deleted by another plugin or by hand, and created again under the same name within those 30
seconds, is deleted by a confirmation given for the one before it (#19). -
/world delete <名称>现在会在删除前先询问。它在原有检查(权限、该名称的世界存在、不是默认世界、
不在protected_worlds中)之后,不再立即删除,而是打开标题为"Confirm Delete: <名称>"的确认窗口;
只有点击窗口中绿色的OK按钮才会删除世界。点击红色的Cancel按钮,或以其他任何方式关闭窗口,都
不会删除任何内容。点击OK时会再次检查权限、默认世界与protected_worlds,因为窗口打开期间它们可能
发生变化;并且一个窗口最多只执行一次删除,关闭后不再执行,且只响应窗口自身OK按钮的点击(不会响应在
自己背包同一格位的点击)。窗口有效期为 30 秒,与控制台确认使用相同的时限和时钟:超过后点击OK不会删除
任何内容,并提示重新执行命令。若窗口打开期间本模块因另一个请求删除了该世界(或开始删除但中途失败),你的OK同样不会删除任何内容。
聊天提示也随之改变:原来的"正在删除世界……"、"世界已删除"、
"删除世界失败"三行(world.delete.deleting、world.delete.success、world.delete.failed)不再发送给玩家;
改由窗口发送"世界 <名称> 已删除"或"删除世界 <名称> 失败"(command.delete.success、
command.delete.failed),点击Cancel时发送"已取消删除操作"(command.delete.cancelled)。如果你为玩家
自定义过旧的三行文本,请把文本迁移到自定义语言文件的新键上,而不是官方的lang/*.yml:在同一lang/目录中把
官方文件复制为以其语言代码加连字符开头的文件(例如lang/zh-myserver.yml),并在plugins/UltiTools/config.yml
中设置language: zh-myserver。在官方文件中做过的修改不会保留:升级后的首次启动会恢复该文件,并把原文件保留为
.bak,你原来的文本就在其中(UltiKits/UltiTools-Reborn#616)。旧的三行现在由控制台使用(见下一条)
(#19)。 -
服务器控制台现在可以删除世界,但需要打字确认。 此前整个
/world命令仅限玩家使用,控制台完全无法
执行/world delete。现在可以执行,但第一次请求绝不会删除:控制台执行/world delete <名称>时会做与
玩家相同的检查(存在该名称的世界、不是默认世界、不在protected_worlds中),不删除任何内容,并提示在
30 秒内再次执行同一条命令。只有这次重复——世界名称的拼写和大小写完全相同、且在 30 秒内——才会删除,并且
删除前会再次完成全部检查;随后输出"正在删除世界……",再输出"世界已删除"或"删除世界失败"。超过 30 秒的
重复不会删除任何内容,而是重新开始 30 秒等待;若在请求之后本模块因另一个请求删除(或开始删除)了该名称的世界,重复不会删除
任何内容,会给出提示,并视为新的请求;请求或重复被任一检查拒绝时,待确认的请求随之取消;每个
请求只允许一次删除。待确认的请求只保存在内存中,重启后即失效;这 30 秒按不受系统时间调整影响的时钟计算。命令方块等既非玩家也非控制台的发送者会被
拒绝,RCON(mcrcon及许多聊天桥接工具使用的远程控制台协议)同样被拒绝:它不能删除世界。其余所有/world子命令与以前一样仅限玩家;控制台执行/world help时现在只列出
/world delete(#19)。 -
所有以服务器控制台身份执行的命令都算作控制台,并且它们共用同一个身份:都报告名称
CONSOLE,因此对每个
世界名称,它们合起来只有一个待确认请求,其中任何一个都能确认由另一个发起的请求。这包括 UltiPanel 远程命令、
用/world postcmd add添加的传送后命令,以及其他模块或插件以控制台身份执行的命令(例如定时命令、菜单
动作、礼包命令、邮件命令)。- UltiPanel。 面板用户在 30 秒内发送两次
world delete <名称>即可删除世界。服务器接受命令分派时,
command_result的data.output为
"Command dispatched to the server console. Its output appears in the server log stream."
这只确认命令已分派,不代表删除成功:命令以服务器控制台身份执行,确认提示、执行结果与拒绝原因写入服务器日志,
不会写入data.output。请查看服务器日志中的这些行(若开启了日志流,也可在面板的日志视图中查看)。 - 传送后命令。 作为传送后命令保存的
world delete <名称>,会在任何玩家通过/world tp或世界列表传送
进该世界时执行。30 秒内任意两次这样的传送(同一玩家或不同玩家)都会删除该世界;30 秒内一次这样的传送加上
来自控制台、面板或任何其他控制台命令的同一条命令,同样会删除。若保存为world delete {world},它会作用于
被传送进入的那个世界。确认提示发给控制台,传送的玩家不会得到任何提示。请不要添加这样的命令。添加传送后
命令需要ultiworlds.admin.settings权限,因此该权限实际上足以删除任何未受保护的世界
(#19)。
- UltiPanel。 面板用户在 30 秒内发送两次
-
已知限制。 删除确认(无论来自玩家还是控制台)不会尝试识别"是否还是同一个世界":它只受 30 秒时限和本模块
自身删除操作的约束。若某个世界在这 30 秒内被其他插件或手工删除、又以同名重新创建,为原世界给出的确认会删除
新创建的世界(#19)。
Fixed
-
World settings on servers that share one database. A world setting changed on one server is no longer
undone by the next settings command on another server that shares the database. Each server kept every
world's settings row in memory from its first read and wrote that whole copy back on every change, so a
change made elsewhere in the meantime --/world set,protect,unprotect,block,unblock,
difficulty,postcmd add/clearorsetspawn, on any setting of that world -- was reverted. Every change
now reads the world's row from the database, changes only what the command sets, and writes it only if the
row still holds what was read; if another server wrote the row in between, the change is read again and
re-applied, up to three times, after which the console logs "Failed to update world settings" and the change
is kept in this server's memory only, as after any failed write, until this server's next successful change to
that world or a restart. A change made on another server reaches this server's own checks (the module's PvP
damage check, protection, access, the world list) when this server next changes any setting of that world, or
after a restart; the world's own PvP flag follows when a player changes into that world, and a difficulty
change reaches this server's world only after a restart. One narrow limit is documented inFEATURES.md
(ultiworlds.settings.shared-db-external-change-kept) (#55). -
共享同一数据库的多台服务器上的世界设置。 在一台服务器上修改的世界设置,不会再被共享该数据库的另一台服务器的下一条设置命令撤销。
此前每台服务器从首次读取起就把每个世界的设置记录保存在内存里,每次修改都把整份副本写回,因此期间在别处做的修改——
/world set、protect、unprotect、block、unblock、difficulty、postcmd add/clear或setspawn,
涉及该世界的任一设置——都会被还原。现在每次修改都会从数据库重新读取该世界的记录,只改动命令所设置的内容,并且仅当记录仍是读取时的
内容时才写入;若另一台服务器在此期间写过该记录,则重新读取并重新应用这次修改,最多三次,之后控制台记录“更新世界设置失败”,
这次修改只保留在本服务器内存中,与任何写入失败时相同,直到本服务器下次成功修改该世界或重启为止。另一台服务器做的修改,会在本服务器下次修改该世界的任一设置时、或重启后,
进入本服务器自身的检查(模块的 PvP 伤害检查、保护、进入权限、世界列表);世界本身的 PvP 开关要等玩家切换进该世界时才跟上,
难度修改要到重启后才作用到本服务器的世界。一项范围很窄的限制记录在FEATURES.md
(ultiworlds.settings.shared-db-external-change-kept)(#55)。 -
/world deletetyped in another letter case than the world's name now deletes the world's own folder.
The world was found ignoring case and unloaded, but the folder was looked up under the typed text; on a
case-sensitive filesystem (Linux) that folder does not exist, so nothing was removed and the deletion
was reported as done, leaving the world on disk (#52). -
以与世界名不同的大小写输入的
/world delete现在会删除该世界自己的文件夹。此前世界按不区分大小写找到并被卸载,
文件夹却按输入的文字去找;在区分大小写的文件系统(Linux)上该文件夹并不存在,所以什么也没删除,却报告已删除,
世界仍留在磁盘上(#52)。 -
A world-settings change whose stored row no longer exists is now logged on the console as failed
("Failed to update world settings"); before, it passed as saved without a trace. This can happen when
two servers share one database and one deletes a world's row while the other still has it in memory,
or when someone deletes the row by hand: the command answered success and the setting was gone after
the next restart. The command's own reply is unchanged; only the console line is new. Needs
UltiTools-API 6.3.0 (#51, UltiKits/UltiTools-Reborn#558). -
世界设置的改动若发现其对应的已存记录已不存在,现在会在控制台记录为失败(“更新世界设置失败”);此前它会不留痕迹地被当作已保存。
两台服务器共用一个数据库、其中一台删除了某世界的记录而另一台内存里仍有它时,或有人手动删除该记录时都会这样:命令回复成功,
下次重启后设置却没了。命令本身的回复不变,只多了这条控制台输出。需要 UltiTools-API 6.3.0
(#51,UltiKits/UltiTools-Reborn#558)。 -
Clicking a world in the world list now teleports you one tick after the click, not inside it. The
teleport runs the world's post-teleport commands, and since UltiTools 6.3.0 a command of an
UltiTools module runs the moment it is dispatched; one that opens another module's window (a menu,
say) would otherwise try to open it inside the click event, which Paper refuses. A player who
leaves in that tick is not teleported./world tptyped as a command is unchanged
(#50). -
在世界列表中点击一个世界后,现在会在点击的下一个 tick 传送,而不是在点击事件之内。传送会运行该世界的传送后命令,
而自 UltiTools 6.3.0 起,UltiTools 模块的命令在被分派的那一刻就运行;若某条命令会打开另一个模块的界面(例如菜单),
就会在点击事件之内尝试打开,而 Paper 不允许这样做。在那一个 tick 内离线的玩家不会被传送。作为命令输入的/world tp不变
(#50)。 -
A world-inventory save whose stored row no longer exists is now reported as failed on every storage
type, in the same console line a failed write always produced ("Failed to save inventory for
"). Before, only the JSON storage reported it; on SQLite and MySQL the save wrote nothing
and passed as saved. Needs UltiTools-API 6.3.0 (#49, UltiKits/UltiTools-Reborn#558). -
世界背包的保存若发现其对应的已存记录已不存在,现在在所有存储类型上都会报告失败,沿用保存失败时一贯的那一行控制台输出
(“保存 <玩家> 的背包失败”)。此前只有 JSON 存储会报告;SQLite 和 MySQL 上这次保存什么也没写,却被当作已保存。
需要 UltiTools-API 6.3.0(#49,UltiKits/UltiTools-Reborn#558)。 -
/world listno longer lists a world you marked hidden (/world set <world> hidden true). The world
list window already left it out; the text list showed it anyway, and counted it in the total
(#48). -
/world list不再列出被你标记为隐藏的世界(/world set <世界> hidden true)。世界列表界面本来就不显示它,
文字列表却照样列出并计入总数(#48)。 -
Every
/worldcommand now reads and writes a world's settings under the world's own name, however
you type it./world set MYWORLD pvp falsefoundmyworld(the server ignores case) but stored the
change in a new settings row namedMYWORLDthat nothing reads, so the change applied once and was
undone the next time a player entered the world, while the command reported success.set,
protect,unprotect,block,unblock,difficulty,postcmd,tp(and a click in the world
list) anddeleteall use the world's own name now;/world tpalso no longer opens a blocked or
locked world typed in another case. Rows already stored under another spelling are not merged:
at start-up each one that matches a loaded world only when case is ignored is listed in one warning,
naming the row and the world, and is otherwise left alone; the warning says that on MySQL, whose default
collation ignores case, a lookup may still reach such a row (#46). -
现在每条
/world命令都按世界自己的名字读写该世界的设置,不论你怎么输入。此前/world set MYWORLD pvp false
能找到myworld(服务器不区分大小写),却把改动存进一行名为MYWORLD、无人读取的新设置里,于是改动只生效一次,
下次有玩家进入该世界时就被撤销,而命令却报告成功。set、protect、unprotect、block、unblock、difficulty、
postcmd、tp(以及世界列表中的点击)和delete现在都使用世界自己的名字;/world tp也不再让以其他大小写输入的
被封锁或被锁定的世界放行。已按其他写法保存的旧行不会被合并:启动时,只有忽略大小写才与某个已加载世界同名的每一行,
会各用一条警告列出,点明该行与该世界,其余保持原样;警告中说明,在默认排序规则忽略大小写的 MySQL 上,查找仍可能读到这样的行
(#46)。 -
A value UltiWorlds cannot use is now named instead of being passed over silently: a
default_worldthat is no loaded world is reported at start and on/ul reload, with the world
players are sent to instead (the server's first world); aload_worlds_on_startentry that cannot
be loaded is reported at start; and/world set <world> icon <item>refuses a name that is no
item, where it stored it and showed the default icon. -
UltiWorlds 无法使用的值现在会被点名,而不是被悄悄忽略:不是已加载世界的
default_world会在启动和/ul reload时提示,
并说明玩家实际会被送往的世界(服务器的第一个世界);无法加载的load_worlds_on_start条目会在启动时提示;
/world set <世界> icon <物品>会拒绝不是物品的名字,此前它会被保存并显示为默认图标。 -
auto_unload.check_intervalnow decides how often empty worlds are checked, in seconds; a value
changed with/ul reloadapplies at that reload (see the UltiTools 6.3.0 entry above). The check ran every
60 seconds whatever the key said (#38). -
auto_unload.check_interval现在决定检查无人世界的间隔(秒);用/ul reload修改后在该次重载时生效(见上方 UltiTools 6.3.0
条目)。此前无论该键为何值,都每 60 秒检查一次(#38)。 -
world_isolation.shared_worldsnow matches world names ignoring case, as the server does. An
entry typed in another case than the world's name (MyWorldformyworld) matched nothing, so
each world became its own group and walking through a portal between them emptied the player's
inventory. A world listed twice, in any case, is reported at start and stays in the group of its
first entry (#34). -
world_isolation.shared_worlds现在与服务器一样按不区分大小写的方式匹配世界名。此前大小写与世界名不同的条目(例如用
MyWorld指myworld)匹配不到任何世界,于是每个世界各自成组,玩家在它们之间穿过传送门时背包会被清空。
同一个世界(不论大小写)被列出两次时,会在启动时提示,并保留在第一次出现的组中(#34)。 -
Console and chat lines show a path, a world name or text you typed exactly as it is. A value that
contained a later placeholder of its line, such as{KEY}in the configuration file's path, or
{WORLD}in a description set with/world set, was rewritten by it. This covers the removed-key
warning, the world-environment and invalid-difficulty warnings, the/world listlines and the
/world setconfirmation (#43). -
控制台与聊天中的行现在按原样显示路径、世界名或你输入的文字。此前若值中含有该行随后的占位符(例如配置文件路径中的
{KEY},或用/world set设置的描述中的{WORLD}),会被其改写。涉及已移除配置键的警告、世界环境与无效难度的警告、
/world list的各行以及/world set的确认消息(#43)。 -
/world infoshows every setting a world stores: its difficulty and all twelve flags by name
(PvP, monsters, animals, weather, the four protections, hidden, locked, blocked and auto-unload).
It showed four, one of them a single "protection" line for all four protections./world info <world>shows a named world./world setnow also acceptsautoUnload,protectBreak,
protectPlace,protectInteractandprotectExplosion, which had no command to change them
(#17). -
/world info现在显示世界保存的全部设置:难度,以及按名称列出的全部十二个开关(PvP、怪物、动物、天气、四项保护、隐藏、
锁定、禁止进入和自动卸载)。此前只显示四项,其中一项是把四种保护合并成的一行。/world info <世界>可查看指定世界。
/world set现在还接受autoUnload、protectBreak、protectPlace、protectInteract与protectExplosion,
此前没有任何命令能修改它们(#17)。 -
A world description with several lines shows every line in the world list's icon. The whole
description was one lore line, and the client shows nothing after a line break inside one, so
only the first line appeared. A Windows line break (\r\n) now splits the same way in the list
and in the lines shown on teleport (#26). -
多行的世界描述现在会在世界列表图标中显示每一行。此前整段描述是一行 lore,而客户端不显示一行 lore 中换行之后的内容,
因此只显示了第一行。Windows 换行(\r\n)现在在列表和传送时显示的描述中按同样方式拆分(#26)。 -
A player who hits another player in a world with PvP off is now told "PVP is disabled in this
world!". The hit was stopped, but the line never arrived: the server stops such a hit before the
module's damage handler runs, so the line is now sent on the attack attempt (#23). -
在关闭 PvP 的世界中攻击其他玩家时,攻击者现在会收到“此世界已禁用 PVP”的提示。此前攻击会被阻止,但提示从未送达:
服务器会在模块的伤害处理之前拦下这次攻击,因此提示现在改为在攻击发起时发送(#23)。 -
A world with weather disabled (
/world set <world> weather false) now also keeps thunder from
starting. Rain was blocked, but thunder is a separate state, so a world could still turn
thundering (#24). -
关闭天气的世界(
/world set <世界> weather false)现在也会阻止雷暴开始。此前只阻止了下雨,而雷暴是独立的状态,
因此世界仍可能进入雷暴(#24)。 -
language: zhnow applies to this module's console lines that were fixed English text: the
lines about a world's environment when it is loaded, the refusal to delete a protected world, the
symbolic-link and incomplete-deletion lines of/world delete, the empty-world auto-unload line,
an invalid stored difficulty, and a failed save of world settings or of a player's inventory.
Their English wording is unchanged. The/worldcommand's description (shown by/help) now
followslanguagetoo; it was fixed Chinese text. -
/world helpnow shows an admin the/world unprotectand/world unblocklines. Both commands
worked, and the language files carried their help text, but the help never printed it. -
language: zh现在也对本模块原先写死为英文的控制台日志生效:加载世界时关于其环境的日志、拒绝删除受保护世界的日志、
/world delete遇到符号链接与未能完整删除时的日志、空世界自动卸载日志、已存储的无效难度,以及保存世界设置或玩家背包
失败的日志。它们的英文措辞不变。/world命令的描述(由/help显示)现在也跟随language;原先是写死的中文。 -
/world help现在会向管理员显示/world unprotect与/world unblock两行。这两个命令本来就能用,语言文件里
也有它们的帮助文本,但帮助从未打印过。 -
/world loadnow brings a NETHER or THE_END world back as itself instead of as an overworld.
Reloading such a world previously reported success while rebinding it to theNORMAL
environment, so overworld terrain generated over the stored world. The environment is read from
the dimension folder the server writes inside the world folder, and it is read again every time
the command runs -- so it survives a restart, and it describes the folder as it is now rather
than as it was earlier in the session. That is what makes themove X out ->column below
something you can act on without restarting the server (#22). -
/world load现在会把下界或末地世界按其原本维度载入,而不再变为主世界。此前重新载入这类世界会提示成功,
却把世界改绑到NORMAL维度,导致主世界地形覆盖原有世界。维度读取自服务器写入世界文件夹中的维度目录,
且每次执行该命令时都会重新读取——因此重启后同样有效,并且反映文件夹当前的状态,而不是本次会话中较早时
的状态。这也是下方move X out ->一列无需重启服务器即可生效的原因(#22)。 -
/world loadnow works out a world's environment when it has to, refuses to work it out when
the world folder is ambiguous, and says in the console which of those happened and what it saw.
The console line reports what was found; it never tells you what to do, because the module has
just said it cannot read the folder. The shapes below are listed in the order the module tries
them, and the first one that matches decides — so a folder answering to more than one description,
both dimension directories and noregion, say, is the earlier shape:- shape 1 — a dimension entry that is a link leading nowhere — an unmounted volume or a moved
directory. Nothing is applied. Restore what the link points at, or replace the link with a real
directory. - shape 2 — no dimension entry at all — the ordinary overworld case. Nothing is worked out,
nothing is logged, and nothing changes from previous versions. - shape 3 — a dimension entry that is a symbolic link — the module does not follow links when
reading a world folder, so it did not read what the link points at. Nothing is applied. Because
the order above reaches this before the two shapes under it, moving other directories out cannot
help while the link is still a link; replace it with a real directory and the folder is read as
whichever shape it then matches. - shape 4 — both
DIM-1andDIM1at the top level — a single-player save or a downloaded
map, where all three dimensions share one folder. Nothing is applied. Moving the dimension
directory you do not want out leaves you in shape 5 if the folder also has a top-levelregion
directory, as a single-player save does, and in shape 6 if it does not. - shape 5 — a dimension directory AND a top-level
regiondirectory — two worlds' terrain in
one folder, which is whatUltiKits/UltiWorlds#22produced. Nothing is applied. Whichever
directory you move out, move it and do not delete it: players may have built in either one. - shape 6 — a dimension directory and no top-level
region— an ordinary nether (or end)
world, and the one shape where an environment is applied.
The outcomes are the table below rather than prose, because a test reads this table and fails if
it and the code ever disagree.folder holdslists the world folder's top-level entries,
(link)marking a symbolic link to a directory and(dangling)one whose target is missing;
appliedis the environment the server is given,nonemeaning the module supplies none and the
server uses its own default;move X out ->is what you get after moving that entry to a path
outside the world folder.folder holds applied move X out -> DIM-1NETHER DIM-1-> noneDIM1THE_END DIM1-> noneDIM-1,regionnone region-> NETHER;DIM-1-> noneDIM1,regionnone region-> THE_END;DIM1-> noneDIM-1,DIM1,regionnone DIM1-> none;DIM-1-> noneDIM-1,DIM1none DIM1-> NETHER;DIM-1-> THE_ENDDIM-1(link),regionnone region-> noneDIM-1(dangling)none DIM-1-> noneregionnone (#22)
- shape 1 — a dimension entry that is a link leading nowhere — an unmounted volume or a moved
-
/world load在需要时推断世界维度;当世界文件夹自相矛盾时则拒绝推断,并在控制台说明发生了哪一种
情况、以及它看到了什么。该控制台行只陈述观察到的事实,不会告诉你该怎么做——因为模块刚刚声明自己无法
读懂这个文件夹。下列形态按模块实际判断的顺序排列,第一个匹配的形态即为结果——因此同时符合多条描述的
文件夹(例如两个维度目录都在、又没有region)按靠前的那一条处理:- 形态 1 —— 维度目录是指向不存在位置的链接 —— 例如卷未挂载或目录被移走。不应用任何维度。请恢复
链接指向的内容,或用真实目录替换该链接。 - 形态 2 —— 完全没有维度目录条目 —— 普通主世界。不推断、不输出日志,与旧版本完全一致。
- 形态 3 —— 维度目录是符号链接 —— 本模块读取世界文件夹时不跟随链接,因此没有读取链接指向的内容。
不应用任何维度。由于上述顺序会在下面两种形态之前到达这一项,只要链接还是链接,移动其他目录都无济
于事;用真实目录替换该链接后,该文件夹会按它当时匹配的形态重新判断。 - 形态 4 —— 顶层同时有
DIM-1与DIM1—— 单人存档或下载的地图,三个维度共用一个文件夹。不应用
任何维度。移出不需要的那个维度目录后:若该文件夹还有顶层region目录(单人存档就是如此),会落到
形态 5;若没有,则落到形态 6。 - 形态 5 —— 同时有维度目录与顶层
region目录 —— 一个文件夹里存着两个世界的地形,正是
UltiKits/UltiWorlds#22造成的。不应用任何维度。无论移出哪一个目录,都请移动而不要删除:两个
目录里都可能有玩家建造的地形。 - 形态 6 —— 有维度目录且没有顶层
region—— 普通的下界(或末地)世界,也是唯一会应用维度的形态。
各形态的结果见上方英文表格,而不是散在正文里:有一项测试会读取那张表,一旦表与代码不一致即失败
(#22)。 - 形态 1 —— 维度目录是指向不存在位置的链接 —— 例如卷未挂载或目录被移走。不应用任何维度。请恢复
-
/world unloadand/world deletenow compare the name you typed againstdefault_world
without regard to letter case. Withdefault_world: lobby,/world unload LOBBYused to miss
the "Cannot unload the default world!" refusal and unload the lobby anyway, after which players
ejected from other worlds landed somewhere else; and/world delete WORLDcould be told it was
"listed in protected_worlds" when that list was empty (#20). -
/world unload与/world delete现在在与default_world比对时忽略字母大小写。此前在
default_world: lobby下,/world unload LOBBY不会触发"无法卸载默认世界!"的拒绝,仍会把
lobby 卸载,随后从其他世界被移出的玩家会落到别处;/world delete WORLD也可能被告知它"已列入
protected_worlds",而那份列表其实是空的(#20)。 -
/world deletenow refuses a world listed inprotected_worlds, as that key's own comment
("Worlds that cannot be auto-unloaded or deleted") always promised. The sender is told
"World<name>is listed in protected_worlds and cannot be deleted!" and nothing is removed —
neither the world folder nor its stored settings. With the shipped defaults this means
/world delete world_netherand/world delete world_the_endno longer permanently delete those
worlds. The refusal lives in the service rather than in the command, so any future caller
inherits it (#20). -
/world delete现在会拒绝删除列入protected_worlds的世界,兑现该配置项自身注释
("Worlds that cannot be auto-unloaded or deleted")一直以来的承诺。执行者会收到
"World<名称>is listed in protected_worlds and cannot be deleted!",并且不会移除任何内容——
世界文件夹和已保存的设置都会保留。按出厂默认配置,这意味着/world delete world_nether与
/world delete world_the_end不再永久删除这两个世界。该拒绝逻辑位于服务层而非命令层,因此今后
新增的调用方也会自动受到同一保护(#20)。 -
/world deleteno longer deletes through a symbolic link. A world folder that is itself a link
had that link followed: everything under the directory it pointed at was deleted, and only the
link entry was removed, so the command reported success for data that lived somewhere else
entirely. The module already held that a linked directory is not part of a world folder and that
only the link entry is removed — that rule covered a link found inside a world folder and not one
standing in the world folder's own position, and it now covers both. A link whose own name is not
inprotected_worldsis therefore not a route to a protected world's data. The console says when
the thing named is a link, and says it as a statement of what the command can reach rather than of
what it has already done, so the line stays true even when the link cannot be removed; a link that
could not be removed is reported as a link left in place, not as files left in a folder
(#20). -
/world delete不再沿符号链接删除。当世界文件夹本身就是一个链接时,该链接此前会被跟随:链接指向的
目录下的全部内容都会被删除,而被移除的只有链接本身,于是命令为一份存放在别处的数据报告了成功。本模块
一向认为链接目录不属于世界文件夹、只移除链接条目——此前该规则只覆盖世界文件夹内部的链接,不覆盖处于
世界文件夹自身位置的链接,现在两者都覆盖。因此,名称本身不在protected_worlds中的链接,也不再是
通往受保护世界数据的通路。当目标是链接时,控制台会说明这一点,并且以「本命令能触及什么」而非
「已经做了什么」的方式陈述,因此即使链接删除失败,该行依然成立;删除失败时报告的是「链接仍留在世界
容器中」,而不是「文件夹中还有文件残留」(#20)。 -
protected_worldsis now matched without regard to letter case, both when refusing a deletion and
when the empty-world auto-unload task skips a world. A world listed asMyWorldwhile the server
calls itmyworldis now covered by both; previously only an exact spelling matched
(#20). -
protected_worlds现在在两处读取时都忽略字母大小写:拒绝删除时,以及空世界自动卸载任务跳过世界时。
若配置写作MyWorld而服务器中的世界名为myworld,现在两处都会生效;此前只有完全一致的拼写才匹配
(#20)。 -
After
/upm uninstall UltiWorlds, this module's commands are now really removed and its
listeners stop firing. Previously this module's unload method replaced the framework's and only
logged a line, so both stayed active until the server restarted (#27). -
执行
/upm uninstall UltiWorlds后,本模块的命令现在会被真正移除,其监听器也不再触发。此前本模块的卸载
方法替换了框架的卸载方法且只输出一行日志,因此两者都会一直保持生效,直到服务器重启
(#27)。
Removed
-
The
/walias of/world.wis a vanilla command label (/msg's alias, with/tell), so
/w <player> <message>could reach this module instead of a private message. Use/worldor
/worlds(#45). -
移除
/world的别名/w。w是原版命令标签(/msg的别名,与/tell相同),因此/w <玩家> <消息>
可能被本模块接收,而不是发送私聊。请使用/world或/worlds(#45)。 -
Six
config/worlds.ymlkeys that no code ever read:gui_titleandmessages.world_teleport,
messages.world_not_found,messages.no_permission,messages.world_created,
messages.world_deleted. Changing any of them never changed anything: the world list's title and
every world message come from the language files (lang/en.yml,lang/zh.yml); to customise them, copy
the official language file to one whose name starts with its language code and a hyphen (for example
lang/en-myserver.yml), edit the entries there and setlanguage: en-myserverin
plugins/UltiTools/config.yml(an edit made in the official file itself is restored at the next start or module reload,
UltiKits/UltiTools-Reborn#616). They are gone from the shippedconfig/worlds.ymltoo, so a new server's file no
longer carries them. A leftover key in an existing file is reported at startup and on reload (see
Added) (part of #38). -
Two deprecated
config/worlds.ymlkeys that no code read:unload_empty_worlds(the key that
decides isauto_unload.enabled) andunload_delay(auto_unload.unload_after). They are gone
from the shipped file, and a leftover in an existing file is reported like the six above
(#38). -
移除
config/worlds.yml中两个从未被任何代码读取的已弃用键:unload_empty_worlds(起作用的是auto_unload.enabled)
与unload_delay(起作用的是auto_unload.unload_after)。它们已从出厂文件中删除,已有文件中残留的这两个键会像上面六个键一样被提示
(#38)。 -
38 language-file entries that no code displayed, from
lang/en.ymlandlang/zh.yml: the older
command.help.*help lines (other thanunprotect,unblock,difficultyandpostcmd, which
/world helpshows),command.usage,command.set_options, the unusedcommonwords for on and
off, theerror.*andsuccess.*lines whose messages come from other entries, the
gui.delete.confirm,gui.delete.cancelandgui.delete.warninglines (the confirmation window's
buttons come from UltiTools itself), and the fourinventory.*lines. -
移除
config/worlds.yml中从未被任何代码读取的六个键:gui_title以及messages.world_teleport、
messages.world_not_found、messages.no_permission、messages.world_created、messages.world_deleted。
修改其中任何一个都从未改变任何东西:世界列表的标题和所有世界相关消息都来自语言文件(lang/en.yml、lang/zh.yml),
要自定义,请把官方语言文件复制为以其语言代码加连字符开头的文件(例如lang/zh-myserver.yml),在副本中修改,并在
plugins/UltiTools/config.yml中设置language: zh-myserver(直接修改官方文件的改动会在下次启动或模块重载时被恢复,
UltiKits/UltiTools-Reborn#616)。随插件分发的config/worlds.yml中也已删除它们,新服务器的文件不再包含这些键。已有文件中残留的键会在启动和
重载时报告(见 Added)(#38 的一部分)。 -
从
lang/en.yml与lang/zh.yml中移除 38 条从未被任何代码显示的条目:旧的command.help.*帮助行(unprotect、
unblock、difficulty、postcmd除外,/world help会显示它们)、command.usage、command.set_options、
common中未使用的「开」「关」、其消息改由其他条目提供的error.*与success.*行、gui.delete.confirm、
gui.delete.cancel、gui.delete.warning(确认窗口的按钮由 UltiTools 自身提供),以及四条inventory.*。 -
The module's own console lines "UltiWorlds has been disabled!" on unload (and its
worlds_disabledlanguage key inlang/en.ymlandlang/zh.yml) and
"UltiWorlds configuration reloaded!" on/ul reload UltiWorlds(printed in English under either
languagesetting). UltiTools 6.3.0 logs one reload line per module
(Module 'UltiWorlds' reloaded.); reloading still re-readsconfig/worlds.ymland reports
@ConditionalOnConfigdrift, because the framework's reload method does both
(#27). -
移除本模块在卸载时输出的"UltiWorlds 已禁用!"控制台行(及
lang/en.yml、lang/zh.yml中的
worlds_disabled语言键),以及在/ul reload UltiWorlds时输出的"UltiWorlds configuration
reloaded!"控制台行(无论language设置如何均以英文输出)。UltiTools 6.3.0 会为每个模块输出一行重载日志;
重载仍会重新读取config/worlds.yml并报告@ConditionalOnConfig漂移,因为框架的重载方法会完成这两步
(#27)。