// 
// Decompiled by Procyon v0.6.0
// 

package com.hypixel.hytale.builtin.buildertools;

import java.util.UUID;
import com.hypixel.hytale.protocol.ColorLight;
import com.hypixel.hytale.server.core.modules.entity.component.PersistentDynamicLight;
import com.hypixel.hytale.server.core.modules.entity.component.DynamicLight;
import com.hypixel.hytale.protocol.InteractionType;
import com.hypixel.hytale.server.core.modules.interaction.Interactions;
import com.hypixel.hytale.server.core.modules.entity.item.PreventPickup;
import com.hypixel.hytale.server.core.modules.entity.component.Interactable;
import com.hypixel.hytale.server.core.modules.entity.component.EntityScaleComponent;
import com.hypixel.hytale.server.core.modules.entity.component.PropComponent;
import com.hypixel.hytale.builtin.buildertools.prefabeditor.PrefabEditSession;
import com.hypixel.hytale.builtin.buildertools.prefabeditor.PrefabEditSessionManager;
import com.hypixel.hytale.protocol.ModelTransform;
import com.hypixel.hytale.server.core.modules.entity.component.HeadRotation;
import com.hypixel.hytale.server.core.asset.type.buildertool.config.BrushData;
import com.hypixel.hytale.protocol.packets.buildertools.BrushOrigin;
import com.hypixel.hytale.protocol.packets.buildertools.BrushShape;
import com.hypixel.hytale.protocol.packets.buildertools.Axis;
import com.hypixel.hytale.protocol.BlockPosition;
import com.hypixel.hytale.server.core.inventory.ItemStack;
import com.hypixel.hytale.server.core.prefab.selection.mask.BlockPattern;
import com.hypixel.hytale.math.vector.Vector3f;
import com.hypixel.hytale.math.matrix.Matrix4d;
import com.hypixel.hytale.server.core.asset.type.buildertool.config.BuilderTool;
import com.hypixel.hytale.protocol.packets.interface_.BlockChange;
import com.hypixel.hytale.protocol.packets.interface_.EditorBlocksChange;
import com.hypixel.hytale.server.core.prefab.selection.standard.BlockSelection;
import com.hypixel.hytale.protocol.Packet;
import com.hypixel.hytale.protocol.packets.buildertools.BuilderToolSelectionToolReplyWithClipboard;
import com.hypixel.hytale.protocol.packets.interface_.FluidChange;
import java.util.ArrayList;
import com.hypixel.hytale.math.vector.Vector3d;
import com.hypixel.hytale.protocol.packets.buildertools.BuilderToolAction;
import com.hypixel.hytale.math.vector.Vector3i;
import com.hypixel.hytale.math.util.MathUtil;
import com.hypixel.hytale.server.core.modules.entity.component.TransformComponent;
import com.hypixel.hytale.builtin.buildertools.commands.CopyCommand;
import com.hypixel.hytale.server.core.command.commands.world.entity.EntityRemoveCommand;
import com.hypixel.hytale.server.core.command.commands.world.entity.EntityCloneCommand;
import com.hypixel.hytale.server.core.command.system.CommandSender;
import com.hypixel.hytale.server.core.command.system.CommandManager;
import com.hypixel.hytale.server.core.entity.UUIDComponent;
import com.hypixel.hytale.component.ComponentAccessor;
import com.hypixel.hytale.server.core.universe.world.World;
import com.hypixel.hytale.component.Store;
import com.hypixel.hytale.server.core.universe.PlayerRef;
import com.hypixel.hytale.builtin.buildertools.tooloperations.ToolOperation;
import java.util.logging.Level;
import com.hypixel.hytale.component.Ref;
import com.hypixel.hytale.server.core.universe.world.storage.EntityStore;
import com.hypixel.hytale.server.core.Message;
import javax.annotation.Nonnull;
import com.hypixel.hytale.server.core.entity.entities.Player;
import com.hypixel.hytale.protocol.packets.buildertools.BuilderToolSetNPCDebug;
import com.hypixel.hytale.protocol.packets.buildertools.BuilderToolSetEntityLight;
import com.hypixel.hytale.protocol.packets.buildertools.BuilderToolSetEntityPickupEnabled;
import com.hypixel.hytale.protocol.packets.buildertools.PrefabUnselectPrefab;
import com.hypixel.hytale.protocol.packets.buildertools.BuilderToolSetTransformationModeState;
import com.hypixel.hytale.protocol.packets.buildertools.BuilderToolStackArea;
import com.hypixel.hytale.protocol.packets.buildertools.BuilderToolSelectionTransform;
import com.hypixel.hytale.protocol.packets.buildertools.BuilderToolSetEntityScale;
import com.hypixel.hytale.protocol.packets.buildertools.BuilderToolSetEntityTransform;
import com.hypixel.hytale.protocol.packets.buildertools.BuilderToolLineAction;
import com.hypixel.hytale.protocol.packets.buildertools.BuilderToolSelectionToolAskForClipboard;
import com.hypixel.hytale.protocol.packets.buildertools.BuilderToolOnUseInteraction;
import com.hypixel.hytale.protocol.packets.buildertools.BuilderToolPasteClipboard;
import com.hypixel.hytale.protocol.packets.buildertools.BuilderToolRotateClipboard;
import com.hypixel.hytale.protocol.packets.buildertools.BuilderToolExtrudeAction;
import com.hypixel.hytale.protocol.packets.buildertools.BuilderToolSelectionUpdate;
import com.hypixel.hytale.protocol.packets.buildertools.BuilderToolGeneralAction;
import com.hypixel.hytale.protocol.packets.buildertools.BuilderToolEntityAction;
import com.hypixel.hytale.protocol.packets.buildertools.BuilderToolArgUpdate;
import com.hypixel.hytale.protocol.packets.player.SaveHotbar;
import com.hypixel.hytale.protocol.packets.player.LoadHotbar;
import com.hypixel.hytale.server.core.io.handlers.IPacketHandler;
import com.hypixel.hytale.logger.HytaleLogger;
import com.hypixel.hytale.server.core.io.handlers.SubPacketHandler;

