Refactor Code

This commit is contained in:
Simon Chuu 2019-03-30 01:29:26 -04:00
parent 9f41e62de5
commit 9ecd44019d
6 changed files with 122 additions and 80 deletions

View File

@ -3,18 +3,35 @@
Better Phantom handling for SMP Better Phantom handling for SMP
# Configuration # Configuration
There is only one option to configure. The configuration details are inside
the config file and will appear after first server run with this plugin.
```yml There are two configuration options that you can set.
# PhantomSMP by SimonOrJ
# Remove phantoms that try to target player slept within three (Minecraft) days? * `remove-targeting-rested`: *Default: true.* Remove phantoms that try to
# true = remove phantom targeting rested player target players who recently rested.
# false = Keep phantoms (and make phantoms try to target another player) * `remove-when-sleeping`: *Default: false.* Remove phantoms as soon as player
remove-targeting-rested: true gets in the bed.
* `disallow-targeting-for`: *Default: 72000.* Ticks since player's last rest
before a phantom starts targeting them.
``` For additional information, check [`config.yml`](src/main/resources/config.yml).
## Permissions
All permission nodes are not applied by default, even to server operators.
* `phantomsmp.disallowspawn`: If given, phantoms will not spawn on this player.
* `phantomsmp.ignore`: If given, phantoms will essentially ignore this player.
For additional information, check [`plugin.yml`](src/main/resources/plugin.yml).
# Disallowing Phantom Spawn
The Bukkit API does not allow for directly checking which player caused the
phantoms to spawn. Therefore, if `disallow-targeting-for` is greater than
72000, phantoms will spawn in for a few seconds until they start targeting a
player. When the very first target of the phantom is a well-rested player,
they will despawn immediately. The same happens when the player is given the
`phantomsmp.disallowspawn` permission.
# External Links # External Links

View File

