Fixes a few problems

Makes sure to actually load the configuration when starting the plugin
Makes sure all numeric configuration values are within expected bounds
Adds improved descriptions of configuration values' bounds
Removes the option to not override the vertical speed
Adds options for whether sneaking and sprinting should be blocked while in an arena
Adds more materials to the default config's whitelist
Fixes reloading not properly loading the new config
Fixes config options not loading because the root node was missing
Prevents players combusting while in an arena
This commit is contained in:
Kristian Knarvik 2023-04-11 20:04:04 +02:00
parent 2f4d4ff4c6
commit 4de5ae469b
10 changed files with 132 additions and 60 deletions

View File

@ -111,7 +111,7 @@ public final class Dropper extends JavaPlugin {
// Reload configuration // Reload configuration
this.reloadConfig(); this.reloadConfig();
this.configuration.load(); this.configuration.load(this.getConfig());
// Clear record caches // Clear record caches
this.dropperRecordExpansion.clearCaches(); this.dropperRecordExpansion.clearCaches();
@ -136,6 +136,9 @@ public final class Dropper extends JavaPlugin {
// Plugin startup logic // Plugin startup logic
instance = this; instance = this;
this.saveDefaultConfig(); this.saveDefaultConfig();
getConfig().options().copyDefaults(true);
saveConfig();
reloadConfig();
this.configuration = new DropperConfiguration(this.getConfig()); this.configuration = new DropperConfiguration(this.getConfig());
this.configuration.load(); this.configuration.load();
this.playerRegistry = new DropperArenaPlayerRegistry(); this.playerRegistry = new DropperArenaPlayerRegistry();
@ -163,7 +166,7 @@ public final class Dropper extends JavaPlugin {
if (Bukkit.getPluginManager().getPlugin("PlaceholderAPI") != null) { if (Bukkit.getPluginManager().getPlugin("PlaceholderAPI") != null) {
this.dropperRecordExpansion = new DropperRecordExpansion(this); this.dropperRecordExpansion = new DropperRecordExpansion(this);
if (!this.dropperRecordExpansion.register()) { if (!this.dropperRecordExpansion.register()) {
getLogger().log(Level.WARNING, "Unable to register PlaceholderAPI expansion!"); log(Level.WARNING, "Unable to register PlaceholderAPI expansion!");
} }
} }
} }
@ -195,7 +198,7 @@ public final class Dropper extends JavaPlugin {
command.setTabCompleter(tabCompleter); command.setTabCompleter(tabCompleter);
} }
} else { } else {
getLogger().log(Level.SEVERE, "Unable to register the command " + commandName); log(Level.SEVERE, "Unable to register the command " + commandName);
} }
} }

View File

