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

WorldEdit/CraftScript

来自Minecraft插件百科
Tdiant留言 | 贡献2016年1月17日 (日) 10:28的版本 →‎介绍
跳转到导航 跳转到搜索
本页面已存在其他语言的内容,请协助翻译为本地化的中文。
  • 点击此处开始翻译。
  • 如本模板出现在原文存档页面,请注意更新主页面后,仍需要去除此处该模板。
  • 如当前页面已经没有需要翻译的内容,请删去待翻译模板。
  • 有标题的大篇幅文章,如果短时间内无法全部翻译,请先把所有的标题翻译出来,以便之后的贡献者选择与翻译章节内容。


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

想要得到方块,使用基于EditSessiongetBlock()函数。你将也能得到一个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);
    }
}