@ -4,6 +4,7 @@ import org.bukkit.configuration.file.FileConfiguration;
class ConfigSaver { class ConfigSaver {
static final String REMOVE_TARGETING_RESTED_NODE = "remove-targeting-rested"; static final String REMOVE_TARGETING_RESTED_NODE = "remove-targeting-rested";
static final String REMOVE_WHEN_SLEEPING_NODE = "remove-when-sleeping";
static final String DISALLOW_SPAWNING_FOR_NODE = "disallow-targeting-for"; static final String DISALLOW_SPAWNING_FOR_NODE = "disallow-targeting-for";
static final String CONFIG_VERSION_NODE = "config-version"; static final String CONFIG_VERSION_NODE = "config-version";
static final int version = 1; static final int version = 1;
@ -20,6 +21,11 @@ class ConfigSaver {
"# true = remove phantom targeting rested player\n" + "# true = remove phantom targeting rested player\n" +
"# false = Keep phantoms (and make phantoms try to target another player)\n"; "# false = Keep phantoms (and make phantoms try to target another player)\n";
private static final String REMOVE_WHEN_SLEEPING =
"# Remove phantoms right away when the player sleeps in bed?\n" +
"# true = remove phantoms as soon as player sleeps\n" +
"# false = Keep phantoms (and let the above option take care of it)\n";
private static final String DISALLOW_SPAWNING_FOR = private static final String DISALLOW_SPAWNING_FOR =
"# How many ticks since player rested should phantoms ignore the player?\n" + "# How many ticks since player rested should phantoms ignore the player?\n" +
"# NOTE: Any value under 72000 (3 full Minecraft days) will essentially be\n" + "# NOTE: Any value under 72000 (3 full Minecraft days) will essentially be\n" +
@ -31,6 +37,7 @@ class ConfigSaver {
static String saveToString(FileConfiguration config) { static String saveToString(FileConfiguration config) {
boolean remove = config.getBoolean(REMOVE_TARGETING_RESTED_NODE, true); boolean remove = config.getBoolean(REMOVE_TARGETING_RESTED_NODE, true);
boolean sleeping = config.getBoolean(REMOVE_WHEN_SLEEPING_NODE, true);
int disallow = config.getInt(DISALLOW_SPAWNING_FOR_NODE, 72000); int disallow = config.getInt(DISALLOW_SPAWNING_FOR_NODE, 72000);
return HEADER + return HEADER +
@ -39,6 +46,10 @@ class ConfigSaver {
REMOVE_TARGETING_RESTED_NODE + REMOVE_TARGETING_RESTED_NODE +
": " + remove + ": " + remove +
"\n\n" + "\n\n" +
REMOVE_WHEN_SLEEPING +
REMOVE_WHEN_SLEEPING_NODE +
": " + sleeping +
"\n\n" +
DISALLOW_SPAWNING_FOR + DISALLOW_SPAWNING_FOR +
DISALLOW_SPAWNING_FOR_NODE + DISALLOW_SPAWNING_FOR_NODE +
": " + disallow + ": " + disallow +

View File

@ -18,18 +18,16 @@ import org.bukkit.event.player.PlayerJoinEvent;
import org.bukkit.event.player.PlayerQuitEvent; import org.bukkit.event.player.PlayerQuitEvent;
import org.bukkit.event.world.ChunkLoadEvent; import org.bukkit.event.world.ChunkLoadEvent;
import java.util.HashMap; import java.util.*;
import java.util.Iterator;
import java.util.LinkedHashSet;
import java.util.Map;
public class PhantomListener implements Listener { public class PhantomListener implements Listener {
private static final String DISALLOW_SPAWN_PERM = "phantomsmp.disallowspawn"; private static final String DISALLOW_SPAWN_PERM = "phantomsmp.disallowspawn";
private static final String IGNORE_PERM = "phantomsmp.ignore"; private static final String IGNORE_PERM = "phantomsmp.ignore";
private Map<Player, LinkedHashSet<Phantom>> playerPhantomMap = new HashMap<>(); private final Map<Player, LinkedHashSet<Phantom>> playerPhantomMap = new HashMap<>();
private Map<Phantom, Player> phantomPlayerMap = new HashMap<>(); private final Map<Phantom, Player> phantomPlayerMap = new HashMap<>();
private PhantomSMP plugin; private final Set<Phantom> newPhantom = new LinkedHashSet<>();
private final PhantomSMP plugin;
PhantomListener() { PhantomListener() {
this.plugin = PhantomSMP.getInstance(); this.plugin = PhantomSMP.getInstance();
@ -44,75 +42,88 @@ public class PhantomListener implements Listener {
for (Entity e : w.getLivingEntities()) for (Entity e : w.getLivingEntities())
if (e instanceof Phantom) if (e instanceof Phantom)
addPhantom((Phantom) e); targeting((Phantom) e, null, null);
} }
} }
void disable() { private boolean recentlyRested(Player p) {
this.playerPhantomMap = null; return p.getStatistic(Statistic.TIME_SINCE_REST) < plugin.disallowSpawningFor;
this.phantomPlayerMap = null;
this.plugin = null;
} }
private boolean phantomSpawnAllowed(Player p) { private void targeting(Phantom phantom, Player newTarget, Cancellable e) {
return p.getStatistic(Statistic.TIME_SINCE_REST) > plugin.disallowSpawningFor || p.hasPermission(DISALLOW_SPAWN_PERM); plugin.getLogger().info("Targeting triggered");
} Player p;
if (newTarget != null)
private boolean phantomIgnore(Player p) { p = newTarget;
return plugin.removeTargetingRested || p.hasPermission(IGNORE_PERM); else if (phantom.getTarget() instanceof Player) {
} p = (Player) phantom.getTarget();
} else {
private void addPhantom(Phantom phantom) { plugin.getLogger().info("Target is null");
addPhantom(phantom, null);
}
private void addPhantom(Phantom phantom, Cancellable e) {
addPhantom(phantom, null, e);
}
private void addPhantom(Phantom phantom, Player newTarget, Cancellable e) {
if (newTarget == null && !(phantom.getTarget() instanceof Player)) {
return; return;
} }
Player p = newTarget != null ? newTarget : (Player) phantom.getTarget(); // If newly spawned phantom
if (newPhantom.remove(phantom)) {
if (p.hasPermission(DISALLOW_SPAWN_PERM) || recentlyRested(p)) {
if (e != null)
e.setCancelled(true);
phantom.remove();
plugin.getLogger().info("Phantom removed");
return;
}
}
// Player rested before // If targeting is not allowed
if (!phantomSpawnAllowed(p)) { boolean ignore = p.hasPermission(IGNORE_PERM);
if (ignore || recentlyRested(p)) {
if (e != null) if (e != null)
e.setCancelled(true); e.setCancelled(true);
else
phantom.setTarget(null);
if (phantomIgnore(p)) if (!ignore && plugin.removeTargetingRested && phantom.getCustomName() == null)
if (phantom.getCustomName() == null) phantom.remove();
phantom.remove();
plugin.getLogger().info("Phantom targetting cancelled");
return;
} }
// Phantom spawn is legal // Phantom spawn is legal
playerPhantomMap.computeIfAbsent(p, k -> new LinkedHashSet<>()).add(phantom); playerPhantomMap.computeIfAbsent(p, k -> new LinkedHashSet<>()).add(phantom);
phantomPlayerMap.put(phantom, p); phantomPlayerMap.put(phantom, p);
plugin.getLogger().info("Phantom is now targetting");
} }
private void removePlayerPhantom(Player p) { private void spawned(Phantom phantom) {
newPhantom.add(phantom);
plugin.getLogger().info("New phantom spawned");
}
private void untarget(Player p, boolean sleeping) {
Iterator<Phantom> i = playerPhantomMap.get(p).iterator(); Iterator<Phantom> i = playerPhantomMap.get(p).iterator();
while(i.hasNext()) { while(i.hasNext()) {
Phantom phantom = i.next(); Phantom phantom = i.next();
if (phantom.getTarget() == p) { if (phantom.getTarget() == p) {
phantomPlayerMap.remove(phantom); phantomPlayerMap.remove(phantom);
phantom.setTarget(null); phantom.setTarget(null);
plugin.getLogger().info("Phantom no longer targets");
}
if (sleeping && plugin.removeWhenSleeping) {
phantom.remove();
plugin.getLogger().info("Phantom removed");
} }
i.remove(); i.remove();
} }
} }
// Initiate when player joins
@EventHandler(priority = EventPriority.MONITOR) @EventHandler(priority = EventPriority.MONITOR)
public void playerJoin(PlayerJoinEvent e) { public void onPlayerJoin(PlayerJoinEvent e) {
playerPhantomMap.put(e.getPlayer(), new LinkedHashSet<>()); playerPhantomMap.put(e.getPlayer(), new LinkedHashSet<>());
} }
// Reset when player leaves
@EventHandler @EventHandler
public void playerLeave(PlayerQuitEvent e) { public void onPlayerLeave(PlayerQuitEvent e) {
Player p = e.getPlayer(); Player p = e.getPlayer();
for (Phantom phantom : playerPhantomMap.get(p)) { for (Phantom phantom : playerPhantomMap.get(p)) {
@ -123,54 +134,51 @@ public class PhantomListener implements Listener {
} }
} }
// Remove phantoms when player sleeps
@EventHandler @EventHandler
public void playerUseBed(PlayerBedEnterEvent e) { public void onPhantomSpawn(CreatureSpawnEvent e) {
if (e.isCancelled())
return;
removePlayerPhantom(e.getPlayer());
}
@EventHandler
public void playerDied(PlayerDeathEvent e) {
removePlayerPhantom(e.getEntity());
}
// Check phantom when they spawn wrongly
@EventHandler
public void phantomSpawn(CreatureSpawnEvent e) {
if (e.isCancelled() || !(e.getEntity() instanceof Phantom)) { if (e.isCancelled() || !(e.getEntity() instanceof Phantom)) {
return; return;
} }
addPhantom((Phantom) e.getEntity(), e); spawned((Phantom) e.getEntity());
}
@EventHandler
public void onPlayerSleeping(PlayerBedEnterEvent e) {
if (e.isCancelled())
return;
untarget(e.getPlayer(), true);
}
@EventHandler
public void onPlayerDeath(PlayerDeathEvent e) {
untarget(e.getEntity(), false);
} }
// Remove phantom that targets player who slept // Remove phantom that targets player who slept
@EventHandler @EventHandler
public void phantomTarget(EntityTargetLivingEntityEvent e) { public void onPhantomTargeting(EntityTargetLivingEntityEvent e) {
if (e.isCancelled() || !(e.getEntity() instanceof Phantom && e.getTarget() instanceof Player)) { if (e.isCancelled() || !(e.getEntity() instanceof Phantom && e.getTarget() instanceof Player)) {
return; return;
} }
addPhantom((Phantom) e.getEntity(), (Player) e.getTarget(), e); targeting((Phantom) e.getEntity(), (Player) e.getTarget(), e);
} }
// Check phantom in loaded chunks // Check phantom in loaded chunks
@EventHandler @EventHandler
public void phantomInLoadedChunk(ChunkLoadEvent e) { public void onPhantomInLoadedChunk(ChunkLoadEvent e) {
if (e.getWorld().getEnvironment() != World.Environment.NORMAL) if (e.getWorld().getEnvironment() != World.Environment.NORMAL)
return; return;
for (Entity ent : e.getChunk().getEntities()) for (Entity ent : e.getChunk().getEntities())
if (ent instanceof Phantom) if (ent instanceof Phantom)
addPhantom((Phantom) ent); targeting((Phantom) ent, null, null);
} }
// Check phantom on death
@EventHandler @EventHandler
public void phantomDied(EntityDeathEvent e) { public void onPhantomDeath(EntityDeathEvent e) {
if (!(e.getEntity() instanceof Phantom)) if (!(e.getEntity() instanceof Phantom))
return; return;

View File

@ -10,6 +10,7 @@ public class PhantomSMP extends JavaPlugin {
private static PhantomSMP instance = null; private static PhantomSMP instance = null;
private PhantomListener listener = null; private PhantomListener listener = null;
boolean removeTargetingRested; boolean removeTargetingRested;
boolean removeWhenSleeping;
int disallowSpawningFor; int disallowSpawningFor;
@Override @Override
@ -21,6 +22,7 @@ public class PhantomSMP extends JavaPlugin {
saveConfig(); saveConfig();
this.removeTargetingRested = getConfig().getBoolean(ConfigSaver.REMOVE_TARGETING_RESTED_NODE, true); this.removeTargetingRested = getConfig().getBoolean(ConfigSaver.REMOVE_TARGETING_RESTED_NODE, true);
this.removeWhenSleeping = getConfig().getBoolean(ConfigSaver.REMOVE_WHEN_SLEEPING_NODE, false);
this.disallowSpawningFor= getConfig().getInt(ConfigSaver.DISALLOW_SPAWNING_FOR_NODE, 72000); this.disallowSpawningFor= getConfig().getInt(ConfigSaver.DISALLOW_SPAWNING_FOR_NODE, 72000);
this.listener = new PhantomListener(); this.listener = new PhantomListener();
@ -29,9 +31,8 @@ public class PhantomSMP extends JavaPlugin {
@Override @Override
public void onDisable() { public void onDisable() {
PhantomSMP.instance = null;
listener.disable();
listener = null; listener = null;
PhantomSMP.instance = null;
} }
@Override @Override
@ -51,7 +52,7 @@ public class PhantomSMP extends JavaPlugin {
} }
} }
public static PhantomSMP getInstance() { static PhantomSMP getInstance() {
return instance; return instance;
} }
} }

View File

@ -6,9 +6,14 @@
# Remove phantoms that try to target player slept within three (Minecraft) # Remove phantoms that try to target player slept within three (Minecraft)
# days? # days?
# true = remove phantom targeting rested player # true = remove phantom targeting rested player
# false = Keep phantoms (and make phantoms try to target another player) # false = Keep phantoms (and make phantoms ignore the player)
remove-targeting-rested: true remove-targeting-rested: true
# Remove phantoms right away when the player sleeps in bed?
# true = remove phantoms as soon as player sleeps
# false = Keep phantoms (and let the above option take care of it)
remove-when-sleeping: false
# How many ticks since player rested should phantoms ignore the player? # How many ticks since player rested should phantoms ignore the player?
# NOTE: Any value under 72000 (3 full Minecraft days) will essentially be # NOTE: Any value under 72000 (3 full Minecraft days) will essentially be
# ignored for phantom spawning. It will only have an effect on already # ignored for phantom spawning. It will only have an effect on already

View File

@ -8,11 +8,11 @@ api-version: 1.13
permissions: permissions:
phantomsmp.disallowspawn: phantomsmp.disallowspawn:
description: Don't let phantom spawn on the player at all. description: Don't let phantom spawn on the player.
default: false default: false
phantomsmp.ignore: phantomsmp.ignore:
description: > description: >
Don't let phantoms target the player or be removed. Don't let phantoms target the player.
This will ignore `remove-targeting-rested` configuration option for the This will ignore `remove-targeting-rested` configuration option for the
player and keep the phantom flying around. player and keep the phantom flying around as if nothing happened.
default: false default: false