• 欢迎来到Minecraft插件百科!
  • 对百科编辑一脸懵逼?帮助:快速入门带您快速熟悉百科编辑!
  • 因近日遭受攻击,百科现已限制编辑,有意编辑请加入插件百科企鹅群:223812289

“WorldEdit/CraftScript”的版本间的差异

来自Minecraft插件百科
跳转至: 导航搜索
(原文搬运)
 
(去除原文模板)
第5行: 第5行:
 
* Hook right into WorldEdit's undo/redo system
 
* Hook right into WorldEdit's undo/redo system
 
* Use WorldEdit's block place prioritization
 
* Use WorldEdit's block place prioritization
* Accept WorldEdit's powerful block type syntax ({{cmd|//set sign:3|How|are|you?}})
+
* Accept WorldEdit's powerful block type syntax //set sign:3|How|are|you?
 
* Get the region selected by the user
 
* Get the region selected by the user
  
第12行: 第12行:
 
Scripting support was re-added in v2.13 after having been removed in v0.8. However, scripts written for v0.8 and below are not compatible.  
 
Scripting support was re-added in v2.13 after having been removed in v0.8. However, scripts written for v0.8 and below are not compatible.  
  
{{warning|text=Do not run scripts from untrusted sources.}}
+
{{warning|Do not run scripts from untrusted sources.}}
  
 
Check out [http://docs.sk89q.com/ WorldEdit's API documentation].
 
Check out [http://docs.sk89q.com/ WorldEdit's API documentation].
第24行: 第24行:
 
* <code>argv</code> is a Java array of arguments as strings
 
* <code>argv</code> is a Java array of arguments as strings
  
To run scripts, use {{cmd|/cs yourscript.js}}.
+
To run scripts, use /cs yourscript.js.
  
 
== Working with blocks ==
 
== Working with blocks ==
第34行: 第34行:
 
Every time you call that method, you will get a new <code>EditSession</code>, so be sure to keep one around. To set blocks, rather than giving a block type number, you give a <code>[http://docs.sk89q.com/worldedit/apidocs/com/sk89q/worldedit/blocks/BaseBlock.html BaseBlock]</code>. The reason is that blocks contain data (and in some cases, complex data like chest contents), and if only block types were passed around, a lot of data would be lost. <code>BaseBlock</code> is an independent representation of a block; it doesn't know where it is in the world. That means that you can pass a <code>BaseBlock</code> around everywhere and reuse it. <code>BaseBlock</code>s remember block type and block data. For more complex blocks such as signs and chests, you will use a <code>BaseBlock</code> derivative such as <code>[http://docs.sk89q.com/worldedit/apidocs/com/sk89q/worldedit/blocks/SignBlock.html SignBlock]</code>.
 
Every time you call that method, you will get a new <code>EditSession</code>, so be sure to keep one around. To set blocks, rather than giving a block type number, you give a <code>[http://docs.sk89q.com/worldedit/apidocs/com/sk89q/worldedit/blocks/BaseBlock.html BaseBlock]</code>. The reason is that blocks contain data (and in some cases, complex data like chest contents), and if only block types were passed around, a lot of data would be lost. <code>BaseBlock</code> is an independent representation of a block; it doesn't know where it is in the world. That means that you can pass a <code>BaseBlock</code> around everywhere and reuse it. <code>BaseBlock</code>s remember block type and block data. For more complex blocks such as signs and chests, you will use a <code>BaseBlock</code> derivative such as <code>[http://docs.sk89q.com/worldedit/apidocs/com/sk89q/worldedit/blocks/SignBlock.html SignBlock]</code>.
  
{{example|title=Setting a cloth block with color value 4|text=<pre>importPackage(Packages.com.sk89q.worldedit.blocks);
+
Example:<br/>
 
+
Setting a cloth block with color value 4
 +
<br/>
 +
<pre>
 +
importPackage(Packages.com.sk89q.worldedit.blocks);
 
var sess = context.remember();
 
var sess = context.remember();
 
sess.setBlock(player.getBlockOn(), new BaseBlock(BlockID.CLOTH, 4));</pre>}}
 
sess.setBlock(player.getBlockOn(), new BaseBlock(BlockID.CLOTH, 4));</pre>}}
第47行: 第50行:
 
Arguments are passed in under the <code>argv</code> variable. If you need to check whether the right number of arguments was provided by the user, you can use <code>CraftScriptContext.[http://docs.sk89q.com/worldedit/apidocs/com/sk89q/worldedit/scripting/CraftScriptContext.html#checkArgs%28int,%20int,%20java.lang.String%29 checkArgs]()</code>.
 
Arguments are passed in under the <code>argv</code> variable. If you need to check whether the right number of arguments was provided by the user, you can use <code>CraftScriptContext.[http://docs.sk89q.com/worldedit/apidocs/com/sk89q/worldedit/scripting/CraftScriptContext.html#checkArgs%28int,%20int,%20java.lang.String%29 checkArgs]()</code>.
  
{{example|title=Checking arguments|text=<pre>context.checkArgs(1, 3, "<block> [width] [height]");</pre>}}
+
Exmaple:Checking arguments<br/>
 +
<pre>context.checkArgs(1, 3, "<block> [width] [height]");</pre>
  
 
If you need to resolve a block name to a <code>BaseBlock</code>, you can use <code>CraftScriptContext.[http://docs.sk89q.com/worldedit/apidocs/com/sk89q/worldedit/scripting/CraftScriptContext.html#getBlock%28java.lang.String%29 getBlock]()</code>. That method checks the block blacklist, however. If you need a block for, for example, replacing, you can 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].
 
If you need to resolve a block name to a <code>BaseBlock</code>, you can use <code>CraftScriptContext.[http://docs.sk89q.com/worldedit/apidocs/com/sk89q/worldedit/scripting/CraftScriptContext.html#getBlock%28java.lang.String%29 getBlock]()</code>. That method checks the block blacklist, however. If you need a block for, for example, replacing, you can 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].
  
{{example|title=Getting the passed in block|text=<pre>context.checkArgs(1, 3, "<block> [width] [height]");
+
Example:Getting the passed in block<br/>
var block = context.getBlock(argv[1]);</pre>}}
+
<pre>
 +
context.checkArgs(1, 3, "<block> [width] [height]");
 +
var block = context.getBlock(argv[1]);
 +
</pre>
  
 
What happens if the user inputs an invalid block? An exception will be raised and if you don't catch it, the user will be informed about their error and your script will be halted.
 
What happens if the user inputs an invalid block? An exception will be raised and if you don't catch it, the user will be informed about their error and your script will be halted.
第62行: 第69行:
 
  importPackage(Packages.package.name.here);
 
  importPackage(Packages.package.name.here);
  
{{tip|text=The "Packages." prefix is not required if you installed Mozilla's Rhino library, but to keep portability with the default bundle of Rhino in Java, it is recommended that you use it.}}
+
Tip: The "Packages." prefix is not required if you installed Mozilla's Rhino library, but to keep portability with the default bundle of Rhino in Java, it is recommended that you use it.
  
 
You have access to all of Java's vast library as it is installed. WorldEdit's classes are also fully available.
 
You have access to all of Java's vast library as it is installed. WorldEdit's classes are also fully available.
第68行: 第75行:
 
== Example scripts ==
 
== Example scripts ==
  
{{example|title=Set nearby dispensers to be filled with arrows|text=<pre>importPackage(Packages.com.sk89q.worldedit.blocks);
+
Example:Set nearby dispensers to be filled with arrows
 +
<pre>
 +
importPackage(Packages.com.sk89q.worldedit.blocks);
  
 
var session = context.remember();
 
var session = context.remember();
第94行: 第103行:
 
         }
 
         }
 
     }
 
     }
}</pre>}}
+
}</pre>
  
{{example|title=Maze generation script|text=<pre>importPackage(Packages.com.sk89q.worldedit);
+
Example: Maze generation script
 +
<pre>
 +
importPackage(Packages.com.sk89q.worldedit);
 
importPackage(Packages.com.sk89q.worldedit.blocks);
 
importPackage(Packages.com.sk89q.worldedit.blocks);
  
第197行: 第208行:
 
         sess.setBlock(origin.add(x * 2 - 1, 1, y * 2 - 1), block);
 
         sess.setBlock(origin.add(x * 2 - 1, 1, y * 2 - 1), block);
 
     }
 
     }
}</pre>}}
+
}</pre>