public class BuilderToolsPacketHandler implements SubPacketHandler
{
    private static final HytaleLogger LOGGER;
    private final IPacketHandler packetHandler;
    static final /* synthetic */ boolean $assertionsDisabled;
    
    public BuilderToolsPacketHandler(final IPacketHandler packetHandler) {
        this.packetHandler = packetHandler;
    }
    
    @Override
    public void registerHandlers() {
        if (BuilderToolsPlugin.get().isDisabled()) {
            this.packetHandler.registerNoOpHandlers(400, 401, 412, 409, 403, 406, 407, 413, 414, 417);
            return;
        }
        this.packetHandler.registerHandler(106, p -> this.handle((LoadHotbar)p));
        this.packetHandler.registerHandler(107, p -> this.handle((SaveHotbar)p));
        this.packetHandler.registerHandler(400, p -> this.handle((BuilderToolArgUpdate)p));
        this.packetHandler.registerHandler(401, p -> this.handle((BuilderToolEntityAction)p));
        this.packetHandler.registerHandler(412, p -> this.handle((BuilderToolGeneralAction)p));
        this.packetHandler.registerHandler(409, p -> this.handle((BuilderToolSelectionUpdate)p));
        this.packetHandler.registerHandler(403, p -> this.handle((BuilderToolExtrudeAction)p));
        this.packetHandler.registerHandler(406, p -> this.handle((BuilderToolRotateClipboard)p));
        this.packetHandler.registerHandler(407, p -> this.handle((BuilderToolPasteClipboard)p));
        this.packetHandler.registerHandler(413, p -> this.handle((BuilderToolOnUseInteraction)p));
        this.packetHandler.registerHandler(410, p -> this.handle((BuilderToolSelectionToolAskForClipboard)p));
        this.packetHandler.registerHandler(414, p -> this.handle((BuilderToolLineAction)p));
        this.packetHandler.registerHandler(402, p -> this.handle((BuilderToolSetEntityTransform)p));
        this.packetHandler.registerHandler(420, p -> this.handle((BuilderToolSetEntityScale)p));
        this.packetHandler.registerHandler(405, p -> this.handle((BuilderToolSelectionTransform)p));
        this.packetHandler.registerHandler(404, p -> this.handle((BuilderToolStackArea)p));
        this.packetHandler.registerHandler(408, p -> this.handle((BuilderToolSetTransformationModeState)p));
        this.packetHandler.registerHandler(417, p -> this.handle((PrefabUnselectPrefab)p));
        this.packetHandler.registerHandler(421, p -> this.handle((BuilderToolSetEntityPickupEnabled)p));
        this.packetHandler.registerHandler(422, p -> this.handle((BuilderToolSetEntityLight)p));
        this.packetHandler.registerHandler(423, p -> this.handle((BuilderToolSetNPCDebug)p));
    }
    
    static boolean hasPermission(@Nonnull final Player player) {
        if (!player.hasPermission("hytale.editor.builderTools")) {
            player.sendMessage(Message.translation("server.builderTools.usageDenied"));
            return false;
        }
        return true;
    }
    
    static boolean hasPermission(@Nonnull final Player player, @Nonnull final String permission) {
        if (player.hasPermission(permission) || player.hasPermission("hytale.editor.builderTools")) {
            return true;
        }
        player.sendMessage(Message.translation("server.builderTools.usageDenied"));
        return false;
    }
    
    public void handle(@Nonnull final BuilderToolSetTransformationModeState packet) {
        final PlayerRef playerRef = this.packetHandler.getPlayerRef();
        final Ref<EntityStore> ref = playerRef.getReference();
        if (ref == null || !ref.isValid()) {
            throw new RuntimeException("Unable to process BuilderToolSetTransformationModeState packet. Player ref is invalid!");
        }
        final Store<EntityStore> store = ref.getStore();
        final World world = store.getExternalData().getWorld();
        world.execute(() -> {
            final Player playerComponent = store.getComponent(ref, Player.getComponentType());
            if (!(!hasPermission(playerComponent))) {
                BuilderToolsPacketHandler.LOGGER.at(Level.INFO).log("%s: %s", this.packetHandler.getIdentifier(), packet);
                ToolOperation.getOrCreatePrototypeSettings(playerRef.getUuid()).setInSelectionTransformationMode(packet.enabled);
            }
        });
    }
    
    public void handle(@Nonnull final BuilderToolArgUpdate packet) {
        final PlayerRef playerRef = this.packetHandler.getPlayerRef();
        final Ref<EntityStore> ref = playerRef.getReference();
        if (ref == null || !ref.isValid()) {
            throw new RuntimeException("Unable to process BuilderToolArgUpdate packet. Player ref is invalid!");
        }
        final Store<EntityStore> store = ref.getStore();
        final World world = store.getExternalData().getWorld();
        world.execute(() -> {
            final Player playerComponent = store.getComponent(ref, Player.getComponentType());
            if (!(!hasPermission(playerComponent, "hytale.editor.brush.config"))) {
                BuilderToolsPlugin.get().onToolArgUpdate(playerRef, playerComponent, packet);
            }
        });
    }
    
    public void handle(@Nonnull final LoadHotbar packet) {
        final PlayerRef playerRef = this.packetHandler.getPlayerRef();
        final Ref<EntityStore> ref = playerRef.getReference();
        if (ref == null || !ref.isValid()) {
            throw new RuntimeException("Unable to process LoadHotbar packet. Player ref is invalid!");
        }
        final Store<EntityStore> store = ref.getStore();
        final World world = store.getExternalData().getWorld();
        world.execute(() -> {
            final Player playerComponent = store.getComponent(ref, Player.getComponentType());
            if (!BuilderToolsPacketHandler.$assertionsDisabled && playerComponent == null) {
                throw new AssertionError();
            }
            else {
                playerComponent.getHotbarManager().loadHotbar(ref, packet.inventoryRow, store);
            }
        });
    }
    
