diff --git a/src/bukkit/java/com/sk89q/worldedit/bukkit/WorldEditListener.java b/src/bukkit/java/com/sk89q/worldedit/bukkit/WorldEditListener.java index fbb335543..50e7f9e37 100644 --- a/src/bukkit/java/com/sk89q/worldedit/bukkit/WorldEditListener.java +++ b/src/bukkit/java/com/sk89q/worldedit/bukkit/WorldEditListener.java @@ -125,7 +125,7 @@ public class WorldEditListener implements Listener { Action action = event.getAction(); if (action == Action.LEFT_CLICK_BLOCK) { final Block clickedBlock = event.getClickedBlock(); - final WorldVector pos = new WorldVector(LocalWorldAdapter.wrap(world), clickedBlock.getX(), clickedBlock.getY(), clickedBlock.getZ()); + final WorldVector pos = new WorldVector(LocalWorldAdapter.adapt(world), clickedBlock.getX(), clickedBlock.getY(), clickedBlock.getZ()); if (we.handleBlockLeftClick(player, pos)) { event.setCancelled(true); @@ -159,7 +159,7 @@ public class WorldEditListener implements Listener { } else if (action == Action.RIGHT_CLICK_BLOCK) { final Block clickedBlock = event.getClickedBlock(); - final WorldVector pos = new WorldVector(LocalWorldAdapter.wrap(world), clickedBlock.getX(), + final WorldVector pos = new WorldVector(LocalWorldAdapter.adapt(world), clickedBlock.getX(), clickedBlock.getY(), clickedBlock.getZ()); if (we.handleBlockRightClick(player, pos)) { diff --git a/src/forge/java/com/sk89q/worldedit/forge/ForgePlayer.java b/src/forge/java/com/sk89q/worldedit/forge/ForgePlayer.java index 01e178f71..a3d441385 100644 --- a/src/forge/java/com/sk89q/worldedit/forge/ForgePlayer.java +++ b/src/forge/java/com/sk89q/worldedit/forge/ForgePlayer.java @@ -59,7 +59,7 @@ public class ForgePlayer extends LocalPlayer { } public WorldVector getPosition() { - return new WorldVector(LocalWorldAdapter.wrap(ForgeWorldEdit.inst.getWorld(this.player.worldObj)), this.player.posX, this.player.posY, this.player.posZ); + return new WorldVector(LocalWorldAdapter.adapt(ForgeWorldEdit.inst.getWorld(this.player.worldObj)), this.player.posX, this.player.posY, this.player.posZ); } public com.sk89q.worldedit.world.World getWorld() { diff --git a/src/forge/java/com/sk89q/worldedit/forge/ForgeWorldEdit.java b/src/forge/java/com/sk89q/worldedit/forge/ForgeWorldEdit.java index 283e99a97..1b1b7f621 100644 --- a/src/forge/java/com/sk89q/worldedit/forge/ForgeWorldEdit.java +++ b/src/forge/java/com/sk89q/worldedit/forge/ForgeWorldEdit.java @@ -137,7 +137,7 @@ public class ForgeWorldEdit { Action action = event.action; switch (action) { case LEFT_CLICK_BLOCK: { - WorldVector pos = new WorldVector(LocalWorldAdapter.wrap(world), event.x, event.y, event.z); + WorldVector pos = new WorldVector(LocalWorldAdapter.adapt(world), event.x, event.y, event.z); if (we.handleBlockLeftClick(player, pos)) { event.setCanceled(true); @@ -148,7 +148,7 @@ public class ForgeWorldEdit { } } case RIGHT_CLICK_BLOCK: { - WorldVector pos = new WorldVector(LocalWorldAdapter.wrap(world), event.x, event.y, event.z); + WorldVector pos = new WorldVector(LocalWorldAdapter.adapt(world), event.x, event.y, event.z); if (we.handleBlockRightClick(player, pos)) { event.setCanceled(true); diff --git a/src/main/java/com/sk89q/worldedit/WorldEdit.java b/src/main/java/com/sk89q/worldedit/WorldEdit.java index cf137bb4d..f38966c90 100644 --- a/src/main/java/com/sk89q/worldedit/WorldEdit.java +++ b/src/main/java/com/sk89q/worldedit/WorldEdit.java @@ -24,6 +24,7 @@ import com.sk89q.worldedit.CuboidClipboard.FlipDirection; import com.sk89q.worldedit.blocks.BaseBlock; import com.sk89q.worldedit.blocks.BlockType; import com.sk89q.worldedit.command.tool.*; +import com.sk89q.worldedit.event.actor.BlockInteractEvent; import com.sk89q.worldedit.event.extent.EditSessionEvent; import com.sk89q.worldedit.event.platform.CommandEvent; import com.sk89q.worldedit.extension.input.ParserContext; @@ -55,6 +56,7 @@ import java.util.Set; import java.util.logging.Logger; import static com.google.common.base.Preconditions.checkNotNull; +import static com.sk89q.worldedit.event.actor.InteractionType.PRIMARY_INPUT; /** * The entry point and container for a working implementation of WorldEdit. @@ -831,41 +833,9 @@ public class WorldEdit { * @return false if you want the action to go through */ public boolean handleBlockLeftClick(LocalPlayer player, WorldVector clicked) { - LocalSession session = getSession(player); - - if (player.getItemInHand() == getConfiguration().wandItem) { - if (!session.isToolControlEnabled()) { - return false; - } - - if (!player.hasPermission("worldedit.selection.pos")) { - return false; - } - - RegionSelector selector = session.getRegionSelector(player.getWorld()); - if (selector.selectPrimary(clicked)) { - selector.explainPrimarySelection(player, session, clicked); - } - - return true; - } - - if (player.isHoldingPickAxe() && session.hasSuperPickAxe()) { - final BlockTool superPickaxe = session.getSuperPickaxe(); - if (superPickaxe != null && superPickaxe.canUse(player)) { - return superPickaxe.actPrimary(getServer(), getConfiguration(), player, session, clicked); - } - } - - Tool tool = session.getTool(player.getItemInHand()); - if (tool != null && tool instanceof DoubleActionBlockTool) { - if (tool.canUse(player)) { - ((DoubleActionBlockTool) tool).actSecondary(getServer(), getConfiguration(), player, session, clicked); - return true; - } - } - - return false; + BlockInteractEvent event = new BlockInteractEvent(player, clicked.toLocation(), PRIMARY_INPUT); + getEventBus().post(event); + return event.isCancelled(); } /** diff --git a/src/main/java/com/sk89q/worldedit/WorldVector.java b/src/main/java/com/sk89q/worldedit/WorldVector.java index 2e901f823..5e3d12b2e 100644 --- a/src/main/java/com/sk89q/worldedit/WorldVector.java +++ b/src/main/java/com/sk89q/worldedit/WorldVector.java @@ -19,6 +19,8 @@ package com.sk89q.worldedit; +import com.sk89q.worldedit.internal.LocalWorldAdapter; + /** * @deprecated Use {@link com.sk89q.worldedit.util.Location} wherever possible */ @@ -81,14 +83,23 @@ public class WorldVector extends Vector { /** * Construct the Vector object. - * - * @param world + * + * @param world */ public WorldVector(LocalWorld world) { super(); this.world = world; } + /** + * Construct the Vector object. + * + * @param location the location + */ + public WorldVector(com.sk89q.worldedit.util.Location location) { + this(LocalWorldAdapter.adapt(location.getWorld()), location.getX(), location.getY(), location.getZ()); + } + /** * Get the world. * @@ -122,4 +133,15 @@ public class WorldVector extends Vector { public BlockWorldVector toWorldBlockVector() { return new BlockWorldVector(this); } + + /** + * Return this object as a new preferred Location + * object. + * + * @return a new location object + */ + public com.sk89q.worldedit.util.Location toLocation() { + return new com.sk89q.worldedit.util.Location(getWorld(), this); + } + } diff --git a/src/main/java/com/sk89q/worldedit/command/tool/brush/SmoothBrush.java b/src/main/java/com/sk89q/worldedit/command/tool/brush/SmoothBrush.java index fe1811c02..d72dc333b 100644 --- a/src/main/java/com/sk89q/worldedit/command/tool/brush/SmoothBrush.java +++ b/src/main/java/com/sk89q/worldedit/command/tool/brush/SmoothBrush.java @@ -46,7 +46,7 @@ public class SmoothBrush implements Brush { public void build(EditSession editSession, Vector pos, Pattern mat, double size) throws MaxChangedBlocksException { double rad = size; - WorldVector min = new WorldVector(LocalWorldAdapter.wrap(editSession.getWorld()), pos.subtract(rad, rad, rad)); + WorldVector min = new WorldVector(LocalWorldAdapter.adapt(editSession.getWorld()), pos.subtract(rad, rad, rad)); Vector max = pos.add(rad, rad + 10, rad); Region region = new CuboidRegion(editSession.getWorld(), min, max); HeightMap heightMap = new HeightMap(editSession, region, naturalOnly); diff --git a/src/main/java/com/sk89q/worldedit/event/actor/BlockInteractEvent.java b/src/main/java/com/sk89q/worldedit/event/actor/BlockInteractEvent.java new file mode 100644 index 000000000..cec761cdd --- /dev/null +++ b/src/main/java/com/sk89q/worldedit/event/actor/BlockInteractEvent.java @@ -0,0 +1,91 @@ +/* + * WorldEdit, a Minecraft world manipulation toolkit + * Copyright (C) sk89q + * Copyright (C) WorldEdit team and contributors + * + * This program is free software: you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published by the + * Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program. If not, see . + */ + +package com.sk89q.worldedit.event.actor; + +import com.sk89q.worldedit.event.Cancellable; +import com.sk89q.worldedit.event.Event; +import com.sk89q.worldedit.extension.platform.Actor; +import com.sk89q.worldedit.util.Location; + +import static com.google.common.base.Preconditions.checkNotNull; + +/** + * Called when a block is interacted with. + */ +public class BlockInteractEvent extends Event implements Cancellable { + + private final Actor cause; + private final Location location; + private final InteractionType type; + private boolean cancelled; + + /** + * Create a new event. + * + * @param cause the causing actor + * @param location the location of the block + * @param type the type of interaction + */ + public BlockInteractEvent(Actor cause, Location location, InteractionType type) { + checkNotNull(cause); + checkNotNull(location); + checkNotNull(type); + this.cause = cause; + this.location = location; + this.type = type; + } + + /** + * Get the cause of this event. + * + * @return the cause + */ + public Actor getCause() { + return cause; + } + + /** + * Get the location of the block that was interacted with. + * + * @return the location + */ + public Location getLocation() { + return location; + } + + /** + * Get the type of interaction. + * + * @return the type of interaction + */ + public InteractionType getType() { + return type; + } + + @Override + public boolean isCancelled() { + return cancelled; + } + + @Override + public void setCancelled(boolean cancelled) { + this.cancelled = cancelled; + } +} diff --git a/src/main/java/com/sk89q/worldedit/event/actor/InteractionType.java b/src/main/java/com/sk89q/worldedit/event/actor/InteractionType.java new file mode 100644 index 000000000..f965de7c1 --- /dev/null +++ b/src/main/java/com/sk89q/worldedit/event/actor/InteractionType.java @@ -0,0 +1,36 @@ +/* + * WorldEdit, a Minecraft world manipulation toolkit + * Copyright (C) sk89q + * Copyright (C) WorldEdit team and contributors + * + * This program is free software: you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published by the + * Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program. If not, see . + */ + +package com.sk89q.worldedit.event.actor; + +/** + * The type of interaction. + */ +public enum InteractionType { + + /** + * Refers to primary input usage (left click). + */ + PRIMARY_INPUT, + + /** + * Refers to secondary input usage (right click). + */ + SECONDARY_INPUT +} diff --git a/src/main/java/com/sk89q/worldedit/extension/platform/PlatformManager.java b/src/main/java/com/sk89q/worldedit/extension/platform/PlatformManager.java index 5f10187ee..e6843853e 100644 --- a/src/main/java/com/sk89q/worldedit/extension/platform/PlatformManager.java +++ b/src/main/java/com/sk89q/worldedit/extension/platform/PlatformManager.java @@ -19,9 +19,16 @@ package com.sk89q.worldedit.extension.platform; -import com.sk89q.worldedit.LocalConfiguration; -import com.sk89q.worldedit.ServerInterface; -import com.sk89q.worldedit.WorldEdit; +import com.sk89q.worldedit.*; +import com.sk89q.worldedit.command.tool.BlockTool; +import com.sk89q.worldedit.command.tool.DoubleActionBlockTool; +import com.sk89q.worldedit.command.tool.Tool; +import com.sk89q.worldedit.entity.Player; +import com.sk89q.worldedit.event.actor.BlockInteractEvent; +import com.sk89q.worldedit.internal.ServerInterfaceAdapter; +import com.sk89q.worldedit.regions.RegionSelector; +import com.sk89q.worldedit.util.Location; +import com.sk89q.worldedit.util.eventbus.Subscribe; import javax.annotation.Nullable; import java.util.ArrayList; @@ -43,6 +50,7 @@ public class PlatformManager { private final LocalConfiguration defaultConfig = new DefaultConfiguration(); private final List platforms = new ArrayList(); + private final WorldEdit worldEdit; private final CommandManager commandManager; private @Nullable Platform primary = null; @@ -53,7 +61,11 @@ public class PlatformManager { */ public PlatformManager(WorldEdit worldEdit) { checkNotNull(worldEdit); + this.worldEdit = worldEdit; this.commandManager = new CommandManager(worldEdit); + + // Register this instance for events + worldEdit.getEventBus().register(this); } /** @@ -182,13 +194,66 @@ public class PlatformManager { if (platform instanceof ServerInterface) { return (ServerInterface) platform; } else { - return new ServerInterfaceAdapter(platform); + return ServerInterfaceAdapter.adapt(platform); } } else { throw new IllegalStateException("No platform has been registered"); } } + @Subscribe + public void handleBlockInteract(BlockInteractEvent event) { + Actor actor = event.getCause(); + Location location = event.getLocation(); + Vector vector = location.toVector(); + + // At this time, only handle interaction from players + if (actor instanceof Player) { + Player player = (Player) actor; + LocalSession session = worldEdit.getSessionManager().get(actor); + + if (player.getItemInHand() == getConfiguration().wandItem) { + if (!session.isToolControlEnabled()) { + return; + } + + if (!actor.hasPermission("worldedit.selection.pos")) { + return; + } + + RegionSelector selector = session.getRegionSelector(player.getWorld()); + + if (selector.selectPrimary(location.toVector())) { + selector.explainPrimarySelection(actor, session, vector); + } + + event.setCancelled(true); + return; + } + + if (player instanceof LocalPlayer) { // Temporary workaround + LocalPlayer localPlayer = (LocalPlayer) player; + WorldVector worldVector = new WorldVector(location); + + if (player.isHoldingPickAxe() && session.hasSuperPickAxe()) { + final BlockTool superPickaxe = session.getSuperPickaxe(); + if (superPickaxe != null && superPickaxe.canUse(localPlayer)) { + event.setCancelled(superPickaxe.actPrimary(getServerInterface(), getConfiguration(), localPlayer, session, worldVector)); + return; + } + } + + Tool tool = session.getTool(player.getItemInHand()); + if (tool != null && tool instanceof DoubleActionBlockTool) { + if (tool.canUse(localPlayer)) { + ((DoubleActionBlockTool) tool).actSecondary(getServerInterface(), getConfiguration(), localPlayer, session, worldVector); + event.setCancelled(true); + } + } + } + } + } + /** * A default configuration for when none is set. */ diff --git a/src/main/java/com/sk89q/worldedit/internal/LocalWorldAdapter.java b/src/main/java/com/sk89q/worldedit/internal/LocalWorldAdapter.java index 3e061de36..ea509acc3 100644 --- a/src/main/java/com/sk89q/worldedit/internal/LocalWorldAdapter.java +++ b/src/main/java/com/sk89q/worldedit/internal/LocalWorldAdapter.java @@ -309,7 +309,7 @@ public class LocalWorldAdapter extends LocalWorld { return world.commit(); } - public static LocalWorldAdapter wrap(World world) { + public static LocalWorldAdapter adapt(World world) { return new LocalWorldAdapter(world); } diff --git a/src/main/java/com/sk89q/worldedit/extension/platform/ServerInterfaceAdapter.java b/src/main/java/com/sk89q/worldedit/internal/ServerInterfaceAdapter.java similarity index 84% rename from src/main/java/com/sk89q/worldedit/extension/platform/ServerInterfaceAdapter.java rename to src/main/java/com/sk89q/worldedit/internal/ServerInterfaceAdapter.java index 5f1bd80f4..fa71a403a 100644 --- a/src/main/java/com/sk89q/worldedit/extension/platform/ServerInterfaceAdapter.java +++ b/src/main/java/com/sk89q/worldedit/internal/ServerInterfaceAdapter.java @@ -17,11 +17,12 @@ * along with this program. If not, see . */ -package com.sk89q.worldedit.extension.platform; +package com.sk89q.worldedit.internal; import com.sk89q.minecraft.util.commands.Command; import com.sk89q.minecraft.util.commands.CommandsManager; import com.sk89q.worldedit.*; +import com.sk89q.worldedit.extension.platform.Platform; import com.sk89q.worldedit.world.World; import java.util.List; @@ -31,7 +32,7 @@ import static com.google.common.base.Preconditions.checkNotNull; /** * Adapts {@link Platform}s into the legacy {@link ServerInterface}. */ -class ServerInterfaceAdapter extends ServerInterface { +public class ServerInterfaceAdapter extends ServerInterface { private final Platform platform; @@ -40,7 +41,7 @@ class ServerInterfaceAdapter extends ServerInterface { * * @param platform the platform */ - ServerInterfaceAdapter(Platform platform) { + private ServerInterfaceAdapter(Platform platform) { checkNotNull(platform); this.platform = platform; } @@ -106,4 +107,14 @@ class ServerInterfaceAdapter extends ServerInterface { return platform.getPlatformVersion(); } + /** + * Adapt an {@link Platform} instance into a {@link ServerInterface}. + * + * @param platform the platform + * @return the server interface + */ + public static ServerInterface adapt(Platform platform) { + return new ServerInterfaceAdapter(platform); + } + } diff --git a/src/main/java/com/sk89q/worldedit/util/TargetBlock.java b/src/main/java/com/sk89q/worldedit/util/TargetBlock.java index 700dce3f8..2d62e8b37 100644 --- a/src/main/java/com/sk89q/worldedit/util/TargetBlock.java +++ b/src/main/java/com/sk89q/worldedit/util/TargetBlock.java @@ -49,7 +49,7 @@ public class TargetBlock { * @param player player to work with */ public TargetBlock(LocalPlayer player) { - this.world = LocalWorldAdapter.wrap(player.getWorld()); + this.world = LocalWorldAdapter.adapt(player.getWorld()); this.setValues(player.getPosition(), player.getYaw(), player.getPitch(), 300, 1.65, 0.2); } @@ -73,7 +73,7 @@ public class TargetBlock { * @param checkDistance how often to check for blocks, the smaller the more precise */ public TargetBlock(Entity player, int maxDistance, double checkDistance) { - this.world = LocalWorldAdapter.wrap(player.getWorld()); + this.world = LocalWorldAdapter.adapt(player.getWorld()); this.setValues(player.getPosition(), player.getYaw(), player.getPitch(), maxDistance, 1.65, checkDistance); }