diff --git a/Prism/src/main/java/network/darkhelmet/prism/PrismConfig.java b/Prism/src/main/java/network/darkhelmet/prism/PrismConfig.java index 1db60c9e..853371be 100644 --- a/Prism/src/main/java/network/darkhelmet/prism/PrismConfig.java +++ b/Prism/src/main/java/network/darkhelmet/prism/PrismConfig.java @@ -136,6 +136,8 @@ public FileConfiguration getConfig() { config.addDefault("prism.tracking.creeper-explode", true); config.addDefault("prism.tracking.crop-trample", true); config.addDefault("prism.tracking.dragon-eat", true); + config.addDefault("prism.tracking.dragonegg-click", true); + config.addDefault("prism.tracking.dragonegg-teleport", true); config.addDefault("prism.tracking.enchant-item", false); config.addDefault("prism.tracking.enderman-pickup", true); config.addDefault("prism.tracking.enderman-place", true); diff --git a/Prism/src/main/java/network/darkhelmet/prism/actionlibs/ActionFactory.java b/Prism/src/main/java/network/darkhelmet/prism/actionlibs/ActionFactory.java index 88eb4cf0..efe1ba7c 100644 --- a/Prism/src/main/java/network/darkhelmet/prism/actionlibs/ActionFactory.java +++ b/Prism/src/main/java/network/darkhelmet/prism/actionlibs/ActionFactory.java @@ -4,6 +4,7 @@ import network.darkhelmet.prism.actions.BlockChangeAction; import network.darkhelmet.prism.actions.BlockFallAction; import network.darkhelmet.prism.actions.BlockShiftAction; +import network.darkhelmet.prism.actions.BlockTeleportAction; import network.darkhelmet.prism.actions.EntityAction; import network.darkhelmet.prism.actions.EntityTravelAction; import network.darkhelmet.prism.actions.GrowAction; @@ -188,6 +189,23 @@ public static Handler createBlockShift(String actionType, Block from, Location t return a; } + /** + * BlockFromToEvent. + * + * @param actionType the action. + * @param from teleported block from. + * @param to teleported block to. + * @param isFrom if the location is where the block teleported from. + */ + public static Handler createBlockTeleport(String actionType, Block from, Block to, boolean isFrom, Player player) { + final BlockTeleportAction a = new BlockTeleportAction(); + a.setActionType(actionType); + a.setPlayer(player); + a.setFrom(isFrom); + a.setBlock(from, to); + return a; + } + /** * BlockFallAction. diff --git a/Prism/src/main/java/network/darkhelmet/prism/actionlibs/ActionRegistry.java b/Prism/src/main/java/network/darkhelmet/prism/actionlibs/ActionRegistry.java index b787d3d9..68ef1e63 100644 --- a/Prism/src/main/java/network/darkhelmet/prism/actionlibs/ActionRegistry.java +++ b/Prism/src/main/java/network/darkhelmet/prism/actionlibs/ActionRegistry.java @@ -6,6 +6,7 @@ import network.darkhelmet.prism.actions.BlockChangeAction; import network.darkhelmet.prism.actions.BlockFallAction; import network.darkhelmet.prism.actions.BlockShiftAction; +import network.darkhelmet.prism.actions.BlockTeleportAction; import network.darkhelmet.prism.actions.EntityAction; import network.darkhelmet.prism.actions.EntityTravelAction; import network.darkhelmet.prism.actions.GrowAction; @@ -177,6 +178,10 @@ private void registerPrismDefaultActions() { BlockAction.class, Il8nHelper.getRawMessage("trampled"))); registerAction(new ActionTypeImpl("dragon-eat", false, true, true, BlockAction.class, Il8nHelper.getRawMessage("ate"))); + registerAction(new ActionTypeImpl("dragonegg-click", true, true, true, + BlockTeleportAction.class, Il8nHelper.getRawMessage("teleported"))); + registerAction(new ActionTypeImpl("dragonegg-teleport", true, true, true, + BlockTeleportAction.class, Il8nHelper.getRawMessage("teleported"))); registerAction(new ActionTypeImpl("enchant-item", false, false, false, ItemStackAction.class, Il8nHelper.getRawMessage("enchanted"))); registerAction(new ActionTypeImpl("enderman-pickup", false, true, true, diff --git a/Prism/src/main/java/network/darkhelmet/prism/actions/BlockAction.java b/Prism/src/main/java/network/darkhelmet/prism/actions/BlockAction.java index 71295500..4df742ad 100644 --- a/Prism/src/main/java/network/darkhelmet/prism/actions/BlockAction.java +++ b/Prism/src/main/java/network/darkhelmet/prism/actions/BlockAction.java @@ -13,7 +13,6 @@ import network.darkhelmet.prism.utils.TypeUtils; import network.darkhelmet.prism.utils.block.Utilities; import org.bukkit.Bukkit; -import org.bukkit.ChatColor; import org.bukkit.DyeColor; import org.bukkit.Nameable; import org.bukkit.Tag; @@ -287,6 +286,8 @@ ChangeResult placeBlock(Player player, PrismParameters parameters, boolean isPre // (essentially liquid/air). final boolean cancelIfBadPlace = !getActionType().requiresHandler(BlockChangeAction.class) + && !getActionType().requiresHandler(BlockFallAction.class) + && !getActionType().requiresHandler(BlockTeleportAction.class) && !getActionType().requiresHandler(PrismRollbackAction.class) && !parameters.hasFlag(Flag.OVERWRITE); if (cancelIfBadPlace && !Utilities.isAcceptableForBlockPlace(block.getType())) { diff --git a/Prism/src/main/java/network/darkhelmet/prism/actions/BlockTeleportAction.java b/Prism/src/main/java/network/darkhelmet/prism/actions/BlockTeleportAction.java new file mode 100644 index 00000000..279160ad --- /dev/null +++ b/Prism/src/main/java/network/darkhelmet/prism/actions/BlockTeleportAction.java @@ -0,0 +1,83 @@ +package network.darkhelmet.prism.actions; + +import network.darkhelmet.prism.Prism; +import org.bukkit.Location; +import org.bukkit.Material; +import org.bukkit.block.Block; + +public class BlockTeleportAction extends BlockChangeAction { + + private TeleportActionData actionData = new TeleportActionData(); + + public void setOtherLoc(Location other) { + actionData.x = other.getBlock().getX(); + actionData.y = other.getBlock().getY(); + actionData.z = other.getBlock().getZ(); + } + + public void setFrom(boolean from) { + actionData.from = from; + } + + public void setBlock(Block from, Block to) { + if (isFrom()) { + setOtherLoc(to.getLocation()); + setOldMaterial(from.getType()); + setOldBlockData(from.getBlockData()); + + setLoc(from.getLocation()); + setMaterial(Material.AIR); + } else { + setOtherLoc(from.getLocation()); + setOldMaterial(to.getType()); + setOldBlockData(to.getBlockData()); + + setLoc(to.getLocation()); + setMaterial(from.getType()); + setBlockData(from.getBlockData()); + } + } + + public boolean isFrom() { + return actionData.from; + } + + @Override + public boolean hasExtraData() { + return true; + } + + @Override + public String serialize() { + return gson().toJson(actionData); + } + + @Override + public void deserialize(String data) { + if (data != null && data.startsWith("{")) { + actionData = gson().fromJson(data, TeleportActionData.class); + } + } + + @Override + public String getNiceName() { + String extraInfo = " unknown"; + if (actionData != null) { + if (actionData.from) { + extraInfo = " to " + actionData.x + " " + actionData.y + " " + actionData.z; + } else { + extraInfo = " from " + actionData.x + " " + actionData.y + " " + actionData.z; + } + } + + return (isFrom() ? Prism.getItems().getAlias(getOldMaterial(), getOldBlockData()) : Prism.getItems().getAlias(getMaterial(), getBlockData())) + extraInfo; + } + + public static class TeleportActionData { + boolean from; + int x; + int y; + int z; + } + +} diff --git a/Prism/src/main/java/network/darkhelmet/prism/listeners/PrismBlockEvents.java b/Prism/src/main/java/network/darkhelmet/prism/listeners/PrismBlockEvents.java index cf7abf47..277012e4 100644 --- a/Prism/src/main/java/network/darkhelmet/prism/listeners/PrismBlockEvents.java +++ b/Prism/src/main/java/network/darkhelmet/prism/listeners/PrismBlockEvents.java @@ -18,7 +18,6 @@ import org.bukkit.block.data.type.Bed; import org.bukkit.block.data.type.Chest; import org.bukkit.block.data.type.Chest.Type; -import org.bukkit.block.data.type.RespawnAnchor; import org.bukkit.entity.Entity; import org.bukkit.entity.EntityType; import org.bukkit.entity.Player; @@ -58,7 +57,7 @@ public class PrismBlockEvents extends BaseListener { .newBuilder() .expireAfterWrite(30, TimeUnit.SECONDS) .build(); - private final Cache anchorWeakCache = CacheBuilder + private final Cache interactWeakCache = CacheBuilder .newBuilder() .expireAfterWrite(30, TimeUnit.SECONDS) .build(); @@ -380,7 +379,7 @@ public void onBlockExplode(BlockExplodeEvent event) { if (!Prism.getIgnore().event("respawnanchor-explode", event.getBlock())) { return; } - Player player = anchorWeakCache.getIfPresent(event.getBlock().getLocation()); + Player player = interactWeakCache.getIfPresent(event.getBlock().getLocation()); if (player == null) { return; } @@ -388,7 +387,7 @@ public void onBlockExplode(BlockExplodeEvent event) { List affected = event.blockList(); RecordingQueue.addToQueue(ActionFactory.createBlock("respawnanchor-explode", event.getBlock().getState(), player)); contructBlockEvent("respawnanchor-explode", source, affected); - anchorWeakCache.invalidate(event.getBlock().getLocation()); + interactWeakCache.invalidate(event.getBlock().getLocation()); } } @@ -398,8 +397,9 @@ public void onBlockExplode(BlockExplodeEvent event) { */ @EventHandler(priority = EventPriority.MONITOR) public void onRespawnAnchorUse(PlayerInteractEvent event) { - if (event.hasBlock() && event.getClickedBlock().getType() == Material.RESPAWN_ANCHOR) { - anchorWeakCache.put(event.getClickedBlock().getLocation(), event.getPlayer()); + if (event.hasBlock() + && (event.getClickedBlock().getType() == Material.RESPAWN_ANCHOR || event.getClickedBlock().getType() == Material.DRAGON_EGG)) { + interactWeakCache.put(event.getClickedBlock().getLocation(), event.getPlayer()); } } @@ -618,39 +618,46 @@ public void onBlockFall(final EntityChangeBlockEvent event) { */ @EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true) public void onBlockFromTo(final BlockFromToEvent event) { + Block block = event.getBlock(); + if (block.isLiquid()) { + final BlockState from = block.getState(); + final BlockState to = event.getToBlock().getState(); + + // Watch for blocks that the liquid can break + if (Utilities.canFlowBreakMaterial(to.getType())) { + if (from.getType() == Material.WATER) { + if (Prism.getIgnore().event("water-break", block)) { + RecordingQueue.addToQueue(ActionFactory.createBlock("water-break", event.getToBlock(), "Water")); + } + } else if (from.getType() == Material.LAVA) { + if (Prism.getIgnore().event("lava-break", block)) { + RecordingQueue.addToQueue(ActionFactory.createBlock("lava-break", event.getToBlock(), "Lava")); + } + } + } - // Ignore blocks that aren't liquid. @todo what else triggers this? - if (!event.getBlock().isLiquid()) { - return; - } - - final BlockState from = event.getBlock().getState(); - final BlockState to = event.getToBlock().getState(); - - // Watch for blocks that the liquid can break - if (Utilities.canFlowBreakMaterial(to.getType())) { + // Record water flow if (from.getType() == Material.WATER) { - if (Prism.getIgnore().event("water-break", event.getBlock())) { - RecordingQueue.addToQueue(ActionFactory.createBlock("water-break", event.getToBlock(), "Water")); - } - } else if (from.getType() == Material.LAVA) { - if (Prism.getIgnore().event("lava-break", event.getBlock())) { - RecordingQueue.addToQueue(ActionFactory.createBlock("lava-break", event.getToBlock(), "Lava")); + if (Prism.getIgnore().event("water-flow", block)) { + RecordingQueue.addToQueue(ActionFactory.createBlock("water-flow", block, "Water")); } } - } - // Record water flow - if (from.getType() == Material.WATER) { - if (Prism.getIgnore().event("water-flow", event.getBlock())) { - RecordingQueue.addToQueue(ActionFactory.createBlock("water-flow", event.getBlock(), "Water")); + // Record lava flow + if (from.getType() == Material.LAVA) { + if (Prism.getIgnore().event("lava-flow", block)) { + RecordingQueue.addToQueue(ActionFactory.createBlock("lava-flow", block, "Lava")); + } } - } - // Record lava flow - if (from.getType() == Material.LAVA) { - if (Prism.getIgnore().event("lava-flow", event.getBlock())) { - RecordingQueue.addToQueue(ActionFactory.createBlock("lava-flow", event.getBlock(), "Lava")); + } else if (block.getType() == Material.DRAGON_EGG) { + if (Prism.getIgnore().event("dragonegg-click", block)) { + RecordingQueue.addToQueue(ActionFactory.createBlockTeleport("dragonegg-click", block, event.getToBlock(), + true, interactWeakCache.getIfPresent(block.getLocation()))); + } + if (Prism.getIgnore().event("dragonegg-teleport", block)) { + RecordingQueue.addToQueue(ActionFactory.createBlockTeleport("dragonegg-teleport", block, event.getToBlock(), + false, interactWeakCache.getIfPresent(block.getLocation()))); } } }