    public void handle(@Nonnull final SaveHotbar packet) {
        final PlayerRef playerRef = this.packetHandler.getPlayerRef();
        final Ref<EntityStore> ref = playerRef.getReference();
        if (ref == null || !ref.isValid()) {
            throw new RuntimeException("Unable to process SaveHotbar packet. Player ref is invalid!");
        }
        final Store<EntityStore> store = ref.getStore();
        final World world = store.getExternalData().getWorld();
        world.execute(() -> {
            final Player playerComponent = store.getComponent(ref, Player.getComponentType());
            if (!BuilderToolsPacketHandler.$assertionsDisabled && playerComponent == null) {
                throw new AssertionError();
            }
            else {
                playerComponent.getHotbarManager().saveHotbar(ref, packet.inventoryRow, store);
            }
        });
    }
    
    public void handle(@Nonnull final BuilderToolEntityAction packet) {
        final PlayerRef playerRef = this.packetHandler.getPlayerRef();
        final Ref<EntityStore> ref = playerRef.getReference();
        if (ref == null || !ref.isValid()) {
            throw new RuntimeException("Unable to process BuilderToolEntityAction packet. Player ref is invalid!");
        }
        final Store<EntityStore> store = ref.getStore();
        final World world = store.getExternalData().getWorld();
        world.execute(() -> {
            final Player playerComponent = store.getComponent(ref, Player.getComponentType());
            if (!(!hasPermission(playerComponent))) {
                final int entityId = packet.entityId;
                final Ref<EntityStore> entityReference = world.getEntityStore().getRefFromNetworkId(entityId);
                if (entityReference == null) {
                    playerComponent.sendMessage(Message.translation("server.general.entityNotFound").param("id", entityId));
                }
                else {
                    final Player targetPlayerComponent = store.getComponent(entityReference, Player.getComponentType());
                    if (targetPlayerComponent != null) {
                        playerComponent.sendMessage(Message.translation("server.builderTools.entityTool.cannotTargetPlayer"));
                    }
                    else {
                        BuilderToolsPacketHandler.LOGGER.at(Level.INFO).log("%s: %s", this.packetHandler.getIdentifier(), packet);
                        switch (packet.action) {
                            case Freeze: {
                                final UUIDComponent uuidComponent = store.getComponent(entityReference, UUIDComponent.getComponentType());
                                if (uuidComponent != null) {
                                    CommandManager.get().handleCommand((CommandSender)playerComponent, "npc freeze --toggle --entity " + String.valueOf(uuidComponent.getUuid()));
                                    break;
                                }
                                else {
                                    break;
                                }
                                break;
                            }
                            case Clone: {
                                world.execute(() -> EntityCloneCommand.cloneEntity(playerComponent, entityReference, store));
                                break;
                            }
                            case Remove: {
                                world.execute(() -> EntityRemoveCommand.removeEntity(ref, entityReference, store));
                                break;
                            }
                        }
                    }
                }
            }
        });
    }
    
    public void handle(@Nonnull final BuilderToolGeneralAction packet) {
        final PlayerRef playerRef = this.packetHandler.getPlayerRef();
        final Ref<EntityStore> ref = playerRef.getReference();
        if (ref == null || !ref.isValid()) {
            throw new RuntimeException("Unable to process BuilderToolGeneralAction packet. Player ref is invalid!");
        }
        final Store<EntityStore> store = ref.getStore();
        final World world = store.getExternalData().getWorld();
        world.execute(() -> {
            final Player playerComponent = store.getComponent(ref, Player.getComponentType());
            if (!BuilderToolsPacketHandler.$assertionsDisabled && playerComponent == null) {
                throw new AssertionError();
            }
            else {
                BuilderToolsPacketHandler.LOGGER.at(Level.INFO).log("%s: %s", this.packetHandler.getIdentifier(), packet);
                switch (packet.action) {
                    case HistoryUndo: {
                        if (!hasPermission(playerComponent, "hytale.editor.history")) {
                            return;
                        }
                        else {
                            BuilderToolsPlugin.addToQueue(playerComponent, playerRef, (r, s, componentAccessor) -> s.undo(r, 1, componentAccessor));
                            break;
                        }
                        break;
                    }
                    case HistoryRedo: {
                        if (!hasPermission(playerComponent, "hytale.editor.history")) {
                            return;
                        }
                        else {
                            BuilderToolsPlugin.addToQueue(playerComponent, playerRef, (r, s, componentAccessor) -> s.redo(r, 1, componentAccessor));
                            break;
                        }
                        break;
                    }
                    case SelectionCopy: {
                        if (!hasPermission(playerComponent, "hytale.editor.selection.clipboard")) {
                            return;
                        }
                        else {
                            CopyCommand.copySelection(ref, store);
                            break;
                        }
                        break;
                    }
                    case SelectionPosition1:
                    case SelectionPosition2: {
                        if (!hasPermission(playerComponent, "hytale.editor.selection.use")) {
                            return;
                        }
                        else {
                            final TransformComponent transformComponent = store.getComponent(ref, TransformComponent.getComponentType());
                            final BuilderToolsPlugin.BuilderState builderState = BuilderToolsPlugin.getState(playerComponent, playerRef);
                            final Vector3d position = transformComponent.getPosition();
                            final Vector3i intTriple = new Vector3i(MathUtil.floor(position.getX()), MathUtil.floor(position.getY()), MathUtil.floor(position.getZ()));
                            BuilderToolsPlugin.addToQueue(playerComponent, playerRef, (r, s, componentAccessor) -> {
                                if (packet.action == BuilderToolAction.SelectionPosition1) {
                                    builderState.pos1(intTriple, componentAccessor);
                                }
                                else {
                                    builderState.pos2(intTriple, componentAccessor);
                                }
                                return;
                            });
                            break;
                        }
                        break;
                    }
                    case ActivateToolMode: {
                        if (!hasPermission(playerComponent)) {
                            return;
                        }
                        else {
                            playerComponent.getInventory().setUsingToolsItem(true);
                            break;
                        }
                        break;
                    }
                    case DeactivateToolMode: {
                        if (!hasPermission(playerComponent)) {
                            return;
                        }
                        else {
                            playerComponent.getInventory().setUsingToolsItem(false);
                            break;
                        }
                        break;
                    }
                }
            }
        });
    }
    
