Reworked Trigger System

This commit is contained in:
Sn0wStorm 2013-08-02 22:54:35 +02:00
parent bad062d4e6
commit 5704852bd4
13 changed files with 434 additions and 173 deletions

View File

@ -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);
}
}
}

View File

@ -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<DMob> dmobs = new CopyOnWriteArrayList<DMob>();
public CopyOnWriteArrayList<GameChest> gchests = new CopyOnWriteArrayList<GameChest>();
public CopyOnWriteArrayList<DSign> dSigns = new CopyOnWriteArrayList<DSign>();
public CopyOnWriteArrayList<Block> untouchable = new CopyOnWriteArrayList<Block>();
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();
}
}

View File

@ -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);
}
}
}

View File

@ -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<Trigger> triggers = new HashSet<Trigger>();
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() {

View File

@ -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();
}
}

View File

@ -140,7 +140,7 @@ public class SIGNMob extends DSign {
amount--;
} else {
killTask();
sign.gworld.dSigns.remove(sign);
sign.remove();
}
}

View File

@ -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();
}
}

View File

@ -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

View File

@ -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<Integer> used = new HashSet<Integer>();
// Variables
private int triggerId;
@ -25,11 +25,14 @@ public class SIGNTrigger extends DSign {
@Override
public boolean check() {
used.clear();
Set<Integer> used = new HashSet<Integer>();
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);
}
}
}

View File

@ -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<GameWorld, ArrayList<DistanceTrigger>> triggers = new HashMap<GameWorld, ArrayList<DistanceTrigger>>();
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<DistanceTrigger> list = new ArrayList<DistanceTrigger>();
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<DistanceTrigger> getTriggers(GameWorld gworld) {
return triggers.get(gworld);
}
public static DistanceTrigger[] getTriggersArray(GameWorld gworld) {
return getTriggers(gworld).toArray(new DistanceTrigger[getTriggers(gworld).size()]);
}
}

View File

@ -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<GameWorld, ArrayList<RedstoneTrigger>> triggers = new HashMap<GameWorld, ArrayList<RedstoneTrigger>>();
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<RedstoneTrigger> list = new ArrayList<RedstoneTrigger>();
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<RedstoneTrigger> getTriggers(GameWorld gworld) {
return triggers.get(gworld);
}
public static RedstoneTrigger[] getTriggersArray(GameWorld gworld) {
return getTriggers(gworld).toArray(new RedstoneTrigger[getTriggers(gworld).size()]);
}
}

View File

@ -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<GameWorld, ArrayList<SignTrigger>> triggers = new HashMap<GameWorld, ArrayList<SignTrigger>>();
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<SignTrigger> list = new ArrayList<SignTrigger>();
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);
}
}

View File

@ -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<DSign> dsigns = new HashSet<DSign>();
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();
}
}
}