diff --git a/src/com/dre/dungeonsxl/DPlayer.java b/src/com/dre/dungeonsxl/DPlayer.java index 32976d6b..9432f921 100644 --- a/src/com/dre/dungeonsxl/DPlayer.java +++ b/src/com/dre/dungeonsxl/DPlayer.java @@ -24,7 +24,7 @@ import org.getspout.spoutapi.Spout; import org.getspout.spoutapi.player.SpoutPlayer; import com.dre.dungeonsxl.game.GameWorld; -import com.dre.dungeonsxl.signs.DSign; +import com.dre.dungeonsxl.trigger.DistanceTrigger; public class DPlayer { public static P p = P.p; @@ -489,17 +489,7 @@ public class DPlayer { } // Check Distance Trigger Signs - for (DSign sign : gworld.dSigns) { - if (sign != null) { - if (sign.isDistanceTrigger()) { - if ((sign.isRedstoneTrigger() == false && sign.isSignTrigger() == false) || sign.isPowered()) { - if (dplayer.player.getLocation().distance(sign.getSign().getLocation()) < sign.getDtDistance()) { - sign.onTrigger(); - } - } - } - } - } + DistanceTrigger.triggerAllInDistance(dplayer.player, gworld); } } } diff --git a/src/com/dre/dungeonsxl/game/GameWorld.java b/src/com/dre/dungeonsxl/game/GameWorld.java index 0e00366a..f4134265 100644 --- a/src/com/dre/dungeonsxl/game/GameWorld.java +++ b/src/com/dre/dungeonsxl/game/GameWorld.java @@ -27,6 +27,7 @@ import com.dre.dungeonsxl.DPlayer; import com.dre.dungeonsxl.P; import com.dre.dungeonsxl.signs.DSign; import com.dre.dungeonsxl.EditWorld; +import com.dre.dungeonsxl.trigger.RedstoneTrigger; public class GameWorld { private static P p = P.p; @@ -52,7 +53,6 @@ public class GameWorld { public CopyOnWriteArrayList dmobs = new CopyOnWriteArrayList(); public CopyOnWriteArrayList gchests = new CopyOnWriteArrayList(); public CopyOnWriteArrayList dSigns = new CopyOnWriteArrayList(); - public CopyOnWriteArrayList untouchable = new CopyOnWriteArrayList(); public DConfig config; public GameWorld() { @@ -92,16 +92,14 @@ public class GameWorld { } } } + if (RedstoneTrigger.hasTriggers(this)) { + for (RedstoneTrigger trigger : RedstoneTrigger.getTriggersArray(this)) { + trigger.onTrigger(); + } + } for (DSign dSign : this.dSigns) { if (dSign != null) { - if (dSign.isRedstoneTrigger()) { - if (dSign.getRtBlock().isBlockPowered()) { - dSign.onUpdate(0, true); - } else { - dSign.onUpdate(0, false); - } - } - if (!dSign.isRedstoneTrigger() && !dSign.isDistanceTrigger() && !dSign.isSignTrigger()) { + if (!dSign.hasTriggers()) { dSign.onTrigger(); } } diff --git a/src/com/dre/dungeonsxl/listener/BlockListener.java b/src/com/dre/dungeonsxl/listener/BlockListener.java index d1ff1e0a..47e43525 100644 --- a/src/com/dre/dungeonsxl/listener/BlockListener.java +++ b/src/com/dre/dungeonsxl/listener/BlockListener.java @@ -23,6 +23,7 @@ import com.dre.dungeonsxl.LeaveSign; import com.dre.dungeonsxl.game.GamePlaceableBlock; import com.dre.dungeonsxl.game.GameWorld; import com.dre.dungeonsxl.signs.DSign; +import com.dre.dungeonsxl.trigger.RedstoneTrigger; public class BlockListener implements Listener { @@ -189,30 +190,20 @@ public class BlockListener implements Listener { @EventHandler(priority = EventPriority.NORMAL) public void onBlockRedstoneEvent(BlockRedstoneEvent event) { - new RedstoneEventTask(event).runTaskLater(P.p, 1); + new RedstoneEventTask(event.getBlock()).runTaskLater(P.p, 1); } public class RedstoneEventTask extends BukkitRunnable { - private final BlockRedstoneEvent event; + private final Block block; - public RedstoneEventTask(BlockRedstoneEvent event) { - this.event = event; + public RedstoneEventTask(final Block block) { + this.block = block; } public void run() { for (GameWorld gworld : GameWorld.gworlds) { - if (event.getBlock().getWorld() == gworld.world) { - for (DSign sign : gworld.dSigns) { - if (sign != null) { - if (sign.isRedstoneTrigger()) { - if (sign.getRtBlock().isBlockPowered()) { - sign.onUpdate(0, true); - } else { - sign.onUpdate(0, false); - } - } - } - } + if (block.getWorld() == gworld.world) { + RedstoneTrigger.updateAll(gworld); } } } diff --git a/src/com/dre/dungeonsxl/signs/DSign.java b/src/com/dre/dungeonsxl/signs/DSign.java index 0fa27de0..0e573945 100644 --- a/src/com/dre/dungeonsxl/signs/DSign.java +++ b/src/com/dre/dungeonsxl/signs/DSign.java @@ -1,12 +1,14 @@ package com.dre.dungeonsxl.signs; -import org.bukkit.Material; -import org.bukkit.block.Block; -import org.bukkit.block.BlockFace; +import java.util.HashSet; +import java.util.Set; + import org.bukkit.block.Sign; +import org.bukkit.entity.Player; import com.dre.dungeonsxl.P; import com.dre.dungeonsxl.game.GameWorld; +import com.dre.dungeonsxl.trigger.Trigger; public abstract class DSign { protected static P p = P.p; @@ -14,19 +16,8 @@ public abstract class DSign { protected Sign sign; protected GameWorld gworld; - // Distance Trigger - private boolean isDistanceTrigger = false; - private int dtDistance = 5; - - // Redstone Trigger - private boolean isRedstoneTrigger = false; - private Block rtBlock; - - // Sign Trigger - private boolean isSignTrigger = false; - private int stId; - - private boolean[] isPowered = new boolean[2]; + // List of Triggers + private Set triggers = new HashSet(); public abstract boolean check(); @@ -42,43 +33,10 @@ public abstract class DSign { String[] typeSplit = sign.getLine(3).split(","); for (String typeSplitPart : typeSplit) { String[] splitted = typeSplitPart.split(" "); - if (splitted.length > 0) { - if (splitted[0].equalsIgnoreCase("R")) { - if (sign.getBlock().getType() == Material.WALL_SIGN) { - switch (sign.getData().getData()) { - case 5: - rtBlock = sign.getBlock().getRelative(BlockFace.WEST); - break; - case 4: - rtBlock = sign.getBlock().getRelative(BlockFace.EAST); - break; - case 3: - rtBlock = sign.getBlock().getRelative(BlockFace.NORTH); - break; - case 2: - rtBlock = sign.getBlock().getRelative(BlockFace.SOUTH); - break; - } - } else { - rtBlock = sign.getBlock().getRelative(BlockFace.DOWN); - } - - if (rtBlock != null) { - this.isRedstoneTrigger = true; - } - } else if (splitted[0].equalsIgnoreCase("D")) { - this.isDistanceTrigger = true; - - if (splitted.length > 1) { - dtDistance = p.parseInt(splitted[1]); - } - } else if (splitted[0].equalsIgnoreCase("T")) { - this.isSignTrigger = true; - - if (splitted.length > 1) { - stId = p.parseInt(splitted[1]); - } - } + Trigger trigger = Trigger.getOrCreate(splitted, this); + if (trigger != null) { + trigger.addListener(this); + this.triggers.add(trigger); } } } @@ -91,20 +49,41 @@ public abstract class DSign { } + public boolean onPlayerTrigger(Player player) { + return false; + } + public void onDisable() { } - public void onUpdate(int type, boolean powered) { - setPowered(type, powered); - if (isPowered()) { - if (!isDistanceTrigger) { - onTrigger(); + public void onUpdate() { + for (Trigger trigger : triggers) { + if (!trigger.triggered) { + onDisable(); + return; + } + if (triggers.size() == 1) { + if (trigger.player != null) { + if (onPlayerTrigger(trigger.player)) { + return; + } + } } - } else { - onDisable(); } + onTrigger(); + } + + public void remove() { + for (Trigger trigger : triggers) { + trigger.removeListener(this); + } + gworld.dSigns.remove(this); + } + + public boolean hasTriggers() { + return !triggers.isEmpty(); } public static DSign create(Sign sign, GameWorld gworld) { @@ -155,40 +134,8 @@ public abstract class DSign { } // Getter and Setter - public void setPowered(int type, boolean powered) { - isPowered[type] = powered; - } - - public boolean isPowered() {// 0=Redstone 1=Sign - if ((isPowered[0] || !isRedstoneTrigger()) && (isPowered[1] || !isSignTrigger())) { - return true; - } else { - return false; - } - } - - public boolean isRedstoneTrigger() { - return isRedstoneTrigger; - } - - public boolean isDistanceTrigger() { - return isDistanceTrigger; - } - - public Block getRtBlock() { - return rtBlock; - } - - public int getDtDistance() { - return dtDistance; - } - - public boolean isSignTrigger() { - return isSignTrigger; - } - - public int getStId() { - return stId; + public GameWorld getGameWorld() { + return gworld; } public Sign getSign() { diff --git a/src/com/dre/dungeonsxl/signs/SIGNCheckpoint.java b/src/com/dre/dungeonsxl/signs/SIGNCheckpoint.java index 506faf04..15a4a2c4 100644 --- a/src/com/dre/dungeonsxl/signs/SIGNCheckpoint.java +++ b/src/com/dre/dungeonsxl/signs/SIGNCheckpoint.java @@ -41,7 +41,7 @@ public class SIGNCheckpoint extends DSign { P.p.msg(dplayer.player, P.p.language.get("Player_CheckpointReached")); } - this.gworld.dSigns.remove(this); + remove(); } } diff --git a/src/com/dre/dungeonsxl/signs/SIGNMob.java b/src/com/dre/dungeonsxl/signs/SIGNMob.java index 87485e11..7b73d327 100644 --- a/src/com/dre/dungeonsxl/signs/SIGNMob.java +++ b/src/com/dre/dungeonsxl/signs/SIGNMob.java @@ -140,7 +140,7 @@ public class SIGNMob extends DSign { amount--; } else { killTask(); - sign.gworld.dSigns.remove(sign); + sign.remove(); } } diff --git a/src/com/dre/dungeonsxl/signs/SIGNMsg.java b/src/com/dre/dungeonsxl/signs/SIGNMsg.java index 445295ee..69bfe936 100644 --- a/src/com/dre/dungeonsxl/signs/SIGNMsg.java +++ b/src/com/dre/dungeonsxl/signs/SIGNMsg.java @@ -45,21 +45,27 @@ public class SIGNMsg extends DSign { initialized = true; } + @Override + public boolean onPlayerTrigger(Player player) { + if (initialized) { + if (!done.contains(player)) { + p.msg(player, msg); + done.add(player); + } + if (done.size() >= gworld.world.getPlayers().size()) { + remove(); + } + } + return true; + } + @Override public void onTrigger() { if (initialized) { for (Player player : gworld.world.getPlayers()) { - if (!done.contains(player)) { - if (!isDistanceTrigger() || player.getLocation().distance(sign.getLocation()) < getDtDistance()) { - p.msg(player, msg); - done.add(player); - } - } - } - - if (done.size() >= gworld.world.getPlayers().size()) { - this.gworld.dSigns.remove(this); + p.msg(player, msg); } + remove(); } } diff --git a/src/com/dre/dungeonsxl/signs/SIGNSoundMsg.java b/src/com/dre/dungeonsxl/signs/SIGNSoundMsg.java index e3f81065..5886acd9 100644 --- a/src/com/dre/dungeonsxl/signs/SIGNSoundMsg.java +++ b/src/com/dre/dungeonsxl/signs/SIGNSoundMsg.java @@ -55,22 +55,36 @@ public class SIGNSoundMsg extends DSign { if (initialized) { if (P.p.isSpoutEnabled) { for (Player player : gworld.world.getPlayers()) { - if (!done.contains(player)) { - if (!isDistanceTrigger() || player.getLocation().distance(sign.getLocation()) < getDtDistance()) { - done.add(player); - SpoutPlayer sPlayer = Spout.getServer().getPlayer(player.getName()); - if (sPlayer.isSpoutCraftEnabled()) { - SpoutManager.getSoundManager().playCustomMusic(P.p, sPlayer, this.msg, false, this.sign.getLocation()); - } - } + SpoutPlayer sPlayer = Spout.getServer().getPlayer(player.getName()); + if (sPlayer.isSpoutCraftEnabled()) { + SpoutManager.getSoundManager().playCustomMusic(P.p, sPlayer, this.msg, false, this.sign.getLocation()); } } } + remove(); + } + } + + @Override + public boolean onPlayerTrigger(Player player) { + if (initialized) { + if (P.p.isSpoutEnabled) { + if (!done.contains(player)) { + done.add(player); + SpoutPlayer sPlayer = Spout.getServer().getPlayer(player.getName()); + if (sPlayer.isSpoutCraftEnabled()) { + SpoutManager.getSoundManager().playCustomMusic(P.p, sPlayer, this.msg, false, this.sign.getLocation()); + } + } + } else { + remove(); + } if (done.size() >= gworld.world.getPlayers().size()) { - this.gworld.dSigns.remove(this); + remove(); } } + return true; } @Override diff --git a/src/com/dre/dungeonsxl/signs/SIGNTrigger.java b/src/com/dre/dungeonsxl/signs/SIGNTrigger.java index 08d5d975..e45894ab 100644 --- a/src/com/dre/dungeonsxl/signs/SIGNTrigger.java +++ b/src/com/dre/dungeonsxl/signs/SIGNTrigger.java @@ -8,12 +8,12 @@ import org.bukkit.block.Block; import com.dre.dungeonsxl.game.GameWorld; import com.dre.dungeonsxl.EditWorld; +import com.dre.dungeonsxl.trigger.SignTrigger; public class SIGNTrigger extends DSign { public static String name = "Trigger"; public String buildPermissions = "dxl.sign.trigger"; public boolean onDungeonInit = false; - public static Set used = new HashSet(); // Variables private int triggerId; @@ -25,11 +25,14 @@ public class SIGNTrigger extends DSign { @Override public boolean check() { - used.clear(); + Set used = new HashSet(); for (Block block : EditWorld.get(sign.getLocation().getWorld()).sign) { - if (block.getState() instanceof Sign) { - Sign rsign = (Sign) block.getState(); - if (rsign != null) { + if (block != null) { + if (!block.getChunk().isLoaded()) { + block.getChunk().load(); + } + if (block.getState() instanceof Sign) { + Sign rsign = (Sign) block.getState(); if (rsign.getLine(0).equalsIgnoreCase("[" + name + "]")) { used.add(p.parseInt(rsign.getLine(1))); } @@ -69,14 +72,9 @@ public class SIGNTrigger extends DSign { @Override public void onTrigger() { if (initialized) { - for (DSign dsign : this.gworld.dSigns) { - if (dsign != null) { - if (dsign.isSignTrigger()) { - if (triggerId == dsign.getStId()) { - dsign.onUpdate(1, true); - } - } - } + SignTrigger trigger = SignTrigger.get(triggerId, gworld); + if (trigger != null) { + trigger.onTrigger(true); } } } @@ -84,14 +82,9 @@ public class SIGNTrigger extends DSign { @Override public void onDisable() { if (initialized) { - for (DSign dsign : this.gworld.dSigns) { - if (dsign != null) { - if (dsign.isSignTrigger()) { - if (triggerId == dsign.getStId()) { - dsign.onUpdate(1, false); - } - } - } + SignTrigger trigger = SignTrigger.get(triggerId, gworld); + if (trigger != null) { + trigger.onTrigger(false); } } } diff --git a/src/com/dre/dungeonsxl/trigger/DistanceTrigger.java b/src/com/dre/dungeonsxl/trigger/DistanceTrigger.java new file mode 100644 index 00000000..18c29622 --- /dev/null +++ b/src/com/dre/dungeonsxl/trigger/DistanceTrigger.java @@ -0,0 +1,75 @@ +package com.dre.dungeonsxl.trigger; + +import java.util.Map; +import java.util.HashMap; +import java.util.ArrayList; + +import org.bukkit.Location; +import org.bukkit.entity.Player; +import com.dre.dungeonsxl.game.GameWorld; + +public class DistanceTrigger extends Trigger { + + private static Map> triggers = new HashMap>(); + + private int distance = 5; + private Location loc; + + + public DistanceTrigger(int distance, Location loc) { + if (distance >= 0) { + this.distance = distance; + } + this.loc = loc; + } + + public DistanceTrigger(Location loc) { + this.loc = loc; + } + + public void onTrigger(Player player) { + triggered = true; + this.player = player; + updateDSigns(); + + } + + public void register(GameWorld gworld) { + if (!hasTriggers(gworld)) { + ArrayList list = new ArrayList(); + list.add(this); + triggers.put(gworld, list); + } else { + triggers.get(gworld).add(this); + } + } + + public void unregister(GameWorld gworld) { + if (hasTriggers(gworld)) { + triggers.get(gworld).remove(this); + } + } + + public static void triggerAllInDistance(Player player, GameWorld gworld) { + if (hasTriggers(gworld)) { + for (DistanceTrigger trigger : getTriggersArray(gworld)) { + if (player.getLocation().distance(trigger.loc) < trigger.distance) { + trigger.onTrigger(player); + } + } + } + } + + public static boolean hasTriggers(GameWorld gworld) { + return !triggers.isEmpty() && triggers.containsKey(gworld); + } + + public static ArrayList getTriggers(GameWorld gworld) { + return triggers.get(gworld); + } + + public static DistanceTrigger[] getTriggersArray(GameWorld gworld) { + return getTriggers(gworld).toArray(new DistanceTrigger[getTriggers(gworld).size()]); + } + +} diff --git a/src/com/dre/dungeonsxl/trigger/RedstoneTrigger.java b/src/com/dre/dungeonsxl/trigger/RedstoneTrigger.java new file mode 100644 index 00000000..0eca1f64 --- /dev/null +++ b/src/com/dre/dungeonsxl/trigger/RedstoneTrigger.java @@ -0,0 +1,109 @@ +package com.dre.dungeonsxl.trigger; + +import java.util.Map; +import java.util.HashMap; +import java.util.ArrayList; + +import org.bukkit.block.Block; +import org.bukkit.block.BlockFace; +import org.bukkit.Material; +import org.bukkit.block.Sign; + +import com.dre.dungeonsxl.game.GameWorld; + + +public class RedstoneTrigger extends Trigger { + + private static Map> triggers = new HashMap>(); + + private Block rtBlock; + + public RedstoneTrigger(Block block) { + this.rtBlock = block; + } + + public void onTrigger() { + if (rtBlock.isBlockPowered()) { + if (!triggered) { + triggered = true; + updateDSigns(); + } + } else { + if (triggered) { + triggered = false; + updateDSigns(); + } + } + } + + public void register(GameWorld gworld) { + if (!hasTriggers(gworld)) { + ArrayList list = new ArrayList(); + list.add(this); + triggers.put(gworld, list); + } else { + triggers.get(gworld).add(this); + } + } + + public void unregister(GameWorld gworld) { + if (hasTriggers(gworld)) { + triggers.get(gworld).remove(this); + } + } + + public static RedstoneTrigger getOrCreate(Sign sign, GameWorld gworld) { + Block rtBlock = null; + if (sign.getBlock().getType() == Material.WALL_SIGN) { + switch (sign.getData().getData()) { + case 5: + rtBlock = sign.getBlock().getRelative(BlockFace.WEST); + break; + case 4: + rtBlock = sign.getBlock().getRelative(BlockFace.EAST); + break; + case 3: + rtBlock = sign.getBlock().getRelative(BlockFace.NORTH); + break; + case 2: + rtBlock = sign.getBlock().getRelative(BlockFace.SOUTH); + break; + } + } else { + rtBlock = sign.getBlock().getRelative(BlockFace.DOWN); + } + + if (rtBlock != null) { + if (hasTriggers(gworld)) { + for (RedstoneTrigger trigger : getTriggers(gworld)) { + if (trigger.rtBlock.equals(rtBlock)) { + return trigger; + } + } + } + return new RedstoneTrigger(rtBlock); + } + return null; + } + + public static void updateAll(GameWorld gworld) { + if (hasTriggers(gworld)) { + for (RedstoneTrigger trigger : getTriggersArray(gworld)) { + trigger.onTrigger(); + } + } + } + + public static boolean hasTriggers(GameWorld gworld) { + return !triggers.isEmpty() && triggers.containsKey(gworld); + } + + public static ArrayList getTriggers(GameWorld gworld) { + return triggers.get(gworld); + } + + public static RedstoneTrigger[] getTriggersArray(GameWorld gworld) { + return getTriggers(gworld).toArray(new RedstoneTrigger[getTriggers(gworld).size()]); + } + +} diff --git a/src/com/dre/dungeonsxl/trigger/SignTrigger.java b/src/com/dre/dungeonsxl/trigger/SignTrigger.java new file mode 100644 index 00000000..09be5642 --- /dev/null +++ b/src/com/dre/dungeonsxl/trigger/SignTrigger.java @@ -0,0 +1,65 @@ +package com.dre.dungeonsxl.trigger; + +import java.util.Map; +import java.util.HashMap; +import java.util.ArrayList; +import com.dre.dungeonsxl.game.GameWorld; + + +public class SignTrigger extends Trigger { + + private static Map> triggers = new HashMap>(); + + private int stId; + + public SignTrigger(int stId) { + this.stId = stId; + } + + public void onTrigger(boolean enable) { + if (enable != triggered) { + triggered = enable; + updateDSigns(); + } + } + + public void register(GameWorld gworld) { + if (!hasTriggers(gworld)) { + ArrayList list = new ArrayList(); + list.add(this); + triggers.put(gworld, list); + } else { + triggers.get(gworld).add(this); + } + } + + public void unregister(GameWorld gworld) { + if (hasTriggers(gworld)) { + triggers.get(gworld).remove(this); + } + } + + public static SignTrigger getOrCreate(int id, GameWorld gworld) { + SignTrigger trigger = get(id, gworld); + if (trigger != null) { + return trigger; + } + return new SignTrigger(id); + } + + public static SignTrigger get(int id, GameWorld gworld) { + if (hasTriggers(gworld)) { + for (SignTrigger trigger : triggers.get(gworld)) { + if (trigger.stId == id) { + return trigger; + } + } + } + return null; + } + + public static boolean hasTriggers(GameWorld gworld) { + return !triggers.isEmpty() && triggers.containsKey(gworld); + } + +} diff --git a/src/com/dre/dungeonsxl/trigger/Trigger.java b/src/com/dre/dungeonsxl/trigger/Trigger.java new file mode 100644 index 00000000..efd786ff --- /dev/null +++ b/src/com/dre/dungeonsxl/trigger/Trigger.java @@ -0,0 +1,73 @@ +package com.dre.dungeonsxl.trigger; + +import java.util.Set; +import java.util.HashSet; + +import org.bukkit.entity.Player; + +import com.dre.dungeonsxl.P; +import com.dre.dungeonsxl.signs.DSign; +import com.dre.dungeonsxl.game.GameWorld; + +public abstract class Trigger { + + protected Set dsigns = new HashSet(); + public boolean triggered = false; + public Player player = null; // Holds Player for Player specific Triggers + + public Trigger() { + + } + + public abstract void register(GameWorld gworld); + + public abstract void unregister(GameWorld gworld); + + public static Trigger getOrCreate(String[] splitted, DSign dsign) { + Trigger trigger = null; + + if (splitted.length > 0) { + if (splitted[0].equalsIgnoreCase("R")) { + + trigger = RedstoneTrigger.getOrCreate(dsign.getSign(), dsign.getGameWorld()); + + } else if (splitted[0].equalsIgnoreCase("D")) { + + if (splitted.length > 1) { + trigger = new DistanceTrigger(P.p.parseInt(splitted[1]), dsign.getSign().getLocation()); + } else { + trigger = new DistanceTrigger(dsign.getSign().getLocation()); + } + + } else if (splitted[0].equalsIgnoreCase("T")) { + + if (splitted.length > 1) { + trigger = SignTrigger.getOrCreate(P.p.parseInt(splitted[1]), dsign.getGameWorld()); + } + + } + } + return trigger; + } + + public void addListener(DSign dsign) { + if (dsigns.isEmpty()) { + register(dsign.getGameWorld()); + } + dsigns.add(dsign); + } + + public void removeListener(DSign dsign) { + dsigns.remove(dsign); + if (dsigns.isEmpty()) { + unregister(dsign.getGameWorld()); + } + } + + public void updateDSigns() { + for (DSign dsign : dsigns.toArray(new DSign[dsigns.size()])) { + dsign.onUpdate(); + } + } + +}