    public void handle(@Nonnull final BuilderToolSelectionUpdate packet) {
        final PlayerRef playerRef = this.packetHandler.getPlayerRef();
        final Ref<EntityStore> ref = playerRef.getReference();
        if (ref == null || !ref.isValid()) {
            throw new RuntimeException("Unable to process BuilderToolSelectionUpdate packet. Player ref is invalid!");
        }
        final Store<EntityStore> store = ref.getStore();
        final World world = store.getExternalData().getWorld();
        world.execute(() -> {
            final Player playerComponent = store.getComponent(ref, Player.getComponentType());
            if (!(!hasPermission(playerComponent, "hytale.editor.selection.use"))) {
                BuilderToolsPacketHandler.LOGGER.at(Level.INFO).log("%s: %s", this.packetHandler.getIdentifier(), packet);
                BuilderToolsPlugin.addToQueue(playerComponent, playerRef, (r, s, componentAccessor) -> s.update(packet.xMin, packet.yMin, packet.zMin, packet.xMax, packet.yMax, packet.zMax));
            }
        });
    }
    
    public void handle(final BuilderToolSelectionToolAskForClipboard packet) {
        final PlayerRef playerRef = this.packetHandler.getPlayerRef();
        final Ref<EntityStore> ref = playerRef.getReference();
        if (ref == null || !ref.isValid()) {
            throw new RuntimeException("Unable to process BuilderToolSelectionToolAskForClipboard packet. Player ref is invalid!");
        }
        final Store<EntityStore> store = ref.getStore();
        final World world = store.getExternalData().getWorld();
        world.execute(() -> {
            final Player playerComponent = store.getComponent(ref, Player.getComponentType());
            if (!(!hasPermission(playerComponent, "hytale.editor.selection.clipboard"))) {
                BuilderToolsPacketHandler.LOGGER.at(Level.INFO).log("%s: %s", this.packetHandler.getIdentifier(), packet);
                final PrototypePlayerBuilderToolSettings prototypeSettings = ToolOperation.getOrCreatePrototypeSettings(playerRef.getUuid());
                BuilderToolsPlugin.addToQueue(playerComponent, playerRef, (r, s, componentAccessor) -> {
                    final BlockSelection selection = s.getSelection();
                    if (selection != null) {
                        final EditorBlocksChange editorPacket = selection.toPacket();
                        final BlockChange[] blocksChange = editorPacket.blocksChange;
                        prototypeSettings.setBlockChangesForPlaySelectionToolPasteMode(blocksChange);
                        final ArrayList<PrototypePlayerBuilderToolSettings.FluidChange> fluidChanges = new ArrayList<PrototypePlayerBuilderToolSettings.FluidChange>();
                        final int anchorX = selection.getAnchorX();
                        final int anchorY = selection.getAnchorY();
                        final int anchorZ = selection.getAnchorZ();
                        selection.forEachFluid((x, y, z, fluidId, fluidLevel) -> fluidChanges.add(new PrototypePlayerBuilderToolSettings.FluidChange(x - anchorX, y - anchorY, z - anchorZ, fluidId, fluidLevel)));
                        final PrototypePlayerBuilderToolSettings.FluidChange[] fluidChangesArray = fluidChanges.toArray(PrototypePlayerBuilderToolSettings.FluidChange[]::new);
                        prototypeSettings.setFluidChangesForPlaySelectionToolPasteMode(fluidChangesArray);
                        final FluidChange[] packetFluids = new FluidChange[fluidChangesArray.length];
                        for (int i = 0; i < fluidChangesArray.length; ++i) {
                            final PrototypePlayerBuilderToolSettings.FluidChange fc = fluidChangesArray[i];
                            packetFluids[i] = new FluidChange(fc.x(), fc.y(), fc.z(), fc.fluidId(), fc.fluidLevel());
                        }
                        playerRef.getPacketHandler().write(new BuilderToolSelectionToolReplyWithClipboard(blocksChange, packetFluids));
                    }
                });
            }
        });
    }
    
    public int toInt(final float value) {
        return (int)Math.floor(value + 0.1);
    }
    
