【问题标题】:How to use Minecraft's WorldEdit undo stack in a Bukkit mod如何在 Bukkit mod 中使用 Minecraft 的 WorldEdit 撤消堆栈
【发布时间】:2018-08-23 03:04:43
【问题描述】:

我正在尝试在 Bukkit 模组中更新 Minecraft 中的块,并能够//undo Minecraft 中的这些更改。我可以更改块,但我不能//undo 更改。

我一定错过了一些简单的事情,因为 Google 没有帮助我找到解决方案。

这是我的模组。它将当前选定区域的单个块设置为空气。注释掉的行是我尝试过但对我不起作用的东西。

public class Main extends JavaPlugin implements Listener
{
    // ... //

    @Override
    public boolean onCommand(CommandSender sender, Command command, String label, String[] args) 
    {
        if (command.getName().equalsIgnoreCase("setair")) 
        {           
            org.bukkit.entity.Player bukkitPlayer = (org.bukkit.entity.Player) sender;  

            WorldEditPlugin worldEditPlugin = null;
            worldEditPlugin = (WorldEditPlugin) Bukkit.getServer().getPluginManager().getPlugin("WorldEdit");
            if(worldEditPlugin == null){
                bukkitPlayer.sendMessage("Error: WorldEdit is null.");   
            }
            else
            {               
                com.sk89q.worldedit.bukkit.selections.Selection s = worldEditPlugin.getSelection(bukkitPlayer);
                com.sk89q.worldedit.LocalSession localSession = worldEditPlugin.getSession(bukkitPlayer);
                com.sk89q.worldedit.world.World localWorld = localSession.getSelectionWorld();
                com.sk89q.worldedit.bukkit.BukkitPlayer wrappedPlayer = worldEditPlugin.wrapPlayer(bukkitPlayer);
                com.sk89q.worldedit.LocalPlayer localPlayer = wrappedPlayer;
                //com.sk89q.worldedit.world.World localWorld2 = localPlayer.getWorld();

                com.sk89q.worldedit.EditSession editSession = worldEditPlugin.getWorldEdit().getEditSessionFactory().getEditSession(localWorld, -1, localPlayer);
                //com.sk89q.worldedit.EditSession editSession = worldEditPlugin.createEditSession(bukkitPlayer);

                //localSession.remember(editSession);

                Vector minV = s.getNativeMinimumPoint();
                try {
                    editSession.setBlock(minV, new com.sk89q.worldedit.blocks.BaseBlock(0,0));
                } catch (MaxChangedBlocksException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }

                //try {
                //  localWorld.setBlock(minV, new com.sk89q.worldedit.blocks.BaseBlock(0,0));
                //} catch (WorldEditException e) {
                    // TODO Auto-generated catch block
                //  e.printStackTrace();
                //}


                localSession.getRegionSelector(localWorld).learnChanges();
                localSession.getRegionSelector(localWorld).explainRegionAdjust(localPlayer, localSession);

                bukkitPlayer.performCommand("tellraw @p \"Done setair\"");
            }

            return true;
        }
    }
}

编辑:这是有效的。感谢sorifiend在下面的回答。为了让它工作,我还必须将localSession.remember(editSession) 移到 setBlock 调用之后。

@Override
public boolean onCommand(CommandSender sender, Command command, String label, String[] args) 
{
    if (command.getName().equalsIgnoreCase("setair")) 
    {           
        org.bukkit.entity.Player bukkitPlayer = (org.bukkit.entity.Player) sender;  

        WorldEditPlugin worldEditPlugin = null;
        worldEditPlugin = (WorldEditPlugin) Bukkit.getServer().getPluginManager().getPlugin("WorldEdit");
        if(worldEditPlugin == null){
            bukkitPlayer.sendMessage("Error: WorldEdit is null.");   
        }
        else
        {               
            com.sk89q.worldedit.bukkit.selections.Selection s = worldEditPlugin.getSelection(bukkitPlayer);
            com.sk89q.worldedit.LocalSession localSession = worldEditPlugin.getSession(bukkitPlayer);

            com.sk89q.worldedit.EditSession editSession = worldEditPlugin.createEditSession(bukkitPlayer);

            Vector minV = s.getNativeMinimumPoint();
            try {
                editSession.setBlock(minV, new com.sk89q.worldedit.blocks.BaseBlock(0,0));
            } catch (MaxChangedBlocksException e) {
                e.printStackTrace();
            }

            localSession.remember(editSession);

            bukkitPlayer.performCommand("tellraw @p \"Done setair\"");
        }

        return true;
    }
}

现在我可以使用 WorldEdit 选择一些东西,运行 /setair 将其中一个块设置为空气。 //undo 符合您的预期。

【问题讨论】:

  • 我不明白为什么这不起作用editSession = worldEditPlugin.createEditSession(bukkitPlayer);。你得到什么样的错误?如果您按照自己的方式进行操作,则需要在设置块之前使用editSession.enableQueue();

标签: java minecraft bukkit


【解决方案1】:

我不明白为什么这不起作用editSession = worldEditPlugin.createEditSession(bukkitPlayer);,但是因为您选择了更长的方式worldEditPlugin.getWorldEdit().getEditSessionFactory().getEditSession(bukkitPlayer),所以之后您还需要使用:editSession.enableQueue();


下一个问题可能是您如何设置块。快速查看source code 中的setBlock 方法。有一个数字表明:

/**
 * Set a block, bypassing history but still utilizing block re-ordering.
 *
 * @param position the position to set the block at
 * @param block the block
 * @return whether the block changed
 */ 
 public boolean setBlock(Vector position, BlockStateHolder block) {

注意它是怎么说的“设置一个块,绕过历史记录和块重新排序”。

因此,如果您想记住块更改,您需要自己跟踪它,或者使用不同的 setBlock 方法:

/**
 * Sets the block at a position, subject to both history and block re-ordering.
 *
 * @param position the position
 * @param pattern a pattern to use
 * @return Whether the block changed -- not entirely dependable
 * @throws MaxChangedBlocksException thrown if too many blocks are changed
 */
 public boolean setBlock(Vector position, Pattern pattern)

注意它是怎么说的“将块设置在一个位置,历史记录和块重新排序”。

例如,这会将一个区块设置为空,并将保留区块历史:

Pattern pattern = new BlockPattern(BlockTypes.AIR.getDefaultState());
editSession.setBlock(minV, pattern);

现在您可以像这样稍后使用 undo 方法:

//use a different EditSession to perform the undo in:
EditSession undoSession = ......;
editSession.undo(undoSession);

请注意,undoSession 不应与您尝试撤消的会话相同。

编辑:源代码目前正在对版本 1.13 支持进行大量编辑/更改(EditSession 类已于 23 小时前更新)。因此,在继续之前,您的 WorldEdit 库/插件可能需要更新。

【讨论】:

  • 非常感谢!我使用 public boolean setBlock(Vector position, BlockStateHolder block) 是因为在 worldedit/EditSession.java 它确实没有有评论说它绕过历史。
猜你喜欢
  • 2016-08-01
  • 2021-06-04
  • 2017-10-06
  • 1970-01-01
  • 1970-01-01
  • 2017-07-19
  • 1970-01-01
  • 1970-01-01
  • 2017-03-16
相关资源
最近更新 更多