@ -129,7 +129,7 @@ public class DropperArenaGroup implements ConfigurationSerializable {
DropperArena dropperArena = arenaHandler.getArena(anArenaId); DropperArena dropperArena = arenaHandler.getArena(anArenaId);
if (dropperArena == null) { if (dropperArena == null) {
// The arena would only be null if the arena has been deleted, but not removed from this group // The arena would only be null if the arena has been deleted, but not removed from this group
Dropper.getInstance().getLogger().log(Level.WARNING, "The dropper group " + this.getGroupName() + Dropper.log(Level.WARNING, "The dropper group " + this.getGroupName() +
" contains the arena id " + anArenaId + " which is not a valid arena id!"); " contains the arena id " + anArenaId + " which is not a valid arena id!");
continue; continue;
} }
@ -166,7 +166,7 @@ public class DropperArenaGroup implements ConfigurationSerializable {
DropperArena dropperArena = arenaHandler.getArena(anArenaId); DropperArena dropperArena = arenaHandler.getArena(anArenaId);
if (dropperArena == null) { if (dropperArena == null) {
// The arena would only be null if the arena has been deleted, but not removed from this group // The arena would only be null if the arena has been deleted, but not removed from this group
Dropper.getInstance().getLogger().log(Level.WARNING, String.format("The dropper group %s contains the" + Dropper.log(Level.WARNING, String.format("The dropper group %s contains the" +
" arena id %s which is not a valid arena id!", this.getGroupName(), anArenaId)); " arena id %s which is not a valid arena id!", this.getGroupName(), anArenaId));
continue; continue;
} }

View File

@ -164,8 +164,8 @@ public class DropperArenaHandler {
this.arenaNameLookup.remove(arena.getArenaNameSanitized()); this.arenaNameLookup.remove(arena.getArenaNameSanitized());
this.arenaGroups.remove(arenaId); this.arenaGroups.remove(arenaId);
if (!ArenaStorageHelper.removeArenaData(arenaId)) { if (!ArenaStorageHelper.removeArenaData(arenaId)) {
Dropper.getInstance().getLogger().log(Level.WARNING, "Unable to remove dropper arena data file " + Dropper.log(Level.WARNING, "Unable to remove dropper arena data file " + arenaId + ".yml. " +
arenaId + ".yml. You must remove it manually!"); "You must remove it manually!");
} }
this.saveArenas(); this.saveArenas();
} }
@ -179,8 +179,8 @@ public class DropperArenaHandler {
try { try {
ArenaStorageHelper.saveArenaData(this.arenas.get(arenaId).getData()); ArenaStorageHelper.saveArenaData(this.arenas.get(arenaId).getData());
} catch (IOException e) { } catch (IOException e) {
Dropper.getInstance().getLogger().log(Level.SEVERE, "Unable to save arena data! Data loss can occur!"); Dropper.log(Level.SEVERE, "Unable to save arena data! Data loss can occur!");
Dropper.getInstance().getLogger().log(Level.SEVERE, e.getMessage()); Dropper.log(Level.SEVERE, e.getMessage());
} }
} }
@ -191,9 +191,9 @@ public class DropperArenaHandler {
try { try {
ArenaStorageHelper.saveDropperArenaGroups(new HashSet<>(this.arenaGroups.values())); ArenaStorageHelper.saveDropperArenaGroups(new HashSet<>(this.arenaGroups.values()));
} catch (IOException e) { } catch (IOException e) {
Dropper.getInstance().getLogger().log(Level.SEVERE, "Unable to save current arena groups! " + Dropper.log(Level.SEVERE, "Unable to save current arena groups! " +
"Data loss can occur!"); "Data loss can occur!");
Dropper.getInstance().getLogger().log(Level.SEVERE, e.getMessage()); Dropper.log(Level.SEVERE, e.getMessage());
} }
} }
@ -218,9 +218,9 @@ public class DropperArenaHandler {
try { try {
ArenaStorageHelper.saveArenas(this.arenas); ArenaStorageHelper.saveArenas(this.arenas);
} catch (IOException e) { } catch (IOException e) {
Dropper.getInstance().getLogger().log(Level.SEVERE, "Unable to save current arenas! " + Dropper.log(Level.SEVERE, "Unable to save current arenas! " +
"Data loss can occur!"); "Data loss can occur!");
Dropper.getInstance().getLogger().log(Level.SEVERE, e.getMessage()); Dropper.log(Level.SEVERE, e.getMessage());
} }
} }

View File

@ -109,8 +109,8 @@ public class DropperArenaSession {
// Remove this session for game sessions to stop listeners from fiddling more with the player // Remove this session for game sessions to stop listeners from fiddling more with the player
boolean removedSession = Dropper.getInstance().getPlayerRegistry().removePlayer(player.getUniqueId()); boolean removedSession = Dropper.getInstance().getPlayerRegistry().removePlayer(player.getUniqueId());
if (!removedSession) { if (!removedSession) {
Dropper.getInstance().getLogger().log(Level.SEVERE, "Unable to remove dropper arena session for " + Dropper.log(Level.SEVERE, "Unable to remove dropper arena session for " + player.getName() + ". " +
player.getName() + ". This will have unintended consequences."); "This will have unintended consequences.");
} }
} }