    private void handle(@Nonnull final BuilderToolSelectionTransform packet) {
        final PlayerRef playerRef = this.packetHandler.getPlayerRef();
        final Ref<EntityStore> ref = playerRef.getReference();
        if (ref == null || !ref.isValid()) {
            throw new RuntimeException("Unable to process BuilderToolSelectionTransform packet. Player ref is invalid!");
        }
        final Store<EntityStore> store = ref.getStore();
        final World world = store.getExternalData().getWorld();
        world.execute(() -> {
            final Player playerComponent = store.getComponent(ref, Player.getComponentType());
            if (!(!hasPermission(playerComponent, "hytale.editor.selection.clipboard"))) {
                BuilderToolsPacketHandler.LOGGER.at(Level.INFO).log("%s: %s", this.packetHandler.getIdentifier(), packet);
                boolean keepEmptyBlocks = true;
                final BuilderTool builderTool = BuilderTool.getActiveBuilderTool(playerComponent);
                if (builderTool != null && builderTool.getId().equals("Selection")) {
                    final BuilderTool.ArgData args = builderTool.getItemArgData(playerComponent.getInventory().getItemInHand());
                    if (args != null && args.tool() != null) {
                        keepEmptyBlocks = args.tool().getOrDefault("KeepEmptyBlocks", true);
                    }
                }
                final boolean finalKeepEmptyBlocks = keepEmptyBlocks;
                final float[] tmx = new float[16];
                for (int i = 0; i < packet.transformationMatrix.length; ++i) {
                    tmx[i] = (float)this.toInt(packet.transformationMatrix[i]);
                }
                final Matrix4d transformationMatrix = new Matrix4d().assign(tmx[0], tmx[4], tmx[8], tmx[12], tmx[1], tmx[5], tmx[9], tmx[13], tmx[2], tmx[6], tmx[10], tmx[14], tmx[3], tmx[7], tmx[11], tmx[15]);
                final Vector3i initialSelectionMin = new Vector3i(packet.initialSelectionMin.x, packet.initialSelectionMin.y, packet.initialSelectionMin.z);
                final Vector3i initialSelectionMax = new Vector3i(packet.initialSelectionMax.x, packet.initialSelectionMax.y, packet.initialSelectionMax.z);
                final Vector3f rotationOrigin = new Vector3f(packet.initialRotationOrigin.x, packet.initialRotationOrigin.y, packet.initialRotationOrigin.z);
                final PrototypePlayerBuilderToolSettings prototypeSettings = ToolOperation.getOrCreatePrototypeSettings(playerRef.getUuid());
                BuilderToolsPlugin.addToQueue(playerComponent, playerRef, (r, s, componentAccessor) -> {
                    final int blockCount = s.getSelection().getSelectionVolume();
                    final boolean large = blockCount > 20000;
                    if (large) {
                        playerComponent.sendMessage(Message.translation("server.builderTools.selection.large.warning"));
                    }
                    if (prototypeSettings.getBlockChangesForPlaySelectionToolPasteMode() == null) {
                        s.select(initialSelectionMin, initialSelectionMax, "SelectionTranslatePacket", componentAccessor);
                        if (packet.cutOriginal) {
                            s.copyOrCut(r, initialSelectionMin.x, initialSelectionMin.y, initialSelectionMin.z, initialSelectionMax.x, initialSelectionMax.y, initialSelectionMax.z, 138, store);
                        }
                        else {
                            s.copyOrCut(r, initialSelectionMin.x, initialSelectionMin.y, initialSelectionMin.z, initialSelectionMax.x, initialSelectionMax.y, initialSelectionMax.z, 136, store);
                        }
                        final BlockSelection selection = s.getSelection();
                        final BlockChange[] blocksChange = selection.toPacket().blocksChange;
                        prototypeSettings.setBlockChangesForPlaySelectionToolPasteMode(blocksChange);
                        final ArrayList<PrototypePlayerBuilderToolSettings.FluidChange> fluidChanges = new ArrayList<PrototypePlayerBuilderToolSettings.FluidChange>();
                        final int anchorX = selection.getAnchorX();
                        final int anchorY = selection.getAnchorY();
                        final int anchorZ = selection.getAnchorZ();
                        selection.forEachFluid((x, y, z, fluidId, fluidLevel) -> fluidChanges.add(new PrototypePlayerBuilderToolSettings.FluidChange(x - anchorX, y - anchorY, z - anchorZ, fluidId, fluidLevel)));
                        prototypeSettings.setFluidChangesForPlaySelectionToolPasteMode(fluidChanges.toArray(PrototypePlayerBuilderToolSettings.FluidChange[]::new));
                        prototypeSettings.setBlockChangeOffsetOrigin(new Vector3i(selection.getX(), selection.getY(), selection.getZ()));
                    }
                    Vector3i blockChangeOffsetOrigin = prototypeSettings.getBlockChangeOffsetOrigin();
                    if (packet.initialPastePointForClipboardPaste != null) {
                        blockChangeOffsetOrigin = new Vector3i(packet.initialPastePointForClipboardPaste.x, packet.initialPastePointForClipboardPaste.y, packet.initialPastePointForClipboardPaste.z);
                    }
                    if (blockChangeOffsetOrigin == null) {
                        playerComponent.sendMessage(Message.translation("server.builderTools.selection.noBlockChangeOffsetOrigin"));
                    }
                    else {
                        s.transformThenPasteClipboard(prototypeSettings.getBlockChangesForPlaySelectionToolPasteMode(), prototypeSettings.getFluidChangesForPlaySelectionToolPasteMode(), transformationMatrix, rotationOrigin, blockChangeOffsetOrigin, finalKeepEmptyBlocks, componentAccessor);
                        s.select(initialSelectionMin, initialSelectionMax, "SelectionTranslatePacket", componentAccessor);
                        s.transformSelectionPoints(transformationMatrix, rotationOrigin);
                        if (large) {
                            playerComponent.sendMessage(Message.translation("server.builderTools.selection.large.complete"));
                        }
                        if (packet.isExitingTransformMode) {
                            prototypeSettings.setInSelectionTransformationMode(false);
                        }
                    }
                });
            }
        });
    }
    
    public void handle(@Nonnull final BuilderToolExtrudeAction packet) {
        final PlayerRef playerRef = this.packetHandler.getPlayerRef();
        final Ref<EntityStore> ref = playerRef.getReference();
        if (ref == null || !ref.isValid()) {
            throw new RuntimeException("Unable to process BuilderToolExtrudeAction packet. Player ref is invalid!");
        }
        final Store<EntityStore> store = ref.getStore();
        final World world = store.getExternalData().getWorld();
        world.execute(() -> {
            final Player playerComponent = store.getComponent(ref, Player.getComponentType());
            if (!(!hasPermission(playerComponent, "hytale.editor.selection.modify"))) {
                final BuilderTool builderTool = BuilderTool.getActiveBuilderTool(playerComponent);
                if (builderTool != null && builderTool.getId().equals("Extrude")) {
                    final ItemStack activeItemStack = playerComponent.getInventory().getItemInHand();
                    final BuilderTool.ArgData args = builderTool.getItemArgData(activeItemStack);
                    final int extrudeDepth = args.tool().get("ExtrudeDepth");
                    final int extrudeRadius = args.tool().get("ExtrudeRadius");
                    final int blockId = args.tool().get("ExtrudeMaterial").firstBlock();
                    BuilderToolsPacketHandler.LOGGER.at(Level.INFO).log("%s: %s", this.packetHandler.getIdentifier(), packet);
                    BuilderToolsPlugin.addToQueue(playerComponent, playerRef, (r, s, componentAccessor) -> s.extendFace(packet.x, packet.y, packet.z, packet.xNormal, packet.yNormal, packet.zNormal, extrudeDepth, extrudeRadius, blockId, null, null, componentAccessor));
                }
            }
        });
    }
    