2015年12月20日 (日) 02:43的版本

Icon-info.png
本页面已存在其他语言的内容,请协助翻译为本地化的中文。
  • 点击此处开始翻译。
  • 如本模板出现在原文存档页面,请注意更新主页面后,仍需要去除此处该模板。
  • 如当前页面已经没有需要翻译的内容,请删去待翻译模板。
  • 有标题的大篇幅文章,如果短时间内无法全部翻译,请先把所有的标题翻译出来,以便之后的贡献者选择与翻译章节内容。


Scripting in WorldEdit allows you to write world manipulation code without having to learn Java or compile your code. Scripts, called CraftScripts in WorldEdit, and are written in JavaScript and go into your craftscripts/ directory. The advantages of writing scripts with WorldEdit are:

  • Hook right into WorldEdit's undo/redo system
  • Use WorldEdit's block place prioritization
  • Accept WorldEdit's powerful block type syntax //set sign:3|How|are|you?
  • Get the region selected by the user

The Mozilla Rhino JavaScript engine bundled with Java 6 and above is used to evaluate the scripts. However, if an independent version of Rhino is found in WorldEdit's classpath, it will be used instead. For maximum portability, write scripts for Java's built-in version of Rhino.

Scripting support was re-added in v2.13 after having been removed in v0.8. However, scripts written for v0.8 and below are not compatible.

