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
# 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
# PhantomSMP by SimonOrJ
There are two configuration options that you can set.
# Remove phantoms that try to target player slept within three (Minecraft) days?
# true = remove phantom targeting rested player
# false = Keep phantoms (and make phantoms try to target another player)
remove-targeting-rested: true
* `remove-targeting-rested`: *Default: true.* Remove phantoms that try to
target players who recently rested.
* `remove-when-sleeping`: *Default: false.* Remove phantoms as soon as player
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

View File

@ -4,6 +4,7 @@ import org.bukkit.configuration.file.FileConfiguration;
class ConfigSaver {
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 CONFIG_VERSION_NODE = "config-version";
static final int version = 1;
@ -20,6 +21,11 @@ class ConfigSaver {
"# true = remove phantom targeting rested 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 =
"# 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" +
@ -31,6 +37,7 @@ class ConfigSaver {
static String saveToString(FileConfiguration config) {
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);
return HEADER +
@ -39,6 +46,10 @@ class ConfigSaver {
REMOVE_TARGETING_RESTED_NODE +
": " + remove +
"\n\n" +
REMOVE_WHEN_SLEEPING +
REMOVE_WHEN_SLEEPING_NODE +
": " + sleeping +
"\n\n" +
DISALLOW_SPAWNING_FOR +
DISALLOW_SPAWNING_FOR_NODE +
": " + disallow +

View File

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

View File

@ -10,6 +10,7 @@ public class PhantomSMP extends JavaPlugin {
private static PhantomSMP instance = null;
private PhantomListener listener = null;
boolean removeTargetingRested;
boolean removeWhenSleeping;
int disallowSpawningFor;
@Override
@ -21,6 +22,7 @@ public class PhantomSMP extends JavaPlugin {
saveConfig();
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.listener = new PhantomListener();
@ -29,9 +31,8 @@ public class PhantomSMP extends JavaPlugin {
@Override
public void onDisable() {
PhantomSMP.instance = null;
listener.disable();
listener = null;
PhantomSMP.instance = null;
}
@Override
@ -51,7 +52,7 @@ public class PhantomSMP extends JavaPlugin {
}
}
public static PhantomSMP getInstance() {
static PhantomSMP getInstance() {
return instance;
}
}

View File

@ -6,9 +6,14 @@
# Remove phantoms that try to target player slept within three (Minecraft)
# days?
# 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 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?
# NOTE: Any value under 72000 (3 full Minecraft days) will essentially be
# ignored for phantom spawning. It will only have an effect on already

View File

@ -8,11 +8,11 @@ api-version: 1.13
permissions:
phantomsmp.disallowspawn:
description: Don't let phantom spawn on the player at all.
description: Don't let phantom spawn on the player.
default: false
phantomsmp.ignore:
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
player and keep the phantom flying around.
player and keep the phantom flying around as if nothing happened.
default: false