Как сделать копирование /copy и /paste логику

Как сделать копирование /copy и вставить /paste логику с асинхронными потоками
код:

<?php
namespace FastAsyncWorldEdit;

use pocketmine\plugin\PluginBase;
use pocketmine\event\Listener;
use pocketmine\command\Command;
use pocketmine\block\BlockIds;
use pocketmine\command\CommandSender;
use pocketmine\Player;
use pocketmine\math\Vector3;
use pocketmine\block\Block;
use pocketmine\scheduler\AsyncTask;
use pocketmine\Server;

class Main extends PluginBase implements Listener {

    private array $positions = [];

    public function onEnable() {
        $this->getServer()->getPluginManager()->registerEvents($this, $this);
    }

    public function onCommand(CommandSender $sender, Command $command, $label, array $args): bool {
        if (!$sender instanceof Player) {
            $sender->sendMessage("Эта команда доступна только для игроков.");
            return true;
        }

        switch ($command->getName()) {
            case "pos1":
                $this->setPlayerPosition($sender, "pos1");
                return true;

            case "pos2":
                $this->setPlayerPosition($sender, "pos2");
                return true;

            case "set":
                if (!isset($args[0])) {
                    $sender->sendMessage("Использование: /set <блок>");
                    return true;
                }

                if (!$this->arePositionsSet($sender)) {
                    $sender->sendMessage("Сначала установите обе точки с помощью //pos1 и //pos2.");
                    return true;
                }

                
                $pos1 = $this->positions[$sender->getName()]["pos1"];
                $pos2 = $this->positions[$sender->getName()]["pos2"];
                $blockId = $args[0]; 

                
                $block = Block::get($blockId);
                if ($block === null) {
                    $sender->sendMessage("Неверный блок: {$blockId}");
                    return true;
                }

                
                $this->getServer()->getScheduler()->scheduleAsyncTask(new SetBlocksTask(
                    $sender->getLevel()->getName(),
                    [$pos1->getX(), $pos1->getY(), $pos1->getZ()], 
                    [$pos2->getX(), $pos2->getY(), $pos2->getZ()],  
                    $block->getId() 
                ));

                $sender->sendMessage("Блоки будут изменены асинхронно.");
                return true;
        }

        return false;
    }

    /**
     * Устанавливает позицию игрока (pos1 или pos2).
     */
    private function setPlayerPosition(Player $player, string $positionType): void {
        $this->positions[$player->getName()][$positionType] = $player->getPosition();
        $player->sendMessage(ucfirst($positionType) . " установлена: " . $this->formatPosition($player->getPosition()));
    }

    /**
     * Проверяет, установлены ли обе позиции для игрока.
     */
    private function arePositionsSet(Player $player): bool {
        return isset($this->positions[$player->getName()]["pos1"], $this->positions[$player->getName()]["pos2"]);
    }

    /**
     * Форматирует позицию для отображения игроку.
     */
    private function formatPosition(Vector3 $pos): string {
        return "x: {$pos->getX()}, y: {$pos->getY()}, z: {$pos->getZ()}";
    }
}

class SetBlocksTask extends AsyncTask {
    private string $levelName;
    private array $pos1;
    private array $pos2;
    private int $blockId;

    public function __construct(string $levelName, array $pos1, array $pos2, int $blockId) {
        $this->levelName = $levelName;
        $this->pos1 = $pos1;
        $this->pos2 = $pos2;
        $this->blockId = $blockId;
    }

    /**
     * Выполняется в отдельном потоке для генерации списка блоков.
     */
    public function onRun() {
        
        $pos1 = new Vector3($this->pos1[0], $this->pos1[1], $this->pos1[2]);
        $pos2 = new Vector3($this->pos2[0], $this->pos2[1], $this->pos2[2]);

        $blocks = $this->generateBlocks($pos1, $pos2);
        $this->setResult($blocks);
    }

    /**
     * Генерация всех координат блоков в выбранной области.
     */
    private function generateBlocks(Vector3 $pos1, Vector3 $pos2): array {
        [$x1, $y1, $z1] = [$pos1->getX(), $pos1->getY(), $pos1->getZ()];
        [$x2, $y2, $z2] = [$pos2->getX(), $pos2->getY(), $pos2->getZ()];

       
        if ($x1 > $x2) [$x1, $x2] = [$x2, $x1];
        if ($y1 > $y2) [$y1, $y2] = [$y2, $y1];
        if ($z1 > $z2) [$z1, $z2] = [$z2, $z1];

        $blocks = [];
        for ($x = $x1; $x <= $x2; $x++) {
            for ($y = $y1; $y <= $y2; $y++) {
                for ($z = $z1; $z <= $z2; $z++) {
                    $blocks[] = [$x, $y, $z];
                }
            }
        }

        return $blocks;
    }

    /**
     * Выполняется на основном потоке после завершения задачи.
     */
    public function onCompletion(Server $server) {
        $level = $server->getLevelByName($this->levelName);
        if ($level === null) {
            return; 
        }

        foreach ($this->getResult() as [$x, $y, $z]) {
            $level->setBlock(new Vector3($x, $y, $z), Block::get($this->blockId));
        }
    }
}

?>

LiteCore 1.1.5


До тех пор пока ты не изучишь язык нормально, ты ничего не добьешься

Что это за дичь боже

В AsyncTask нету инициированного сервера, соответственно мир ты никак не получить, а уж работать с ним в тем более. serialize тоже не прокатит. Да и в целом, AsyncTask это вообще другое измерение, где без ебли мозгов ты никак не достигнешь результата.

единственный норм чел

mix max нельзя использовать