Warning.png Do not run scripts from untrusted sources.

Check out WorldEdit's API documentation.

Introduction

Scripts have the following three variables in their global namespace:

  • context is an instance of CraftScriptContext
  • player is a copy of the player, an instance of LocalPlayer
  • argv is a Java array of arguments as strings

To run scripts, use /cs yourscript.js.

Working with blocks

All block editing in WorldEdit is done through an EditSession. This object handles history and block placement order all automatically. To get an edit session for your own script, use:

var sess = context.remember();

Every time you call that method, you will get a new EditSession, so be sure to keep one around. To set blocks, rather than giving a block type number, you give a BaseBlock. The reason is that blocks contain data (and in some cases, complex data like chest contents), and if only block types were passed around, a lot of data would be lost. BaseBlock is an independent representation of a block; it doesn't know where it is in the world. That means that you can pass a BaseBlock around everywhere and reuse it. BaseBlocks remember block type and block data. For more complex blocks such as signs and chests, you will use a BaseBlock derivative such as SignBlock.

Example:
Setting a cloth block with color value 4

importPackage(Packages.com.sk89q.worldedit.blocks);
var sess = context.remember();
sess.setBlock(player.getBlockOn(), new BaseBlock(BlockID.CLOTH, 4));

}}

Note that because BaseBlock is in the com.sk89q.worldedit.blocks namespace, it had to be imported first. BlockID has a list of block types. The first argument for setBlock() is a Vector indicating the position in the world.

To get blocks, use getBlock() on EditSession. You'll get back a BaseBlock too.

Processing arguments

Arguments are passed in under the argv variable. If you need to check whether the right number of arguments was provided by the user, you can use CraftScriptContext.checkArgs().

Exmaple:Checking arguments

context.checkArgs(1, 3, "<block> [width] [height]");

If you need to resolve a block name to a BaseBlock, you can use CraftScriptContext.getBlock(). That method checks the block blacklist, however. If you need a block for, for example, replacing, you can ignore the blacklist by adding a boolean "true" for a third parameter.

Example:Getting the passed in block

context.checkArgs(1, 3, "<block> [width] [height]");
var block = context.getBlock(argv[1]);

What happens if the user inputs an invalid block? An exception will be raised and if you don't catch it, the user will be informed about their error and your script will be halted.

Working with Java packages

To import a java package, you can use the following syntax:

importPackage(Packages.package.name.here);

Tip: The "Packages." prefix is not required if you installed Mozilla's Rhino library, but to keep portability with the default bundle of Rhino in Java, it is recommended that you use it.

You have access to all of Java's vast library as it is installed. WorldEdit's classes are also fully available.

Example scripts

Example:Set nearby dispensers to be filled with arrows

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);
            }
        }
    }
}

Example: Maze generation script

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);
    }
}