diff --git a/plugin.yml b/plugin.yml index d103cdaa..d730ffd8 100644 --- a/plugin.yml +++ b/plugin.yml @@ -38,6 +38,8 @@ permissions: factions.flag.list: {description: list flags, default: false} factions.flag.set: {description: set flags, default: false} factions.flag.show: {description: show flags, default: false} + factions.fly: {description: faction fly, default: false} + factions.fly.other: {description: set faction fly for others, default: false} factions.invite: {description: manage invites, default: false} factions.invite.list: {description: list invited players, default: false} factions.invite.list.other: {description: list invited players of another factions, default: false} @@ -142,6 +144,8 @@ permissions: factions.flag.list: true factions.flag.set: true factions.flag.show: true + factions.fly: true + factions.fly.other: true factions.home: true factions.invite: true factions.invite.list: true @@ -243,6 +247,7 @@ permissions: factions.leader.any: true factions.officer.any: true factions.access.any: true + factions.fly.other: true factions.setpower: true factions.kit.rank1: default: false @@ -280,6 +285,7 @@ permissions: factions.flag.list: true factions.flag.set: true factions.flag.show: true + factions.fly: true factions.home: true factions.invite: true factions.invite.list: true diff --git a/src/com/massivecraft/factions/Factions.java b/src/com/massivecraft/factions/Factions.java index 7d4f2b49..f732dbff 100644 --- a/src/com/massivecraft/factions/Factions.java +++ b/src/com/massivecraft/factions/Factions.java @@ -33,6 +33,7 @@ import com.massivecraft.factions.engine.EngineFlagExplosion; import com.massivecraft.factions.engine.EngineFlagFireSpread; import com.massivecraft.factions.engine.EngineFlagSpawn; import com.massivecraft.factions.engine.EngineFlagZombiegrief; +import com.massivecraft.factions.engine.EngineFly; import com.massivecraft.factions.engine.EngineLastActivity; import com.massivecraft.factions.engine.EngineMotd; import com.massivecraft.factions.engine.EngineMoveChunk; @@ -220,6 +221,7 @@ public class Factions extends MassivePlugin EngineFlagFireSpread.class, EngineFlagSpawn.class, EngineFlagZombiegrief.class, + EngineFly.class, EngineLastActivity.class, EngineMotd.class, EngineMoveChunk.class, diff --git a/src/com/massivecraft/factions/Perm.java b/src/com/massivecraft/factions/Perm.java index 33394b0e..363f7620 100644 --- a/src/com/massivecraft/factions/Perm.java +++ b/src/com/massivecraft/factions/Perm.java @@ -37,6 +37,8 @@ public enum Perm implements Identified FLAG_LIST, FLAG_SET, FLAG_SHOW, + FLY, + FLY_OTHER, HOME, INVITE, INVITE_LIST, diff --git a/src/com/massivecraft/factions/cmd/CmdFactions.java b/src/com/massivecraft/factions/cmd/CmdFactions.java index ab9c5d22..49f960c0 100644 --- a/src/com/massivecraft/factions/cmd/CmdFactions.java +++ b/src/com/massivecraft/factions/cmd/CmdFactions.java @@ -54,6 +54,7 @@ public class CmdFactions extends FactionsCommand public CmdFactionsRelationOld cmdFactionsRelationOldEnemy = new CmdFactionsRelationOld("enemy"); public CmdFactionsPerm cmdFactionsPerm = new CmdFactionsPerm(); public CmdFactionsFlag cmdFactionsFlag = new CmdFactionsFlag(); + public CmdFactionsFly cmdFactionsFly = new CmdFactionsFly(); public CmdFactionsUnstuck cmdFactionsUnstuck = new CmdFactionsUnstuck(); public CmdFactionsOverride cmdFactionsOverride = new CmdFactionsOverride(); public CmdFactionsDisband cmdFactionsDisband = new CmdFactionsDisband(); diff --git a/src/com/massivecraft/factions/cmd/CmdFactionsFly.java b/src/com/massivecraft/factions/cmd/CmdFactionsFly.java new file mode 100644 index 00000000..c5fc2c71 --- /dev/null +++ b/src/com/massivecraft/factions/cmd/CmdFactionsFly.java @@ -0,0 +1,63 @@ +package com.massivecraft.factions.cmd; + +import com.massivecraft.factions.engine.EngineFly; +import com.massivecraft.factions.entity.MPlayer; +import com.massivecraft.massivecore.MassiveException; +import com.massivecraft.massivecore.command.MassiveCommandToggle; +import com.massivecraft.massivecore.engine.EngineMassiveCorePlayerUpdate; +import com.massivecraft.massivecore.ps.PS; +import com.massivecraft.massivecore.util.IdUtil; +import org.bukkit.entity.Player; + +public class CmdFactionsFly extends MassiveCommandToggle +{ + // -------------------------------------------- // + // INSTANCE + // -------------------------------------------- // + + private static CmdFactionsFly i = new CmdFactionsFly(); + public static CmdFactionsFly get() { return i; } + + // -------------------------------------------- // + // CONSTRUCT + // -------------------------------------------- // + + public CmdFactionsFly() + { + super(); + this.setAliases("fly"); + } + + // -------------------------------------------- // + // OVERRIDE + // -------------------------------------------- // + + @Override + public String getName() + { + return "faction flying"; + } + + @Override + public boolean getValue() throws MassiveException + { + return MPlayer.get(sender).isFlying(); + } + + public void setValue(boolean value) throws MassiveException + { + MPlayer mplayer = MPlayer.get(sender); + Player player = IdUtil.getPlayer(sender); + if (player == null) throw new MassiveException().addMsg("Could not find player."); + + PS ps = PS.valueOf(player); + if (value && !EngineFly.canFlyInTerritory(mplayer, ps)) + { + throw new MassiveException().addMsg("You can't fly where you are."); + } + + mplayer.setFlying(value); + EngineMassiveCorePlayerUpdate.update(player, false); + } + +} diff --git a/src/com/massivecraft/factions/engine/EngineFly.java b/src/com/massivecraft/factions/engine/EngineFly.java new file mode 100644 index 00000000..335c3db4 --- /dev/null +++ b/src/com/massivecraft/factions/engine/EngineFly.java @@ -0,0 +1,101 @@ +package com.massivecraft.factions.engine; + +import com.massivecraft.factions.entity.BoardColl; +import com.massivecraft.factions.entity.Faction; +import com.massivecraft.factions.entity.MConf; +import com.massivecraft.factions.entity.MFlag; +import com.massivecraft.factions.entity.MPlayer; +import com.massivecraft.massivecore.Engine; +import com.massivecraft.massivecore.event.EventMassiveCorePlayerUpdate; +import com.massivecraft.massivecore.ps.PS; +import com.massivecraft.massivecore.util.MUtil; +import org.bukkit.entity.Player; +import org.bukkit.event.EventHandler; +import org.bukkit.event.EventPriority; +import org.bukkit.event.player.PlayerMoveEvent; + +public class EngineFly extends Engine +{ + // -------------------------------------------- // + // INSTANCE & CONSTRUCT + // -------------------------------------------- // + + private static EngineFly i = new EngineFly(); + public static EngineFly get() { return i; } + + // -------------------------------------------- // + // LISTENER + // -------------------------------------------- // + + @EventHandler(priority = EventPriority.HIGH, ignoreCancelled = true) + public void onMassiveCorePlayerUpdate(EventMassiveCorePlayerUpdate event) + { + // If we are updating a player ... + Player player = event.getPlayer(); + if (MUtil.isntPlayer(player)) return; + + // ... and that player isn't in creative or spectator mode ... + if (EventMassiveCorePlayerUpdate.isFlyAllowed(player, false)) return; + + // ... and the player is alive ... + if (player.isDead()) return; + + MPlayer mplayer = MPlayer.get(player); + + // ... and the player enables flying ... + if (!mplayer.isFlying()) return; + + // ... and the player enables flying ... + if (!canFlyInTerritory(mplayer, PS.valueOf(player))) return; + + // ... set allowed ... + event.setAllowed(true); + + // ... set speed ... + event.setFlySpeed(MConf.get().flySpeed); + } + + @EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true) + public void moveChunkDetect(PlayerMoveEvent event) + { + // If the player is moving from one chunk to another ... + if (MUtil.isSameChunk(event)) return; + Player player = event.getPlayer(); + if (MUtil.isntPlayer(player)) return; + + // ... gather info on the player and the move ... + MPlayer mplayer = MPlayer.get(player); + PS chunkTo = PS.valueOf(event.getTo()).getChunk(true); + + // ... and they are currently flying ... + if (!mplayer.isFlying()) return; + + // ... but can't fly at the new place ... + if (canFlyInTerritory(mplayer, chunkTo)) return; + + // ... then perhaps they should not be + mplayer.setFlying(false); + deactivateForPlayer(player); + } + + public static boolean canFlyInTerritory(MPlayer mplayer, PS ps) + { + Faction faction = mplayer.getFaction(); + Faction locationFaction = BoardColl.get().getFactionAt(ps.getChunk(true)); + + if (faction != locationFaction) return false; + if (!faction.getFlag(MFlag.getFlagFly())) return false; + + return true; + } + + public static void deactivateForPlayer(Player player) + { + EventMassiveCorePlayerUpdate.resetFlyAllowed(player); + EventMassiveCorePlayerUpdate.resetFlyActive(player); + EventMassiveCorePlayerUpdate.resetFlySpeed(player); + + EventMassiveCorePlayerUpdate.run(player); + } + +} diff --git a/src/com/massivecraft/factions/entity/MConf.java b/src/com/massivecraft/factions/entity/MConf.java index 3c6b1b3a..b394cc09 100644 --- a/src/com/massivecraft/factions/entity/MConf.java +++ b/src/com/massivecraft/factions/entity/MConf.java @@ -321,6 +321,9 @@ public class MConf extends Entity // Make faction disbanding a confirmation thing public boolean requireConfirmationForFactionDisbanding = true; + + // At what speed can players fly with /f fly? + public float flySpeed = 0.1f; // -------------------------------------------- // // DENY COMMANDS diff --git a/src/com/massivecraft/factions/entity/MFlag.java b/src/com/massivecraft/factions/entity/MFlag.java index 59a6eda0..38e150c3 100644 --- a/src/com/massivecraft/factions/entity/MFlag.java +++ b/src/com/massivecraft/factions/entity/MFlag.java @@ -34,6 +34,7 @@ public class MFlag extends Entity implements Prioritized, Registerable, N public final static transient String ID_PERMANENT = "permanent"; public final static transient String ID_PEACEFUL = "peaceful"; public final static transient String ID_INFPOWER = "infpower"; + public final static transient String ID_FLY = "fly"; public final static transient int PRIORITY_OPEN = 1_000; public final static transient int PRIORITY_MONSTERS = 2_000; @@ -50,6 +51,7 @@ public class MFlag extends Entity implements Prioritized, Registerable, N public final static transient int PRIORITY_PERMANENT = 13_000; public final static transient int PRIORITY_PEACEFUL = 14_000; public final static transient int PRIORITY_INFPOWER = 15_000; + public final static transient int PRIORITY_FLY = 16_000; // -------------------------------------------- // // META: CORE @@ -89,6 +91,7 @@ public class MFlag extends Entity implements Prioritized, Registerable, N getFlagPermanent(); getFlagPeaceful(); getFlagInfpower(); + getFlagFly(); } public static MFlag getFlagOpen() { return getCreative(PRIORITY_OPEN, ID_OPEN, ID_OPEN, "Can the faction be joined without an invite?", "Anyone can join. No invite required.", "An invite is required to join.", false, true, true); } @@ -106,6 +109,7 @@ public class MFlag extends Entity implements Prioritized, Registerable, N public static MFlag getFlagPermanent() { return getCreative(PRIORITY_PERMANENT, ID_PERMANENT, ID_PERMANENT, "Is the faction immune to deletion?", "The faction can NOT be deleted.", "The faction can be deleted.", false, false, true); } public static MFlag getFlagPeaceful() { return getCreative(PRIORITY_PEACEFUL, ID_PEACEFUL, ID_PEACEFUL, "Is the faction in truce with everyone?", "The faction is in truce with everyone.", "The faction relations work as usual.", false, false, true); } public static MFlag getFlagInfpower() { return getCreative(PRIORITY_INFPOWER, ID_INFPOWER, ID_INFPOWER, "Does the faction have infinite power?", "The faction has infinite power.", "The faction power works as usual.", false, false, true); } + public static MFlag getFlagFly() { return getCreative(PRIORITY_FLY, ID_FLY, ID_FLY, "Is flying allowed for members in faction territory?", "Members can fly in faction territory.", "Members can not fly in faction territory.", false, false, true); } public static MFlag getCreative(int priority, String id, String name, String desc, String descYes, String descNo, boolean standard, boolean editable, boolean visible) { diff --git a/src/com/massivecraft/factions/entity/MPlayer.java b/src/com/massivecraft/factions/entity/MPlayer.java index 99970865..bbf8e47e 100644 --- a/src/com/massivecraft/factions/entity/MPlayer.java +++ b/src/com/massivecraft/factions/entity/MPlayer.java @@ -175,6 +175,9 @@ public class MPlayer extends SenderEntity implements FactionsParticipat // Null means default specified in MConf. private Boolean territoryInfoTitles = null; + // Is the player doing faction flying? + private Boolean flying = null; + // The Faction this player is currently autoclaiming for. // Null means the player isn't auto claiming. // NOTE: This field will not be saved to the database ever. @@ -582,6 +585,20 @@ public class MPlayer extends SenderEntity implements FactionsParticipat this.changed(); } + // -------------------------------------------- // + // FIELD: fly + // -------------------------------------------- // + + public boolean isFlying() + { + return this.convertGet(this.flying, false, Perm.FLY); + } + + public void setFlying(Boolean flying) + { + this.flying = this.convertSet(flying, this.flying, false); + } + // -------------------------------------------- // // TITLE, NAME, FACTION NAME AND CHAT // -------------------------------------------- //