View File

@ -15,9 +15,13 @@ import java.util.logging.Level;
import java.util.regex.Matcher; import java.util.regex.Matcher;
import java.util.regex.Pattern; import java.util.regex.Pattern;
/**
* The configuration keeping track of the player's current configuration
*/
public class DropperConfiguration { public class DropperConfiguration {
private final FileConfiguration configuration; private FileConfiguration configuration;
private final static String rootNode = "dropper.";
private double verticalVelocity; private double verticalVelocity;
private float horizontalVelocity; private float horizontalVelocity;
@ -27,9 +31,10 @@ public class DropperConfiguration {
private boolean mustDoNormalModeFirst; private boolean mustDoNormalModeFirst;
private boolean makePlayersInvisible; private boolean makePlayersInvisible;
private boolean disableHitCollision; private boolean disableHitCollision;
private boolean overrideVerticalVelocity;
private double liquidHitBoxDepth; private double liquidHitBoxDepth;
private double solidHitBoxDistance; private double solidHitBoxDistance;
private boolean blockSneaking;
private boolean blockSprinting;
private Set<Material> blockWhitelist; private Set<Material> blockWhitelist;
/** /**
@ -41,15 +46,6 @@ public class DropperConfiguration {
this.configuration = configuration; this.configuration = configuration;
} }
/**
* Gets whether vertical velocity should be overridden
*
* @return <p>Whether vertical velocity should be overridden</p>
*/
public boolean overrideVerticalVelocity() {
return this.overrideVerticalVelocity;
}
/** /**
* Gets the default vertical velocity * Gets the default vertical velocity
* *
@ -155,21 +151,50 @@ public class DropperConfiguration {
return this.solidHitBoxDistance; return this.solidHitBoxDistance;
} }
/**
* Gets whether players trying to sneak while in a dropper arena to increase their downwards speed should be blocked
*
* @return <p>Whether to block sneak to speed up</p>
*/
public boolean blockSneaking() {
return blockSneaking;
}
/**
* Gets whether players trying to sprint to improve their horizontal speed while in a dropper arena should be blocked
*
* @return <p>Whether to block sprint to speed up</p>
*/
public boolean blockSprinting() {
return this.blockSprinting;
}
/**
* Loads all configuration values from disk
*
* @param configuration <p>The configuration to load</p>
*/
public void load(FileConfiguration configuration) {
this.configuration = configuration;
this.load();
}
/** /**
* Loads all configuration values from disk * Loads all configuration values from disk
*/ */
public void load() { public void load() {
this.verticalVelocity = configuration.getDouble("verticalVelocity", 1.0); this.verticalVelocity = configuration.getDouble(rootNode + "verticalVelocity", 1.0);
this.horizontalVelocity = (float) configuration.getDouble("horizontalVelocity", 1.0); this.horizontalVelocity = (float) configuration.getDouble(rootNode + "horizontalVelocity", 1.0);
this.randomlyInvertedTimer = configuration.getInt("randomlyInvertedTimer", 7); this.randomlyInvertedTimer = configuration.getInt(rootNode + "randomlyInvertedTimer", 7);
this.mustDoGroupedInSequence = configuration.getBoolean("mustDoGroupedInSequence", true); this.mustDoGroupedInSequence = configuration.getBoolean(rootNode + "mustDoGroupedInSequence", true);
this.ignoreRecordsUntilGroupBeatenOnce = configuration.getBoolean("ignoreRecordsUntilGroupBeatenOnce", false); this.ignoreRecordsUntilGroupBeatenOnce = configuration.getBoolean(rootNode + "ignoreRecordsUntilGroupBeatenOnce", false);
this.mustDoNormalModeFirst = configuration.getBoolean("mustDoNormalModeFirst", true); this.mustDoNormalModeFirst = configuration.getBoolean(rootNode + "mustDoNormalModeFirst", true);
this.makePlayersInvisible = configuration.getBoolean("makePlayersInvisible", false); this.makePlayersInvisible = configuration.getBoolean(rootNode + "makePlayersInvisible", false);
this.disableHitCollision = configuration.getBoolean("disableHitCollision", true); this.disableHitCollision = configuration.getBoolean(rootNode + "disableHitCollision", true);
this.overrideVerticalVelocity = configuration.getBoolean("overrideVerticalVelocity", true); this.liquidHitBoxDepth = configuration.getDouble(rootNode + "liquidHitBoxDepth", -0.8);
this.liquidHitBoxDepth = configuration.getDouble("liquidHitBoxDepth", -0.8); this.solidHitBoxDistance = configuration.getDouble(rootNode + "solidHitBoxDistance", 0.2);
this.solidHitBoxDistance = configuration.getDouble("solidHitBoxDistance", 0.2); this.blockSprinting = configuration.getBoolean(rootNode + "blockSprinting", true);
this.blockSneaking = configuration.getBoolean(rootNode + "blockSneaking", true);
sanitizeValues(); sanitizeValues();
loadBlockWhitelist(); loadBlockWhitelist();
@ -205,7 +230,7 @@ public class DropperConfiguration {
*/ */
private void loadBlockWhitelist() { private void loadBlockWhitelist() {
this.blockWhitelist = new HashSet<>(); this.blockWhitelist = new HashSet<>();
List<?> blockWhitelist = configuration.getList("blockWhiteList", new ArrayList<>()); List<?> blockWhitelist = configuration.getList(rootNode + "blockWhitelist", new ArrayList<>());
for (Object value : blockWhitelist) { for (Object value : blockWhitelist) {
if (!(value instanceof String string)) { if (!(value instanceof String string)) {
continue; continue;
@ -249,4 +274,25 @@ public class DropperConfiguration {
return false; return false;
} }
@Override
public String toString() {
StringBuilder builder = new StringBuilder(
"Current configuration:" +
"\n" + "Vertical velocity: " + verticalVelocity +
"\n" + "Horizontal velocity: " + horizontalVelocity +
"\n" + "Randomly inverted timer: " + randomlyInvertedTimer +
"\n" + "Must do groups in sequence: " + mustDoGroupedInSequence +
"\n" + "Ignore records until group beaten once: " + ignoreRecordsUntilGroupBeatenOnce +
"\n" + "Must do normal mode first: " + mustDoNormalModeFirst +
"\n" + "Make players invisible: " + makePlayersInvisible +
"\n" + "Disable hit collision: " + disableHitCollision +
"\n" + "Liquid hit box depth: " + liquidHitBoxDepth +
"\n" + "Solid hit box distance: " + solidHitBoxDistance +
"\n" + "Block whitelist: ");
for (Material material : blockWhitelist) {
builder.append("\n - ").append(material.name());
}
return builder.toString();
}
} }

View File

@ -1,11 +1,13 @@
package net.knarcraft.dropper.listener; package net.knarcraft.dropper.listener;
import net.knarcraft.dropper.Dropper; import net.knarcraft.dropper.Dropper;
import net.knarcraft.dropper.arena.DropperArenaPlayerRegistry;
import net.knarcraft.dropper.arena.DropperArenaSession; import net.knarcraft.dropper.arena.DropperArenaSession;
import org.bukkit.entity.EntityType; import org.bukkit.entity.EntityType;
import org.bukkit.entity.Player; import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler; import org.bukkit.event.EventHandler;
import org.bukkit.event.Listener; import org.bukkit.event.Listener;
import org.bukkit.event.entity.EntityCombustEvent;
import org.bukkit.event.entity.EntityDamageEvent; import org.bukkit.event.entity.EntityDamageEvent;
/** /**
@ -36,4 +38,18 @@ public class DamageListener implements Listener {
} }
} }
@EventHandler(ignoreCancelled = true)
public void onPlayerCombustion(EntityCombustEvent event) {
if (event.getEntityType() != EntityType.PLAYER) {
return;
}
DropperArenaPlayerRegistry registry = Dropper.getInstance().getPlayerRegistry();
DropperArenaSession arenaSession = registry.getArenaSession(event.getEntity().getUniqueId());
if (arenaSession != null) {
// Cancel combustion for any player in an arena
event.setCancelled(true);
}
}
} }

View File

@ -48,9 +48,11 @@ public class MoveListener implements Listener {
if (arenaSession == null) { if (arenaSession == null) {
return; return;
} }
// Prevent the player from flying upwards while in flight mode // Prevent the player from flying upwards while in flight mode
if (event.getFrom().getY() < event.getTo().getY()) { if (event.getFrom().getY() < event.getTo().getY() ||
(configuration.blockSneaking() && event.getPlayer().isSneaking()) ||
(configuration.blockSprinting() && event.getPlayer().isSprinting())) {
event.setCancelled(true); event.setCancelled(true);
return; return;
} }
@ -125,14 +127,12 @@ public class MoveListener implements Listener {
* @param session <p>The session to update the velocity for</p> * @param session <p>The session to update the velocity for</p>
*/ */
private void updatePlayerVelocity(@NotNull DropperArenaSession session) { private void updatePlayerVelocity(@NotNull DropperArenaSession session) {
// Override the vertical velocity, if enabled // Override the vertical velocity
if (configuration.overrideVerticalVelocity()) { Player player = session.getPlayer();
Player player = session.getPlayer(); Vector playerVelocity = player.getVelocity();
Vector playerVelocity = player.getVelocity(); double arenaVelocity = session.getArena().getPlayerVerticalVelocity();
double arenaVelocity = session.getArena().getPlayerVerticalVelocity(); Vector newVelocity = new Vector(playerVelocity.getX() * 5, -arenaVelocity, playerVelocity.getZ() * 5);
Vector newVelocity = new Vector(playerVelocity.getX(), -arenaVelocity, playerVelocity.getZ()); player.setVelocity(newVelocity);
player.setVelocity(newVelocity);
}
// Toggle the direction of the player's flying, as necessary // Toggle the direction of the player's flying, as necessary
toggleFlyInversion(session); toggleFlyInversion(session);

View File

@ -32,7 +32,7 @@ public class PlayerLeaveListener implements Listener {
return; return;
} }
Dropper.getInstance().getLogger().log(Level.WARNING, "Found player " + player.getUniqueId() + Dropper.log(Level.WARNING, "Found player " + player.getUniqueId() +
" leaving in the middle of a session!"); " leaving in the middle of a session!");
leftSessions.put(player.getUniqueId(), arenaSession); leftSessions.put(player.getUniqueId(), arenaSession);
} }
@ -42,10 +42,10 @@ public class PlayerLeaveListener implements Listener {
UUID playerId = event.getPlayer().getUniqueId(); UUID playerId = event.getPlayer().getUniqueId();
// Force the player to quit from the session once they re-join // Force the player to quit from the session once they re-join
if (leftSessions.containsKey(playerId)) { if (leftSessions.containsKey(playerId)) {
Dropper.getInstance().getLogger().log(Level.WARNING, "Found un-exited dropper session!"); Dropper.log(Level.WARNING, "Found un-exited dropper session!");
Bukkit.getScheduler().runTaskLater(Dropper.getInstance(), () -> { Bukkit.getScheduler().runTaskLater(Dropper.getInstance(), () -> {
leftSessions.get(playerId).triggerQuit(false); leftSessions.get(playerId).triggerQuit(false);
Dropper.getInstance().getLogger().log(Level.WARNING, "Triggered a quit!"); Dropper.log(Level.WARNING, "Triggered a quit!");
leftSessions.remove(playerId); leftSessions.remove(playerId);
}, 80); }, 80);
} }

View File

@ -24,7 +24,6 @@ import java.util.Map;
import java.util.Set; import java.util.Set;
import java.util.UUID; import java.util.UUID;
import java.util.logging.Level; import java.util.logging.Level;
import java.util.logging.Logger;
/** /**
* A helper class for saving and loading arenas * A helper class for saving and loading arenas
@ -153,10 +152,9 @@ public final class ArenaStorageHelper {
ArenaStorageKey.PLAYER_HORIZONTAL_VELOCITY.getKey())); ArenaStorageKey.PLAYER_HORIZONTAL_VELOCITY.getKey()));
SerializableMaterial winBlockType = (SerializableMaterial) configurationSection.get( SerializableMaterial winBlockType = (SerializableMaterial) configurationSection.get(
ArenaStorageKey.WIN_BLOCK_TYPE.getKey()); ArenaStorageKey.WIN_BLOCK_TYPE.getKey());
Logger logger = Dropper.getInstance().getLogger();
if (arenaName == null || spawnLocation == null) { if (arenaName == null || spawnLocation == null) {
logger.log(Level.SEVERE, "Could not load the arena at configuration " + Dropper.log(Level.SEVERE, "Could not load the arena at configuration " +
"section " + configurationSection.getName() + ". Please check the arenas storage file for issues."); "section " + configurationSection.getName() + ". Please check the arenas storage file for issues.");
return null; return null;
} }
@ -166,7 +164,7 @@ public final class ArenaStorageHelper {
DropperArenaData arenaData = loadArenaData(arenaId); DropperArenaData arenaData = loadArenaData(arenaId);
if (arenaData == null) { if (arenaData == null) {
logger.log(Level.SEVERE, "Unable to load arena data for " + arenaId); Dropper.log(Level.SEVERE, "Unable to load arena data for " + arenaId);
Map<ArenaGameMode, DropperArenaRecordsRegistry> recordRegistries = new HashMap<>(); Map<ArenaGameMode, DropperArenaRecordsRegistry> recordRegistries = new HashMap<>();
for (ArenaGameMode arenaGameMode : ArenaGameMode.values()) { for (ArenaGameMode arenaGameMode : ArenaGameMode.values()) {
@ -222,7 +220,7 @@ public final class ArenaStorageHelper {
private static @NotNull File getArenaDataFile(@NotNull UUID arenaId) { private static @NotNull File getArenaDataFile(@NotNull UUID arenaId) {
File arenaDataFile = new File(arenaDataFolder, arenaId + ".yml"); File arenaDataFile = new File(arenaDataFolder, arenaId + ".yml");
if (!arenaDataFolder.exists() && !arenaDataFolder.mkdirs()) { if (!arenaDataFolder.exists() && !arenaDataFolder.mkdirs()) {
Dropper.getInstance().getLogger().log(Level.SEVERE, "Unable to create the arena data directories"); Dropper.log(Level.SEVERE, "Unable to create the arena data directories");
} }
return arenaDataFile; return arenaDataFile;
} }

View File

@ -1,8 +1,10 @@
# Configuration values for droppers # Configuration values for droppers
dropper: dropper:
# Whether the vertical velocity should be overridden, and thus changeable. If not enabled, all horizontalVelocity # Whether to block using the shift key to drop faster than the intended drop speed
# settings, both the global one and per-arena, will be ignored. blockSneaking: true
overrideVerticalVelocity: true
# Whether to block using the sprint key for slightly improved air speed
blockSprinting: true
# The vertical velocity used as default for all arenas. Must be greater than 0. 3.92 is the max speed of a falling # The vertical velocity used as default for all arenas. Must be greater than 0. 3.92 is the max speed of a falling
# player. # player.
@ -47,4 +49,11 @@ dropper:
- LAVA - LAVA
- +WALL_SIGNS - +WALL_SIGNS
- +STANDING_SIGNS - +STANDING_SIGNS
- STRUCTURE_VOID - STRUCTURE_VOID
- WALL_TORCH
- SOUL_WALL_TORCH
- REDSTONE_WALL_TORCH
- +BANNERS
- +BUTTONS
- +CORALS
- +WALL_CORALS