Cómo utilizar la pila de deshacer WorldEdit de Minecraft en un mod Bukkit

Ian:

Estoy intentando actualizar los bloques de Minecraft Bukkit dentro de un mod y ser capaz de //undoesos cambios dentro de Minecraft. Puedo cambiar el bloque, pero no puedo //undoel cambio.

Debo estar perdiendo algo sencillo ya que Google no me ha ayudado a encontrar una solución.

Aquí está mi mod. Se establece un único bloque de la región seleccionada actualmente al aire. Las líneas comentadas son las cosas que he intentado que no funcionó para mí.

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

EDIT: Esto es lo que funciona. Gracias sorifiend para la respuesta a continuación. Para conseguir que funcione, también tuve que mover localSession.remember(editSession)a setBlock después de la llamada.

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

Ahora puedo seleccionar algo con WorldEdit, dirigido /setaira un conjunto de los bloques a la atmósfera. Y //undohace lo que se espera.

sorifiend:

No entiendo por qué esto no funciona editSession = worldEditPlugin.createEditSession(bukkitPlayer);, sin embargo, ya que han optado por hacerlo de la manera ya worldEditPlugin.getWorldEdit().getEditSessionFactory().getEditSession(bukkitPlayer)que también tendrá a su uso: editSession.enableQueue();después.


El siguiente problema puede estar en la forma en que está configurando el bloque. Echar un vistazo rápido a los setBlockmétodos en el código fuente . hay un número de ese estado:

/**
 * 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) {

Nota cómo se dice "Establecer un bloque, sin pasar por la historia y bloque de reordenación".

Así que si quieres recordar el cambio de secuencia que se va a necesitar para realizar un seguimiento de usted mismo, o utilizar un método diferente 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)

Nota cómo se dice "Establece el bloque en una posición, sujeta a la historia y bloque de reordenación".

Por ejemplo, esto establecerá un bloque al aire y también conservará la historia de bloque:

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

Ahora se puede utilizar el método de deshacer más adelante como esto:

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

Tenga en cuenta que el undoSessionno debe ser la misma que la sesión que está tratando de deshacer.

Editar: El código fuente está pasando actualmente a través de un número de ediciones / cambios de apoyo versión 1.13 (La clase EditSession se actualizó hace 23h). Por lo que su biblioteca WorldEdit / plugin puede necesitar ponerse al día antes de continuar.

Supongo que te gusta

Origin http://43.154.161.224:23101/article/api/json?id=176865&siteId=1
Recomendado
Clasificación