diff --git a/pom.xml b/pom.xml
index 8b1d5158..7ef8484e 100644
--- a/pom.xml
+++ b/pom.xml
@@ -6,7 +6,7 @@
dev.efnilite
witp
- 1.0
+ 1.8
diff --git a/src/main/java/dev/efnilite/witp/WITP.java b/src/main/java/dev/efnilite/witp/WITP.java
index 4660db08..a2753ece 100644
--- a/src/main/java/dev/efnilite/witp/WITP.java
+++ b/src/main/java/dev/efnilite/witp/WITP.java
@@ -5,6 +5,7 @@
import dev.efnilite.witp.generator.subarea.SubareaDivider;
import dev.efnilite.witp.hook.PlaceholderHook;
import dev.efnilite.witp.player.ParkourPlayer;
+import dev.efnilite.witp.player.ParkourUser;
import dev.efnilite.witp.util.Configuration;
import dev.efnilite.witp.util.Util;
import dev.efnilite.witp.util.Verbose;
@@ -61,7 +62,7 @@ public void onEnable() {
break;
default:
Verbose.error("You are trying to start this plugin using an invalid server version");
- Verbose.error("This plugin only works in version 1.16.4");
+ Verbose.error("This plugin only works in version 1.16.4, 1.16.3 or 1.16.2");
this.getServer().getPluginManager().disablePlugin(this);
return;
}
@@ -118,16 +119,18 @@ public void join(PlayerJoinEvent event) {
Player player = event.getPlayer();
World world = WITP.getDivider().getWorld();
if (configuration.getFile("config").getBoolean("bungeecord.enabled")) {
- if (configuration.getFile("config").getBoolean("messages.join-leave-enabled")) {
- event.setJoinMessage(configuration.getString("config", "messages.join").replaceAll("%[a-z]",
- player.getName()));
- }
try {
ParkourPlayer.register(player);
} catch (IOException ex) {
ex.printStackTrace();
Verbose.error("Something went wrong while trying to fetch a player's (" + player.getName() + ") data");
}
+ if (configuration.getFile("lang").getBoolean("messages.join-leave-enabled")) {
+ event.setJoinMessage(null);
+ for (ParkourUser user : ParkourUser.getUsers()) {
+ user.sendTranslated("join", player.getName());
+ }
+ }
} else if (player.getWorld() == WITP.getDivider().getWorld()) {
World fallback = Bukkit.getWorld(configuration.getString("config", "world.fall-back"));
if (fallback != null) {
@@ -149,29 +152,40 @@ public void join(PlayerJoinEvent event) {
@EventHandler
public void damage(EntityDamageEvent event) {
if (event.getEntity() instanceof Player) {
- if (ParkourPlayer.getPlayer((Player) event.getEntity()) != null) {
+ if (ParkourUser.getUser((Player) event.getEntity()) != null) {
+ event.setCancelled(true);
+ }
+ }
+ }
+
+ @EventHandler
+ public void command(PlayerCommandPreprocessEvent event) {
+ if (ParkourGenerator.Configurable.FOCUS_MODE) {
+ ParkourUser user = ParkourUser.getUser(event.getPlayer());
+ if (user != null && !(event.getMessage().toLowerCase().contains("witp"))) {
event.setCancelled(true);
+ user.sendTranslated("cant-do");
}
}
}
@EventHandler
public void onDrop(PlayerDropItemEvent event) {
- if (ParkourPlayer.getPlayer(event.getPlayer()) != null) {
+ if (ParkourUser.getUser(event.getPlayer()) != null) {
event.setCancelled(true);
}
}
@EventHandler
public void onPlace(BlockPlaceEvent event) {
- if (ParkourPlayer.getPlayer(event.getPlayer()) != null) {
+ if (ParkourUser.getUser(event.getPlayer()) != null) {
event.setCancelled(true);
}
}
@EventHandler
public void onBreak(BlockBreakEvent event) {
- if (ParkourPlayer.getPlayer(event.getPlayer()) != null) {
+ if (ParkourUser.getUser(event.getPlayer()) != null) {
event.setCancelled(true);
}
}
@@ -196,7 +210,7 @@ public void interact(PlayerInteractEvent event) {
@EventHandler
public void onSwitch(PlayerChangedWorldEvent event) {
ParkourPlayer player = ParkourPlayer.getPlayer(event.getPlayer());
- if (player != null && player.getPlayer().getWorld().getName().equals(WITP.getDivider().getWorld().getName())) {
+ if (player != null && player.getPlayer().getWorld().getUID() != WITP.getDivider().getWorld().getUID()) {
try {
ParkourPlayer.unregister(player, true);
} catch (IOException ex) {
@@ -210,9 +224,11 @@ public void onSwitch(PlayerChangedWorldEvent event) {
public void leave(PlayerQuitEvent event) {
ParkourPlayer player = ParkourPlayer.getPlayer(event.getPlayer());
if (player != null) {
- if (configuration.getFile("config").getBoolean("messages.join-leave-enabled")) {
- event.setQuitMessage(configuration.getString("config", "messages.leave").replaceAll("%p",
- event.getPlayer().getName()));
+ if (configuration.getFile("lang").getBoolean("messages.join-leave-enabled")) {
+ event.setQuitMessage(null);
+ for (ParkourUser user : ParkourUser.getUsers()) {
+ user.sendTranslated("leave", player.getPlayer().getName());
+ }
}
try {
ParkourPlayer.unregister(player, false);
diff --git a/src/main/java/dev/efnilite/witp/command/MainCommand.java b/src/main/java/dev/efnilite/witp/command/MainCommand.java
index 8d48bcd3..3102ce6f 100644
--- a/src/main/java/dev/efnilite/witp/command/MainCommand.java
+++ b/src/main/java/dev/efnilite/witp/command/MainCommand.java
@@ -1,6 +1,8 @@
package dev.efnilite.witp.command;
import dev.efnilite.witp.player.ParkourPlayer;
+import dev.efnilite.witp.player.ParkourSpectator;
+import dev.efnilite.witp.player.ParkourUser;
import dev.efnilite.witp.util.Util;
import dev.efnilite.witp.util.Verbose;
import dev.efnilite.witp.util.wrapper.BukkitCommand;
@@ -9,6 +11,7 @@
import org.bukkit.entity.Player;
import java.io.IOException;
+import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
@@ -26,6 +29,7 @@ public boolean execute(CommandSender sender, String[] args) {
sender.sendMessage(Util.color("&a/witp join [player] &f- &7Join the game on this server or make another player join"));
sender.sendMessage(Util.color("&a/witp leave &f- &7Leave the game on this server"));
sender.sendMessage(Util.color("&a/witp menu &f- &7Open the customization menu"));
+ sender.sendMessage(Util.color("&a/witp gamemode &f- &7Open the gamemode menu"));
sender.sendMessage(Util.color("&a/witp leaderboard &f- &7Open the leaderboard"));
return true;
} else if (args.length == 1) {
@@ -37,7 +41,7 @@ public boolean execute(CommandSender sender, String[] args) {
ParkourPlayer.register(player);
ParkourPlayer pp = ParkourPlayer.getPlayer(player);
if (pp != null) {
- pp.send("&aYou joined the parkour");
+ pp.sendTranslated("joined");
}
} catch (IOException ex) {
ex.printStackTrace();
@@ -47,7 +51,7 @@ public boolean execute(CommandSender sender, String[] args) {
ParkourPlayer pp = ParkourPlayer.getPlayer(player);
if (pp != null) {
try {
- pp.send("&cYou left the parkour");
+ pp.sendTranslated("left");
ParkourPlayer.unregister(pp, true);
} catch (IOException ex) {
ex.printStackTrace();
@@ -59,6 +63,16 @@ public boolean execute(CommandSender sender, String[] args) {
if (pp != null) {
pp.menu();
}
+ } else if (args[0].equalsIgnoreCase("gamemode") || args[0].equalsIgnoreCase("gm")) {
+ ParkourUser user = ParkourUser.getUser(player);
+ if (user != null) {
+ user.gamemode();
+ }
+ } else if (args[0].equalsIgnoreCase("leaderboard")) {
+ ParkourUser user = ParkourUser.getUser(player);
+ if (user != null) {
+ user.scoreboard(1);
+ }
}
} else if (args.length == 2) {
if (args[0].equalsIgnoreCase("leaderboard") && args[1] != null && player != null) {
@@ -78,13 +92,31 @@ public boolean execute(CommandSender sender, String[] args) {
ParkourPlayer.register(join);
ParkourPlayer pp = ParkourPlayer.getPlayer(join);
if (pp != null) {
- pp.send("&aYou joined the parkour");
+ pp.sendTranslated("joined");
}
} catch (IOException ex) {
ex.printStackTrace();
Verbose.error("Error while joining");
}
}
+ } else if (args[0].equalsIgnoreCase("search") && player != null) {
+ ParkourUser user = ParkourUser.getUser(player);
+ if (user != null) {
+ if (args[1] == null || player.getName().equalsIgnoreCase(args[1])) {
+ user.sendTranslated("not-there-search");
+ } else {
+ Player search = Bukkit.getPlayer(args[1]);
+ if (search != null) {
+ ParkourUser searchUser = ParkourUser.getUser(search);
+ if (searchUser instanceof ParkourPlayer) {
+ ParkourPlayer searchPp = (ParkourPlayer) searchUser;
+ if (searchPp.getGenerator() != null) {
+ new ParkourSpectator(user, searchPp);
+ }
+ }
+ }
+ }
+ }
}
}
return true;
@@ -92,6 +124,19 @@ public boolean execute(CommandSender sender, String[] args) {
@Override
public List tabComplete(Player player, String[] args) {
- return Arrays.asList("join", "generate", "customize", "leave");
+ if (args.length == 2) {
+ if (args[0].equalsIgnoreCase("search")) {
+ List names = new ArrayList<>();
+ for (ParkourPlayer pp : ParkourUser.getActivePlayers()) {
+ String name = pp.getPlayer().getName();
+ if (player.getName().equals(name)) {
+ continue;
+ }
+ names.add(name);
+ }
+ return names;
+ }
+ }
+ return Arrays.asList("join", "leave", "menu", "leaderboard", "gamemode");
}
}
diff --git a/src/main/java/dev/efnilite/witp/events/BlockGenerateEvent.java b/src/main/java/dev/efnilite/witp/events/BlockGenerateEvent.java
index 9c758637..eee43f62 100644
--- a/src/main/java/dev/efnilite/witp/events/BlockGenerateEvent.java
+++ b/src/main/java/dev/efnilite/witp/events/BlockGenerateEvent.java
@@ -1,7 +1,7 @@
package dev.efnilite.witp.events;
-import dev.efnilite.witp.player.ParkourPlayer;
import dev.efnilite.witp.generator.ParkourGenerator;
+import dev.efnilite.witp.player.ParkourPlayer;
import dev.efnilite.witp.util.wrapper.EventWrapper;
import org.bukkit.block.Block;
diff --git a/src/main/java/dev/efnilite/witp/generator/ParkourGenerator.java b/src/main/java/dev/efnilite/witp/generator/ParkourGenerator.java
index 2206988e..dbd6e00a 100644
--- a/src/main/java/dev/efnilite/witp/generator/ParkourGenerator.java
+++ b/src/main/java/dev/efnilite/witp/generator/ParkourGenerator.java
@@ -1,11 +1,11 @@
package dev.efnilite.witp.generator;
-import dev.efnilite.witp.player.ParkourPlayer;
import dev.efnilite.witp.WITP;
import dev.efnilite.witp.events.BlockGenerateEvent;
import dev.efnilite.witp.events.PlayerFallEvent;
import dev.efnilite.witp.events.PlayerScoreEvent;
import dev.efnilite.witp.generator.subarea.SubareaPoint;
+import dev.efnilite.witp.player.ParkourPlayer;
import dev.efnilite.witp.util.Util;
import dev.efnilite.witp.util.Verbose;
import dev.efnilite.witp.util.particle.ParticleData;
@@ -113,10 +113,14 @@ public void run() {
if (stopped) {
this.cancel();
return;
- }
+ } // todo check if first location isn't current
Location playerLoc = player.getPlayer().getLocation();
- if (playerLoc.getWorld() != lastPlayer.getWorld()) {
- lastPlayer = playerLoc.clone();
+ if (playerLoc.getWorld().getUID() != lastPlayer.getWorld().getUID()) {
+ Verbose.error("Worlds are not the same (1)");
+ return;
+ }
+ if (playerLoc.getWorld().getUID() != playerSpawn.getWorld().getUID()) {
+ Verbose.error("Worlds are not the same (2)");
return;
}
// Fall check
@@ -136,9 +140,6 @@ public void run() {
// Structure deletion check
if (structureBlocks.contains(current) && current.getType() == Material.RED_WOOL && !deleteStructure) {
score += 10;
- if (player.showScoreboard && Configurable.SCOREBOARD) {
- player.updateScoreboard();
- }
structureCooldown = 20;
generateNext(player.blockLead);
deleteStructure = true;
@@ -166,9 +167,6 @@ public void run() {
}
new PlayerScoreEvent(player).call();
- if (player.showScoreboard && Configurable.SCOREBOARD) {
- player.updateScoreboard();
- }
List locations = new ArrayList<>(buildLog.keySet());
int lastIndex = locations.indexOf(last) + 1;
int size = locations.size();
@@ -195,6 +193,7 @@ public void run() {
if (player.showScoreboard && Configurable.SCOREBOARD) {
player.updateScoreboard();
}
+ player.updateSpectators();
}
}, Configurable.GENERATOR_CHECK);
}
@@ -212,14 +211,14 @@ public void reset(boolean regenerate) {
for (Block block : structureBlocks) {
block.setType(Material.AIR);
}
- structureBlocks.clear();
for (String s : buildLog.keySet()) {
Util.parseLocation(s).getBlock().setType(Material.AIR);
}
+ structureBlocks.clear();
structureCooldown = 20;
buildLog.clear();
player.getPlayer().teleport(playerSpawn);
- if (player.showDeathMsg) {
+ if (player.showDeathMsg && regenerate) {
String message;
int number = 0;
if (score == player.highScore) {
@@ -237,7 +236,7 @@ public void reset(boolean regenerate) {
player.sendTranslated("divider");
player.sendTranslated("score", Integer.toString(score));
player.sendTranslated("time", time);
- player.sendTranslated("highscore", Integer.toString(score));
+ player.sendTranslated("highscore", Integer.toString(player.highScore));
player.sendTranslated(message, Integer.toString(number));
player.sendTranslated("divider");
} else {
@@ -495,7 +494,7 @@ public void generateNext() {
break;
}
- int listSize = player.blockLead + 7; // the size of the queue of parkour blocks
+ int listSize = player.blockLead + 10; // the size of the queue of parkour blocks
listSize--;
List locations = new ArrayList<>(buildLog.keySet());
if (locations.size() > listSize) {
@@ -522,6 +521,7 @@ public void generateNext() {
*/
public void generateFirst(Location spawn, Location block) {
playerSpawn = spawn.clone();
+ lastPlayer = spawn.clone();
blockSpawn = block.clone();
lastSpawn = block.clone();
generateNext(player.blockLead);
@@ -625,6 +625,10 @@ public static class Configurable {
public static boolean SCOREBOARD;
public static boolean INVENTORY_HANDLING;
+ public static String SCOREBOARD_TITLE;
+ public static List SCOREBOARD_LINES;
+ public static boolean PERMISSIONS;
+ public static boolean FOCUS_MODE;
// Advanced settings
public static double BORDER_SIZE;
@@ -676,7 +680,11 @@ public static void init() {
}
SCOREBOARD = config.getBoolean("scoreboard.enabled");
+ SCOREBOARD_TITLE = Util.color(config.getString("scoreboard.title"));
+ SCOREBOARD_LINES = Util.color(config.getStringList("scoreboard.lines"));
INVENTORY_HANDLING = config.getBoolean("options.inventory-handling");
+ PERMISSIONS = config.getBoolean("permissions.enabled");
+ FOCUS_MODE = config.getBoolean("focus-mode.enabled");
SOUND_TYPE = Sound.valueOf(config.getString("particles.sound-type").toUpperCase());
SOUND_PITCH = config.getInt("particles.sound-pitch");
diff --git a/src/main/java/dev/efnilite/witp/generator/subarea/SubareaDivider.java b/src/main/java/dev/efnilite/witp/generator/subarea/SubareaDivider.java
index 77690ad8..60a76172 100644
--- a/src/main/java/dev/efnilite/witp/generator/subarea/SubareaDivider.java
+++ b/src/main/java/dev/efnilite/witp/generator/subarea/SubareaDivider.java
@@ -1,8 +1,8 @@
package dev.efnilite.witp.generator.subarea;
-import dev.efnilite.witp.player.ParkourPlayer;
import dev.efnilite.witp.WITP;
import dev.efnilite.witp.generator.ParkourGenerator;
+import dev.efnilite.witp.player.ParkourPlayer;
import dev.efnilite.witp.util.Util;
import dev.efnilite.witp.util.Verbose;
import dev.efnilite.witp.util.VoidGenerator;
@@ -11,13 +11,16 @@
import org.bukkit.*;
import org.bukkit.block.Block;
import org.bukkit.configuration.file.FileConfiguration;
+import org.bukkit.craftbukkit.libs.org.apache.commons.io.FileUtils;
import org.bukkit.entity.Player;
import org.bukkit.scheduler.BukkitRunnable;
+import org.bukkit.util.FileUtil;
import org.bukkit.util.Vector;
import org.jetbrains.annotations.NotNull;
import javax.annotation.Nullable;
import java.io.File;
+import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
@@ -70,7 +73,12 @@ public SubareaDivider() {
}
File folder = new File(worldName);
if (folder.exists() && folder.isDirectory()) {
- folder.delete();
+ try {
+ FileUtils.deleteDirectory(folder);
+ } catch (IOException ex) {
+ ex.printStackTrace();
+ Verbose.error("Error while deleting the playing world");
+ }
}
this.world = createWorld(worldName);
FileConfiguration gen = WITP.getConfiguration().getFile("generation");
@@ -101,7 +109,7 @@ public World getWorld() {
*/
public @Nullable SubareaPoint getPoint(@NotNull ParkourPlayer player) {
for (SubareaPoint point : collection.keySet()) {
- if (collection.get(point) == player) {
+ if (collection.get(point).getPlayer().getUniqueId() == player.getPlayer().getUniqueId()) {
return point;
}
}
@@ -123,10 +131,10 @@ public synchronized void generate(@NotNull ParkourPlayer player) {
SubareaPoint last = openSpaces.get(openSpaces.size() - 1);
createIsland(player, last);
openSpaces.remove(last);
+ Verbose.verbose("Used Subarea divided to " + player.getPlayer().getName());
return;
}
if (copy % 8 == 0) { // every new layer has +8 area points
-
createIsland(player, current);
current = current.zero();
layer++;
@@ -206,6 +214,7 @@ private void fetchPossibleInLayer() {
world.setGameRule(GameRule.DO_DAYLIGHT_CYCLE, false);
world.setGameRule(GameRule.DO_WEATHER_CYCLE, false);
world.setGameRule(GameRule.LOG_ADMIN_COMMANDS, false);
+ world.setGameRule(GameRule.ANNOUNCE_ADVANCEMENTS, false);
world.setWeatherDuration(1000);
world.setDifficulty(Difficulty.PEACEFUL);
world.setAutoSave(false);
@@ -213,7 +222,7 @@ private void fetchPossibleInLayer() {
return world;
}
- private void setBorder(@NotNull ParkourPlayer player, @NotNull SubareaPoint point) {
+ public void setBorder(@NotNull ParkourPlayer player, @NotNull SubareaPoint point) {
int size = (int) player.getGenerator().borderOffset * 2;
Vector estimated = point.getEstimatedCenter(size);
WITP.getVersionManager().setWorldBorder(player.getPlayer(), estimated, size);
@@ -281,6 +290,6 @@ public void run() {
setBorder(pp, point);
}
};
- Tasks.syncDelay(delay, 10 * 20);
+ Tasks.syncDelay(delay, 5 * 20);
}
}
diff --git a/src/main/java/dev/efnilite/witp/hook/PlaceholderHook.java b/src/main/java/dev/efnilite/witp/hook/PlaceholderHook.java
index 7c07da40..24b8770e 100644
--- a/src/main/java/dev/efnilite/witp/hook/PlaceholderHook.java
+++ b/src/main/java/dev/efnilite/witp/hook/PlaceholderHook.java
@@ -1,7 +1,7 @@
package dev.efnilite.witp.hook;
-import dev.efnilite.witp.player.ParkourPlayer;
import dev.efnilite.witp.WITP;
+import dev.efnilite.witp.player.ParkourPlayer;
import me.clip.placeholderapi.expansion.PlaceholderExpansion;
import org.bukkit.Bukkit;
import org.bukkit.entity.Player;
diff --git a/src/main/java/dev/efnilite/witp/player/ParkourPlayer.java b/src/main/java/dev/efnilite/witp/player/ParkourPlayer.java
index ecadd858..e2a5b48f 100644
--- a/src/main/java/dev/efnilite/witp/player/ParkourPlayer.java
+++ b/src/main/java/dev/efnilite/witp/player/ParkourPlayer.java
@@ -1,7 +1,5 @@
package dev.efnilite.witp.player;
-import com.google.gson.Gson;
-import com.google.gson.GsonBuilder;
import com.google.gson.annotations.Expose;
import dev.efnilite.witp.WITP;
import dev.efnilite.witp.WITPAPI;
@@ -13,19 +11,19 @@
import dev.efnilite.witp.util.inventory.ItemBuilder;
import dev.efnilite.witp.util.task.Tasks;
import fr.mrmicky.fastboard.FastBoard;
-import net.md_5.bungee.api.chat.BaseComponent;
-import net.md_5.bungee.api.chat.ClickEvent;
-import net.md_5.bungee.api.chat.ComponentBuilder;
-import org.bukkit.*;
+import org.bukkit.Bukkit;
+import org.bukkit.ChatColor;
+import org.bukkit.Material;
import org.bukkit.entity.Player;
-import org.bukkit.inventory.Inventory;
-import org.bukkit.inventory.ItemStack;
import org.bukkit.scheduler.BukkitRunnable;
import org.bukkit.util.Vector;
import org.jetbrains.annotations.NotNull;
import javax.annotation.Nullable;
-import java.io.*;
+import java.io.File;
+import java.io.FileReader;
+import java.io.FileWriter;
+import java.io.IOException;
import java.util.*;
import java.util.concurrent.ThreadLocalRandom;
@@ -51,14 +49,10 @@ public class ParkourPlayer extends ParkourUser {
public @Expose String style;
public @Expose String lang;
- public UUID openInventory;
- private FastBoard board;
+ private ParkourGenerator generator;
private List possibleStyle;
private final File file;
- private final ParkourGenerator generator;
- private static final HashMap players = new HashMap<>();
- private static HashMap highScores = new LinkedHashMap<>();
- private static final Gson gson = new GsonBuilder().disableHtmlEscaping().excludeFieldsWithoutExposeAnnotation().create();
+ private final HashMap spectators;
/**
* Creates a new instance of a ParkourPlayer
@@ -68,19 +62,6 @@ public ParkourPlayer(@NotNull Player player, int highScore, String time, String
boolean useDifficulty, boolean useStructure, boolean useSpecial, boolean showDeathMsg, boolean showScoreboard) {
super(player);
Verbose.verbose("Init of Player " + player.getName());
- this.previousLocation = player.getLocation().clone();
- this.previousGamemode = player.getGameMode();
- this.previousInventory = new HashMap<>();
- if (ParkourGenerator.Configurable.INVENTORY_HANDLING) {
- int index = 0;
- Inventory inventory = player.getInventory();
- for (ItemStack item : inventory.getContents()) {
- if (item != null) {
- previousInventory.put(index, item);
- }
- index++;
- }
- }
this.useSpecial = useSpecial;
this.showDeathMsg = showDeathMsg;
this.highScore = highScore;
@@ -91,10 +72,10 @@ public ParkourPlayer(@NotNull Player player, int highScore, String time, String
this.useDifficulty = useDifficulty;
this.useStructure = useStructure;
this.showScoreboard = showScoreboard;
+ this.spectators = new HashMap<>();
this.file = new File(WITP.getInstance().getDataFolder() + "/players/" + player.getUniqueId().toString() + ".json");
this.possibleStyle = new ArrayList<>();
- this.board = new FastBoard(player);
setStyle(style);
this.generator = new ParkourGenerator(this);
@@ -117,46 +98,38 @@ public ParkourPlayer(@NotNull Player player, int highScore, String time, String
}
}
-
- /**
- * Gets a message from lang.yml
- *
- * @param path
- * The path name in lang.yml (for example: 'time-preference')
- *
- * @param replaceable
- * What can be replaced (for example: %s to yes)
- */
- public void sendTranslated(String path, String... replaceable) { // todo add lang.yml
- path = "messages." + path;
- String string = WITP.getConfiguration().getString("config", path);
- if (string == null) {
- Verbose.error("Unknown path: " + path);
- return;
+ public void removeSpectators(ParkourSpectator... spectators) {
+ for (ParkourSpectator spectator : spectators) {
+ this.spectators.remove(spectator.getPlayer().getName());
}
- for (String s : replaceable) {
- string = string.replaceAll("%[a-z]", s);
+ }
+
+ public void addSpectator(ParkourSpectator... spectators) {
+ for (ParkourSpectator spectator : spectators) {
+ this.spectators.put(spectator.getPlayer().getName(), spectator);
}
- send(string);
}
/**
- * Gets the scoreboard of the player
- *
- * @return the {@link FastBoard} of the player
+ * Updates the stats for spectators
*/
- public FastBoard getBoard() {
- return board;
+ public void updateSpectators() {
+ for (ParkourSpectator spectator : spectators.values()) {
+ spectator.checkDistance();
+ spectator.updateScoreboard();
+ }
}
/**
* Updates the scoreboard
*/
+ @Override
public void updateScoreboard() {
- board.updateTitle(WITP.getConfiguration().getString("config", "scoreboard.title"));
+ board.updateTitle(ParkourGenerator.Configurable.SCOREBOARD_TITLE);
List list = new ArrayList<>();
- List lines = WITP.getConfiguration().getStringList("config", "scoreboard.lines");
+ List lines = ParkourGenerator.Configurable.SCOREBOARD_LINES;
if (lines == null) {
+ Verbose.error("Scoreboard lines are null! Check your config!");
return;
}
for (String s : lines) {
@@ -206,72 +179,78 @@ public void setHighScore(int score) {
*/
public void menu() {
InventoryBuilder builder = new InventoryBuilder(this, 3, "Customize").open();
- InventoryBuilder builder1 = new InventoryBuilder(this, 3, "Lead").open();
- InventoryBuilder builder2 = new InventoryBuilder(this, 3, "Parkour style").open();
- InventoryBuilder builder3 = new InventoryBuilder(this, 3, "Time").open();
+ InventoryBuilder lead = new InventoryBuilder(this, 3, "Lead").open();
+ InventoryBuilder styling = new InventoryBuilder(this, 3, "Parkour style").open();
+ InventoryBuilder timeofday = new InventoryBuilder(this, 3, "Time").open();
+ String close = getTranslated("item-close");
if (WITP.getConfiguration().getFile("config").getBoolean("styles.enabled")) {
builder.setItem(9, new ItemBuilder(Material.END_STONE, "&a&lParkour style")
.setLore("&7The style of your parkour.", "&7(which blocks will be used)", "", "&7Currently: &a" + style).build(), (t, e) -> {
- List styles = Util.getNode(WITP.getConfiguration().getFile("config"), "styles.list");
- if (styles == null) {
- Verbose.error("Error while trying to fetch possible styles from config.yml");
- return;
- }
- int i = 0;
- for (String style : styles) {
- if (i == 26) {
- Verbose.error("There are too many styles to display!");
- return;
- }
- List possible = this.getPossibleMaterials(style);
- if (possible == null) {
- continue;
- }
- Material material = possible.get(possible.size() - 1);
- builder2.setItem(i, new ItemBuilder(material, "&b&l" + Util.capitalizeFirst(style)).build(), (t2, e2) -> {
- String selected = ChatColor.stripColor(e2.getItemMeta().getDisplayName()).toLowerCase();
- this.setStyle(selected);
- this.send("&7You selected style &c" + selected + "&7!");
- this.saveStats();
- });
- i++;
- builder2.setItem(26, new ItemBuilder(Material.ARROW, "&c&lClose").build(), (t2, e2) -> player.closeInventory());
- }
- builder2.build();
+ if (checkPermission("witp.style")) {
+ List styles = Util.getNode(WITP.getConfiguration().getFile("config"), "styles.list");
+ if (styles == null) {
+ Verbose.error("Error while trying to fetch possible styles from config.yml");
+ return;
+ }
+ int i = 0;
+ for (String style : styles) {
+ if (i == 26) {
+ Verbose.error("There are too many styles to display!");
+ return;
+ }
+ List possible = this.getPossibleMaterials(style);
+ if (possible == null) {
+ continue;
+ }
+ Material material = possible.get(possible.size() - 1);
+ styling.setItem(i, new ItemBuilder(material, "&b&l" + Util.capitalizeFirst(style)).build(), (t2, e2) -> {
+ String selected = ChatColor.stripColor(e2.getItemMeta().getDisplayName()).toLowerCase();
+ setStyle(selected);
+ sendTranslated("selected-style", selected);
+ saveStats();
+ });
+ i++;
+ styling.setItem(26, new ItemBuilder(Material.ARROW, close).build(), (t2, e2) -> player.closeInventory());
+ }
+ styling.build();
+ }
});
}
builder.setItem(10, new ItemBuilder(Material.GLASS, "&a&lLead")
.setLore("&7How many blocks will", "&7be generated ahead of you.", "", "&7Currently: &a" + blockLead + " blocks").build(), (t, e) -> {
- for (int i = 10; i < 17; i++) {
- builder1.setItem(i, new ItemBuilder(Material.PAPER, "&b&l" + (i - 9) + " block(s)").build(), (t2, e2) -> {
- int amount = t2.getSlot() - 9;
- blockLead = amount;
- send("&7You selected a " + amount + " block lead.");
- saveStats();
- });
+ if (checkPermission("witp.lead")) {
+ for (int i = 10; i < 17; i++) {
+ lead.setItem(i, new ItemBuilder(Material.PAPER, "&b&l" + (i - 9) + " block(s)").build(), (t2, e2) -> {
+ blockLead = t2.getSlot() - 9;
+ sendTranslated("selected-block-lead", Integer.toString(blockLead));
+ saveStats();
+ });
+ }
+ lead.setItem(26, new ItemBuilder(Material.ARROW, close).build(), (t2, e2) -> player.closeInventory());
+ lead.build();
}
- builder1.setItem(26, new ItemBuilder(Material.ARROW, "&c&lClose").build(), (t2, e2) -> player.closeInventory());
- builder1.build();
});
builder.setItem(11, new ItemBuilder(Material.CLOCK, "&a&lTime")
.setLore("&7The time of day.", "", "&7Currently: &a" + time.toLowerCase()).build(), (t, e) -> {
- List times = Arrays.asList("Day", "Noon", "Dawn", "Night", "Midnight");
- int i = 11;
- for (String time : times) {
- builder3.setItem(i, new ItemBuilder(Material.PAPER, "&b&l" + time).build(), (t2, e2) -> {
- if (e2.getItemMeta() != null) {
- String name = ChatColor.stripColor(e2.getItemMeta().getDisplayName());
- this.time = name;
- send("&7You changed your time preference to &a" + time.toLowerCase());
- player.setPlayerTime(getTime(name), false);
- saveStats();
- }
- });
- i++;
+ if (checkPermission("witp.time")) {
+ List times = Arrays.asList("Day", "Noon", "Dawn", "Night", "Midnight");
+ int i = 11;
+ for (String time : times) {
+ timeofday.setItem(i, new ItemBuilder(Material.PAPER, "&b&l" + time).build(), (t2, e2) -> {
+ if (e2.getItemMeta() != null) {
+ String name = ChatColor.stripColor(e2.getItemMeta().getDisplayName());
+ this.time = name;
+ sendTranslated("selected-time", time.toLowerCase());
+ player.setPlayerTime(getTime(name), false);
+ saveStats();
+ }
+ });
+ i++;
+ }
+ timeofday.setItem(26, new ItemBuilder(Material.ARROW, close).build(), (t2, e2) -> player.closeInventory());
+ timeofday.build();
}
- builder3.setItem(26, new ItemBuilder(Material.ARROW, "&c&lClose").build(), (t2, e2) -> player.closeInventory());
- builder3.build();
});
Material difficulty = useDifficulty ? Material.GREEN_WOOL : Material.RED_WOOL;
String difficultyString = Boolean.toString(useDifficulty);
@@ -279,11 +258,12 @@ public void menu() {
builder.setItem(12, new ItemBuilder(difficulty, "&a&lUse difficulty")
.setLore("&7If enabled having a higher score will mean", "&7the parkour becomes more difficult.", "",
"&7Currently: " + difficultyValue).build(), (t2, e2) -> {
- useDifficulty = !useDifficulty;
- send("&7You changed your usage of difficulty to " +
- Util.normalizeBoolean(Util.colorBoolean(Util.reverseBoolean(difficultyString))));
- saveStats();
- player.closeInventory();
+ if (checkPermission("witp.difficulty")) {
+ useDifficulty = !useDifficulty;
+ sendTranslated("selected-difficulty", Util.normalizeBoolean(Util.colorBoolean(Util.reverseBoolean(difficultyString))));
+ saveStats();
+ player.closeInventory();
+ }
});
Material particles = useParticles ? Material.GREEN_WOOL : Material.RED_WOOL;
String particlesString = Boolean.toString(useParticles);
@@ -291,11 +271,12 @@ public void menu() {
builder.setItem(13, new ItemBuilder(particles, "&a&lUse particles and sounds")
.setLore("&7If enabled every generated block", "&7will show particles and play a sound.", "",
"&7Currently: " + particlesValue).build(), (t2, e2) -> {
- useParticles = !useParticles;
- send("&7You changed your usage of particles to " +
- Util.normalizeBoolean(Util.colorBoolean(Util.reverseBoolean(particlesString))));
- saveStats();
- player.closeInventory();
+ if (checkPermission("witp.particles")) {
+ useParticles = !useParticles;
+ sendTranslated("selected-particles", Util.normalizeBoolean(Util.colorBoolean(Util.reverseBoolean(particlesString))));
+ saveStats();
+ player.closeInventory();
+ }
});
Material scoreboard = showScoreboard ? Material.GREEN_WOOL : Material.RED_WOOL;
String scoreboardString = Boolean.toString(showScoreboard);
@@ -303,17 +284,22 @@ public void menu() {
builder.setItem(14, new ItemBuilder(scoreboard, "&a&lShow scoreboard")
.setLore("&7If enabled shows the scoreboard", "",
"&7Currently: " + scoreboardValue).build(), (t2, e2) -> {
- showScoreboard = !showScoreboard;
- if (showScoreboard) {
- board = new FastBoard(player);
- updateScoreboard();
- } else {
- board.delete();
+ if (checkPermission("witp.scoreboard")) {
+ if (ParkourGenerator.Configurable.SCOREBOARD) {
+ showScoreboard = !showScoreboard;
+ if (showScoreboard) {
+ board = new FastBoard(player);
+ updateScoreboard();
+ } else {
+ board.delete();
+ }
+ sendTranslated("selected-scoreboard", Util.normalizeBoolean(Util.colorBoolean(Util.reverseBoolean(scoreboardString))));
+ saveStats();
+ player.closeInventory();
+ } else {
+ sendTranslated("cant-do");
+ }
}
- send("&7You changed your usage of the scoreboard to " +
- Util.normalizeBoolean(Util.colorBoolean(Util.reverseBoolean(scoreboardString))));
- saveStats();
- player.closeInventory();
});
Material deathMsg = showDeathMsg ? Material.GREEN_WOOL : Material.RED_WOOL;
String deathString = Boolean.toString(showDeathMsg);
@@ -321,11 +307,12 @@ public void menu() {
builder.setItem(15, new ItemBuilder(deathMsg, "&a&lShow fall message")
.setLore("&7If enabled shows a message when you fall", "&7with extra info", "",
"&7Currently: " + deathValue).build(), (t2, e2) -> {
- showDeathMsg = !showDeathMsg;
- send("&7You changed your showing of the fall message to " +
- Util.normalizeBoolean(Util.colorBoolean(Util.reverseBoolean(deathString))));
- saveStats();
- player.closeInventory();
+ if (checkPermission("witp.fall")) {
+ showDeathMsg = !showDeathMsg;
+ sendTranslated("selected-fall-message", Util.normalizeBoolean(Util.colorBoolean(Util.reverseBoolean(deathString))));
+ saveStats();
+ player.closeInventory();
+ }
});
Material special = useSpecial ? Material.GREEN_WOOL : Material.RED_WOOL;
String specialString = Boolean.toString(useSpecial);
@@ -333,31 +320,41 @@ public void menu() {
builder.setItem(16, new ItemBuilder(special, "&a&lUse special blocks")
.setLore("&7If enabled uses special blocks like ice and slabs.", "",
"&7Currently: " + specialValue).build(), (t2, e2) -> {
- useSpecial = !useSpecial;
- send("&7You changed your usage of special blocks to " +
- Util.normalizeBoolean(Util.colorBoolean(Util.reverseBoolean(specialString))));
- saveStats();
- player.closeInventory();
+ if (checkPermission("witp.special")) {
+ useSpecial = !useSpecial;
+ sendTranslated("selected-special-blocks", Util.normalizeBoolean(Util.colorBoolean(Util.reverseBoolean(specialString))));
+ saveStats();
+ player.closeInventory();
+ }
});
Material structures = useStructure ? Material.GREEN_WOOL : Material.RED_WOOL;
String structuresString = Boolean.toString(useStructure);
String structuresValue = Util.normalizeBoolean(Util.colorBoolean(structuresString));
builder.setItem(17, new ItemBuilder(structures, "&a&lUse structures")
- .setLore("&7If enabled static structures", "&7will appear throughout the parkour.", "",
- "&7Currently: " + structuresValue).build(), (t2, e2) -> {
- useStructure = !useStructure;
- send("&7You changed your usage of structures to " +
- Util.normalizeBoolean(Util.colorBoolean(Util.reverseBoolean(structuresString))));
- saveStats();
- player.closeInventory();
+ .setLore("&7If enabled static structures", "&7will appear throughout the parkour.", "", "&7Currently: " + structuresValue).build(), (t2, e2) -> {
+ if (checkPermission("witp.structures")) {
+ useStructure = !useStructure;
+ sendTranslated("selected-structures", Util.normalizeBoolean(Util.colorBoolean(Util.reverseBoolean(structuresString))));
+ saveStats();
+ player.closeInventory();
+ }
+ });
+ builder.setItem(18, new ItemBuilder(Material.PAPER, "&c&lGamemode").build(), (t2, e2) -> {
+ if (checkPermission("witp.gamemode")) {
+ player.closeInventory();
+ gamemode();
+ }
});
Integer score = highScores.get(player.getUniqueId());
- builder.setItem(22, new ItemBuilder(Material.GOLD_BLOCK, "&6&lLeaderboard")
- .setLore("&7Your rank: &f#" + getRank(player.getUniqueId()) + " &7(" + (score == null ? 0 : score) + ")").build(), (t2, e2) -> {
- scoreboard(1);
- player.closeInventory();
+ builder.setItem(19, new ItemBuilder(Material.GOLD_BLOCK, "&6&lLeaderboard")
+ .setLore(getTranslated("your-rank", Integer.toString(getRank(player.getUniqueId())), Integer.toString(score == null ? 0 : score)))
+ .build(), (t2, e2) -> {
+ if (checkPermission("witp.leaderboard")) {
+ scoreboard(1);
+ player.closeInventory();
+ }
});
- builder.setItem(26, new ItemBuilder(Material.BARRIER, "&4&lQuit").build(), (t2, e2) -> {
+ builder.setItem(26, new ItemBuilder(Material.BARRIER, getTranslated("item-quit")).build(), (t2, e2) -> {
try {
ParkourPlayer.unregister(this, true);
} catch (IOException ex) {
@@ -365,10 +362,21 @@ public void menu() {
Verbose.error("Error while trying to quit player " + player.getName());
}
});
- builder.setItem(25, new ItemBuilder(Material.ARROW, "&c&lClose").build(), (t2, e2) -> player.closeInventory());
+ builder.setItem(25, new ItemBuilder(Material.ARROW, close).build(), (t2, e2) -> player.closeInventory());
builder.build();
}
+ private boolean checkPermission(String perm) {
+ if (ParkourGenerator.Configurable.PERMISSIONS) {
+ boolean check = player.hasPermission(perm);
+ if (!check) {
+ sendTranslated("cant-do");
+ }
+ return check;
+ }
+ return true;
+ }
+
private void saveStats() {
BukkitRunnable runnable = new BukkitRunnable() {
@Override
@@ -423,76 +431,6 @@ public void save() throws IOException {
writer.close();
}
- /**
- * Sends a message or array of it - coloured allowed, using '&'
- *
- * @param messages
- * The message
- */
- public void send(String... messages) {
- for (String msg : messages) {
- player.sendMessage(Util.color(msg));
- }
- }
-
- /**
- * Shows the scoreboard (as a chat message)
- */
- public void scoreboard(int page) {
- if (highScores.size() == 0) {
- try {
- fetchHighScores();
- } catch (IOException ex) {
- ex.printStackTrace();
- Verbose.error("Error while trying to fetch the high scores!");
- }
- }
-
- int lowest = page * 10;
- int highest = (page - 1) * 10;
- if (page < 1) {
- return;
- }
- if (page > 1 && highest > highScores.size()) {
- return;
- }
-
- HashMap sorted = Util.sortByValue(highScores);
- highScores = sorted;
- List uuids = new ArrayList<>(sorted.keySet());
-
- send("", "", "", "", "", "", "", "");
- send("&7----------------------------------------");
- for (int i = highest; i < lowest; i++) {
- if (i == uuids.size()) {
- break;
- }
- UUID uuid = uuids.get(i);
- if (uuid == null) {
- continue;
- }
- String name = Bukkit.getOfflinePlayer(uuid).getName();
- int rank = i + 1;
- send("&c#" + rank + ". &7" + name + " &f- " + highScores.get(uuid));
- }
- send("&7Your rank: &f#" + getRank(player.getUniqueId()) + " &7(" + highScores.get(player.getUniqueId()) + ")");
- send("");
-
- int prevPage = page - 1;
- int nextPage = page + 1;
- BaseComponent[] previous = new ComponentBuilder()
- .append("<< Previous page").color(net.md_5.bungee.api.ChatColor.RED)
- .event(new ClickEvent(ClickEvent.Action.RUN_COMMAND, "/witp leaderboard " + prevPage))
- .append(" | ").color(net.md_5.bungee.api.ChatColor.GRAY)
- .event((ClickEvent) null)
- .append("Next page >>").color(net.md_5.bungee.api.ChatColor.RED)
- .event(new ClickEvent(ClickEvent.Action.RUN_COMMAND, "/witp leaderboard " + nextPage))
- .create();
-
- player.spigot().sendMessage(previous);
- send(WITP.getConfiguration().getString("config", "messages.divider"));
- }
-
/**
* Gets the high score of a player
*
@@ -518,10 +456,6 @@ public static UUID getAtPlace(int place) {
return new ArrayList<>(highScores.keySet()).get(place);
}
- private int getRank(UUID player) {
- return new ArrayList<>(highScores.keySet()).indexOf(player) + 1;
- }
-
/**
* Registers a player
*
@@ -572,27 +506,6 @@ private int getRank(UUID player) {
return players.get(player);
}
- // todo scoreboard
- /**
- * Gets the highscores of all player
- *
- * @throws IOException
- * When creating the file reader goes wrong
- */
- public static void fetchHighScores() throws IOException {
- File folder = new File(WITP.getInstance().getDataFolder() + "/players/");
- if (!(folder.exists())) {
- folder.mkdirs();
- return;
- }
- for (File file : folder.listFiles()) {
- FileReader reader = new FileReader(file);
- ParkourPlayer from = gson.fromJson(reader, ParkourPlayer.class);
- String name = file.getName();
- highScores.put(UUID.fromString(name.substring(0, name.lastIndexOf('.'))), from.highScore);
- }
- }
-
/**
* Gets a ParkourPlayer from a regular Player
*
@@ -651,6 +564,17 @@ public static void unregister(@NotNull ParkourPlayer player, boolean sendBack) t
player.save();
WITP.getDivider().leave(player);
players.remove(player.getPlayer());
+ users.remove(player);
+ for (ParkourSpectator spectator : player.spectators.values()) {
+ try {
+ ParkourPlayer.register(spectator.getPlayer());
+ } catch (IOException ex) {
+ ex.printStackTrace();
+ Verbose.error("Error while trying to register player" + player.getPlayer().getName());
+ }
+ }
+ player.spectators.clear();
+
if (sendBack) {
if (WITP.getConfiguration().getFile("config").getBoolean("bungeecord.enabled")) {
Util.sendPlayer(player.getPlayer(), WITP.getConfiguration().getString("config", "bungeecord.return_server"));
@@ -668,6 +592,7 @@ public static void unregister(@NotNull ParkourPlayer player, boolean sendBack) t
pl.resetPlayerTime();
}
}
+ player.generator = null;
}
/**
@@ -678,13 +603,4 @@ public static void unregister(@NotNull ParkourPlayer player, boolean sendBack) t
public ParkourGenerator getGenerator() {
return generator;
}
-
- /**
- * Gets the Bukkit version of the player
- *
- * @return the player
- */
- public @NotNull Player getPlayer() {
- return player;
- }
}
diff --git a/src/main/java/dev/efnilite/witp/player/ParkourSpectator.java b/src/main/java/dev/efnilite/witp/player/ParkourSpectator.java
index a9ba8852..f06ed292 100644
--- a/src/main/java/dev/efnilite/witp/player/ParkourSpectator.java
+++ b/src/main/java/dev/efnilite/witp/player/ParkourSpectator.java
@@ -1,11 +1,68 @@
package dev.efnilite.witp.player;
-import org.bukkit.entity.Player;
+import dev.efnilite.witp.WITP;
+import dev.efnilite.witp.generator.ParkourGenerator;
+import dev.efnilite.witp.util.Verbose;
+import org.bukkit.GameMode;
import org.jetbrains.annotations.NotNull;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.List;
+
public class ParkourSpectator extends ParkourUser {
- public ParkourSpectator(@NotNull Player player) {
- super(player);
+ protected final ParkourPlayer watching;
+ protected final ParkourGenerator watchingGenerator;
+
+ public ParkourSpectator(@NotNull ParkourUser player, @NotNull ParkourPlayer watching) {
+ super(player.getPlayer());
+ Verbose.verbose("New ParkourSpectator init " + this.player.getName());
+
+ if (player instanceof ParkourPlayer) {
+ try {
+ ParkourPlayer.unregister((ParkourPlayer) player, false);
+ } catch (IOException ex) {
+ ex.printStackTrace();
+ Verbose.error("Error while trying to unregister");
+ }
+ } else if (player instanceof ParkourSpectator) {
+ ParkourSpectator spectator = (ParkourSpectator) player;
+ spectator.watching.removeSpectators(spectator);
+ }
+ users.put(this.player.getName(), this);
+
+ this.watching = watching;
+ this.watchingGenerator = watching.getGenerator();
+ this.player.setGameMode(GameMode.SPECTATOR);
+ double offset = watching.getGenerator().borderOffset * 2;
+ WITP.getVersionManager().setWorldBorder(this.player, WITP.getDivider().getPoint(watching).getEstimatedCenter(offset), offset);
+ watching.addSpectator(this);
+ this.player.teleport(watching.getPlayer().getLocation());
+ sendTranslated("spectator");
+ }
+
+ public void checkDistance() {
+ if (watching.getPlayer().getLocation().distance(player.getLocation()) > 30) {
+ player.teleport(watching.getPlayer().getLocation());
+ }
+ }
+
+ @Override
+ protected void updateScoreboard() {
+ board.updateTitle(ParkourGenerator.Configurable.SCOREBOARD_TITLE);
+ List list = new ArrayList<>();
+ List lines = ParkourGenerator.Configurable.SCOREBOARD_LINES;
+ if (lines == null) {
+ Verbose.error("Scoreboard lines are null! Check your config!");
+ return;
+ }
+ for (String s : lines) {
+ list.add(s
+ .replaceAll("%score%", Integer.toString(watchingGenerator.score))
+ .replaceAll("%time%", watchingGenerator.time));
+ }
+
+ board.updateLines(list);
}
-}
+}
\ No newline at end of file
diff --git a/src/main/java/dev/efnilite/witp/player/ParkourUser.java b/src/main/java/dev/efnilite/witp/player/ParkourUser.java
index fc8777f5..bc3946f7 100644
--- a/src/main/java/dev/efnilite/witp/player/ParkourUser.java
+++ b/src/main/java/dev/efnilite/witp/player/ParkourUser.java
@@ -1,21 +1,302 @@
package dev.efnilite.witp.player;
+import com.google.gson.Gson;
+import com.google.gson.GsonBuilder;
+import dev.efnilite.witp.WITP;
+import dev.efnilite.witp.generator.ParkourGenerator;
+import dev.efnilite.witp.util.Util;
+import dev.efnilite.witp.util.Verbose;
+import dev.efnilite.witp.util.inventory.InventoryBuilder;
+import dev.efnilite.witp.util.inventory.ItemBuilder;
+import fr.mrmicky.fastboard.FastBoard;
+import net.md_5.bungee.api.chat.BaseComponent;
+import net.md_5.bungee.api.chat.ClickEvent;
+import net.md_5.bungee.api.chat.ComponentBuilder;
+import org.bukkit.Bukkit;
import org.bukkit.GameMode;
import org.bukkit.Location;
+import org.bukkit.Material;
import org.bukkit.entity.Player;
+import org.bukkit.inventory.Inventory;
import org.bukkit.inventory.ItemStack;
+import org.bukkit.inventory.meta.SkullMeta;
import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
-import java.util.HashMap;
+import java.io.File;
+import java.io.FileReader;
+import java.io.IOException;
+import java.util.*;
-abstract class ParkourUser {
+public abstract class ParkourUser {
+ public UUID openInventory;
protected final Player player;
+ protected FastBoard board;
protected GameMode previousGamemode;
protected Location previousLocation;
protected HashMap previousInventory;
+ protected static final HashMap users = new HashMap<>();
+ protected static final HashMap players = new HashMap<>();
+ protected static HashMap highScores = new LinkedHashMap<>();
+ protected static final Gson gson = new GsonBuilder().disableHtmlEscaping().excludeFieldsWithoutExposeAnnotation().create();
+
public ParkourUser(@NotNull Player player) {
this.player = player;
+ saveInventory();
+ this.previousLocation = player.getLocation().clone();
+ this.previousGamemode = player.getGameMode();
+ this.board = new FastBoard(player);
+ // remove duplicates
+ users.put(player.getName(), this);
+ }
+
+ protected void saveInventory() {
+ this.previousInventory = new HashMap<>();
+ if (ParkourGenerator.Configurable.INVENTORY_HANDLING) {
+ int index = 0;
+ Inventory inventory = player.getInventory();
+ for (ItemStack item : inventory.getContents()) {
+ if (item != null) {
+ previousInventory.put(index, item);
+ }
+ index++;
+ }
+ }
+ }
+
+ public static @Nullable ParkourUser getUser(@NotNull Player player) {
+ for (ParkourUser user : users.values()) {
+ if (user.player.getUniqueId() == player.getUniqueId()) {
+ return user;
+ }
+ }
+ return null;
+ }
+
+ /**
+ * Updates the scoreboard
+ */
+ protected abstract void updateScoreboard();
+
+ /**
+ * Gets the highscores of all player
+ *
+ * @throws IOException
+ * When creating the file reader goes wrong
+ */
+ public static void fetchHighScores() throws IOException {
+ File folder = new File(WITP.getInstance().getDataFolder() + "/players/");
+ if (!(folder.exists())) {
+ folder.mkdirs();
+ return;
+ }
+ for (File file : folder.listFiles()) {
+ FileReader reader = new FileReader(file);
+ ParkourPlayer from = gson.fromJson(reader, ParkourPlayer.class);
+ String name = file.getName();
+ highScores.put(UUID.fromString(name.substring(0, name.lastIndexOf('.'))), from.highScore);
+ }
+ }
+
+ /**
+ * Sends a message or array of it - coloured allowed, using '&'
+ *
+ * @param messages
+ * The message
+ */
+ public void send(String... messages) {
+ for (String msg : messages) {
+ player.sendMessage(Util.color(msg));
+ }
+ }
+
+ /**
+ * Opens the gamemode menu
+ */
+ public void gamemode() {
+ InventoryBuilder gamemode = new InventoryBuilder(this, 3, "Gamemode").open();
+ InventoryBuilder spectatable = new InventoryBuilder(this, 3, "Select a player").open();
+ gamemode.setItem(12, new ItemBuilder(Material.BARREL, "&c&lNormal").setLore("&7Play the game like normal").build(), (t, e) -> {
+ try {
+ player.closeInventory();
+ if (this instanceof ParkourSpectator) {
+ ParkourSpectator spectator = (ParkourSpectator) this;
+ spectator.watching.removeSpectators(spectator);
+ }
+ ParkourPlayer.register(player);
+ } catch (IOException ex) {
+ ex.printStackTrace();
+ Verbose.error("Error while trying to register player" + player.getName());
+ }
+ });
+ gamemode.setItem(14, new ItemBuilder(Material.GLASS, "&c&lSpectate").setLore("&7Spectate another player").build(), (t, e) -> {
+ int index = 0;
+ player.closeInventory();
+ for (ParkourPlayer pp : getActivePlayers()) {
+ if (pp == null || pp.getGenerator() == null) {
+ continue;
+ }
+ Player player = pp.getPlayer();
+ if (player.getUniqueId() != this.player.getUniqueId()) {
+ ItemStack item = new ItemBuilder(Material.PLAYER_HEAD, 1, "&c&l" + player.getName())
+ .setLore("&7Click to spectate " + player.getName()).build();
+ SkullMeta meta = (SkullMeta) item.getItemMeta();
+ if (meta == null) {
+ continue;
+ }
+ meta.setOwningPlayer(player);
+ item.setItemMeta(meta);
+ spectatable.setItem(index, item, (t2, e2) -> new ParkourSpectator(this, pp));
+ index++;
+ if (index == 25) {
+ break;
+ }
+ }
+ }
+ spectatable.setItem(25, new ItemBuilder(Material.PAPER, getTranslated("item-search")).setLore(getTranslated("item-search-lore")).build(),
+ (t2, e2) -> {
+ player.closeInventory();
+ BaseComponent[] send = new ComponentBuilder().append(getTranslated("click-search"))
+ .event(new ClickEvent(ClickEvent.Action.SUGGEST_COMMAND, "/witp search ")).create();
+ player.spigot().sendMessage(send);
+ });
+ spectatable.setItem(26, new ItemBuilder(Material.ARROW, getTranslated("item-close")).build(), (t2, e2) -> player.closeInventory());
+ spectatable.build();
+ });
+ gamemode.setItem(26, new ItemBuilder(Material.ARROW, getTranslated("item-close")).build(), (t2, e2) -> player.closeInventory());
+ gamemode.build();
+ }
+
+ /**
+ * Shows the scoreboard (as a chat message)
+ */
+ public void scoreboard(int page) {
+ if (highScores.size() == 0) {
+ try {
+ fetchHighScores();
+ } catch (IOException ex) {
+ ex.printStackTrace();
+ Verbose.error("Error while trying to fetch the high scores!");
+ }
+ }
+
+ int lowest = page * 10;
+ int highest = (page - 1) * 10;
+ if (page < 1) {
+ return;
+ }
+ if (page > 1 && highest > highScores.size()) {
+ return;
+ }
+
+ HashMap sorted = Util.sortByValue(highScores);
+ highScores = sorted;
+ List uuids = new ArrayList<>(sorted.keySet());
+
+ send("", "", "", "", "", "", "", "");
+ sendTranslated("divider");
+ for (int i = highest; i < lowest; i++) {
+ if (i == uuids.size()) {
+ break;
+ }
+ UUID uuid = uuids.get(i);
+ if (uuid == null) {
+ continue;
+ }
+ String name = Bukkit.getOfflinePlayer(uuid).getName();
+ int rank = i + 1;
+ send("&a#" + rank + ". &7" + name + " &f- " + highScores.get(uuid));
+ }
+ sendTranslated("your-rank", Integer.toString(getRank(player.getUniqueId())), Integer.toString(highScores.get(player.getUniqueId())));
+ send("");
+
+ int prevPage = page - 1;
+ int nextPage = page + 1;
+ BaseComponent[] previous = new ComponentBuilder()
+ .append(getTranslated("previous-page"))
+ .event(new ClickEvent(ClickEvent.Action.RUN_COMMAND, "/witp leaderboard " + prevPage))
+ .append(" | ").color(net.md_5.bungee.api.ChatColor.GRAY)
+ .event((ClickEvent) null)
+ .append(getTranslated("next-page"))
+ .event(new ClickEvent(ClickEvent.Action.RUN_COMMAND, "/witp leaderboard " + nextPage))
+ .create();
+
+ player.spigot().sendMessage(previous);
+ sendTranslated("divider");
+ }
+
+ /**
+ * Gets the rank of a certain player
+ *
+ * @param player
+ * The player
+ *
+ * @return the rank (starts at 1.)
+ */
+ protected int getRank(UUID player) {
+ return new ArrayList<>(highScores.keySet()).indexOf(player) + 1;
+ }
+
+ /**
+ * Gets a message from lang.yml
+ *
+ * @param path
+ * The path name in lang.yml (for example: 'time-preference')
+ *
+ * @param replaceable
+ * What can be replaced (for example: %s to yes)
+ */
+ public void sendTranslated(String path, String... replaceable) {
+ path = "messages.en." + path;
+ String string = WITP.getConfiguration().getString("lang", path);
+ if (string == null) {
+ Verbose.error("Unknown path: " + path + " - try deleting the config");
+ return;
+ }
+ for (String s : replaceable) {
+ string = string.replaceAll("%[a-z]", s);
+ }
+ send(string);
+ }
+
+ public String getTranslated(String path, String... replaceable) {
+ path = "messages.en." + path;
+ String string = WITP.getConfiguration().getString("lang", path);
+ if (string == null) {
+ Verbose.error("Unknown path: " + path + " - try deleting the config");
+ return "";
+ }
+ for (String s : replaceable) {
+ string = string.replaceAll("%[a-z]", s);
+ }
+ return string;
+ }
+
+ public static List getUsers() {
+ return new ArrayList<>(users.values());
+ }
+
+ public static List getActivePlayers() {
+ return new ArrayList<>(players.values());
+ }
+
+ /**
+ * Gets the scoreboard of the player
+ *
+ * @return the {@link FastBoard} of the player
+ */
+ public FastBoard getBoard() {
+ return board;
+ }
+
+ /**
+ * Gets the Bukkit version of the player
+ *
+ * @return the player
+ */
+ public @NotNull Player getPlayer() {
+ return player;
}
}
\ No newline at end of file
diff --git a/src/main/java/dev/efnilite/witp/util/Configuration.java b/src/main/java/dev/efnilite/witp/util/Configuration.java
index 4604dfad..37152f69 100644
--- a/src/main/java/dev/efnilite/witp/util/Configuration.java
+++ b/src/main/java/dev/efnilite/witp/util/Configuration.java
@@ -32,9 +32,9 @@ public Configuration(Plugin plugin) {
this.plugin = plugin;
files = new HashMap<>();
- defaultFiles = new String[] {"config.yml", "generation.yml"};
+ defaultFiles = new String[] {"config.yml", "generation.yml", "lang.yml"};
- if (!new File(plugin.getDataFolder() + "/config.yml").exists()) {
+ if (!new File(plugin.getDataFolder() + "/lang.yml").exists()) {
plugin.getDataFolder().mkdirs();
for (String file : defaultFiles) {
diff --git a/src/main/java/dev/efnilite/witp/util/Util.java b/src/main/java/dev/efnilite/witp/util/Util.java
index 93571adc..f8914a84 100644
--- a/src/main/java/dev/efnilite/witp/util/Util.java
+++ b/src/main/java/dev/efnilite/witp/util/Util.java
@@ -3,6 +3,7 @@
import com.google.common.io.ByteArrayDataOutput;
import com.google.common.io.ByteStreams;
import dev.efnilite.witp.WITP;
+import dev.efnilite.witp.player.ParkourUser;
import dev.efnilite.witp.util.wrapper.EventWrapper;
import net.milkbowl.vault.economy.Economy;
import org.bukkit.*;
diff --git a/src/main/java/dev/efnilite/witp/util/inventory/InventoryBuilder.java b/src/main/java/dev/efnilite/witp/util/inventory/InventoryBuilder.java
index 58216cfa..04b0ff06 100644
--- a/src/main/java/dev/efnilite/witp/util/inventory/InventoryBuilder.java
+++ b/src/main/java/dev/efnilite/witp/util/inventory/InventoryBuilder.java
@@ -1,7 +1,7 @@
package dev.efnilite.witp.util.inventory;
-import dev.efnilite.witp.player.ParkourPlayer;
import dev.efnilite.witp.WITP;
+import dev.efnilite.witp.player.ParkourUser;
import dev.efnilite.witp.util.Util;
import dev.efnilite.witp.util.Verbose;
import org.bukkit.Bukkit;
@@ -13,7 +13,6 @@
import org.bukkit.event.inventory.InventoryClickEvent;
import org.bukkit.event.inventory.InventoryCloseEvent;
import org.bukkit.inventory.Inventory;
-import org.bukkit.inventory.InventoryHolder;
import org.bukkit.inventory.ItemStack;
import javax.annotation.Nullable;
@@ -27,13 +26,11 @@
*/
public class InventoryBuilder implements Listener {
- private final ParkourPlayer pp;
-
private int rows;
private boolean open;
private String name;
- private Player holder;
private UUID uuid;
+ private final ParkourUser player;
private final HandlerList handlerList;
private final HashMap items;
private final HashMap onClick;
@@ -53,15 +50,12 @@ public InventoryBuilder(int rows, String name) {
/**
* {@link #InventoryBuilder(int, String)} but with the holder
*/
- public InventoryBuilder(@Nullable ParkourPlayer pp, int rows, String name) {
+ public InventoryBuilder(@Nullable ParkourUser player, int rows, String name) {
this.open = false;
this.uuid = null;
this.rows = rows;
this.name = name;
- this.pp = pp;
- if (pp != null) {
- this.holder = pp.getPlayer();
- }
+ this.player = player;
this.handlerList = new HandlerList();
this.items = new HashMap<>();
this.onClick = new HashMap<>();
@@ -77,11 +71,11 @@ public Inventory build() {
}
uuid = UUID.randomUUID();
if (open) {
- if (pp == null) {
+ if (player == null) {
Verbose.error("Tried opening inventory " + uuid.toString() + " but player is null");
} else {
- holder.openInventory(inventory);
- pp.openInventory = uuid;
+ player.getPlayer().openInventory(inventory);
+ player.openInventory = uuid;
}
}
unregister();
@@ -97,14 +91,6 @@ public InventoryBuilder open() {
return this;
}
- /**
- * Set the holder
- */
- public InventoryBuilder setHolder(Player holder) {
- this.holder = holder;
- return this;
- }
-
/**
* Set an item in a slot
*/
@@ -117,8 +103,8 @@ public InventoryBuilder setItem(int slot, ItemStack item, @Nullable InventoryCon
@EventHandler
public void onClose(InventoryCloseEvent event) {
Player player = (Player) event.getPlayer();
- if (player.getOpenInventory().getTitle().equals(name) && ParkourPlayer.getPlayer(player) != null) {
- pp.openInventory = null;
+ if (player.getOpenInventory().getTitle().equals(name) && ParkourUser.getUser(player) != null) {
+ this.player.openInventory = null;
unregister();
}
}
@@ -127,7 +113,7 @@ public void onClose(InventoryCloseEvent event) {
public void onClick(InventoryClickEvent event) {
Player player = (Player) event.getWhoClicked();
ItemStack current = event.getCurrentItem();
- if (player.getOpenInventory().getTitle().equals(name) && ParkourPlayer.getPlayer(player) != null && current != null && uuid == pp.openInventory) {
+ if (player.getOpenInventory().getTitle().equals(name) && ParkourUser.getUser(player) != null && current != null && uuid == this.player.openInventory) {
event.setCancelled(true);
InventoryConsumer consumer = onClick.get(event.getSlot());
if (consumer != null) {
@@ -180,13 +166,6 @@ public int getRows() {
return rows;
}
- /**
- * Gets the holder
- */
- public InventoryHolder getHolder() {
- return holder;
- }
-
/**
* Gets the name
*/
diff --git a/src/main/java/dev/efnilite/witp/util/inventory/ItemBuilder.java b/src/main/java/dev/efnilite/witp/util/inventory/ItemBuilder.java
index da541515..973dd045 100644
--- a/src/main/java/dev/efnilite/witp/util/inventory/ItemBuilder.java
+++ b/src/main/java/dev/efnilite/witp/util/inventory/ItemBuilder.java
@@ -5,7 +5,6 @@
import org.bukkit.ChatColor;
import org.bukkit.Material;
import org.bukkit.NamespacedKey;
-import org.bukkit.inventory.ItemFlag;
import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.meta.Damageable;
import org.bukkit.inventory.meta.ItemMeta;
diff --git a/src/main/resources/config.yml b/src/main/resources/config.yml
index 35cfb8dd..6e16824b 100644
--- a/src/main/resources/config.yml
+++ b/src/main/resources/config.yml
@@ -39,6 +39,20 @@ world:
# The world players will be teleported to if they accidentally join the WITP world without being a player
fall-back: world
+# Options for permissions
+# These permissions are used to determine which things the player can change.
+# List: https://github.com/Efnilite/Walk-in-the-Park/wiki/Permissions
+permissions:
+
+ # If permissions are enabled
+ enabled: false
+
+# Options for focus mode
+focus-mode:
+
+ # If focus mode is enabled players can't use commands while in parkour
+ enabled: false
+
# Options for the option menu
options:
@@ -85,7 +99,7 @@ styles:
scoreboard:
enabled: true
- title: '&c&lInfinite Parkour'
+ title: '&a&lWITP'
lines:
- '&a'
- '&7Score: &f%score%'
@@ -93,24 +107,6 @@ scoreboard:
- '&b'
- '&6&lserver.ip'
-# Options for the messages
-# %p is the player.
-messages:
-
- # If join/leave messages should be shown
- join-leave-enabled: true
- join: '&7%p has joined the server.'
- leave: '&7%p has left the server.'
-
- divider: '&7----------------------------------------'
- score: '&aYour score: &f%s'
- time: '&aYour time: &f%s'
- highscore: '&aYour highscore: &f%s'
- message:
- miss: '&7You missed your high score by %s points!'
- beat: '&7You beat your high score by %s points!'
- tied: '&7You tied your high score!'
-
# Options for custom rewards
rewards:
diff --git a/src/main/resources/lang.yml b/src/main/resources/lang.yml
new file mode 100644
index 00000000..2ace0c6c
--- /dev/null
+++ b/src/main/resources/lang.yml
@@ -0,0 +1,50 @@
+# Options for the messages
+# %p is the player.
+# %[a-z] is the value that can get replaced
+messages:
+
+ # If the scoreboard is enabled
+ scoreboard-enabled: true
+ # If join/leave messages should be shown
+ join-leave-enabled: true
+
+ # English
+ # Currently (v1.8) you can't add any other language, this will be added later
+ en:
+ join: '&7%p has joined the server'
+ leave: '&7%p has left the server'
+ joined: '&aYou joined the parkour'
+ left: '&cYou left the parkour'
+
+ next-page: '&aNext page >>'
+ previous-page: '&a<< Previous page'
+ your-rank: '&7Your rank: &f#%n &7(%h)'
+
+ selected-style: '&7You selected style &c%s&7!'
+ selected-block-lead: '&7You selected a &a%a &7block lead!'
+ selected-time: '&7You changed your time preference to &a%t'
+ selected-difficulty: '&7You changed your usage of difficulty to %v'
+ selected-particles: '&7You changed the showing of particles to %v'
+ selected-scoreboard: '&7You changed the showing of the scoreboard to %v'
+ selected-fall-message: '&7You changed the showing of the fall messages to %v'
+ selected-special-blocks: '&7You changed the usage of special blocks to %v'
+ selected-structures: '&7You changed the usage of structures to %v'
+ cant-do: '&cYou can''t do this right now.'
+
+ item-close: '&c&lClose'
+ item-quit: '&4&lQuit'
+
+ item-search: '&a&lSearch'
+ item-search-lore: '&7Search for a player to spectate'
+ not-there-search: '&7Type the player you want to spectate!'
+ click-search: '&c&l&nClick here&r&c&l to enter the player you want to search.'
+
+ spectator: '&cYou are now a spectator. You can use "/witp gm" to leave/change your gamemode.'
+ divider: '&7----------------------------------------'
+ score: '&aYour score: &f%s'
+ time: '&aYour time: &f%s'
+ highscore: '&aYour highscore: &f%s'
+ message:
+ miss: '&7You missed your high score by %s points!'
+ beat: '&7You beat your high score by %s points!'
+ tied: '&7You tied your high score!'
\ No newline at end of file