Skip to content

Commit

Permalink
Address #2385
Browse files Browse the repository at this point in the history
  • Loading branch information
fullwall committed Nov 16, 2020
1 parent 8b3ce3c commit e0507a7
Show file tree
Hide file tree
Showing 3 changed files with 152 additions and 25 deletions.
126 changes: 101 additions & 25 deletions src/main/java/net/citizensnpcs/api/astar/pathfinder/DoorExaminer.java
Expand Up @@ -2,17 +2,22 @@

import java.util.ListIterator;

import net.citizensnpcs.api.util.SpigotUtil;
import org.bukkit.Bukkit;
import org.bukkit.Material;
import org.bukkit.Sound;
import org.bukkit.block.Block;
import org.bukkit.block.BlockFace;
import org.bukkit.block.BlockState;
import org.bukkit.block.data.Openable;
import org.bukkit.event.Cancellable;
import org.bukkit.event.Event;
import org.bukkit.material.MaterialData;

import net.citizensnpcs.api.astar.pathfinder.PathPoint.PathCallback;
import net.citizensnpcs.api.event.NPCOpenDoorEvent;
import net.citizensnpcs.api.event.NPCOpenGateEvent;
import net.citizensnpcs.api.npc.NPC;
import org.bukkit.block.data.type.Door;
import net.citizensnpcs.api.util.SpigotUtil;