    public void handle(@Nonnull final BuilderToolStackArea packet) {
        final PlayerRef playerRef = this.packetHandler.getPlayerRef();
        final Ref<EntityStore> ref = playerRef.getReference();
        if (ref == null || !ref.isValid()) {
            throw new RuntimeException("Unable to process BuilderToolStackArea packet. Player ref is invalid!");
        }
        final Store<EntityStore> store = ref.getStore();
        final World world = store.getExternalData().getWorld();
        world.execute(() -> {
            final Player playerComponent = store.getComponent(ref, Player.getComponentType());
            if (!BuilderToolsPacketHandler.$assertionsDisabled && playerComponent == null) {
                throw new AssertionError();
            }
            else if (!(!hasPermission(playerComponent, "hytale.editor.selection.clipboard"))) {
                BuilderToolsPacketHandler.LOGGER.at(Level.INFO).log("%s: %s", this.packetHandler.getIdentifier(), packet);
                BuilderToolsPlugin.addToQueue(playerComponent, playerRef, (r, s, componentAccessor) -> {
                    s.select(this.fromBlockPosition(packet.selectionMin), this.fromBlockPosition(packet.selectionMax), "Extrude", componentAccessor);
                    s.stack(r, new Vector3i(packet.xNormal, packet.yNormal, packet.zNormal), packet.numStacks, true, 0, componentAccessor);
                });
            }
        });
    }
    
    @Nonnull
    public Vector3i fromBlockPosition(@Nonnull final BlockPosition position) {
        return new Vector3i(position.x, position.y, position.z);
    }
    
    public void handle(@Nonnull final BuilderToolRotateClipboard packet) {
        final PlayerRef playerRef = this.packetHandler.getPlayerRef();
        final Ref<EntityStore> ref = playerRef.getReference();
        if (ref == null || !ref.isValid()) {
            throw new RuntimeException("Unable to process BuilderToolPasteClipboard packet. Player ref is invalid!");
        }
        final Store<EntityStore> store = ref.getStore();
        final World world = store.getExternalData().getWorld();
        world.execute(() -> {
            final Player playerComponent = store.getComponent(ref, Player.getComponentType());
            if (!(!hasPermission(playerComponent, "hytale.editor.selection.clipboard"))) {
                final com.hypixel.hytale.math.Axis axis = (packet.axis == Axis.X) ? com.hypixel.hytale.math.Axis.X : ((packet.axis == Axis.Y) ? com.hypixel.hytale.math.Axis.Y : com.hypixel.hytale.math.Axis.Z);
                BuilderToolsPacketHandler.LOGGER.at(Level.INFO).log("%s: %s", this.packetHandler.getIdentifier(), packet);
                BuilderToolsPlugin.addToQueue(playerComponent, playerRef, (r, s, componentAccessor) -> s.rotate(r, axis, packet.angle, componentAccessor));
            }
        });
    }
    
    public void handle(@Nonnull final BuilderToolPasteClipboard packet) {
        final PlayerRef playerRef = this.packetHandler.getPlayerRef();
        final Ref<EntityStore> ref = playerRef.getReference();
        if (ref == null || !ref.isValid()) {
            throw new RuntimeException("Unable to process BuilderToolPasteClipboard packet. Player ref is invalid!");
        }
        final Store<EntityStore> store = ref.getStore();
        final World world = store.getExternalData().getWorld();
        world.execute(() -> {
            final Player playerComponent = store.getComponent(ref, Player.getComponentType());
            if (!(!hasPermission(playerComponent, "hytale.editor.selection.clipboard"))) {
                BuilderToolsPacketHandler.LOGGER.at(Level.INFO).log("%s: %s", this.packetHandler.getIdentifier(), packet);
                BuilderToolsPlugin.addToQueue(playerComponent, playerRef, (r, s, componentAccessor) -> s.paste(r, packet.x, packet.y, packet.z, componentAccessor));
            }
        });
    }
    
    public void handle(@Nonnull final BuilderToolLineAction packet) {
        final PlayerRef playerRef = this.packetHandler.getPlayerRef();
        final Ref<EntityStore> ref = playerRef.getReference();
        if (ref == null || !ref.isValid()) {
            throw new RuntimeException("Unable to process BuilderToolLineAction packet. Player ref is invalid!");
        }
        final Store<EntityStore> store = ref.getStore();
        final World world = store.getExternalData().getWorld();
        world.execute(() -> {
            final Player playerComponent = store.getComponent(ref, Player.getComponentType());
            if (!(!hasPermission(playerComponent, "hytale.editor.brush.use"))) {
                final BuilderTool builderTool = BuilderTool.getActiveBuilderTool(playerComponent);
                if (builderTool != null && builderTool.getId().equals("Line")) {
                    final BuilderTool.ArgData args = builderTool.getItemArgData(playerComponent.getInventory().getItemInHand());
                    final BrushData.Values brushData = args.brush();
                    final int lineWidth = args.tool().get("bLineWidth");
                    final int lineHeight = args.tool().get("cLineHeight");
                    final BrushShape lineShape = BrushShape.valueOf(args.tool().get("dLineShape"));
                    final BrushOrigin lineOrigin = BrushOrigin.valueOf(args.tool().get("eLineOrigin"));
                    final int lineWallThickness = args.tool().get("fLineWallThickness");
                    final int lineSpacing = args.tool().get("gLineSpacing");
                    final int lineDensity = args.tool().get("hLineDensity");
                    final BlockPattern lineMaterial = args.tool().get("aLineMaterial");
                    BuilderToolsPacketHandler.LOGGER.at(Level.INFO).log("%s: %s", this.packetHandler.getIdentifier(), packet);
                    BuilderToolsPlugin.addToQueue(playerComponent, playerRef, (r, s, componentAccessor) -> s.editLine(packet.xStart, packet.yStart, packet.zStart, packet.xEnd, packet.yEnd, packet.zEnd, lineMaterial, lineWidth, lineHeight, lineWallThickness, lineShape, lineOrigin, lineSpacing, lineDensity, ToolOperation.combineMasks(brushData, s.getGlobalMask()), componentAccessor));
                }
            }
        });
    }
    
