- 欢迎来到Minecraft插件百科!
- 对百科编辑一脸懵逼?帮助:快速入门带您快速熟悉百科编辑!
- 因近日遭受攻击,百科现已限制编辑,有意编辑请加入插件百科企鹅群:223812289
WorldEdit/CraftScript:修订间差异
(小小的汉化了一下) |
(翻译完成,移除待翻译模板) |
||
(未显示4个用户的18个中间版本) | |||
第1行: | 第1行: | ||
[[分类:开发教程]] | |||
WorldEdit里的脚本可以让你不用Java和编译你的代码,方便地写一个操控世界的代码。这个脚本在WorldEdit中被称作''CraftScripts'' | WorldEdit里的脚本可以让你不用Java和编译你的代码,方便地写一个操控世界的代码。这个脚本在WorldEdit中被称作''CraftScripts'',并且这一切都基于JavaScript和你的'''craftscripts/''' 文件. 使用基于WorldEdit写的脚本有这些优点: | ||
* 能够与WorldEdit的 undo(撤销)/redo(反撤销) 功能对接 | * 能够与WorldEdit的 undo(撤销)/redo(反撤销) 功能对接 | ||
* 能够使用WorldEdit来优化编辑方块的操作 | * 能够使用WorldEdit来优化编辑方块的操作 | ||
* | * 允许使用WorldEdit强大的方块类型语法 //set sign:3|How|are|you? | ||
* 能够轻易获取用户选择的区域空间 | * 能够轻易获取用户选择的区域空间 | ||
此脚本需要通过Mozilla Rhino JavaScript在Java 6 或更高版本上运行。但是,如果WorldEdit的路径下有一个独立的Rhino版本,它会被优先使用。为了最大化的兼容性,请在Rhino的Java稳定版本上编写脚本。 | |||
脚本支持在v0.8时曾被移除。在v2.13后,脚本支持被重新加入。然而v0.8或更低的版本的脚本并不能兼容。 | |||
{{warning|请不要运行来自不受信任的来源的脚本。}} | |||
请查看 [http://docs.sk89q.com/ WorldEdit的API文档]. | |||
== 介绍 == | == 介绍 == | ||
第20行: | 第18行: | ||
脚本有以下在他们的命名空间中的三个变量: | 脚本有以下在他们的命名空间中的三个变量: | ||
* <code>context</code> | * <code>context</code> 是一个 [http://docs.sk89q.com/worldedit/apidocs/com/sk89q/worldedit/scripting/CraftScriptContext.html CraftScriptContext] 的实例。 | ||
* <code>player</code> | * <code>player</code> 是一个玩家的附件,是 [http://docs.sk89q.com/worldedit/apidocs/com/sk89q/worldedit/LocalPlayer.html LocalPlayer] 的实例。 | ||
* <code>argv</code> | * <code>argv</code> 是一个String类型的Java数组 | ||
想要运行一个脚本,请使用指令 /cs YourScript.js | 想要运行一个脚本,请使用指令 /cs YourScript.js | ||
第28行: | 第26行: | ||
== 在方块上工作 == | == 在方块上工作 == | ||
在WorldEdit中所有的方块编辑操作都基于一个 <code>[http://docs.sk89q.com/worldedit/apidocs/com/sk89q/worldedit/EditSession.html EditSession]</code>. | 在WorldEdit中所有的方块编辑操作都基于一个 <code>[http://docs.sk89q.com/worldedit/apidocs/com/sk89q/worldedit/EditSession.html EditSession]</code>. 这个对象会自动处理历史和方块放置的顺序。为了得到你自己的脚本的一个编辑样本,请使用: | ||
<source lang="java"> | |||
var sess = context.remember(); | var sess = context.remember(); | ||
</source> | |||
任何时候你调用这个方法,你都会得到一个新的 <code>EditSession</code>, 所以一定要保持一个左右。要设置一个方块,而不是给一个方块的物品ID。你给一个<code>[http://docs.sk89q.com/worldedit/apidocs/com/sk89q/worldedit/blocks/BaseBlock.html BaseBlock]</code>. | 任何时候你调用这个方法,你都会得到一个新的 <code>EditSession</code>, 所以一定要保持一个左右。要设置一个方块,而不是给一个方块的物品ID。你给一个<code>[http://docs.sk89q.com/worldedit/apidocs/com/sk89q/worldedit/blocks/BaseBlock.html BaseBlock]</code>. 这是因为方块包含各种各样的数据(如箱子方块里面的物品),如果只有方块类型ID的话,很多数据就会被丢失。 <code>BaseBlock</code> 与block是独立的,他并不能获取得到对象所在的世界。这意味着你可以传递一个<code>BaseBlock</code> 到任何地方并重复使用他。 <code>BaseBlock</code>们记录着方块种类和数据。对于一些复杂的方块,比如说告示牌和箱子,你可以使用<code>BaseBlock</code> 就像这样<code>[http://docs.sk89q.com/worldedit/apidocs/com/sk89q/worldedit/blocks/SignBlock.html SignBlock]</code>. | ||
举个例子:<br/> | 举个例子:<br/> | ||
设置一个带有4号颜色的羊毛方块 | |||
<br/> | <br/> | ||
< | <source lang="java"> | ||
importPackage(Packages.com.sk89q.worldedit.blocks); | importPackage(Packages.com.sk89q.worldedit.blocks); | ||
var sess = context.remember(); | var sess = context.remember(); | ||
sess.setBlock(player.getBlockOn(), new BaseBlock(BlockID.CLOTH, 4));</ | sess.setBlock(player.getBlockOn(), new BaseBlock(BlockID.CLOTH, 4));</source> | ||
标记这个是因为 <code>BaseBlock</code> 是在''com.sk89q.worldedit.blocks'' 的命名空间,它必须被引入先. <code>[http://docs.sk89q.com/worldedit/apidocs/com/sk89q/worldedit/blocks/BlockID.html BlockID]</code> 有一个方块类型的列表. <code>setBlock()</code>方法的第一个参数是一个表示在一个世界的位置的<code>[http://docs.sk89q.com/worldedit/apidocs/com/sk89q/worldedit/Vector.html Vector]</code>。 | |||
想要得到方块,使用基于<code>EditSession</code>的<code>getBlock()</code>函数。你将也能得到一个<code>BaseBlock</code>。 | 想要得到方块,使用基于<code>EditSession</code>的<code>getBlock()</code>函数。你将也能得到一个<code>BaseBlock</code>。 | ||
第48行: | 第46行: | ||
== 处理参数 == | == 处理参数 == | ||
Arguments由<code>argv</code>变量传递。如果你需要去检查用户提供的参数是不是正确的,你可以用 <code>CraftScriptContext.[http://docs.sk89q.com/worldedit/apidocs/com/sk89q/worldedit/scripting/CraftScriptContext.html#checkArgs%28int,%20int,%20java.lang.String%29 checkArgs]()</code>. | |||
举个例子:检查参数<br/> | 举个例子:检查参数<br/> | ||
< | <source lang="java">context.checkArgs(1, 3, "<block> [width] [height]");</source> | ||
如果你要去处理一个方块名字使其成为<code>BaseBlock</code>, 你可以使用 <code>CraftScriptContext.[http://docs.sk89q.com/worldedit/apidocs/com/sk89q/worldedit/scripting/CraftScriptContext.html#getBlock%28java.lang.String%29 getBlock]()</code>. 这个方法可以检查方块黑名单, however. 如果你需要一个方块去, 比如说, 替换, 你可以 ignore the blacklist by [http://docs.sk89q.com/worldedit/apidocs/com/sk89q/worldedit/scripting/CraftScriptContext.html#getBlock%28java.lang.String,%20boolean%29 adding a boolean "true" for a third parameter]. | 如果你要去处理一个方块名字使其成为<code>BaseBlock</code>, 你可以使用 <code>CraftScriptContext.[http://docs.sk89q.com/worldedit/apidocs/com/sk89q/worldedit/scripting/CraftScriptContext.html#getBlock%28java.lang.String%29 getBlock]()</code>. 这个方法可以检查方块黑名单, however. 如果你需要一个方块去, 比如说, 替换, 你可以 ignore the blacklist by [http://docs.sk89q.com/worldedit/apidocs/com/sk89q/worldedit/scripting/CraftScriptContext.html#getBlock%28java.lang.String,%20boolean%29 adding a boolean "true" for a third parameter]. | ||
举个例子:Getting the passed in block<br/> | 举个例子:Getting the passed in block<br/> | ||
< | <source lang="java"> | ||
context.checkArgs(1, 3, "<block> [width] [height]"); | context.checkArgs(1, 3, "<block> [width] [height]"); | ||
var block = context.getBlock(argv[1]); | var block = context.getBlock(argv[1]); | ||
</ | </source> | ||
如果用户输入的是一个无效的方块的话,将会抛出一个异常。并且,抛出异常后如果你没有去捕捉他,用户就会被提示这个异常,然后这个脚本就会被终止,就不会再进行下去。 | |||
== | == 配合使用Java包 == | ||
你可以通过使用以下的语法来引入一个Java包: | |||
importPackage(Packages.package.name.here); | importPackage(Packages.package.name.here); | ||
注意:如果你安装了Mozilla's Rhino库,则不需要"Packages."前缀,但为了保持在默认的Java Rhino上运行的稳定性,"Packages."前缀是推荐的。 | |||
当安装了以后,你可以使用所有Java的扩展库,以及所有WorldEdit的类。 | |||
== 例程 == | == 例程 == | ||
例子:设置附近的发射器装满箭 | 例子:设置附近的发射器装满箭 | ||
< | <source lang="java"> | ||
importPackage(Packages.com.sk89q.worldedit.blocks); | importPackage(Packages.com.sk89q.worldedit.blocks); | ||
第103行: | 第100行: | ||
} | } | ||
} | } | ||
}</ | }</source> | ||
例子: 迷宫生成脚本 | |||
< | <source lang="java"> | ||
importPackage(Packages.com.sk89q.worldedit); | importPackage(Packages.com.sk89q.worldedit); | ||
importPackage(Packages.com.sk89q.worldedit.blocks); | importPackage(Packages.com.sk89q.worldedit.blocks); | ||
第208行: | 第205行: | ||
sess.setBlock(origin.add(x * 2 - 1, 1, y * 2 - 1), block); | sess.setBlock(origin.add(x * 2 - 1, 1, y * 2 - 1), block); | ||
} | } | ||
}</ | }</source> |
2016年8月15日 (一) 12:50的最新版本
WorldEdit里的脚本可以让你不用Java和编译你的代码,方便地写一个操控世界的代码。这个脚本在WorldEdit中被称作CraftScripts,并且这一切都基于JavaScript和你的craftscripts/ 文件. 使用基于WorldEdit写的脚本有这些优点:
- 能够与WorldEdit的 undo(撤销)/redo(反撤销) 功能对接
- 能够使用WorldEdit来优化编辑方块的操作
- 允许使用WorldEdit强大的方块类型语法 //set sign:3|How|are|you?
- 能够轻易获取用户选择的区域空间
此脚本需要通过Mozilla Rhino JavaScript在Java 6 或更高版本上运行。但是,如果WorldEdit的路径下有一个独立的Rhino版本,它会被优先使用。为了最大化的兼容性,请在Rhino的Java稳定版本上编写脚本。 脚本支持在v0.8时曾被移除。在v2.13后,脚本支持被重新加入。然而v0.8或更低的版本的脚本并不能兼容。 请不要运行来自不受信任的来源的脚本。
请查看 WorldEdit的API文档.
介绍
脚本有以下在他们的命名空间中的三个变量:
context
是一个 CraftScriptContext 的实例。player
是一个玩家的附件,是 LocalPlayer 的实例。argv
是一个String类型的Java数组
想要运行一个脚本,请使用指令 /cs YourScript.js
在方块上工作
在WorldEdit中所有的方块编辑操作都基于一个 EditSession
. 这个对象会自动处理历史和方块放置的顺序。为了得到你自己的脚本的一个编辑样本,请使用:
var sess = context.remember();
任何时候你调用这个方法,你都会得到一个新的 EditSession
, 所以一定要保持一个左右。要设置一个方块,而不是给一个方块的物品ID。你给一个BaseBlock
. 这是因为方块包含各种各样的数据(如箱子方块里面的物品),如果只有方块类型ID的话,很多数据就会被丢失。 BaseBlock
与block是独立的,他并不能获取得到对象所在的世界。这意味着你可以传递一个BaseBlock
到任何地方并重复使用他。 BaseBlock
们记录着方块种类和数据。对于一些复杂的方块,比如说告示牌和箱子,你可以使用BaseBlock
就像这样SignBlock
.
举个例子:
设置一个带有4号颜色的羊毛方块
importPackage(Packages.com.sk89q.worldedit.blocks);
var sess = context.remember();
sess.setBlock(player.getBlockOn(), new BaseBlock(BlockID.CLOTH, 4));
标记这个是因为 BaseBlock
是在com.sk89q.worldedit.blocks 的命名空间,它必须被引入先. BlockID
有一个方块类型的列表. setBlock()
方法的第一个参数是一个表示在一个世界的位置的Vector
。
想要得到方块,使用基于EditSession
的getBlock()
函数。你将也能得到一个BaseBlock
。
处理参数
Arguments由argv
变量传递。如果你需要去检查用户提供的参数是不是正确的,你可以用 CraftScriptContext.checkArgs()
.
举个例子:检查参数
context.checkArgs(1, 3, "<block> [width] [height]");
如果你要去处理一个方块名字使其成为BaseBlock
, 你可以使用 CraftScriptContext.getBlock()
. 这个方法可以检查方块黑名单, however. 如果你需要一个方块去, 比如说, 替换, 你可以 ignore the blacklist by adding a boolean "true" for a third parameter.
举个例子:Getting the passed in block
context.checkArgs(1, 3, "<block> [width] [height]");
var block = context.getBlock(argv[1]);
如果用户输入的是一个无效的方块的话,将会抛出一个异常。并且,抛出异常后如果你没有去捕捉他,用户就会被提示这个异常,然后这个脚本就会被终止,就不会再进行下去。
配合使用Java包
你可以通过使用以下的语法来引入一个Java包:
importPackage(Packages.package.name.here);
注意:如果你安装了Mozilla's Rhino库,则不需要"Packages."前缀,但为了保持在默认的Java Rhino上运行的稳定性,"Packages."前缀是推荐的。 当安装了以后,你可以使用所有Java的扩展库,以及所有WorldEdit的类。
例程
例子:设置附近的发射器装满箭
importPackage(Packages.com.sk89q.worldedit.blocks);
var session = context.remember();
var origin = player.getPosition();
var arrows = new BaseItemStack(262, 64);
var items = [arrows, arrows, arrows,
arrows, arrows, arrows,
arrows, arrows, arrows]
for (var x = -4; x <= 4; x++) {
for (var y = -4; y <= 4; y++) {
for (var z = -4; z <= 4; z++) {
var pt = origin.add(x, y, z);
var id = session.getBlockType(pt);
if (id == BlockID.DISPENSER) {
var block = session.getBlock(pt);
block.setItems(items);
session.setBlock(pt, block);
player.print("Arrows set @ " + pt);
}
}
}
}
例子: 迷宫生成脚本
importPackage(Packages.com.sk89q.worldedit);
importPackage(Packages.com.sk89q.worldedit.blocks);
context.checkArgs(1, 3, "<block> [width] [height]");
var sess = context.remember();
// This may throw an exception that is caught by the script processor
var block = context.getBlock(argv[1]);
var w = argv.length > 2 ? parseInt(argv[2]) : 5;
var h = argv.length > 3 ? parseInt(argv[3]) : 5;
function id(x, y) {
return y * (w + 1) + x;
}
function $x(i) {
return i % (w + 1);
}
function $y(i) {
return Math.floor(i / (w + 1));
}
function shuffle(arr) {
var i = arr.length;
if (i == 0) return false;
while (--i) {
var j = Math.floor(Math.random() * (i + 1));
var tempi = arr[i];
var tempj = arr[j];
arr[i] = tempj;
arr[j] = tempi;
}
}
var stack = [];
var visited = {};
var noWallLeft = new Array(w * h);
var noWallAbove = new Array(w * h);
var current = 0;
stack.push(id(0, 0))
while (stack.length > 0) {
var cell = stack.pop();
var x = $x(cell), y = $y(cell);
visited[cell] = true;
var neighbors = []
if (x > 0) neighbors.push(id(x - 1, y));
if (x < w - 1) neighbors.push(id(x + 1, y));
if (y > 0) neighbors.push(id(x, y - 1));
if (y < h - 1) neighbors.push(id(x, y + 1));
shuffle(neighbors);
while (neighbors.length > 0) {
var neighbor = neighbors.pop();
var nx = $x(neighbor), ny = $y(neighbor);
if (visited[neighbor] != true) {
stack.push(cell);
if (y == ny) {
if (nx < x) {
noWallLeft[cell] = true;
} else {
noWallLeft[neighbor] = true;
}
} else {
if (ny < y) {
noWallAbove[cell] = true;
} else {
noWallAbove[neighbor] = true;
}
}
stack.push(neighbor);
break;
}
}
}
var origin = player.getBlockIn();
for (var y = 0; y <= h; y++) {
for (var x = 0; x <= w; x++) {
var cell = id(x, y)
if (!noWallLeft[cell] && y < h) {
sess.setBlock(origin.add(x * 2 - 1, 0, y * 2), block);
sess.setBlock(origin.add(x * 2 - 1, 1, y * 2), block);
}
if (!noWallAbove[cell] && x < w) {
sess.setBlock(origin.add(x * 2, 0, y * 2 - 1), block);
sess.setBlock(origin.add(x * 2, 1, y * 2 - 1), block);
}
sess.setBlock(origin.add(x * 2 - 1, 0, y * 2 - 1), block);
sess.setBlock(origin.add(x * 2 - 1, 1, y * 2 - 1), block);
}
}