public class DoorExaminer implements BlockExaminer {
@Override
Expand All @@ -23,52 +28,123 @@ public float getCost(BlockSource source, PathPoint point) {
@Override
public PassableState isPassable(BlockSource source, PathPoint point) {
Material in = source.getMaterialAt(point.getVector());
if (MinecraftBlockExaminer.isDoor(in)) {
if (MinecraftBlockExaminer.isDoor(in) || MinecraftBlockExaminer.isGate(in)) {
point.addCallback(new DoorOpener());
return PassableState.PASSABLE;
}
return PassableState.IGNORE;
}

static class DoorOpener implements PathCallback {
@Override
public void run(NPC npc, Block point, ListIterator<Block> path) {
if (!MinecraftBlockExaminer.isDoor(point.getType()))
return;
if (npc.getStoredLocation().distanceSquared(point.getLocation().add(0.5, 0, 0.5)) > 4)
return;
boolean opened = false;

private void close(Block point) {
closeOpenable(point);
}

private void closeOpenable(Block point) {
if (SpigotUtil.isUsing1_13API()) {
Door door = (Door) point.getBlockData();
if (door.isOpen()) {
Openable open = (Openable) point.getBlockData();
if (!open.isOpen()) {
return;
}
NPCOpenDoorEvent event = new NPCOpenDoorEvent(npc, point);
Bukkit.getPluginManager().callEvent(event);
open.setOpen(false);
point.setBlockData(open);
} else {
point = getCorrectDoor(point);
BlockState state = point.getState();
org.bukkit.material.Openable open = (org.bukkit.material.Openable) state.getData();
if (!open.isOpen()) {
return;
}
open.setOpen(false);
state.setData((MaterialData) open);
state.update();
}
if (SUPPORTS_SOUNDS) {
try {
Sound sound = MinecraftBlockExaminer.isDoor(point.getType())
? (point.getType() == Material.IRON_DOOR ? Sound.BLOCK_IRON_DOOR_CLOSE
: Sound.BLOCK_WOODEN_DOOR_CLOSE)
: Sound.BLOCK_FENCE_GATE_CLOSE;
point.getWorld().playSound(point.getLocation(), sound, 10, 1);
} catch (Exception ex) {
SUPPORTS_SOUNDS = false;
}
}
}

@SuppressWarnings("deprecation")
private Block getCorrectDoor(Block point) {
MaterialData data = point.getState().getData();
if (data instanceof org.bukkit.material.Door) {
return point;
}
org.bukkit.material.Door door = (org.bukkit.material.Door) data;
boolean bottom = !door.isTopHalf();
return bottom ? point : point.getRelative(BlockFace.DOWN);
}

private void open(NPC npc, Block point) {
if (SpigotUtil.isUsing1_13API()) {
Openable open = (Openable) point.getBlockData();
if (open.isOpen()) {
return;
}
Cancellable event = MinecraftBlockExaminer.isDoor(point.getType()) ? new NPCOpenDoorEvent(npc, point)
: new NPCOpenGateEvent(npc, point);
Bukkit.getPluginManager().callEvent((Event) event);
if (event.isCancelled()) {
return;
}
door.setOpen(true);
point.setBlockData(door);
open.setOpen(true);
point.setBlockData(open);
opened = true;
} else {
point = getCorrectDoor(point);
BlockState state = point.getState();
org.bukkit.material.Door door = (org.bukkit.material.Door) state.getData();
boolean bottom = !door.isTopHalf();
Block set = bottom ? point : point.getRelative(BlockFace.DOWN);
state = set.getState();
door = (org.bukkit.material.Door) state.getData();
if (door.isOpen()) {
org.bukkit.material.Openable open = (org.bukkit.material.Openable) state.getData();
if (open.isOpen()) {
return;
}
NPCOpenDoorEvent event = new NPCOpenDoorEvent(npc, point);
Bukkit.getPluginManager().callEvent(event);
Cancellable event = MinecraftBlockExaminer.isDoor(point.getType()) ? new NPCOpenDoorEvent(npc, point)
: new NPCOpenGateEvent(npc, point);
Bukkit.getPluginManager().callEvent((Event) event);
if (event.isCancelled()) {
return;
}
door.setOpen(true);
state.setData(door);
open.setOpen(true);
state.setData((MaterialData) open);
state.update();
opened = true;
}
if (SUPPORTS_SOUNDS) {
try {
Sound sound = MinecraftBlockExaminer.isDoor(point.getType())
? (point.getType() == Material.IRON_DOOR ? Sound.BLOCK_IRON_DOOR_OPEN
: Sound.BLOCK_WOODEN_DOOR_OPEN)
: Sound.BLOCK_FENCE_GATE_OPEN;
point.getWorld().playSound(point.getLocation(), sound, 10, 1);
} catch (Exception ex) {
SUPPORTS_SOUNDS = false;
}
}
}

@Override
public void run(NPC npc, Block point, ListIterator<Block> path) {
if (!MinecraftBlockExaminer.isDoor(point.getType()))
return;
if (npc.getStoredLocation().distanceSquared(point.getLocation().add(0.5, 0, 0.5)) > 4) {
if (opened) {
close(point);
opened = false;
}
return;
}
open(npc, point);
}

private static boolean SUPPORTS_SOUNDS = true;
}
}
Expand Up @@ -202,6 +202,10 @@ public static boolean isDoor(Material in) {
return in.name().contains("DOOR") && !in.name().contains("TRAPDOOR");
}

public static boolean isGate(Material in) {
return in.name().contains("GATE") && !in.name().contains("GATEWAY");
}

public static boolean isLiquid(Material... materials) {
for (Material mat : materials) {
if (LIQUIDS.contains(mat)) {
Expand Down
47 changes: 47 additions & 0 deletions src/main/java/net/citizensnpcs/api/event/NPCOpenGateEvent.java
@@ -0,0 +1,47 @@
package net.citizensnpcs.api.event;

import org.bukkit.block.Block;
import org.bukkit.event.Cancellable;
import org.bukkit.event.HandlerList;

import net.citizensnpcs.api.npc.NPC;

public class NPCOpenGateEvent extends NPCEvent implements Cancellable {
private final Block block;
private boolean cancelled;

public NPCOpenGateEvent(NPC npc, Block block) {
super(npc);
this.block = block;
}

/**
* Returns the {@link Block} that was opened.
*
* @return The block
*/
public Block getGate() {
return block;
}

@Override
public HandlerList getHandlers() {
return handlers;
}

@Override
public boolean isCancelled() {
return cancelled;
}

@Override
public void setCancelled(boolean arg0) {
cancelled = arg0;
}

public static HandlerList getHandlerList() {
return handlers;
}

private static final HandlerList handlers = new HandlerList();
}

0 comments on commit e0507a7

Please sign in to comment.