    public void handle(@Nonnull final BuilderToolOnUseInteraction packet) {
        final PlayerRef playerRef = this.packetHandler.getPlayerRef();
        final Ref<EntityStore> ref = playerRef.getReference();
        if (ref == null || !ref.isValid()) {
            throw new RuntimeException("Unable to process BuilderToolOnUseInteraction packet. Player ref is invalid!");
        }
        final Store<EntityStore> store = ref.getStore();
        final World world = store.getExternalData().getWorld();
        world.execute(() -> {
            final Player playerComponent = store.getComponent(ref, Player.getComponentType());
            if (!(!hasPermission(playerComponent, "hytale.editor.brush.use"))) {
                BuilderToolsPacketHandler.LOGGER.at(Level.INFO).log("%s: %s", this.packetHandler.getIdentifier(), packet);
                BuilderToolsPlugin.addToQueue(playerComponent, playerRef, (r, s, componentAccessor) -> s.edit(ref, packet, componentAccessor));
            }
        });
    }
    
    public void handle(@Nonnull final BuilderToolSetEntityTransform packet) {
        final PlayerRef playerRef = this.packetHandler.getPlayerRef();
        final Ref<EntityStore> ref = playerRef.getReference();
        if (ref == null || !ref.isValid()) {
            throw new RuntimeException("Unable to process BuilderToolSetEntityTransform packet. Player ref is invalid!");
        }
        final Store<EntityStore> store = ref.getStore();
        final World world = store.getExternalData().getWorld();
        world.execute(() -> {
            final Player playerComponent = store.getComponent(ref, Player.getComponentType());
            if (!BuilderToolsPacketHandler.$assertionsDisabled && playerComponent == null) {
                throw new AssertionError();
            }
            else if (!(!hasPermission(playerComponent))) {
                final Ref<EntityStore> entityReference = world.getEntityStore().getRefFromNetworkId(packet.entityId);
                if (entityReference != null) {
                    final TransformComponent transformComponent = store.getComponent(entityReference, TransformComponent.getComponentType());
                    if (!BuilderToolsPacketHandler.$assertionsDisabled && transformComponent == null) {
                        throw new AssertionError();
                    }
                    else {
                        final HeadRotation headRotation = store.getComponent(entityReference, HeadRotation.getComponentType());
                        final ModelTransform modelTransform = packet.modelTransform;
                        if (modelTransform != null) {
                            final boolean hasPosition = modelTransform.position != null;
                            final boolean hasLookOrientation = modelTransform.lookOrientation != null;
                            final boolean hasBodyOrientation = modelTransform.bodyOrientation != null;
                            if (hasPosition) {
                                transformComponent.getPosition().assign(modelTransform.position.x, modelTransform.position.y, modelTransform.position.z);
                            }
                            if (hasLookOrientation && headRotation != null) {
                                headRotation.getRotation().assign(modelTransform.lookOrientation.pitch, modelTransform.lookOrientation.yaw, modelTransform.lookOrientation.roll);
                            }
                            if (hasBodyOrientation) {
                                transformComponent.getRotation().assign(modelTransform.bodyOrientation.pitch, modelTransform.bodyOrientation.yaw, modelTransform.bodyOrientation.roll);
                            }
                            if (hasPosition || hasLookOrientation || hasBodyOrientation) {
                                transformComponent.markChunkDirty(store);
                            }
                        }
                    }
                }
            }
        });
    }
    
    public void handle(@Nonnull final PrefabUnselectPrefab packet) {
        final PlayerRef playerRef = this.packetHandler.getPlayerRef();
        final Ref<EntityStore> ref = playerRef.getReference();
        if (ref == null || !ref.isValid()) {
            throw new RuntimeException("Unable to process PrefabUnselectPrefab packet. Player ref is invalid!");
        }
        final Store<EntityStore> store = ref.getStore();
        final World world = store.getExternalData().getWorld();
        world.execute(() -> {
            final Player playerComponent = store.getComponent(ref, Player.getComponentType());
            if (!(!hasPermission(playerComponent))) {
                BuilderToolsPacketHandler.LOGGER.at(Level.INFO).log("%s: %s", this.packetHandler.getIdentifier(), packet);
                final PrefabEditSessionManager prefabEditSessionManager = BuilderToolsPlugin.get().getPrefabEditSessionManager();
                final PrefabEditSession prefabEditSession = prefabEditSessionManager.getPrefabEditSession(playerRef.getUuid());
                if (prefabEditSession == null) {
                    playerComponent.sendMessage(Message.translation("server.commands.editprefab.notInEditSession"));
                }
                else if (prefabEditSession.clearSelectedPrefab(ref, store)) {
                    playerComponent.sendMessage(Message.translation("server.commands.editprefab.unselected"));
                }
                else {
                    playerComponent.sendMessage(Message.translation("server.commands.editprefab.noPrefabSelected"));
                }
            }
        });
    }
    
