entry : this.collection) {
+ previousIndex = entry.setIndex(previousIndex + 1) + (entry.getProbability() - 1);
+ }
+ }
+
+ /**
+ * Used internally to store information about a object's
+ * state in a collection. Specifically, the probability
+ * and index within the collection.
+ *
+ * Indexes refer to the start position of this element's "block" of space.
+ * The space between element "block"s represents their probability of being selected
+ *
+ * @param Type of element
+ * @author Lewys Davies
+ */
+ final static class ProbabilitySetElement {
+ private final T object;
+ private final int probability;
+ private int index;
+
+ /**
+ * @param object
+ * @param probability
+ */
+ protected ProbabilitySetElement(T object, int probability) {
+ this.object = object;
+ this.probability = probability;
+ }
+
+ /**
+ * @return The actual object
+ */
+ public final T getObject() {
+ return this.object;
+ }
+
+ /**
+ * @return Probability share in this collection
+ */
+ public final int getProbability() {
+ return this.probability;
+ }
+
+ // Used internally, see this class's documentation
+ private final int getIndex() {
+ return this.index;
+ }
+
+ // Used Internally, see this class's documentation
+ private final int setIndex(int index) {
+ this.index = index;
+ return this.index;
+ }
+ }
+}
diff --git a/src/main/java/hdvtdev/blockAndSeek/BlockAndSeek.java b/src/main/java/hdvtdev/blockAndSeek/BlockAndSeek.java
index f2cab4a..68df789 100644
--- a/src/main/java/hdvtdev/blockAndSeek/BlockAndSeek.java
+++ b/src/main/java/hdvtdev/blockAndSeek/BlockAndSeek.java
@@ -3,7 +3,8 @@ package hdvtdev.blockAndSeek;
import hdvtdev.blockAndSeek.managers.ConfigManager;
import me.libraryaddict.disguise.LibsDisguises;
import org.bukkit.Bukkit;
-import org.bukkit.command.CommandExecutor;
+import org.bukkit.command.PluginCommand;
+import org.bukkit.configuration.serialization.ConfigurationSerialization;
import org.bukkit.plugin.Plugin;
import org.bukkit.plugin.java.JavaPlugin;
@@ -13,9 +14,9 @@ import java.io.InputStream;
import java.util.Objects;
import java.util.logging.Logger;
-public class BlockAndSeek extends JavaPlugin implements CommandExecutor {
+public class BlockAndSeek extends JavaPlugin {
- private static Plugin javaPlugin;
+ private static JavaPlugin javaPlugin;
public static Plugin getInstance() {
return javaPlugin;
@@ -45,11 +46,18 @@ public class BlockAndSeek extends JavaPlugin implements CommandExecutor {
return javaPlugin.getLogger();
}
+ public static PluginCommand getCmd(String name) {
+ return javaPlugin.getCommand(name);
+
+ }
+
@Override
public void onEnable() {
javaPlugin = this;
+ ConfigurationSerialization.registerClass(BlockAndSeekMap.class, "BlockAndSeekMap");
+
LibsDisguises libsDisguises = (LibsDisguises) Bukkit.getPluginManager().getPlugin("LibsDisguises");
if (libsDisguises == null) {
@@ -63,7 +71,19 @@ public class BlockAndSeek extends JavaPlugin implements CommandExecutor {
getLogger().severe("Failed to save some .yml configs!");
}
- Objects.requireNonNull(getCommand("blockandseek")).setExecutor(new CommandListener());
+ PluginCommand command = Objects.requireNonNull(getCommand("blockandseek"));
+ command.setExecutor(new CommandListener());
+
+
+
+ /* TODO
+ if (CommodoreProvider.isSupported()) {
+ CommandListener.registerCompletions(CommodoreProvider.getCommodore(this), command);
+ }
+
+ */
+
+
getServer().getPluginManager().registerEvents(new EventListener(), this);
}
diff --git a/src/main/java/hdvtdev/blockAndSeek/BlockAndSeekGame.java b/src/main/java/hdvtdev/blockAndSeek/BlockAndSeekGame.java
index b32195f..4c5aa87 100644
--- a/src/main/java/hdvtdev/blockAndSeek/BlockAndSeekGame.java
+++ b/src/main/java/hdvtdev/blockAndSeek/BlockAndSeekGame.java
@@ -1,16 +1,14 @@
package hdvtdev.blockAndSeek;
+import hdvtdev.blockAndSeek.managers.FreezeManager;
import me.libraryaddict.disguise.DisguiseAPI;
+import org.bukkit.Bukkit;
import org.bukkit.GameMode;
-import org.bukkit.Material;
+import org.bukkit.Location;
import org.bukkit.entity.Player;
import org.bukkit.persistence.PersistentDataType;
-import java.security.SecureRandom;
-import java.util.List;
-import java.util.Map;
-import java.util.Objects;
-import java.util.Set;
+import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.atomic.AtomicBoolean;
@@ -21,24 +19,50 @@ public class BlockAndSeekGame {
private final AtomicBoolean started = new AtomicBoolean(false);
private final String name;
private final int maxPlayers;
+ private final Location lobby;
- public BlockAndSeekGame(String name, int maxPlayers) {
+ public BlockAndSeekGame(String name, int maxPlayers, List lobby) {
this.name = name;
this.maxPlayers = maxPlayers;
+ this.lobby = new Location(Bukkit.getWorld(name), lobby.getFirst(), lobby.get(1), lobby.get(2));
}
public List getHiders() {
return players.entrySet().stream().filter(e -> Objects.equals(e.getValue(), PlayerType.HIDER)).map(Map.Entry::getKey).toList();
}
+ public void preEnd() {
+
+ for (Player hider : getHiders()) {
+ FreezeManager.unfreezeIfFrozen(hider);
+ FreezeManager.removePlayerDisguise(hider);
+ DisguiseAPI.undisguiseToAll(hider);
+ hider.getInventory().clear();
+ hider.setGlowing(true);
+ }
+
+ for (Player player : getPlayers()) {
+ player.setInvulnerable(true);
+ player.setVisibleByDefault(true);
+ }
+
+
+ }
+
public void end() {
+
+ for (Player hider : getHiders()) {
+ FreezeManager.removePlayerDisguise(hider);
+ DisguiseAPI.undisguiseToAll(hider);
+ }
+
for (Player player : players.keySet()) {
- //EventListener.unfreezePlayer(player); TODO
- player.getPersistentDataContainer().remove(BlockAndSeekContainer.PLAYER);
- player.sendBlockChange(player.getLocation(), Material.AIR.createBlockData());
+ player.teleport(lobby);
+ player.getPersistentDataContainer().remove(Keys.PLAYER);
player.setGameMode(GameMode.SURVIVAL);
- DisguiseAPI.undisguiseToAll(player);
+ player.setInvulnerable(false);
+ player.setGlowing(false);
}
}
@@ -46,7 +70,8 @@ public class BlockAndSeekGame {
if (started.get() || playerCount() + 1 > maxPlayers) {
return false;
}
- player.getPersistentDataContainer().set(BlockAndSeekContainer.PLAYER, PersistentDataType.STRING, name);
+ player.getPersistentDataContainer().set(Keys.PLAYER, PersistentDataType.STRING, name);
+ player.teleport(lobby);
players.put(player, PlayerType.HIDER);
return true;
}
@@ -92,17 +117,15 @@ public class BlockAndSeekGame {
}
public Player selectRandomSeeker() {
- SecureRandom random = new SecureRandom();
- int i = 0;
- int randomNum = random.nextInt(0, players.size());
- for (Player player : players.keySet()) {
- if (i == randomNum) {
- players.put(player, PlayerType.SEEKER);
- return player;
- }
- i++;
- }
- return null;
+ return selectRandomSeekers(1).getFirst();
+ }
+
+ public List selectRandomSeekers(int count) {
+ ArrayList playerList = new ArrayList<>(players.keySet());
+ Collections.shuffle(playerList);
+ List seekers = playerList.subList(0, Math.min(count, playerList.size()));
+ for (Player seeker : seekers) players.put(seeker, PlayerType.SEEKER);
+ return seekers;
}
private enum PlayerType {
diff --git a/src/main/java/hdvtdev/blockAndSeek/BlockAndSeekMap.java b/src/main/java/hdvtdev/blockAndSeek/BlockAndSeekMap.java
index a2a2a41..e00fd54 100644
--- a/src/main/java/hdvtdev/blockAndSeek/BlockAndSeekMap.java
+++ b/src/main/java/hdvtdev/blockAndSeek/BlockAndSeekMap.java
@@ -1,17 +1,162 @@
package hdvtdev.blockAndSeek;
+import org.bukkit.Material;
+import org.bukkit.configuration.serialization.ConfigurationSerializable;
import org.bukkit.inventory.ItemStack;
import org.jetbrains.annotations.NotNull;
-import java.util.List;
+import java.util.*;
-public record BlockAndSeekMap(List spawn, List lobby, int duration, int minPlayers, int maxPlayers,
- List blocks) {
+public class BlockAndSeekMap implements ConfigurationSerializable {
-
- public record Block(@NotNull ItemStack block, int chance) {
+ private List spawn;
+ private List lobby;
+ private int duration;
+ private int minPlayers;
+ private int maxPlayers;
+ private List blocks;
+
+ public BlockAndSeekMap() {
}
+ public BlockAndSeekMap(List spawn, List lobby, int duration, int minPlayers, int maxPlayers,
+ List blocks) {
+ this.spawn = spawn;
+ this.lobby = lobby;
+ this.duration = duration;
+ this.minPlayers = minPlayers;
+ this.maxPlayers = maxPlayers;
+ this.blocks = blocks;
+ }
+
+ public List getSpawn() {
+ return spawn;
+ }
+
+ public void setSpawn(List spawn) {
+ this.spawn = spawn;
+ }
+
+ public List getLobby() {
+ return lobby;
+ }
+
+ public void setLobby(List lobby) {
+ this.lobby = lobby;
+ }
+
+ public int getDuration() {
+ return duration;
+ }
+
+ public void setDuration(int duration) {
+ this.duration = duration;
+ }
+
+ public int getMinPlayers() {
+ return minPlayers;
+ }
+
+ public void setMinPlayers(int minPlayers) {
+ this.minPlayers = minPlayers;
+ }
+
+ public int getMaxPlayers() {
+ return maxPlayers;
+ }
+
+ public void setMaxPlayers(int maxPlayers) {
+ this.maxPlayers = maxPlayers;
+ }
+
+ public List getBlocks() {
+ return blocks;
+ }
+
+ public void setBlocks(List blocks) {
+ this.blocks = blocks;
+ }
+
+ public boolean isReady() {
+ return !spawn.isEmpty() && !lobby.isEmpty() && duration > 0 && !blocks.isEmpty() && minPlayers > 0 && maxPlayers > 0;
+ }
+
+ public static BlockAndSeekMap defaultMap() {
+ return new BlockAndSeekMap(List.of(), List.of(), 0, 0, 0, List.of());
+ }
+
+ public Set check() {
+ Set status = new HashSet<>();
+ if (spawn.isEmpty()) status.add(MapStatus.SPAWN_REQUIRED);
+ if (lobby.isEmpty()) status.add(MapStatus.LOBBY_REQUIRED);
+ if (duration <= 0) status.add(MapStatus.DURATION_REQUIRED);
+ if (minPlayers <= 0) status.add(MapStatus.MIN_PLAYERS_REQUIRED);
+ if (maxPlayers <= 0) status.add(MapStatus.MAX_PLAYERS_REQUIRED);
+ if (blocks.isEmpty()) status.add(MapStatus.BLOCKS_REQUIRED);
+ return status;
+ }
+
+ @Override
+ public @NotNull Map serialize() {
+
+ Map map = new HashMap<>();
+ map.put("spawn", spawn);
+ map.put("lobby", lobby);
+ map.put("duration", duration);
+ map.put("min-players", minPlayers);
+ map.put("max-players", maxPlayers);
+ List