mirror of
https://github.com/SunNetservers/MiniGames.git
synced 2025-07-06 16:14:45 +02:00
Compare commits
7 Commits
Author | SHA1 | Date | |
---|---|---|---|
9a56f58f2f | |||
592f53ec9e | |||
49eb0ac82c | |||
0c58860026 | |||
6385b4c5e8 | |||
14572de102 | |||
fba75d2c3f |
@ -2,6 +2,7 @@ package net.knarcraft.dropper;
|
||||
|
||||
import net.knarcraft.dropper.arena.DropperArenaHandler;
|
||||
import net.knarcraft.dropper.arena.DropperArenaPlayerRegistry;
|
||||
import net.knarcraft.dropper.arena.DropperArenaRecordsRegistry;
|
||||
import net.knarcraft.dropper.command.CreateArenaCommand;
|
||||
import net.knarcraft.dropper.command.EditArenaCommand;
|
||||
import net.knarcraft.dropper.command.EditArenaTabCompleter;
|
||||
@ -9,13 +10,18 @@ import net.knarcraft.dropper.command.JoinArenaCommand;
|
||||
import net.knarcraft.dropper.command.JoinArenaTabCompleter;
|
||||
import net.knarcraft.dropper.command.LeaveArenaCommand;
|
||||
import net.knarcraft.dropper.command.ListArenaCommand;
|
||||
import net.knarcraft.dropper.command.ReloadCommand;
|
||||
import net.knarcraft.dropper.command.RemoveArenaCommand;
|
||||
import net.knarcraft.dropper.command.RemoveArenaTabCompleter;
|
||||
import net.knarcraft.dropper.container.SerializableMaterial;
|
||||
import net.knarcraft.dropper.container.SerializableUUID;
|
||||
import net.knarcraft.dropper.listener.DamageListener;
|
||||
import net.knarcraft.dropper.listener.MoveListener;
|
||||
import net.knarcraft.dropper.listener.PlayerLeaveListener;
|
||||
import org.bukkit.command.CommandExecutor;
|
||||
import org.bukkit.command.PluginCommand;
|
||||
import org.bukkit.command.TabCompleter;
|
||||
import org.bukkit.configuration.serialization.ConfigurationSerialization;
|
||||
import org.bukkit.plugin.PluginManager;
|
||||
import org.bukkit.plugin.java.JavaPlugin;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
@ -60,6 +66,23 @@ public final class Dropper extends JavaPlugin {
|
||||
return this.playerRegistry;
|
||||
}
|
||||
|
||||
/**
|
||||
* Reloads all configurations and data from disk
|
||||
*/
|
||||
public void reload() {
|
||||
// Load all arenas again
|
||||
this.arenaHandler.loadArenas();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onLoad() {
|
||||
super.onLoad();
|
||||
// Register serialization classes
|
||||
ConfigurationSerialization.registerClass(SerializableMaterial.class);
|
||||
ConfigurationSerialization.registerClass(DropperArenaRecordsRegistry.class);
|
||||
ConfigurationSerialization.registerClass(SerializableUUID.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onEnable() {
|
||||
// Plugin startup logic
|
||||
@ -83,12 +106,13 @@ public final class Dropper extends JavaPlugin {
|
||||
pluginManager.registerEvents(new MoveListener(), this);
|
||||
pluginManager.registerEvents(new PlayerLeaveListener(), this);
|
||||
|
||||
registerCommand("dropperreload", new ReloadCommand(), null);
|
||||
registerCommand("droppercreate", new CreateArenaCommand(), null);
|
||||
registerCommand("dropperlist", new ListArenaCommand(), null);
|
||||
registerCommand("dropperjoin", new JoinArenaCommand(), new JoinArenaTabCompleter());
|
||||
registerCommand("dropperleave", new LeaveArenaCommand(), null);
|
||||
registerCommand("dropperedit", new EditArenaCommand(), new EditArenaTabCompleter());
|
||||
registerCommand("dropperremove", new RemoveArenaCommand(), null);
|
||||
registerCommand("dropperremove", new RemoveArenaCommand(), new RemoveArenaTabCompleter());
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -1,6 +1,7 @@
|
||||
package net.knarcraft.dropper.arena;
|
||||
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.Material;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
@ -28,7 +29,14 @@ public class DropperArena {
|
||||
/**
|
||||
* The velocity in the y-direction to apply to all players in this arena.
|
||||
*/
|
||||
private final double playerVelocity;
|
||||
private final double playerVerticalVelocity;
|
||||
|
||||
/**
|
||||
* The velocity in the x-direction to apply to all players in this arena
|
||||
*
|
||||
* <p>This is technically the fly speed</p>
|
||||
*/
|
||||
private final double playerHorizontalVelocity;
|
||||
|
||||
/**
|
||||
* The stage number of this arena. If not null, the previous stage number must be cleared before access.
|
||||
@ -40,26 +48,36 @@ public class DropperArena {
|
||||
*/
|
||||
private final @NotNull DropperArenaRecordsRegistry recordsRegistry;
|
||||
|
||||
/**
|
||||
* The material of the block players have to hit to win this dropper arena
|
||||
*/
|
||||
private final @NotNull Material winBlockType;
|
||||
|
||||
//TODO: Store records for this arena (maps with player->deaths/time). It should be possible to get those in sorted
|
||||
// order (smallest to largest)
|
||||
|
||||
/**
|
||||
* Instantiates a new dropper arena
|
||||
*
|
||||
* @param arenaName <p>The name of the arena</p>
|
||||
* @param spawnLocation <p>The location players spawn in when entering the arena</p>
|
||||
* @param exitLocation <p>The location the players are teleported to when exiting the arena, or null</p>
|
||||
* @param playerVelocity <p>The velocity multiplier to use for players' velocity</p>
|
||||
* @param stage <p>The stage number of this stage, or null if not limited to stages</p>
|
||||
* @param recordsRegistry <p>The registry keeping track of all of this arena's records</p>
|
||||
* @param arenaName <p>The name of the arena</p>
|
||||
* @param spawnLocation <p>The location players spawn in when entering the arena</p>
|
||||
* @param exitLocation <p>The location the players are teleported to when exiting the arena, or null</p>
|
||||
* @param playerVerticalVelocity <p>The velocity to use for players' vertical velocity</p>
|
||||
* @param playerHorizontalVelocity <p>The velocity to use for players' horizontal velocity</p>
|
||||
* @param stage <p>The stage number of this stage, or null if not limited to stages</p>
|
||||
* @param winBlockType <p>The material of the block players have to hit to win this dropper arena</p>
|
||||
* @param recordsRegistry <p>The registry keeping track of all of this arena's records</p>
|
||||
*/
|
||||
public DropperArena(@NotNull String arenaName, @NotNull Location spawnLocation, @Nullable Location exitLocation,
|
||||
double playerVelocity, @Nullable Integer stage, @NotNull DropperArenaRecordsRegistry recordsRegistry) {
|
||||
double playerVerticalVelocity, double playerHorizontalVelocity, @Nullable Integer stage, @NotNull Material winBlockType,
|
||||
@NotNull DropperArenaRecordsRegistry recordsRegistry) {
|
||||
this.arenaName = arenaName;
|
||||
this.spawnLocation = spawnLocation;
|
||||
this.exitLocation = exitLocation;
|
||||
this.playerVelocity = playerVelocity;
|
||||
this.playerVerticalVelocity = playerVerticalVelocity;
|
||||
this.playerHorizontalVelocity = playerHorizontalVelocity;
|
||||
this.stage = stage;
|
||||
this.winBlockType = winBlockType;
|
||||
this.recordsRegistry = recordsRegistry;
|
||||
}
|
||||
|
||||
@ -76,9 +94,11 @@ public class DropperArena {
|
||||
this.arenaName = arenaName;
|
||||
this.spawnLocation = spawnLocation;
|
||||
this.exitLocation = null;
|
||||
this.playerVelocity = 1;
|
||||
this.playerVerticalVelocity = 1;
|
||||
this.playerHorizontalVelocity = 1;
|
||||
this.stage = null;
|
||||
this.recordsRegistry = new DropperArenaRecordsRegistry();
|
||||
this.winBlockType = Material.WATER;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -120,15 +140,26 @@ public class DropperArena {
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the velocity for players in this arena
|
||||
* Gets the vertical velocity for players in this arena
|
||||
*
|
||||
* <p>The velocity is the multiplier used to define players' dropping speed in this dropper arena. 1.0 is the normal
|
||||
* falling speed. 0.5 is half speed. 2 is double speed etc.</p>
|
||||
* <p>This velocity will be set on the negative y-axis, for all players in this arena.</p>
|
||||
*
|
||||
* @return <p>Players' velocity in this arena</p>
|
||||
*/
|
||||
public double getPlayerVelocity() {
|
||||
return this.playerVelocity;
|
||||
public double getPlayerVerticalVelocity() {
|
||||
return this.playerVerticalVelocity;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Gets the horizontal for players in this arena
|
||||
*
|
||||
* <p>This will be used for players' fly-speed in this arena</p>
|
||||
*
|
||||
* @return <p>Players' velocity in this arena</p>
|
||||
*/
|
||||
public double getPlayerHorizontalVelocity() {
|
||||
return this.playerHorizontalVelocity;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -143,6 +174,13 @@ public class DropperArena {
|
||||
return this.stage;
|
||||
}
|
||||
|
||||
//TODO: Add the appropriate getters/setters and other methods
|
||||
/**
|
||||
* Gets the type of block a player has to hit to win this arena
|
||||
*
|
||||
* @return <p>The kind of block players must hit</p>
|
||||
*/
|
||||
public @NotNull Material getWinBlockType() {
|
||||
return this.winBlockType;
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -4,6 +4,7 @@ import net.knarcraft.dropper.Dropper;
|
||||
import net.knarcraft.dropper.util.ArenaStorageHelper;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
@ -50,6 +51,22 @@ public class DropperArenaHandler {
|
||||
this.saveArenas();
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the arena with the given name
|
||||
*
|
||||
* @param arenaName <p>The arena to get</p>
|
||||
* @return <p>The arena with the given name, or null if not found</p>
|
||||
*/
|
||||
public @Nullable DropperArena getArena(@NotNull String arenaName) {
|
||||
arenaName = ArenaStorageHelper.sanitizeArenaName(arenaName);
|
||||
for (DropperArena arena : arenas) {
|
||||
if (ArenaStorageHelper.sanitizeArenaName(arena.getArenaName()).equals(arenaName)) {
|
||||
return arena;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets all known arenas
|
||||
*
|
||||
@ -65,6 +82,7 @@ public class DropperArenaHandler {
|
||||
* @param arena <p>The arena to remove</p>
|
||||
*/
|
||||
public void removeArena(@NotNull DropperArena arena) {
|
||||
Dropper.getInstance().getPlayerRegistry().removeForArena(arena);
|
||||
this.arenas.remove(arena);
|
||||
this.saveArenas();
|
||||
}
|
||||
|
@ -43,4 +43,19 @@ public class DropperArenaPlayerRegistry {
|
||||
return this.arenaPlayers.getOrDefault(playerId, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes all active sessions for the given arena
|
||||
*
|
||||
* @param arena <p>The arena to remove sessions for</p>
|
||||
*/
|
||||
public void removeForArena(DropperArena arena) {
|
||||
for (Map.Entry<UUID, DropperArenaSession> entry : this.arenaPlayers.entrySet()) {
|
||||
if (entry.getValue().getArena() == arena) {
|
||||
// Kick the player gracefully
|
||||
entry.getValue().triggerQuit();
|
||||
this.arenaPlayers.remove(entry.getKey());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -1,20 +1,23 @@
|
||||
package net.knarcraft.dropper.arena;
|
||||
|
||||
import net.knarcraft.dropper.Dropper;
|
||||
import net.knarcraft.dropper.container.SerializableUUID;
|
||||
import net.knarcraft.dropper.property.RecordResult;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.configuration.serialization.ConfigurationSerializable;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.UUID;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
/**
|
||||
* A registry keeping track of all records
|
||||
*/
|
||||
public class DropperArenaRecordsRegistry {
|
||||
public class DropperArenaRecordsRegistry implements ConfigurationSerializable {
|
||||
|
||||
private final Map<Player, Integer> leastDeaths;
|
||||
private final Map<Player, Long> shortestTimeMilliSeconds;
|
||||
private final Map<SerializableUUID, Integer> leastDeaths;
|
||||
private final Map<SerializableUUID, Long> shortestTimeMilliSeconds;
|
||||
|
||||
/**
|
||||
* Instantiates a new empty records registry
|
||||
@ -30,8 +33,8 @@ public class DropperArenaRecordsRegistry {
|
||||
* @param leastDeaths <p>The existing least death records to use</p>
|
||||
* @param shortestTimeMilliSeconds <p>The existing leash time records to use</p>
|
||||
*/
|
||||
public DropperArenaRecordsRegistry(@NotNull Map<Player, Integer> leastDeaths,
|
||||
@NotNull Map<Player, Long> shortestTimeMilliSeconds) {
|
||||
public DropperArenaRecordsRegistry(@NotNull Map<SerializableUUID, Integer> leastDeaths,
|
||||
@NotNull Map<SerializableUUID, Long> shortestTimeMilliSeconds) {
|
||||
this.leastDeaths = new HashMap<>(leastDeaths);
|
||||
this.shortestTimeMilliSeconds = new HashMap<>(shortestTimeMilliSeconds);
|
||||
}
|
||||
@ -41,7 +44,7 @@ public class DropperArenaRecordsRegistry {
|
||||
*
|
||||
* @return <p>Existing death records</p>
|
||||
*/
|
||||
public Map<Player, Integer> getLeastDeathsRecords() {
|
||||
public Map<SerializableUUID, Integer> getLeastDeathsRecords() {
|
||||
return new HashMap<>(this.leastDeaths);
|
||||
}
|
||||
|
||||
@ -50,29 +53,32 @@ public class DropperArenaRecordsRegistry {
|
||||
*
|
||||
* @return <p>Existing time records</p>
|
||||
*/
|
||||
public Map<Player, Long> getShortestTimeMilliSecondsRecords() {
|
||||
public Map<SerializableUUID, Long> getShortestTimeMilliSecondsRecords() {
|
||||
return new HashMap<>(this.shortestTimeMilliSeconds);
|
||||
}
|
||||
|
||||
/**
|
||||
* Registers a new deaths-record
|
||||
*
|
||||
* @param player <p>The player that performed the records</p>
|
||||
* @param deaths <p>The number of deaths suffered before the player finished the arena</p>
|
||||
* @param playerId <p>The id of the player that performed the records</p>
|
||||
* @param deaths <p>The number of deaths suffered before the player finished the arena</p>
|
||||
* @return <p>The result explaining what type of record was achieved</p>
|
||||
*/
|
||||
public @NotNull RecordResult registerDeathRecord(@NotNull Player player, int deaths) {
|
||||
public @NotNull RecordResult registerDeathRecord(@NotNull UUID playerId, int deaths) {
|
||||
RecordResult result;
|
||||
Stream<Map.Entry<Player, Integer>> records = leastDeaths.entrySet().stream();
|
||||
Stream<Map.Entry<SerializableUUID, Integer>> records = leastDeaths.entrySet().stream();
|
||||
SerializableUUID serializableUUID = new SerializableUUID(playerId);
|
||||
|
||||
if (records.allMatch((entry) -> deaths < entry.getValue())) {
|
||||
//If the given value is less than all other values, that's a world record!
|
||||
result = RecordResult.WORLD_RECORD;
|
||||
leastDeaths.put(player, deaths);
|
||||
} else if (leastDeaths.containsKey(player) && deaths < leastDeaths.get(player)) {
|
||||
leastDeaths.put(serializableUUID, deaths);
|
||||
save();
|
||||
} else if (leastDeaths.containsKey(serializableUUID) && deaths < leastDeaths.get(serializableUUID)) {
|
||||
//If the given value is less than the player's previous value, that's a personal best!
|
||||
result = RecordResult.PERSONAL_BEST;
|
||||
leastDeaths.put(player, deaths);
|
||||
leastDeaths.put(serializableUUID, deaths);
|
||||
save();
|
||||
} else {
|
||||
result = RecordResult.NONE;
|
||||
}
|
||||
@ -83,22 +89,26 @@ public class DropperArenaRecordsRegistry {
|
||||
/**
|
||||
* Registers a new time-record
|
||||
*
|
||||
* @param player <p>The player that performed the records</p>
|
||||
* @param playerId <p>The id of the player that performed the records</p>
|
||||
* @param milliseconds <p>The number of milliseconds it took the player to finish the dropper arena</p>
|
||||
* @return <p>The result explaining what type of record was achieved</p>
|
||||
*/
|
||||
public @NotNull RecordResult registerTimeRecord(@NotNull Player player, long milliseconds) {
|
||||
public @NotNull RecordResult registerTimeRecord(@NotNull UUID playerId, long milliseconds) {
|
||||
RecordResult result;
|
||||
Stream<Map.Entry<Player, Long>> records = shortestTimeMilliSeconds.entrySet().stream();
|
||||
Stream<Map.Entry<SerializableUUID, Long>> records = shortestTimeMilliSeconds.entrySet().stream();
|
||||
SerializableUUID serializableUUID = new SerializableUUID(playerId);
|
||||
|
||||
if (records.allMatch((entry) -> milliseconds < entry.getValue())) {
|
||||
//If the given value is less than all other values, that's a world record!
|
||||
result = RecordResult.WORLD_RECORD;
|
||||
shortestTimeMilliSeconds.put(player, milliseconds);
|
||||
} else if (shortestTimeMilliSeconds.containsKey(player) && milliseconds < shortestTimeMilliSeconds.get(player)) {
|
||||
shortestTimeMilliSeconds.put(serializableUUID, milliseconds);
|
||||
save();
|
||||
} else if (shortestTimeMilliSeconds.containsKey(serializableUUID) &&
|
||||
milliseconds < shortestTimeMilliSeconds.get(serializableUUID)) {
|
||||
//If the given value is less than the player's previous value, that's a personal best!
|
||||
result = RecordResult.PERSONAL_BEST;
|
||||
shortestTimeMilliSeconds.put(player, milliseconds);
|
||||
shortestTimeMilliSeconds.put(serializableUUID, milliseconds);
|
||||
save();
|
||||
} else {
|
||||
result = RecordResult.NONE;
|
||||
}
|
||||
@ -106,4 +116,36 @@ public class DropperArenaRecordsRegistry {
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Saves changed records
|
||||
*/
|
||||
private void save() {
|
||||
Dropper.getInstance().getArenaHandler().saveArenas();
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public Map<String, Object> serialize() {
|
||||
Map<String, Object> data = new HashMap<>();
|
||||
data.put("leastDeaths", this.leastDeaths);
|
||||
data.put("shortestTime", this.shortestTimeMilliSeconds);
|
||||
return data;
|
||||
}
|
||||
|
||||
/**
|
||||
* Deserializes the given data
|
||||
*
|
||||
* @param data <p>The data to deserialize</p>
|
||||
* @return <p>The deserialized records registry</p>
|
||||
*/
|
||||
@SuppressWarnings({"unused", "unchecked"})
|
||||
public static DropperArenaRecordsRegistry deserialize(Map<String, Object> data) {
|
||||
Map<SerializableUUID, Integer> leastDeathsData =
|
||||
(Map<SerializableUUID, Integer>) data.getOrDefault("leastDeaths", new HashMap<>());
|
||||
Map<SerializableUUID, Long> shortestTimeMillisecondsData =
|
||||
(Map<SerializableUUID, Long>) data.getOrDefault("shortestTime", new HashMap<>());
|
||||
|
||||
return new DropperArenaRecordsRegistry(leastDeathsData, shortestTimeMillisecondsData);
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -21,6 +21,7 @@ public class DropperArenaSession {
|
||||
private final @NotNull Location entryLocation;
|
||||
private int deaths;
|
||||
private final long startTime;
|
||||
private final float playersOriginalFlySpeed;
|
||||
|
||||
/**
|
||||
* Instantiates a new dropper arena session
|
||||
@ -37,19 +38,20 @@ public class DropperArenaSession {
|
||||
this.deaths = 0;
|
||||
this.startTime = System.currentTimeMillis();
|
||||
this.entryLocation = player.getLocation();
|
||||
// Prevent Spigot interference when traveling at high velocities
|
||||
|
||||
// Make the player fly to improve mobility in the air
|
||||
player.setAllowFlight(true);
|
||||
player.setFlying(true);
|
||||
this.playersOriginalFlySpeed = player.getFlySpeed();
|
||||
player.setFlySpeed((float) this.arena.getPlayerHorizontalVelocity());
|
||||
}
|
||||
|
||||
/**
|
||||
* Triggers a win for the player playing in this session
|
||||
*/
|
||||
public void triggerWin() {
|
||||
// Remove this session from game sessions to stop listeners from fiddling more with the player
|
||||
removeSession();
|
||||
|
||||
// No longer allow the player to avoid fly checks
|
||||
player.setAllowFlight(false);
|
||||
// Stop this session
|
||||
stopSession();
|
||||
|
||||
// Check for, and display, records
|
||||
registerRecord();
|
||||
@ -57,15 +59,15 @@ public class DropperArenaSession {
|
||||
//TODO: Give reward?
|
||||
|
||||
// Register and announce any cleared stages
|
||||
Integer arenaStage = arena.getStage();
|
||||
Integer arenaStage = this.arena.getStage();
|
||||
if (arenaStage != null) {
|
||||
boolean clearedNewStage = Dropper.getInstance().getArenaHandler().registerStageCleared(player, arenaStage);
|
||||
boolean clearedNewStage = Dropper.getInstance().getArenaHandler().registerStageCleared(this.player, arenaStage);
|
||||
if (clearedNewStage) {
|
||||
player.sendMessage("You cleared stage " + arenaStage + "!");
|
||||
this.player.sendMessage("You cleared stage " + arenaStage + "!");
|
||||
}
|
||||
}
|
||||
|
||||
player.sendMessage("You won!");
|
||||
this.player.sendMessage("You won!");
|
||||
|
||||
// Teleport the player out of the arena
|
||||
teleportToExit();
|
||||
@ -77,12 +79,12 @@ public class DropperArenaSession {
|
||||
private void teleportToExit() {
|
||||
// Teleport the player out of the arena
|
||||
Location exitLocation;
|
||||
if (arena.getExitLocation() != null) {
|
||||
exitLocation = arena.getExitLocation();
|
||||
if (this.arena.getExitLocation() != null) {
|
||||
exitLocation = this.arena.getExitLocation();
|
||||
} else {
|
||||
exitLocation = entryLocation;
|
||||
exitLocation = this.entryLocation;
|
||||
}
|
||||
PlayerTeleporter.teleportPlayer(player, exitLocation, true);
|
||||
PlayerTeleporter.teleportPlayer(this.player, exitLocation, true);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -101,16 +103,16 @@ public class DropperArenaSession {
|
||||
* Registers the player's record if necessary, and prints record information to the player
|
||||
*/
|
||||
private void registerRecord() {
|
||||
DropperArenaRecordsRegistry recordsRegistry = arena.getRecordsRegistry();
|
||||
RecordResult recordResult = switch (gameMode) {
|
||||
case LEAST_TIME -> recordsRegistry.registerTimeRecord(player,
|
||||
System.currentTimeMillis() - startTime);
|
||||
case LEAST_DEATHS -> recordsRegistry.registerDeathRecord(player, deaths);
|
||||
DropperArenaRecordsRegistry recordsRegistry = this.arena.getRecordsRegistry();
|
||||
RecordResult recordResult = switch (this.gameMode) {
|
||||
case LEAST_TIME -> recordsRegistry.registerTimeRecord(this.player.getUniqueId(),
|
||||
System.currentTimeMillis() - this.startTime);
|
||||
case LEAST_DEATHS -> recordsRegistry.registerDeathRecord(this.player.getUniqueId(), this.deaths);
|
||||
case DEFAULT -> RecordResult.NONE;
|
||||
};
|
||||
switch (recordResult) {
|
||||
case WORLD_RECORD -> player.sendMessage("You just set a new record for this arena!");
|
||||
case PERSONAL_BEST -> player.sendMessage("You just got a new personal record!");
|
||||
case WORLD_RECORD -> this.player.sendMessage("You just set a new record for this arena!");
|
||||
case PERSONAL_BEST -> this.player.sendMessage("You just got a new personal record!");
|
||||
}
|
||||
}
|
||||
|
||||
@ -119,27 +121,38 @@ public class DropperArenaSession {
|
||||
*/
|
||||
public void triggerLoss() {
|
||||
// Add to the death count if playing the least-deaths game-mode
|
||||
if (gameMode == ArenaGameMode.LEAST_DEATHS) {
|
||||
deaths++;
|
||||
if (this.gameMode == ArenaGameMode.LEAST_DEATHS) {
|
||||
this.deaths++;
|
||||
}
|
||||
//Teleport the player back to the top
|
||||
PlayerTeleporter.teleportPlayer(player, arena.getSpawnLocation(), true);
|
||||
PlayerTeleporter.teleportPlayer(this.player, this.arena.getSpawnLocation(), true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Triggers a quit for the player playing in this session
|
||||
*/
|
||||
public void triggerQuit() {
|
||||
// Remove this session from game sessions to stop listeners from fiddling more with the player
|
||||
removeSession();
|
||||
// No longer allow the player to avoid fly checks
|
||||
player.setAllowFlight(false);
|
||||
// Stop this session
|
||||
stopSession();
|
||||
// Teleport the player out of the arena
|
||||
teleportToExit();
|
||||
|
||||
player.sendMessage("You quit the arena!");
|
||||
}
|
||||
|
||||
/**
|
||||
* Stops this session, and disables flight mode
|
||||
*/
|
||||
private void stopSession() {
|
||||
// Remove this session from game sessions to stop listeners from fiddling more with the player
|
||||
removeSession();
|
||||
|
||||
// Remove flight mode
|
||||
this.player.setFlySpeed(this.playersOriginalFlySpeed);
|
||||
this.player.setFlying(false);
|
||||
this.player.setAllowFlight(false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the arena this session is being played in
|
||||
*
|
||||
|
@ -2,7 +2,6 @@ package net.knarcraft.dropper.command;
|
||||
|
||||
import net.knarcraft.dropper.Dropper;
|
||||
import net.knarcraft.dropper.arena.DropperArena;
|
||||
import net.knarcraft.dropper.util.ArenaStorageHelper;
|
||||
import org.bukkit.command.Command;
|
||||
import org.bukkit.command.CommandExecutor;
|
||||
import org.bukkit.command.CommandSender;
|
||||
@ -27,17 +26,14 @@ public class CreateArenaCommand implements CommandExecutor {
|
||||
return false;
|
||||
}
|
||||
|
||||
String arenaName = arguments[0];
|
||||
String sanitized = ArenaStorageHelper.sanitizeArenaName(arenaName);
|
||||
|
||||
for (DropperArena arena : Dropper.getInstance().getArenaHandler().getArenas()) {
|
||||
if (sanitized.equals(ArenaStorageHelper.sanitizeArenaName(arena.getArenaName()))) {
|
||||
commandSender.sendMessage("There already exists a dropper arena with that name!");
|
||||
return false;
|
||||
}
|
||||
DropperArena existingArena = Dropper.getInstance().getArenaHandler().getArena(arguments[0]);
|
||||
if (existingArena != null) {
|
||||
commandSender.sendMessage("There already exists a dropper arena with that name!");
|
||||
return false;
|
||||
}
|
||||
|
||||
//TODO: Make sure the arena name doesn't contain any unwanted characters
|
||||
// Remove known characters that are likely to cause trouble if used in an arena name
|
||||
String arenaName = arguments[0].replaceAll("[§ :=&]", "");
|
||||
|
||||
DropperArena arena = new DropperArena(arenaName, player.getLocation());
|
||||
Dropper.getInstance().getArenaHandler().addArena(arena);
|
||||
|
@ -1,8 +1,11 @@
|
||||
package net.knarcraft.dropper.command;
|
||||
|
||||
import net.knarcraft.dropper.Dropper;
|
||||
import net.knarcraft.dropper.arena.DropperArena;
|
||||
import org.bukkit.command.Command;
|
||||
import org.bukkit.command.CommandExecutor;
|
||||
import org.bukkit.command.CommandSender;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
/**
|
||||
@ -12,8 +15,22 @@ public class EditArenaCommand implements CommandExecutor {
|
||||
|
||||
@Override
|
||||
public boolean onCommand(@NotNull CommandSender commandSender, @NotNull Command command, @NotNull String s,
|
||||
@NotNull String[] strings) {
|
||||
//TODO: Make sure the console cannot run this
|
||||
@NotNull String[] arguments) {
|
||||
if (!(commandSender instanceof Player)) {
|
||||
commandSender.sendMessage("This command must be used by a player");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (arguments.length < 2) {
|
||||
return false;
|
||||
}
|
||||
|
||||
DropperArena specifiedArena = Dropper.getInstance().getArenaHandler().getArena(arguments[0]);
|
||||
if (specifiedArena == null) {
|
||||
commandSender.sendMessage("Unable to find the specified dropper arena.");
|
||||
return false;
|
||||
}
|
||||
|
||||
//TODO: If an arena name and a property is given, display the current value
|
||||
//TODO: If an arena name, a property and a value is given, check if it's valid, and update the property
|
||||
return false;
|
||||
|
@ -5,7 +5,6 @@ import net.knarcraft.dropper.arena.DropperArena;
|
||||
import net.knarcraft.dropper.arena.DropperArenaPlayerRegistry;
|
||||
import net.knarcraft.dropper.arena.DropperArenaSession;
|
||||
import net.knarcraft.dropper.property.ArenaGameMode;
|
||||
import net.knarcraft.dropper.util.ArenaStorageHelper;
|
||||
import net.knarcraft.dropper.util.PlayerTeleporter;
|
||||
import org.bukkit.GameMode;
|
||||
import org.bukkit.command.Command;
|
||||
@ -45,14 +44,7 @@ public class JoinArenaCommand implements CommandExecutor {
|
||||
}
|
||||
|
||||
// Make sure the arena exists
|
||||
String arenaName = ArenaStorageHelper.sanitizeArenaName(arguments[0]);
|
||||
DropperArena specifiedArena = null;
|
||||
for (DropperArena arena : Dropper.getInstance().getArenaHandler().getArenas()) {
|
||||
if (ArenaStorageHelper.sanitizeArenaName(arena.getArenaName()).equals(arenaName)) {
|
||||
specifiedArena = arena;
|
||||
break;
|
||||
}
|
||||
}
|
||||
DropperArena specifiedArena = Dropper.getInstance().getArenaHandler().getArena(arguments[0]);
|
||||
if (specifiedArena == null) {
|
||||
commandSender.sendMessage("Unable to find the specified dropper arena.");
|
||||
return false;
|
||||
|
@ -1,7 +1,6 @@
|
||||
package net.knarcraft.dropper.command;
|
||||
|
||||
import net.knarcraft.dropper.Dropper;
|
||||
import net.knarcraft.dropper.arena.DropperArena;
|
||||
import net.knarcraft.dropper.util.TabCompleteHelper;
|
||||
import org.bukkit.command.Command;
|
||||
import org.bukkit.command.CommandSender;
|
||||
import org.bukkit.command.TabCompleter;
|
||||
@ -18,14 +17,10 @@ public class JoinArenaTabCompleter implements TabCompleter {
|
||||
|
||||
@Override
|
||||
public @Nullable List<String> onTabComplete(@NotNull CommandSender sender, @NotNull Command command,
|
||||
@NotNull String label, @NotNull String[] args) {
|
||||
if (args.length == 1) {
|
||||
List<String> arenaNames = new ArrayList<>();
|
||||
for (DropperArena dropperArena : Dropper.getInstance().getArenaHandler().getArenas()) {
|
||||
arenaNames.add(dropperArena.getArenaName());
|
||||
}
|
||||
return arenaNames;
|
||||
} else if (args.length == 2) {
|
||||
@NotNull String label, @NotNull String[] arguments) {
|
||||
if (arguments.length == 1) {
|
||||
return TabCompleteHelper.getArenas();
|
||||
} else if (arguments.length == 2) {
|
||||
List<String> gameModes = new ArrayList<>();
|
||||
gameModes.add("default");
|
||||
gameModes.add("deaths");
|
||||
|
@ -3,15 +3,19 @@ package net.knarcraft.dropper.command;
|
||||
import net.knarcraft.dropper.Dropper;
|
||||
import net.knarcraft.dropper.arena.DropperArenaSession;
|
||||
import org.bukkit.command.Command;
|
||||
import org.bukkit.command.CommandExecutor;
|
||||
import org.bukkit.command.CommandSender;
|
||||
import org.bukkit.command.TabExecutor;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* The command used to leave the current dropper arena
|
||||
*/
|
||||
public class LeaveArenaCommand implements CommandExecutor {
|
||||
public class LeaveArenaCommand implements TabExecutor {
|
||||
|
||||
@Override
|
||||
public boolean onCommand(@NotNull CommandSender commandSender, @NotNull Command command, @NotNull String s,
|
||||
@ -21,7 +25,8 @@ public class LeaveArenaCommand implements CommandExecutor {
|
||||
return false;
|
||||
}
|
||||
|
||||
DropperArenaSession existingSession = Dropper.getInstance().getPlayerRegistry().getArenaSession(player.getUniqueId());
|
||||
DropperArenaSession existingSession = Dropper.getInstance().getPlayerRegistry().getArenaSession(
|
||||
player.getUniqueId());
|
||||
if (existingSession == null) {
|
||||
commandSender.sendMessage("You are not in a dropper arena!");
|
||||
return false;
|
||||
@ -31,4 +36,11 @@ public class LeaveArenaCommand implements CommandExecutor {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public List<String> onTabComplete(@NotNull CommandSender commandSender, @NotNull Command command, @NotNull String s,
|
||||
@NotNull String[] arguments) {
|
||||
return new ArrayList<>();
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -1,20 +1,37 @@
|
||||
package net.knarcraft.dropper.command;
|
||||
|
||||
import net.knarcraft.dropper.util.TabCompleteHelper;
|
||||
import org.bukkit.command.Command;
|
||||
import org.bukkit.command.CommandExecutor;
|
||||
import org.bukkit.command.CommandSender;
|
||||
import org.bukkit.command.TabExecutor;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* A command for listing existing dropper arenas
|
||||
*/
|
||||
public class ListArenaCommand implements CommandExecutor {
|
||||
public class ListArenaCommand implements TabExecutor {
|
||||
|
||||
@Override
|
||||
public boolean onCommand(@NotNull CommandSender sender, @NotNull Command command, @NotNull String label,
|
||||
@NotNull String[] args) {
|
||||
//TODO: List all existing arenas, and possibly information about a specified arena
|
||||
return false;
|
||||
@NotNull String[] arguments) {
|
||||
sender.sendMessage("Dropper arenas:");
|
||||
for (String arenaName : TabCompleteHelper.getArenas()) {
|
||||
sender.sendMessage(arenaName);
|
||||
}
|
||||
|
||||
//TODO: Allow displaying information about each arena (possibly admin-only)
|
||||
return true;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public List<String> onTabComplete(@NotNull CommandSender commandSender, @NotNull Command command, @NotNull String s,
|
||||
@NotNull String[] arguments) {
|
||||
return new ArrayList<>();
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -0,0 +1,33 @@
|
||||
package net.knarcraft.dropper.command;
|
||||
|
||||
import net.knarcraft.dropper.Dropper;
|
||||
import org.bukkit.command.Command;
|
||||
import org.bukkit.command.CommandSender;
|
||||
import org.bukkit.command.TabExecutor;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* The command for reloading the plugin
|
||||
*/
|
||||
public class ReloadCommand implements TabExecutor {
|
||||
|
||||
@Override
|
||||
public boolean onCommand(@NotNull CommandSender commandSender, @NotNull Command command, @NotNull String s,
|
||||
@NotNull String[] arguments) {
|
||||
Dropper.getInstance().reload();
|
||||
commandSender.sendMessage("Plugin reloaded!");
|
||||
return true;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public List<String> onTabComplete(@NotNull CommandSender commandSender, @NotNull Command command, @NotNull String s,
|
||||
@NotNull String[] arguments) {
|
||||
return new ArrayList<>();
|
||||
}
|
||||
|
||||
}
|
@ -1,5 +1,7 @@
|
||||
package net.knarcraft.dropper.command;
|
||||
|
||||
import net.knarcraft.dropper.Dropper;
|
||||
import net.knarcraft.dropper.arena.DropperArena;
|
||||
import org.bukkit.command.Command;
|
||||
import org.bukkit.command.CommandExecutor;
|
||||
import org.bukkit.command.CommandSender;
|
||||
@ -12,12 +14,23 @@ public class RemoveArenaCommand implements CommandExecutor {
|
||||
|
||||
@Override
|
||||
public boolean onCommand(@NotNull CommandSender commandSender, @NotNull Command command, @NotNull String s,
|
||||
@NotNull String[] strings) {
|
||||
//TODO: Make sure to kick any playing players if the arena is currently in use, by triggering their sessions'
|
||||
// triggerQuit() method
|
||||
//TODO: Remove the arena from DropperArenaHandler
|
||||
//TODO: Notify the user of success
|
||||
return false;
|
||||
@NotNull String[] arguments) {
|
||||
// Abort if no name was specified
|
||||
if (arguments.length < 1) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Get the specified arena
|
||||
DropperArena targetArena = Dropper.getInstance().getArenaHandler().getArena(arguments[0]);
|
||||
if (targetArena == null) {
|
||||
commandSender.sendMessage("Unable to find the specified arena");
|
||||
return false;
|
||||
}
|
||||
|
||||
// Remove the arena
|
||||
Dropper.getInstance().getArenaHandler().removeArena(targetArena);
|
||||
commandSender.sendMessage("The specified arena has been successfully removed");
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -0,0 +1,29 @@
|
||||
package net.knarcraft.dropper.command;
|
||||
|
||||
import net.knarcraft.dropper.util.TabCompleteHelper;
|
||||
import org.bukkit.command.Command;
|
||||
import org.bukkit.command.CommandSender;
|
||||
import org.bukkit.command.TabCompleter;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* The tab-completer for the remove arena command
|
||||
*/
|
||||
public class RemoveArenaTabCompleter implements TabCompleter {
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public List<String> onTabComplete(@NotNull CommandSender commandSender, @NotNull Command command, @NotNull String s,
|
||||
@NotNull String[] arguments) {
|
||||
if (arguments.length == 1) {
|
||||
return TabCompleteHelper.getArenas();
|
||||
} else {
|
||||
return new ArrayList<>();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,37 @@
|
||||
package net.knarcraft.dropper.container;
|
||||
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.configuration.serialization.ConfigurationSerializable;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* A material container able to be serialized
|
||||
*
|
||||
* @param material <p>The material stored by this record</p>
|
||||
*/
|
||||
public record SerializableMaterial(Material material) implements ConfigurationSerializable {
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public Map<String, Object> serialize() {
|
||||
Map<String, Object> data = new HashMap<>();
|
||||
data.put("name", material.name());
|
||||
return data;
|
||||
}
|
||||
|
||||
/**
|
||||
* Deserializes a serialized material
|
||||
*
|
||||
* @param data <p>The serialized data</p>
|
||||
* @return <p>The deserialized material</p>
|
||||
*/
|
||||
@SuppressWarnings("unused")
|
||||
public static SerializableMaterial deserialize(Map<String, Object> data) {
|
||||
Material material = Material.matchMaterial((String) data.getOrDefault("name", "AIR"));
|
||||
return new SerializableMaterial(material);
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,50 @@
|
||||
package net.knarcraft.dropper.container;
|
||||
|
||||
import org.bukkit.configuration.serialization.ConfigurationSerializable;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
* A UUID container able to be serialized
|
||||
*
|
||||
* @param uuid <p>The UUID stored by this record</p>
|
||||
*/
|
||||
public record SerializableUUID(UUID uuid) implements ConfigurationSerializable {
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public Map<String, Object> serialize() {
|
||||
Map<String, Object> data = new HashMap<>();
|
||||
data.put("id", uuid.toString());
|
||||
return data;
|
||||
}
|
||||
|
||||
/**
|
||||
* Deserializes a serialized UUID
|
||||
*
|
||||
* @param data <p>The serialized data</p>
|
||||
* @return <p>The deserialized UUID</p>
|
||||
*/
|
||||
@SuppressWarnings("unused")
|
||||
public static SerializableUUID deserialize(Map<String, Object> data) {
|
||||
String id = (String) data.getOrDefault("id", null);
|
||||
if (id != null) {
|
||||
return new SerializableUUID(UUID.fromString(id));
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object object) {
|
||||
if (object instanceof SerializableUUID) {
|
||||
return this.uuid.equals(((SerializableUUID) object).uuid);
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -12,6 +12,9 @@ import org.bukkit.event.Listener;
|
||||
import org.bukkit.event.player.PlayerMoveEvent;
|
||||
import org.bukkit.util.Vector;
|
||||
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* A listener for players moving inside a dropper arena
|
||||
*/
|
||||
@ -19,6 +22,11 @@ public class MoveListener implements Listener {
|
||||
|
||||
@EventHandler
|
||||
public void onPlayerMove(PlayerMoveEvent event) {
|
||||
// Ignore if no actual movement is happening
|
||||
if (event.getFrom().equals(event.getTo()) || event.getTo() == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
Player player = event.getPlayer();
|
||||
DropperArenaPlayerRegistry playerRegistry = Dropper.getInstance().getPlayerRegistry();
|
||||
DropperArenaSession arenaSession = playerRegistry.getArenaSession(player.getUniqueId());
|
||||
@ -26,29 +34,55 @@ public class MoveListener implements Listener {
|
||||
return;
|
||||
}
|
||||
|
||||
Block targetBlock = event.getTo().getBlock();
|
||||
Material targetBlockType = targetBlock.getType();
|
||||
|
||||
// Hitting water is the trigger for winning
|
||||
if (targetBlockType == Material.WATER) {
|
||||
arenaSession.triggerWin();
|
||||
// Prevent the player from flying upwards while in flight mode
|
||||
if (event.getFrom().getY() < event.getTo().getY()) {
|
||||
event.setCancelled(true);
|
||||
return;
|
||||
}
|
||||
|
||||
Location targetLocation = targetBlock.getLocation();
|
||||
Material beneathPlayerType = targetLocation.getWorld().getBlockAt(targetLocation.add(0, -0.1, 0)).getType();
|
||||
// Only do block type checking if the block beneath the player changes
|
||||
if (event.getFrom().getBlock() != event.getTo().getBlock()) {
|
||||
// Check if the player enters water
|
||||
Material winBlockType = arenaSession.getArena().getWinBlockType();
|
||||
// For water, only trigger when the player enters the water, but trigger earlier for everything else
|
||||
int depth = winBlockType == Material.WATER ? 0 : 1;
|
||||
for (Block block : getBlocksBeneathLocation(event.getTo(), depth)) {
|
||||
if (block.getType() == winBlockType) {
|
||||
arenaSession.triggerWin();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// If hitting something which is not air or water, it must be a solid block, and would end in a loss
|
||||
if (!targetBlockType.isAir() || (beneathPlayerType != Material.WATER &&
|
||||
!beneathPlayerType.isAir())) {
|
||||
arenaSession.triggerLoss();
|
||||
return;
|
||||
// Check if the player is about to hit a non-air and non-liquid block
|
||||
for (Block block : getBlocksBeneathLocation(event.getTo(), 1)) {
|
||||
if (!block.getType().isAir() && block.getType() != Material.STRUCTURE_VOID &&
|
||||
block.getType() != Material.WATER && block.getType() != Material.LAVA) {
|
||||
arenaSession.triggerLoss();
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//Updates the player's velocity to the one set by the arena
|
||||
updatePlayerVelocity(arenaSession);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the blocks at the given location that will be affected by the player's hit-box
|
||||
*
|
||||
* @param location <p>The location to check</p>
|
||||
* @return <p>The blocks beneath the player</p>
|
||||
*/
|
||||
private Set<Block> getBlocksBeneathLocation(Location location, double depth) {
|
||||
Set<Block> blocksBeneath = new HashSet<>();
|
||||
double halfPlayerWidth = 0.3;
|
||||
blocksBeneath.add(location.clone().subtract(halfPlayerWidth, depth, halfPlayerWidth).getBlock());
|
||||
blocksBeneath.add(location.clone().subtract(-halfPlayerWidth, depth, halfPlayerWidth).getBlock());
|
||||
blocksBeneath.add(location.clone().subtract(halfPlayerWidth, depth, -halfPlayerWidth).getBlock());
|
||||
blocksBeneath.add(location.clone().subtract(-halfPlayerWidth, depth, -halfPlayerWidth).getBlock());
|
||||
return blocksBeneath;
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates the velocity of the player in the given session
|
||||
*
|
||||
@ -57,7 +91,7 @@ public class MoveListener implements Listener {
|
||||
private void updatePlayerVelocity(DropperArenaSession session) {
|
||||
Player player = session.getPlayer();
|
||||
Vector playerVelocity = player.getVelocity();
|
||||
double arenaVelocity = session.getArena().getPlayerVelocity();
|
||||
double arenaVelocity = session.getArena().getPlayerVerticalVelocity();
|
||||
Vector newVelocity = new Vector(playerVelocity.getX(), -arenaVelocity, playerVelocity.getZ());
|
||||
player.setVelocity(newVelocity);
|
||||
}
|
||||
|
@ -2,26 +2,61 @@ package net.knarcraft.dropper.listener;
|
||||
|
||||
import net.knarcraft.dropper.Dropper;
|
||||
import net.knarcraft.dropper.arena.DropperArenaSession;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.event.EventHandler;
|
||||
import org.bukkit.event.Listener;
|
||||
import org.bukkit.event.player.PlayerJoinEvent;
|
||||
import org.bukkit.event.player.PlayerQuitEvent;
|
||||
import org.bukkit.event.player.PlayerTeleportEvent;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.UUID;
|
||||
import java.util.logging.Level;
|
||||
|
||||
/**
|
||||
* A listener for players leaving the server or the arena
|
||||
*/
|
||||
public class PlayerLeaveListener implements Listener {
|
||||
|
||||
private final Map<UUID, DropperArenaSession> leftSessions = new HashMap<>();
|
||||
|
||||
@EventHandler
|
||||
public void onPlayerLeave(PlayerQuitEvent event) {
|
||||
triggerQuit(event.getPlayer());
|
||||
Player player = event.getPlayer();
|
||||
DropperArenaSession arenaSession = getSession(player);
|
||||
if (arenaSession == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
Dropper.getInstance().getLogger().log(Level.WARNING, "Found player " + player.getUniqueId() +
|
||||
" leaving in the middle of a session!");
|
||||
leftSessions.put(player.getUniqueId(), arenaSession);
|
||||
}
|
||||
|
||||
@EventHandler
|
||||
public void onPlayerJoin(PlayerJoinEvent event) {
|
||||
UUID playerId = event.getPlayer().getUniqueId();
|
||||
// Force the player to quit from the session once they re-join
|
||||
if (leftSessions.containsKey(playerId)) {
|
||||
Dropper.getInstance().getLogger().log(Level.WARNING, "Found un-exited dropper session!");
|
||||
Bukkit.getScheduler().runTaskLater(Dropper.getInstance(), () -> {
|
||||
leftSessions.get(playerId).triggerQuit();
|
||||
Dropper.getInstance().getLogger().log(Level.WARNING, "Triggered a quit!");
|
||||
leftSessions.remove(playerId);
|
||||
}, 80);
|
||||
}
|
||||
}
|
||||
|
||||
@EventHandler
|
||||
public void onPlayerTeleport(PlayerTeleportEvent event) {
|
||||
if (event.getTo() == null || event.isCancelled()) {
|
||||
return;
|
||||
}
|
||||
|
||||
DropperArenaSession arenaSession = getSession(event.getPlayer());
|
||||
if (arenaSession == null) {
|
||||
return;
|
||||
@ -31,24 +66,7 @@ public class PlayerLeaveListener implements Listener {
|
||||
return;
|
||||
}
|
||||
|
||||
triggerQuit(event.getPlayer());
|
||||
}
|
||||
|
||||
/**
|
||||
* Forces the given player to quit their current arena
|
||||
*
|
||||
* @param player <p>The player to trigger a quit for</p>
|
||||
*/
|
||||
private void triggerQuit(Player player) {
|
||||
DropperArenaSession arenaSession = getSession(player);
|
||||
if (arenaSession == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
arenaSession.triggerQuit();
|
||||
|
||||
//TODO: It might not be possible to alter a leaving player's location here. It might be necessary to move them once
|
||||
// they join again
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -7,11 +7,45 @@ import org.jetbrains.annotations.NotNull;
|
||||
*/
|
||||
public enum ArenaStorageKey {
|
||||
|
||||
/**
|
||||
* The key for an arena's name
|
||||
*/
|
||||
NAME("arenaName"),
|
||||
|
||||
/**
|
||||
* The key for an arena's spawn location
|
||||
*/
|
||||
SPAWN_LOCATION("arenaSpawnLocation"),
|
||||
|
||||
/**
|
||||
* The key for an arena's exit location
|
||||
*/
|
||||
EXIT_LOCATION("arenaExitLocation"),
|
||||
PLAYER_VELOCITY("arenaPlayerVelocity"),
|
||||
|
||||
/**
|
||||
* The key for a player in this arena's vertical velocity
|
||||
*/
|
||||
PLAYER_VERTICAL_VELOCITY("arenaPlayerVerticalVelocity"),
|
||||
|
||||
/**
|
||||
* The key for a player in this arena's horizontal velocity
|
||||
*/
|
||||
PLAYER_HORIZONTAL_VELOCITY("arenaPlayerHorizontalVelocity"),
|
||||
|
||||
/**
|
||||
* The key for this arena's stage
|
||||
*/
|
||||
STAGE("arenaStage"),
|
||||
|
||||
/**
|
||||
* The key for the type of this arena's win block
|
||||
*/
|
||||
WIN_BLOCK_TYPE("winBlockType"),
|
||||
|
||||
/**
|
||||
* The hey for this arena's records
|
||||
*/
|
||||
RECORDS("records"),
|
||||
;
|
||||
|
||||
private final @NotNull String key;
|
||||
|
@ -3,8 +3,10 @@ package net.knarcraft.dropper.util;
|
||||
import net.knarcraft.dropper.Dropper;
|
||||
import net.knarcraft.dropper.arena.DropperArena;
|
||||
import net.knarcraft.dropper.arena.DropperArenaRecordsRegistry;
|
||||
import net.knarcraft.dropper.container.SerializableMaterial;
|
||||
import net.knarcraft.dropper.property.ArenaStorageKey;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.configuration.ConfigurationSection;
|
||||
import org.bukkit.configuration.file.YamlConfiguration;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
@ -45,8 +47,11 @@ public final class ArenaStorageHelper {
|
||||
configSection.set(ArenaStorageKey.NAME.getKey(), arena.getArenaName());
|
||||
configSection.set(ArenaStorageKey.SPAWN_LOCATION.getKey(), arena.getSpawnLocation());
|
||||
configSection.set(ArenaStorageKey.EXIT_LOCATION.getKey(), arena.getExitLocation());
|
||||
configSection.set(ArenaStorageKey.PLAYER_VELOCITY.getKey(), arena.getPlayerVelocity());
|
||||
configSection.set(ArenaStorageKey.PLAYER_VERTICAL_VELOCITY.getKey(), arena.getPlayerVerticalVelocity());
|
||||
configSection.set(ArenaStorageKey.PLAYER_HORIZONTAL_VELOCITY.getKey(), arena.getPlayerHorizontalVelocity());
|
||||
configSection.set(ArenaStorageKey.STAGE.getKey(), arena.getStage());
|
||||
configSection.set(ArenaStorageKey.WIN_BLOCK_TYPE.getKey(), new SerializableMaterial(arena.getWinBlockType()));
|
||||
configSection.set(ArenaStorageKey.RECORDS.getKey(), arena.getRecordsRegistry());
|
||||
}
|
||||
//TODO: Save records belonging to the arena
|
||||
configuration.save(arenaFile);
|
||||
@ -94,16 +99,28 @@ public final class ArenaStorageHelper {
|
||||
String arenaName = configurationSection.getString(ArenaStorageKey.NAME.getKey());
|
||||
Location spawnLocation = (Location) configurationSection.get(ArenaStorageKey.SPAWN_LOCATION.getKey());
|
||||
Location exitLocation = (Location) configurationSection.get(ArenaStorageKey.EXIT_LOCATION.getKey());
|
||||
double playerVelocity = configurationSection.getDouble(ArenaStorageKey.PLAYER_VELOCITY.getKey());
|
||||
double verticalVelocity = configurationSection.getDouble(ArenaStorageKey.PLAYER_VERTICAL_VELOCITY.getKey());
|
||||
double horizontalVelocity = configurationSection.getDouble(ArenaStorageKey.PLAYER_HORIZONTAL_VELOCITY.getKey());
|
||||
Integer stage = (Integer) configurationSection.get(ArenaStorageKey.STAGE.getKey());
|
||||
SerializableMaterial winBlockType = (SerializableMaterial) configurationSection.get(
|
||||
ArenaStorageKey.WIN_BLOCK_TYPE.getKey());
|
||||
DropperArenaRecordsRegistry recordsRegistry = (DropperArenaRecordsRegistry) configurationSection.get(
|
||||
ArenaStorageKey.RECORDS.getKey());
|
||||
|
||||
if (arenaName == null || spawnLocation == null) {
|
||||
Dropper.getInstance().getLogger().log(Level.SEVERE, "Could not load the arena at configuration " +
|
||||
"section " + configurationSection.getName() + ". Please check the arenas storage file for issues.");
|
||||
return null;
|
||||
}
|
||||
//TODO: Load records for this arena
|
||||
return new DropperArena(arenaName, spawnLocation, exitLocation, playerVelocity, stage,
|
||||
new DropperArenaRecordsRegistry());
|
||||
if (winBlockType == null) {
|
||||
winBlockType = new SerializableMaterial(Material.WATER);
|
||||
}
|
||||
if (recordsRegistry == null) {
|
||||
recordsRegistry = new DropperArenaRecordsRegistry();
|
||||
}
|
||||
|
||||
return new DropperArena(arenaName, spawnLocation, exitLocation, verticalVelocity, horizontalVelocity, stage,
|
||||
winBlockType.material(), recordsRegistry);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -0,0 +1,32 @@
|
||||
package net.knarcraft.dropper.util;
|
||||
|
||||
import net.knarcraft.dropper.Dropper;
|
||||
import net.knarcraft.dropper.arena.DropperArena;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* A helper-class for common tab-completions
|
||||
*/
|
||||
public final class TabCompleteHelper {
|
||||
|
||||
private TabCompleteHelper() {
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the names of all current arenas
|
||||
*
|
||||
* @return <p>All arena names</p>
|
||||
*/
|
||||
public static @NotNull List<String> getArenas() {
|
||||
List<String> arenaNames = new ArrayList<>();
|
||||
for (DropperArena dropperArena : Dropper.getInstance().getArenaHandler().getArenas()) {
|
||||
arenaNames.add(dropperArena.getArenaName());
|
||||
}
|
||||
return arenaNames;
|
||||
}
|
||||
|
||||
}
|
@ -5,11 +5,21 @@ api-version: 1.19
|
||||
description: A plugin for dropper mini-games
|
||||
|
||||
commands:
|
||||
dropperreload:
|
||||
aliases:
|
||||
- dreload
|
||||
permission: dropper.admin
|
||||
usage: /<command>
|
||||
description: Reloads all data from disk
|
||||
dropperlist:
|
||||
aliases:
|
||||
- dlist
|
||||
permission: dropper.join
|
||||
usage: /<command>
|
||||
description: Used to list all current dropper arenas
|
||||
dropperjoin:
|
||||
aliases:
|
||||
- djoin
|
||||
permission: dropper.join
|
||||
usage: |
|
||||
/<command> <arena> [mode]
|
||||
@ -18,18 +28,26 @@ commands:
|
||||
time = A shortest-time competitive game-mode
|
||||
description: Used to join a dropper arena
|
||||
dropperleave:
|
||||
aliases:
|
||||
- dleave
|
||||
permission: dropper.join
|
||||
usage: /<command>
|
||||
description: Used to leave the current dropper arena
|
||||
droppercreate:
|
||||
aliases:
|
||||
- dcreate
|
||||
permission: dropper.create
|
||||
usage: /<command> (Details not finalized)
|
||||
description: Used to create a new dropper arena
|
||||
dropperedit:
|
||||
aliases:
|
||||
- dedit
|
||||
permission: dropper.edit
|
||||
usage: /<command> (Details not finalized)
|
||||
description: Used to edit an existing dropper arena
|
||||
dropperremove:
|
||||
aliases:
|
||||
- dremove
|
||||
permission: dropper.remove
|
||||
usage: /<command> <arena>
|
||||
description: Used to remove an existing dropper arena
|
||||
|
Reference in New Issue
Block a user