    public void handle(@Nonnull final BuilderToolSetEntityScale packet) {
        final PlayerRef playerRef = this.packetHandler.getPlayerRef();
        final Ref<EntityStore> ref = playerRef.getReference();
        if (ref == null || !ref.isValid()) {
            throw new RuntimeException("Unable to process BuilderToolSetEntityScale packet. Player ref is invalid!");
        }
        final Store<EntityStore> store = ref.getStore();
        final World world = store.getExternalData().getWorld();
        world.execute(() -> {
            final Player playerComponent = store.getComponent(ref, Player.getComponentType());
            if (!(!hasPermission(playerComponent))) {
                final Ref<EntityStore> entityReference = world.getEntityStore().getRefFromNetworkId(packet.entityId);
                if (entityReference != null) {
                    final PropComponent propComponent = store.getComponent(entityReference, PropComponent.getComponentType());
                    if (propComponent != null) {
                        final EntityScaleComponent scaleComponent = store.getComponent(entityReference, EntityScaleComponent.getComponentType());
                        if (scaleComponent == null) {
                            final EntityScaleComponent scaleComponent2 = new EntityScaleComponent(packet.scale);
                            store.addComponent(entityReference, EntityScaleComponent.getComponentType(), scaleComponent2);
                        }
                        else {
                            scaleComponent.setScale(packet.scale);
                        }
                    }
                }
            }
        });
    }
    
    public void handle(@Nonnull final BuilderToolSetEntityPickupEnabled packet) {
        final PlayerRef playerRef = this.packetHandler.getPlayerRef();
        final Ref<EntityStore> ref = playerRef.getReference();
        if (ref == null || !ref.isValid()) {
            throw new RuntimeException("Unable to process BuilderToolSetEntityPickupEnabled packet. Player ref is invalid!");
        }
        final Store<EntityStore> store = ref.getStore();
        final World world = store.getExternalData().getWorld();
        world.execute(() -> {
            final Player playerComponent = store.getComponent(ref, Player.getComponentType());
            if (!(!hasPermission(playerComponent))) {
                final Ref<EntityStore> entityReference = world.getEntityStore().getRefFromNetworkId(packet.entityId);
                if (entityReference != null) {
                    final PropComponent propComponent = store.getComponent(entityReference, PropComponent.getComponentType());
                    if (propComponent != null) {
                        if (packet.enabled) {
                            store.ensureComponent(entityReference, Interactable.getComponentType());
                            if (store.getComponent(entityReference, PreventPickup.getComponentType()) != null) {
                                store.removeComponent(entityReference, PreventPickup.getComponentType());
                            }
                            Interactions interactionsComponent = store.getComponent(entityReference, Interactions.getComponentType());
                            if (interactionsComponent == null) {
                                interactionsComponent = new Interactions();
                                store.addComponent(entityReference, Interactions.getComponentType(), interactionsComponent);
                            }
                            interactionsComponent.setInteractionId(InteractionType.Use, "*PickupItem");
                            interactionsComponent.setInteractionHint("server.interactionHints.pickup");
                        }
                        else {
                            if (store.getComponent(entityReference, Interactable.getComponentType()) != null) {
                                store.removeComponent(entityReference, Interactable.getComponentType());
                            }
                            if (store.getComponent(entityReference, Interactions.getComponentType()) != null) {
                                store.removeComponent(entityReference, Interactions.getComponentType());
                            }
                            store.ensureComponent(entityReference, PreventPickup.getComponentType());
                        }
                    }
                }
            }
        });
    }
    
    public void handle(@Nonnull final BuilderToolSetEntityLight packet) {
        final PlayerRef playerRef = this.packetHandler.getPlayerRef();
        final Ref<EntityStore> ref = playerRef.getReference();
        if (ref == null || !ref.isValid()) {
            throw new RuntimeException("Unable to process BuilderToolSetEntityLight packet. Player ref is invalid!");
        }
        final Store<EntityStore> store = ref.getStore();
        final World world = store.getExternalData().getWorld();
        world.execute(() -> {
            final Player playerComponent = store.getComponent(ref, Player.getComponentType());
            if (!(!hasPermission(playerComponent))) {
                final Ref<EntityStore> entityReference = world.getEntityStore().getRefFromNetworkId(packet.entityId);
                if (entityReference != null) {
                    if (packet.light == null) {
                        store.removeComponent(entityReference, DynamicLight.getComponentType());
                        store.removeComponent(entityReference, PersistentDynamicLight.getComponentType());
                    }
                    else {
                        final ColorLight colorLight = new ColorLight(packet.light.radius, packet.light.red, packet.light.green, packet.light.blue);
                        store.putComponent(entityReference, DynamicLight.getComponentType(), new DynamicLight(colorLight));
                        store.putComponent(entityReference, PersistentDynamicLight.getComponentType(), new PersistentDynamicLight(colorLight));
                    }
                }
            }
        });
    }
    
    public void handle(@Nonnull final BuilderToolSetNPCDebug packet) {
        final PlayerRef playerRef = this.packetHandler.getPlayerRef();
        final Ref<EntityStore> ref = playerRef.getReference();
        if (ref == null || !ref.isValid()) {
            throw new RuntimeException("Unable to process BuilderToolSetNPCDebug packet. Player ref is invalid!");
        }
        final Store<EntityStore> store = ref.getStore();
        final World world = store.getExternalData().getWorld();
        world.execute(() -> {
            final Player playerComponent = store.getComponent(ref, Player.getComponentType());
            if (!(!hasPermission(playerComponent))) {
                final Ref<EntityStore> entityReference = world.getEntityStore().getRefFromNetworkId(packet.entityId);
                if (entityReference != null) {
                    final UUIDComponent uuidComponent = store.getComponent(entityReference, UUIDComponent.getComponentType());
                    if (uuidComponent != null) {
                        final UUID uuid = uuidComponent.getUuid();
                        final String command = packet.enabled ? ("npc debug set display --entity " + String.valueOf(uuid)) : ("npc debug clear --entity " + String.valueOf(uuid));
                        CommandManager.get().handleCommand(playerComponent, command);
                    }
                }
            }
        });
    }
    
    static {
        LOGGER = HytaleLogger.forEnclosingClass();
    }
}
