idk some "cool" stuff

This commit is contained in:
hdvt
2025-07-01 03:25:09 +03:00
parent e63ac83c17
commit 118f503011
17 changed files with 1060 additions and 317 deletions

View File

@@ -18,12 +18,14 @@ repositories {
name = "sonatype" name = "sonatype"
url = "https://oss.sonatype.org/content/groups/public/" url = "https://oss.sonatype.org/content/groups/public/"
} }
maven { url 'https://libraries.minecraft.net/' }
} }
dependencies { dependencies {
compileOnly("io.papermc.paper:paper-api:1.20.4-R0.1-SNAPSHOT") compileOnly("io.papermc.paper:paper-api:1.20.4-R0.1-SNAPSHOT")
implementation("com.github.lewysDavies:Java-Probability-Collection:v0.8")
implementation group: 'me.libraryaddict.disguises', name: 'libsdisguises', version: '11.0.6' implementation group: 'me.libraryaddict.disguises', name: 'libsdisguises', version: '11.0.6'
//TODO implementation 'me.lucko:commodore:2.2'
} }
@@ -55,10 +57,13 @@ processResources {
} }
jar { jar {
//destinationDirectory.set(file("/home/hadvart/Documents/Minecraft/Pufferfish 1.20.4/plugins"))
destinationDirectory.set(file("/home/hadvart/Documents/Minecraft/Pufferfish 1.20.4/plugins"))
from sourceSets.main.output from sourceSets.main.output
from { configurations.runtimeClasspath.findAll { it.name.startsWith('Java-Probability-Collection') }.collect { zipTree(it) } } from {
configurations.runtimeClasspath.findAll {
it.name.startsWith('Java-Probability-Collection') || it.name.startsWith('commodore') || it.name.startsWith('brigadier')
}.collect { zipTree(it) }
}
duplicatesStrategy = DuplicatesStrategy.EXCLUDE duplicatesStrategy = DuplicatesStrategy.EXCLUDE
} }

View File

@@ -2,17 +2,13 @@
<!DOCTYPE xml> <!DOCTYPE xml>
<project name="BlockAndSeek" default="Build"> <project name="BlockAndSeek" default="Build">
<target name="Build"> <target name="Build">
<jar jarfile="/home/hadvart/Documents/Minecraft/Pufferfish 1.20.4/plugins/${ant.project.name}.jar"> <jar jarfile="/home/hadvart/Documents/Minecraft/Pufferfish 1.20.4/plugins/${ant.project.name}-ant.jar">
<fileset dir="./build/classes/" includes="**/*"/> <fileset dir="./build/classes/java/main" includes="**/*"/>
<fileset dir="./build/resources/main" includes="**/*"/> <fileset dir="./build/resources/main" includes="**/*"/>
<zipfileset
src="/home/hadvart/.gradle/caches/modules-2/files-2.1/com.github.lewysDavies/Java-Probability-Collection/v0.8/51dde432abda7a4846d8a3e2ea48361edc61becf/Java-Probability-Collection-v0.8.jar"
includes="**/*.class" excludes="*.yml"/>
</jar>
</jar>
</target> </target>
</project> </project>

View File

@@ -0,0 +1,246 @@
/*
* Copyright (c) 2020 Lewys Davies
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package com.lewdev.probabilitylib;
import java.util.*;
/**
* ProbabilityCollection for retrieving random elements based on probability.
* <br>
* <br>
* <b>Selection Algorithm Implementation</b>:
* <p>
* <ul>
* <li>Elements have a "block" of space, sized based on their probability share
* <li>"Blocks" start from index 1 and end at the total probability of all elements
* <li>A random number is selected between 1 and the total probability
* <li>Which "block" the random number falls in is the element that is selected
* <li>Therefore "block"s with larger probability have a greater chance of being
* selected than those with smaller probability.
* </p>
* </ul>
*
* @param <E> Type of elements
* @author Lewys Davies
* @version 0.8
*/
public class ProbabilityCollection<E> {
private final NavigableSet<ProbabilitySetElement<E>> collection;
private final SplittableRandom random = new SplittableRandom();
private int totalProbability;
/**
* Construct a new Probability Collection
*/
public ProbabilityCollection() {
this.collection = new TreeSet<>(Comparator.comparingInt(ProbabilitySetElement::getIndex));
this.totalProbability = 0;
}
/**
* @return Number of objects inside the collection
*/
public int size() {
return this.collection.size();
}
/**
* @return True if collection contains no elements, else False
*/
public boolean isEmpty() {
return this.collection.isEmpty();
}
/**
* @param <E> object
* @return True if collection contains the object, else False
* @throws IllegalArgumentException if object is null
*/
public boolean contains(E object) {
if (object == null) {
throw new IllegalArgumentException("Cannot check if null object is contained in this collection");
}
return this.collection.stream()
.anyMatch(entry -> entry.getObject().equals(object));
}
/**
* @return Iterator over this collection
*/
public Iterator<ProbabilitySetElement<E>> iterator() {
return this.collection.iterator();
}
/**
* Add an object to this collection
*
* @param <E> object. Not null.
* @param probability share. Must be greater than 0.
* @throws IllegalArgumentException if object is null
* @throws IllegalArgumentException if probability <= 0
*/
public void add(E object, int probability) {
if (object == null) {
throw new IllegalArgumentException("Cannot add null object");
}
if (probability <= 0) {
throw new IllegalArgumentException("Probability must be greater than 0");
}
ProbabilitySetElement<E> entry = new ProbabilitySetElement<E>(object, probability);
entry.setIndex(this.totalProbability + 1);
this.collection.add(entry);
this.totalProbability += probability;
}
/**
* Remove a object from this collection
*
* @param <E> object
* @return True if object was removed, else False.
* @throws IllegalArgumentException if object is null
*/
public boolean remove(E object) {
if (object == null) {
throw new IllegalArgumentException("Cannot remove null object");
}
Iterator<ProbabilitySetElement<E>> it = this.iterator();
boolean removed = false;
while (it.hasNext()) {
ProbabilitySetElement<E> entry = it.next();
if (entry.getObject().equals(object)) {
this.totalProbability -= entry.getProbability();
it.remove();
removed = true;
}
}
this.updateIndexes();
return removed;
}
/**
* Remove all objects from this collection
*/
public void clear() {
this.collection.clear();
this.totalProbability = 0;
}
/**
* Get a random object from this collection, based on probability.
*
* @return <E> Random object
* @throws IllegalStateException if this collection is empty
*/
public E get() {
if (this.isEmpty()) {
throw new IllegalStateException("Cannot get an object out of a empty collection");
}
ProbabilitySetElement<E> toFind = new ProbabilitySetElement<>(null, 0);
toFind.setIndex(this.random.nextInt(1, this.totalProbability + 1));
return Objects.requireNonNull(this.collection.floor(toFind).getObject());
}
/**
* @return Sum of all element's probability
*/
public final int getTotalProbability() {
return this.totalProbability;
}
/*
* Calculate the size of all element's "block" of space:
* i.e 1-5, 6-10, 11-14, 15, 16
*
* We then only need to store the start index of each element,
* as we make use of the TreeSet#floor
*/
private final void updateIndexes() {
int previousIndex = 0;
for (ProbabilitySetElement<E> 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.
* <p>
* 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 <T> Type of element
* @author Lewys Davies
*/
final static class ProbabilitySetElement<T> {
private final T object;
private final int probability;
private int index;
/**
* @param <T> object
* @param probability
*/
protected ProbabilitySetElement(T object, int probability) {
this.object = object;
this.probability = probability;
}
/**
* @return <T> 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;
}
}
}

View File

@@ -3,7 +3,8 @@ package hdvtdev.blockAndSeek;
import hdvtdev.blockAndSeek.managers.ConfigManager; import hdvtdev.blockAndSeek.managers.ConfigManager;
import me.libraryaddict.disguise.LibsDisguises; import me.libraryaddict.disguise.LibsDisguises;
import org.bukkit.Bukkit; 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.Plugin;
import org.bukkit.plugin.java.JavaPlugin; import org.bukkit.plugin.java.JavaPlugin;
@@ -13,9 +14,9 @@ import java.io.InputStream;
import java.util.Objects; import java.util.Objects;
import java.util.logging.Logger; 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() { public static Plugin getInstance() {
return javaPlugin; return javaPlugin;
@@ -45,11 +46,18 @@ public class BlockAndSeek extends JavaPlugin implements CommandExecutor {
return javaPlugin.getLogger(); return javaPlugin.getLogger();
} }
public static PluginCommand getCmd(String name) {
return javaPlugin.getCommand(name);
}
@Override @Override
public void onEnable() { public void onEnable() {
javaPlugin = this; javaPlugin = this;
ConfigurationSerialization.registerClass(BlockAndSeekMap.class, "BlockAndSeekMap");
LibsDisguises libsDisguises = (LibsDisguises) Bukkit.getPluginManager().getPlugin("LibsDisguises"); LibsDisguises libsDisguises = (LibsDisguises) Bukkit.getPluginManager().getPlugin("LibsDisguises");
if (libsDisguises == null) { if (libsDisguises == null) {
@@ -63,7 +71,19 @@ public class BlockAndSeek extends JavaPlugin implements CommandExecutor {
getLogger().severe("Failed to save some .yml configs!"); 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); getServer().getPluginManager().registerEvents(new EventListener(), this);
} }

View File

@@ -1,16 +1,14 @@
package hdvtdev.blockAndSeek; package hdvtdev.blockAndSeek;
import hdvtdev.blockAndSeek.managers.FreezeManager;
import me.libraryaddict.disguise.DisguiseAPI; import me.libraryaddict.disguise.DisguiseAPI;
import org.bukkit.Bukkit;
import org.bukkit.GameMode; import org.bukkit.GameMode;
import org.bukkit.Material; import org.bukkit.Location;
import org.bukkit.entity.Player; import org.bukkit.entity.Player;
import org.bukkit.persistence.PersistentDataType; import org.bukkit.persistence.PersistentDataType;
import java.security.SecureRandom; import java.util.*;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.atomic.AtomicBoolean; import java.util.concurrent.atomic.AtomicBoolean;
@@ -21,24 +19,50 @@ public class BlockAndSeekGame {
private final AtomicBoolean started = new AtomicBoolean(false); private final AtomicBoolean started = new AtomicBoolean(false);
private final String name; private final String name;
private final int maxPlayers; private final int maxPlayers;
private final Location lobby;
public BlockAndSeekGame(String name, int maxPlayers) { public BlockAndSeekGame(String name, int maxPlayers, List<Integer> lobby) {
this.name = name; this.name = name;
this.maxPlayers = maxPlayers; this.maxPlayers = maxPlayers;
this.lobby = new Location(Bukkit.getWorld(name), lobby.getFirst(), lobby.get(1), lobby.get(2));
} }
public List<Player> getHiders() { public List<Player> getHiders() {
return players.entrySet().stream().filter(e -> Objects.equals(e.getValue(), PlayerType.HIDER)).map(Map.Entry::getKey).toList(); 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() { public void end() {
for (Player hider : getHiders()) {
FreezeManager.removePlayerDisguise(hider);
DisguiseAPI.undisguiseToAll(hider);
}
for (Player player : players.keySet()) { for (Player player : players.keySet()) {
//EventListener.unfreezePlayer(player); TODO player.teleport(lobby);
player.getPersistentDataContainer().remove(BlockAndSeekContainer.PLAYER); player.getPersistentDataContainer().remove(Keys.PLAYER);
player.sendBlockChange(player.getLocation(), Material.AIR.createBlockData());
player.setGameMode(GameMode.SURVIVAL); 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) { if (started.get() || playerCount() + 1 > maxPlayers) {
return false; 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); players.put(player, PlayerType.HIDER);
return true; return true;
} }
@@ -92,17 +117,15 @@ public class BlockAndSeekGame {
} }
public Player selectRandomSeeker() { public Player selectRandomSeeker() {
SecureRandom random = new SecureRandom(); return selectRandomSeekers(1).getFirst();
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++;
} public List<Player> selectRandomSeekers(int count) {
return null; ArrayList<Player> playerList = new ArrayList<>(players.keySet());
Collections.shuffle(playerList);
List<Player> seekers = playerList.subList(0, Math.min(count, playerList.size()));
for (Player seeker : seekers) players.put(seeker, PlayerType.SEEKER);
return seekers;
} }
private enum PlayerType { private enum PlayerType {

View File

@@ -1,17 +1,162 @@
package hdvtdev.blockAndSeek; package hdvtdev.blockAndSeek;
import org.bukkit.Material;
import org.bukkit.configuration.serialization.ConfigurationSerializable;
import org.bukkit.inventory.ItemStack; import org.bukkit.inventory.ItemStack;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import java.util.List; import java.util.*;
public record BlockAndSeekMap(List<Integer> spawn, List<Integer> lobby, int duration, int minPlayers, int maxPlayers, public class BlockAndSeekMap implements ConfigurationSerializable {
List<Block> blocks) {
private List<Integer> spawn;
private List<Integer> lobby;
private int duration;
private int minPlayers;
private int maxPlayers;
private List<Block> blocks;
public record Block(@NotNull ItemStack block, int chance) { public BlockAndSeekMap() {
} }
public BlockAndSeekMap(List<Integer> spawn, List<Integer> lobby, int duration, int minPlayers, int maxPlayers,
List<Block> blocks) {
this.spawn = spawn;
this.lobby = lobby;
this.duration = duration;
this.minPlayers = minPlayers;
this.maxPlayers = maxPlayers;
this.blocks = blocks;
}
public List<Integer> getSpawn() {
return spawn;
}
public void setSpawn(List<Integer> spawn) {
this.spawn = spawn;
}
public List<Integer> getLobby() {
return lobby;
}
public void setLobby(List<Integer> 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<Block> getBlocks() {
return blocks;
}
public void setBlocks(List<Block> 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<MapStatus> check() {
Set<MapStatus> 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<String, Object> serialize() {
Map<String, Object> 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<Map<String, Object>> serBlocks = new ArrayList<>();
for (Block block : blocks) {
serBlocks.add(block.toMap());
}
map.put("blocks", serBlocks);
return map;
}
@NotNull
@SuppressWarnings("unchecked")
public static BlockAndSeekMap deserialize(@NotNull Map<String, Object> args) {
BlockAndSeekMap map = new BlockAndSeekMap();
map.setSpawn((List<Integer>) args.get("spawn"));
map.setLobby((List<Integer>) args.get("lobby"));
map.setDuration((int) args.get("duration"));
map.setMinPlayers((int) args.get("min-players"));
map.setMaxPlayers((int) args.get("max-players"));
map.setBlocks(((List<Map<String, Object>>) args.get("blocks")).stream().map(Block::fromMap).toList());
return map;
}
@Override
public String toString() {
return String.format("BlockAndSeekMap[spawn=%s, lobby=%s, duration=%s, minPlayers=%s, maxPlayers=%s, blocks=%s]", spawn, lobby, duration, minPlayers, maxPlayers, blocks);
}
public enum MapStatus {
SPAWN_REQUIRED,
LOBBY_REQUIRED,
DURATION_REQUIRED,
BLOCKS_REQUIRED,
MIN_PLAYERS_REQUIRED,
MAX_PLAYERS_REQUIRED
}
public record Block(@NotNull ItemStack block, int chance) {
public Map<String, Object> toMap() {
Map<String, Object> map = new HashMap<>();
map.put("block", block.getType().name());
map.put("chance", chance);
return map;
}
public static Block fromMap(Map<String, Object> map) {
return new Block(new ItemStack(Material.valueOf(((String) map.get("block")).toUpperCase())), (int) map.get("chance"));
}
}
} }

View File

@@ -1,15 +1,19 @@
package hdvtdev.blockAndSeek; package hdvtdev.blockAndSeek;
import hdvtdev.blockAndSeek.managers.ConfigManager; //import com.mojang.brigadier.arguments.StringArgumentType;
import hdvtdev.blockAndSeek.managers.FreezeManager; //import com.mojang.brigadier.builder.LiteralArgumentBuilder;
import hdvtdev.blockAndSeek.managers.GamesManager; //import com.mojang.brigadier.builder.RequiredArgumentBuilder;
import hdvtdev.blockAndSeek.managers.*;
import me.libraryaddict.disguise.DisguiseAPI;
import me.libraryaddict.disguise.disguisetypes.DisguiseType;
import me.libraryaddict.disguise.disguisetypes.MiscDisguise;
import net.kyori.adventure.text.minimessage.MiniMessage; import net.kyori.adventure.text.minimessage.MiniMessage;
import org.bukkit.Location; import org.bukkit.Location;
import org.bukkit.Material; import org.bukkit.Material;
import org.bukkit.command.Command; import org.bukkit.command.Command;
import org.bukkit.command.CommandExecutor;
import org.bukkit.command.CommandSender; import org.bukkit.command.CommandSender;
import org.bukkit.command.TabCompleter; import org.bukkit.command.TabExecutor;
import org.bukkit.entity.Player; import org.bukkit.entity.Player;
import org.bukkit.inventory.ItemStack; import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.meta.ItemMeta; import org.bukkit.inventory.meta.ItemMeta;
@@ -18,11 +22,9 @@ import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.Nullable;
import java.io.IOException; import java.io.IOException;
import java.util.ArrayList; import java.util.*;
import java.util.List;
import java.util.Set;
public class CommandListener implements CommandExecutor, TabCompleter { public class CommandListener implements TabExecutor {
private static final MiniMessage miniMessage = MiniMessage.miniMessage(); private static final MiniMessage miniMessage = MiniMessage.miniMessage();
@@ -37,6 +39,7 @@ public class CommandListener implements CommandExecutor, TabCompleter {
return true; return true;
} }
switch (args[0]) { switch (args[0]) {
case "test" -> { case "test" -> {
switch (GamesManager.createGame("dust2")) { switch (GamesManager.createGame("dust2")) {
@@ -55,28 +58,32 @@ public class CommandListener implements CommandExecutor, TabCompleter {
player.sendMessage("eq: " + player.locale().toLanguageTag().equals("en-US")); player.sendMessage("eq: " + player.locale().toLanguageTag().equals("en-US"));
} }
} }
case "freeze" -> { case "menu" -> {
if (sender instanceof Player player) { if (sender instanceof Player player) {
ItemStack foo = new ItemStack(Material.HEART_OF_THE_SEA); GuiManager.Menu.open(player);
ItemMeta fooMeta = foo.getItemMeta();
fooMeta.displayName(MiniMessage.miniMessage().deserialize("<gradient:#084CFB:#ADF3FD><bold>Freeze"));
fooMeta.getPersistentDataContainer().set(BlockAndSeekContainer.FREEZE_ITEM, PersistentDataType.BOOLEAN, true);
foo.setItemMeta(fooMeta);
player.getInventory().addItem(foo);
}
}
case "f" -> {
if (sender instanceof Player player) {
FreezeManager.freeze(player, Material.TARGET);
} }
} }
case "morph" -> {
if (sender instanceof Player player && args.length == 2) {
Material material = Material.valueOf(args[1].toUpperCase());
FreezeManager.addPlayerDisguise(player, material.createBlockData());
DisguiseAPI.disguiseToAll(player, new MiscDisguise(DisguiseType.FALLING_BLOCK, new ItemStack(material)));
}
}
case "armor" -> {
if (sender instanceof Player player) {
player.getInventory().setArmorContents(ItemManager.getSeekerArmor());
}
}
case "foo" -> { case "foo" -> {
if (sender instanceof Player player) { if (sender instanceof Player player) {
ItemStack foo = new ItemStack(Material.BROWN_DYE); ItemStack foo = new ItemStack(Material.BROWN_DYE);
ItemMeta fooMeta = foo.getItemMeta(); ItemMeta fooMeta = foo.getItemMeta();
fooMeta.displayName(MiniMessage.miniMessage().deserialize("<gradient:#00FF00:#01A368><bold>SoundMaker3000")); fooMeta.displayName(MiniMessage.miniMessage().deserialize("<gradient:#00FF00:#01A368><bold>SoundMaker3000"));
fooMeta.getPersistentDataContainer().set(BlockAndSeekContainer.SOUND_ITEM, PersistentDataType.BOOLEAN, true); fooMeta.getPersistentDataContainer().set(Keys.SOUND_ITEM, PersistentDataType.BOOLEAN, true);
foo.setItemMeta(fooMeta); foo.setItemMeta(fooMeta);
player.getInventory().addItem(foo); player.getInventory().addItem(foo);
} }
@@ -88,13 +95,36 @@ public class CommandListener implements CommandExecutor, TabCompleter {
case "list" -> { case "list" -> {
StringBuilder buffer = new StringBuilder(Localization.get("maps-available")); StringBuilder buffer = new StringBuilder(Localization.get("maps-available"));
String listElement = Localization.get("maps-available-element"); String listElement = Localization.get("maps-available-element");
Set<String> readyMaps = ConfigManager.getReadyMaps(); Set<String> readyMaps = null; //TODO ConfigManager.getReadyMaps();
for (String map : ConfigManager.getAllMaps()) { for (String map : ConfigManager.getAllMaps()) {
buffer.append("\n").append(listElement.replace("{map}", map).replace("{color-status}", buffer.append("\n").append(listElement.replace("{map}", map).replace("{color-status}",
readyMaps.contains(map) ? "<green>" : "<red>")); readyMaps.contains(map) ? "<green>" : "<red>"));
} }
sender.sendMessage(miniMessage.deserialize(buffer.toString())); sender.sendMessage(miniMessage.deserialize(buffer.toString()));
} }
default -> {
if (ConfigManager.getAllMaps().contains(args[1])) {
if (argsLen > 3) {
switch (args[2]) {
case "setduration" -> {
try {
int duration = Integer.parseInt(args[3]);
if (duration > 0) {
sender.sendMessage(args[1]);
var map = MapsManager.getMap(args[1]);
map.setDuration(duration);
MapsManager.saveMap(args[1], map);
sender.sendMessage("duration set");
} else sender.sendMessage("idk");
} catch (NumberFormatException | IOException e) {
sender.sendMessage("idk");
}
}
}
}
}
}
} }
} else } else
sender.sendMessage(Localization.getComponent("not-enough-arguments", "{command}", "/blockandseek map", "{help}", "[MAP NAME | COMMANDS]")); sender.sendMessage(Localization.getComponent("not-enough-arguments", "{command}", "/blockandseek map", "{help}", "[MAP NAME | COMMANDS]"));
@@ -132,64 +162,64 @@ public class CommandListener implements CommandExecutor, TabCompleter {
} }
/*
*/
return true; return true;
} }
@Override @Override
public @Nullable List<String> onTabComplete(@NotNull CommandSender sender, @NotNull Command command, @NotNull String label, @NotNull String[] args) { public @Nullable List<String> onTabComplete(@NotNull CommandSender sender, @NotNull Command command, @NotNull String label, @NotNull String[] args) {
boolean hasPermission = sender.hasPermission("blockandseek.manage"); return !sender.hasPermission("blockandseek.manage") ? List.of() : switch (args.length) {
return switch (args.length) { case 1 -> List.of("info", "map", "reload");
case 1 -> {
if (hasPermission) {
yield List.of("reload", "help", "map");
} else yield List.of("help");
}
case 2 -> switch (args[0]) { case 2 -> switch (args[0]) {
case "reload" -> List.of("localization", "config");
case "map" -> { case "map" -> {
List<String> scmds = new ArrayList<>(); List<String> mapCommands = new ArrayList<>(MapsManager.getAllMaps());
mapCommands.add("create");
if (hasPermission) { mapCommands.add("list");
scmds.addAll(List.of("create", "list")); yield mapCommands;
scmds.addAll(ConfigManager.getAllMaps());
}
yield scmds;
}
case "reload" -> {
if (hasPermission) {
yield List.of("localization", "config");
} else yield List.of();
} }
default -> List.of(); default -> List.of();
}; };
case 3 -> switch (args[1]) { case 3 -> {
case "create", "list" -> List.of(); if (MapsManager.getAllMaps().contains(args[1])) {
default -> { yield List.of("status", "setspawn", "setlobby", "setduration", "setminplayers", "setmaxplayers", "addblock", "deleteblock");
}
if (ConfigManager.getAllMaps().contains(args[1]) && hasPermission) { yield List.of();
yield List.of("setspawn", "setlobby", "setduration", "setmaxplayers", "setminplayers", "status", "remove");
} else yield List.of();
} }
};
case 4 -> switch (args[2]) { case 4 -> switch (args[2]) {
case "setspawn", "setlobby" -> { case "setspawn", "setlobby" -> {
if (hasPermission && sender instanceof Player player) { if (sender instanceof Player player) {
Location location = player.getLocation(); Location location = player.getLocation().toCenterLocation();
yield List.of(String.format("%.1f %.0f %.1f", location.getX(), location.getY(), location.getZ())); yield List.of(String.format("%s %s %s", location.getX(), location.getY(), location.getZ()));
} else yield List.of(); } else yield List.of();
} }
case "setduration" -> List.of("[<duration>]");
case "setminplayers", "setmaxplayers" -> List.of("[<count>]");
case "addblock", "removeblock" ->
Arrays.stream(Material.values()).map(Objects::toString).map(String::toLowerCase).toList();
default -> List.of(); default -> List.of();
}; };
case 5 -> args[2].equalsIgnoreCase("addblock") ? List.of("[<chance>]") : List.of();
default -> List.of(); default -> List.of();
}; };
} }
/* TODO
public static void registerCompletions(Commodore commodore, PluginCommand command) {
commodore.register(command, LiteralArgumentBuilder.literal("blockandseek")
.then(RequiredArgumentBuilder.argument("idk", StringArgumentType.greedyString()).suggests((a, b) -> {
b.suggest("sometextidk");
return b.buildFuture();
}).executes(o -> {
System.out.println(23238923);
return 1;
})));
}
*/
} }

View File

@@ -3,42 +3,56 @@ package hdvtdev.blockAndSeek;
import hdvtdev.blockAndSeek.managers.FreezeManager; import hdvtdev.blockAndSeek.managers.FreezeManager;
import hdvtdev.blockAndSeek.managers.GamesManager; import hdvtdev.blockAndSeek.managers.GamesManager;
import hdvtdev.blockAndSeek.managers.GuiManager;
import hdvtdev.blockAndSeek.managers.ItemManager;
import me.libraryaddict.disguise.DisguiseAPI; import me.libraryaddict.disguise.DisguiseAPI;
import me.libraryaddict.disguise.disguisetypes.DisguiseType; import me.libraryaddict.disguise.disguisetypes.DisguiseType;
import me.libraryaddict.disguise.disguisetypes.MiscDisguise; import me.libraryaddict.disguise.disguisetypes.MiscDisguise;
import org.bukkit.Bukkit; import org.bukkit.Bukkit;
import org.bukkit.Material;
import org.bukkit.entity.ArmorStand; import org.bukkit.entity.ArmorStand;
import org.bukkit.entity.Player; import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler; import org.bukkit.event.EventHandler;
import org.bukkit.event.Listener; import org.bukkit.event.Listener;
import org.bukkit.event.block.Action; import org.bukkit.event.block.Action;
import org.bukkit.event.entity.EntityDamageByEntityEvent; import org.bukkit.event.block.BlockBreakEvent;
import org.bukkit.event.block.BlockDamageEvent;
import org.bukkit.event.block.BlockPlaceEvent;
import org.bukkit.event.entity.EntityDismountEvent;
import org.bukkit.event.entity.PlayerDeathEvent; import org.bukkit.event.entity.PlayerDeathEvent;
import org.bukkit.event.inventory.InventoryClickEvent; import org.bukkit.event.inventory.InventoryClickEvent;
import org.bukkit.event.inventory.InventoryCloseEvent; import org.bukkit.event.inventory.InventoryCloseEvent;
import org.bukkit.event.inventory.InventoryType;
import org.bukkit.event.player.PlayerDropItemEvent;
import org.bukkit.event.player.PlayerInteractEvent; import org.bukkit.event.player.PlayerInteractEvent;
import org.bukkit.event.player.PlayerJoinEvent;
import org.bukkit.event.player.PlayerQuitEvent; import org.bukkit.event.player.PlayerQuitEvent;
import org.bukkit.inventory.EquipmentSlot; import org.bukkit.inventory.EquipmentSlot;
import org.bukkit.inventory.Inventory;
import org.bukkit.inventory.InventoryHolder;
import org.bukkit.inventory.ItemStack; import org.bukkit.inventory.ItemStack;
import org.bukkit.persistence.PersistentDataContainer; import org.bukkit.persistence.PersistentDataContainer;
import org.bukkit.persistence.PersistentDataType; import org.bukkit.persistence.PersistentDataType;
import org.bukkit.potion.PotionEffect; import org.bukkit.scheduler.BukkitScheduler;
import org.bukkit.potion.PotionEffectType;
import org.bukkit.scheduler.BukkitTask; import org.bukkit.scheduler.BukkitTask;
import org.bukkit.util.Vector; import org.bukkit.util.Vector;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentHashMap;
public class EventListener implements Listener { public class EventListener implements Listener {
private static final BukkitScheduler scheduler = Bukkit.getScheduler();
private static final Set<Player> coolDown = ConcurrentHashMap.newKeySet();
private static final ConcurrentHashMap<Player, BukkitTask> tasks = new ConcurrentHashMap<>(); private static final ConcurrentHashMap<Player, BukkitTask> tasks = new ConcurrentHashMap<>();
private static final ConcurrentHashMap<Player, Long> soundCoolDown = new ConcurrentHashMap<>(); private static final ConcurrentHashMap<Player, Long> soundCoolDown = new ConcurrentHashMap<>();
private static final ConcurrentHashMap<Player, ArmorStand> frozenPlayers = new ConcurrentHashMap<>();
private static final Vector ZERO_VELOCITY = new Vector(0, 0, 0); private static final Vector ZERO_VELOCITY = new Vector(0, 0, 0);
private static final PotionEffect INVISIBILITY = new PotionEffect(PotionEffectType.INVISIBILITY, PotionEffect.INFINITE_DURATION, 2, false, false); private static final ItemStack freezeItem = ItemManager.getFreezeItem();
private static final ItemStack menuItem = ItemManager.getMenuItem();
public static void createTask(Player player, BukkitTask bukkitTask) { public static void createTask(Player player, BukkitTask bukkitTask) {
tasks.put(player, bukkitTask); tasks.put(player, bukkitTask);
@@ -49,15 +63,40 @@ public class EventListener implements Listener {
task.cancel(); task.cancel();
} }
@EventHandler
public void onDrop(PlayerDropItemEvent event) {
event.setCancelled(true);
}
@EventHandler
public void onBlockDamage(BlockDamageEvent event) {
if (FreezeManager.unfreeze(event.getBlock().getBlockData())) event.setCancelled(true);
}
@EventHandler
public void onPlayerJoin(PlayerJoinEvent event) {
Player player = event.getPlayer();
if (player.getVehicle() instanceof ArmorStand armorStand) {
armorStand.getPersistentDataContainer().remove(Keys.FROZEN_PLAYER);
armorStand.remove();
}
Inventory inventory = player.getInventory();
if (!inventory.contains(ItemManager.getMenuItem())) inventory.addItem(ItemManager.getMenuItem());
}
@EventHandler @EventHandler
public void onPlayerQuit(PlayerQuitEvent event) { public void onPlayerQuit(PlayerQuitEvent event) {
Player player = event.getPlayer(); Player player = event.getPlayer();
PersistentDataContainer container = player.getPersistentDataContainer(); PersistentDataContainer container = player.getPersistentDataContainer();
String arena = container.get(BlockAndSeekContainer.PLAYER, PersistentDataType.STRING); String arena = container.get(Keys.PLAYER, PersistentDataType.STRING);
if (arena != null) { if (arena != null) {
container.remove(BlockAndSeekContainer.PLAYER); container.remove(Keys.PLAYER);
GamesManager.get(arena).removePlayer(player); GamesManager.get(arena).removePlayer(player);
FreezeManager.removePlayerDisguise(player);
} }
} }
@@ -66,11 +105,12 @@ public class EventListener implements Listener {
} }
@EventHandler @EventHandler
public void onDamage(EntityDamageByEntityEvent event) { public void onEntityDismount(EntityDismountEvent event) {
Player player = (Player) event.getEntity();
if (event.getDismounted() instanceof ArmorStand armorStand && armorStand.getPersistentDataContainer().has(Keys.FROZEN_PLAYER)) {
FreezeManager.freeze(player);
}
} }
@@ -78,41 +118,96 @@ public class EventListener implements Listener {
public void onRightClick(PlayerInteractEvent event) { public void onRightClick(PlayerInteractEvent event) {
if (event.getHand() != EquipmentSlot.HAND) return; if (event.getHand() != EquipmentSlot.HAND) return;
Action action = event.getAction(); Action action = event.getAction();
if (action == Action.RIGHT_CLICK_BLOCK || action == Action.RIGHT_CLICK_AIR) {
Player player = event.getPlayer(); Player player = event.getPlayer();
if (player.getInventory().getItemInMainHand().equals(new ItemStack(Material.HEART_OF_THE_SEA))) { if (action.isRightClick() && !coolDown.contains(player)) {
FreezeManager.freeze(player, Material.TARGET);
ItemStack itemInHand = player.getInventory().getItemInMainHand();
if (itemInHand.equals(freezeItem)) {
coolDown.add(player);
scheduler.runTaskLater(BlockAndSeek.getInstance(), () -> coolDown.remove(player), 3L);
FreezeManager.freeze(player);
event.setCancelled(true);
} else if (itemInHand.equals(menuItem)) {
GuiManager.Menu.open(player);
} }
} else event.getPlayer().sendMessage(action.toString()); }
}
@EventHandler
public void onBlockPlacement(BlockPlaceEvent event) {
event.setCancelled(true);
}
@EventHandler
public void onBlockBreak(BlockBreakEvent event) {
event.setCancelled(true);
} }
@EventHandler @EventHandler
public void onClick(InventoryClickEvent event) { public void onInventoryClick(InventoryClickEvent event) {
Player player = (Player) event.getWhoClicked(); Player player = (Player) event.getWhoClicked();
Inventory inventory = event.getClickedInventory();
if (inventory != null) {
InventoryHolder holder = inventory.getHolder();
switch (holder) {
case GuiManager.Menu ignored -> {
switch (event.getSlot()) {
case 13 -> {
GuiManager.Menu.Games.open(player);
}
default -> {
}
}
event.setCancelled(true);
}
case GuiManager.Menu.Games ignored -> {
ItemStack game = event.getCurrentItem();
if (game != null) {
String gameName = game.getItemMeta().getPersistentDataContainer().get(Keys.GAME, PersistentDataType.STRING);
if (gameName != null) GamesManager.get(gameName).addPlayer(player);
}
event.setCancelled(true);
}
case null, default -> {
}
}
}
if (player.hasMetadata("RollingMenu")) { if (player.hasMetadata("RollingMenu")) {
event.setCancelled(true); event.setCancelled(true);
int slot = event.getSlot(); int slot = event.getSlot();
if (slot == 21 || slot == 23 || slot == 25) { if (slot == 21 || slot == 23 || slot == 25) {
if (!tasks.containsKey(player)) { if (!tasks.containsKey(player)) {
MiscDisguise miscDisguise = new MiscDisguise(DisguiseType.FALLING_BLOCK, event.getInventory().getItem(slot)); ItemStack prop = event.getInventory().getItem(slot);
FreezeManager.addPlayerDisguise(player, prop.getType().createBlockData());
MiscDisguise miscDisguise = new MiscDisguise(DisguiseType.FALLING_BLOCK, prop);
DisguiseAPI.disguiseToAll(player, miscDisguise); DisguiseAPI.disguiseToAll(player, miscDisguise);
player.closeInventory(InventoryCloseEvent.Reason.UNKNOWN); player.closeInventory(InventoryCloseEvent.Reason.UNKNOWN);
} }
} }
} else if (event.getSlotType().equals(InventoryType.SlotType.ARMOR)) {
event.setCancelled(true);
} }
} }
@EventHandler @EventHandler
public void onClose(InventoryCloseEvent event) { public void onInventoryClose(InventoryCloseEvent event) {
Player player = (Player) event.getPlayer(); Player player = (Player) event.getPlayer();
if (player.hasMetadata("RollingMenu")) { if (player.hasMetadata("RollingMenu")) {
if (!tasks.containsKey(player)) { if (!tasks.containsKey(player)) {
player.removeMetadata("RollingMenu", BlockAndSeek.getInstance()); player.removeMetadata("RollingMenu", BlockAndSeek.getInstance());
if (!event.getReason().equals(InventoryCloseEvent.Reason.UNKNOWN)) { if (!event.getReason().equals(InventoryCloseEvent.Reason.UNKNOWN)) {
MiscDisguise miscDisguise = new MiscDisguise(DisguiseType.FALLING_BLOCK, event.getInventory().getItem(21)); ItemStack prop = event.getInventory().getItem(21);
FreezeManager.addPlayerDisguise(player, prop.getType().createBlockData());
MiscDisguise miscDisguise = new MiscDisguise(DisguiseType.FALLING_BLOCK, prop);
DisguiseAPI.disguiseToAll(player, miscDisguise); DisguiseAPI.disguiseToAll(player, miscDisguise);
} }
} else { } else {

View File

@@ -5,12 +5,15 @@ import org.bukkit.NamespacedKey;
import org.bukkit.scoreboard.Scoreboard; import org.bukkit.scoreboard.Scoreboard;
import org.bukkit.scoreboard.Team; import org.bukkit.scoreboard.Team;
public class BlockAndSeekContainer { public class Keys {
public static final NamespacedKey SOUND_ITEM = new NamespacedKey(BlockAndSeek.getInstance(), "BlockAndSeekSoundItem"); public static final NamespacedKey SOUND_ITEM = new NamespacedKey(BlockAndSeek.getInstance(), "BlockAndSeekSoundItem");
public static final NamespacedKey FREEZE_ITEM = new NamespacedKey(BlockAndSeek.getInstance(), "BlockAndSeekFreezeItem"); public static final NamespacedKey FREEZE_ITEM = new NamespacedKey(BlockAndSeek.getInstance(), "BlockAndSeekFreezeItem");
public static final NamespacedKey MENU_ITEM = new NamespacedKey(BlockAndSeek.getInstance(), "BlockAndSeekMenuItem");
public static final NamespacedKey FROZEN_PLAYER = new NamespacedKey(BlockAndSeek.getInstance(), "BlockAndSeekFrozenPlayer"); public static final NamespacedKey FROZEN_PLAYER = new NamespacedKey(BlockAndSeek.getInstance(), "BlockAndSeekFrozenPlayer");
public static final NamespacedKey PLAYER = new NamespacedKey(BlockAndSeek.getInstance(), "BlockAndSeekPlayer"); public static final NamespacedKey PLAYER = new NamespacedKey(BlockAndSeek.getInstance(), "BlockAndSeekPlayer");
public static final NamespacedKey GAME = new NamespacedKey(BlockAndSeek.getInstance(), "BlockAndSeekGame");
public static final Team NO_COLLIDE_TEAM; public static final Team NO_COLLIDE_TEAM;

View File

@@ -3,16 +3,15 @@ package hdvtdev.blockAndSeek.managers;
import hdvtdev.blockAndSeek.BlockAndSeek; import hdvtdev.blockAndSeek.BlockAndSeek;
import hdvtdev.blockAndSeek.BlockAndSeekMap; import hdvtdev.blockAndSeek.BlockAndSeekMap;
import hdvtdev.blockAndSeek.Localization; import hdvtdev.blockAndSeek.Localization;
import org.bukkit.Material;
import org.bukkit.configuration.ConfigurationSection; import org.bukkit.configuration.ConfigurationSection;
import org.bukkit.configuration.file.YamlConfiguration; import org.bukkit.configuration.file.YamlConfiguration;
import org.bukkit.inventory.ItemStack;
import org.jetbrains.annotations.Nullable;
import java.io.File; import java.io.File;
import java.io.IOException; import java.io.IOException;
import java.io.InputStreamReader; import java.io.InputStreamReader;
import java.util.*; import java.util.HashMap;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentHashMap;
public class ConfigManager { public class ConfigManager {
@@ -31,99 +30,6 @@ public class ConfigManager {
return YamlConfiguration.loadConfiguration(mapsFile).getKeys(false); return YamlConfiguration.loadConfiguration(mapsFile).getKeys(false);
} }
public enum MapStatus {
SPAWN_REQUIRED,
LOBBY_REQUIRED,
DURATION_REQUIRED,
BLOCKS_REQUIRED,
MIN_PLAYERS_REQUIRED,
MAX_PLAYERS_REQUIRED
}
public static Set<String> getReadyMaps() {
return maps.keySet();
}
public static @Nullable Set<MapStatus> checkMap(String name) {
Set<MapStatus> status = new HashSet<>();
YamlConfiguration configuration = YamlConfiguration.loadConfiguration(mapsFile);
ConfigurationSection section = configuration.getConfigurationSection(name);
if (section != null) {
List<Integer> spawn = section.getIntegerList("spawn");
if (spawn.size() != 3) status.add(MapStatus.SPAWN_REQUIRED);
List<Integer> lobby = section.getIntegerList("lobby");
if (lobby.size() != 3) status.add(MapStatus.LOBBY_REQUIRED);
int duration = section.getInt("duration");
if (duration <= 0) status.add(MapStatus.DURATION_REQUIRED);
int minPlayers = section.getInt("min-players");
if (minPlayers <= 0) status.add(MapStatus.MIN_PLAYERS_REQUIRED);
int maxPlayers = section.getInt("max-players");
if (maxPlayers <= 0) status.add(MapStatus.MAX_PLAYERS_REQUIRED);
List<BlockAndSeekMap.Block> blocks = section.getMapList("blocks").stream().map(
block -> {
try {
return new BlockAndSeekMap.Block(
new ItemStack(Material.valueOf(((String) block.get("block")).toUpperCase())),
(int) block.get("chance")
);
} catch (IllegalArgumentException | ClassCastException ignored) {
return null;
}
}
).toList();
if (blocks.isEmpty() || new HashSet<>(blocks).size() == 1) status.add(MapStatus.BLOCKS_REQUIRED);
if (status.isEmpty())
maps.put(name, new BlockAndSeekMap(spawn, lobby, duration, minPlayers, maxPlayers, blocks));
} else return null;
return status;
}
public static boolean addDefaultMap(String name) {
YamlConfiguration configuration = YamlConfiguration.loadConfiguration(mapsFile);
if (configuration.get(name) != null) return false;
ConfigurationSection section = configuration.createSection(name);
section.set("spawn", List.of());
section.set("lobby", List.of());
section.set("duration", 0);
section.set("min-players", 0);
section.set("max-players", 0);
section.set("blocks", List.of(Map.of()));
try {
configuration.save(mapsFile);
} catch (IOException ignored) {
return false;
}
return true;
}
public static boolean setMapProperty(String map, String property, Object value) {
YamlConfiguration configuration = YamlConfiguration.loadConfiguration(mapsFile);
ConfigurationSection section = configuration.getConfigurationSection(map);
if (section != null) {
section.set(property, value);
try {
configuration.save(mapsFile);
} catch (IOException e) {
return false;
}
}
return true;
}
public static void loadAll() throws IOException { public static void loadAll() throws IOException {
load("config.yml"); load("config.yml");
load("localization.yml"); load("localization.yml");
@@ -166,50 +72,13 @@ public class ConfigManager {
switch (file) { switch (file) {
case "config.yml" -> loadConfig(conf, defaultConfiguration); case "config.yml" -> loadConfig(conf, defaultConfiguration);
case "localization.yml" -> loadLocalization(conf, defaultConfiguration); case "localization.yml" -> loadLocalization(conf, defaultConfiguration);
case "maps.yml" -> loadMaps(conf); case "maps.yml" -> MapsManager.loadMaps();
} }
} }
} }
private static void loadMaps(File configurationFile) throws IOException {
Map<String, BlockAndSeekMap> confMap = new ConcurrentHashMap<>();
YamlConfiguration configuration = YamlConfiguration.loadConfiguration(configurationFile);
for (String map : configuration.getKeys(false)) {
ConfigurationSection section = configuration.getConfigurationSection(map);
if (section != null) {
List<Integer> spawn = section.getIntegerList("spawn");
List<Integer> lobby = section.getIntegerList("lobby");
int duration = section.getInt("duration");
int minPlayers = section.getInt("min-players");
int maxPlayers = section.getInt("max-players");
List<BlockAndSeekMap.Block> blocks = section.getMapList("blocks").stream().map(
block -> {
try {
return new BlockAndSeekMap.Block(
new ItemStack(Material.valueOf(((String) block.get("block")).toUpperCase())),
(int) block.get("chance")
);
} catch (IllegalArgumentException | ClassCastException | NullPointerException ignored) {
return null;
}
}
).filter(Objects::nonNull).toList();
if (!spawn.isEmpty() && !lobby.isEmpty() && duration > 0 && !blocks.isEmpty() && minPlayers > 0 && maxPlayers > 0) {
confMap.put(map, new BlockAndSeekMap(spawn, lobby, duration, minPlayers, maxPlayers, blocks));
}
}
maps = confMap;
}
}
private static void loadConfig(File configurationFile, YamlConfiguration defaultConfiguration) throws IOException { private static void loadConfig(File configurationFile, YamlConfiguration defaultConfiguration) throws IOException {
ConcurrentHashMap<String, String> confMap = new ConcurrentHashMap<>(); ConcurrentHashMap<String, String> confMap = new ConcurrentHashMap<>();

View File

@@ -1,15 +1,16 @@
package hdvtdev.blockAndSeek.managers; package hdvtdev.blockAndSeek.managers;
import hdvtdev.blockAndSeek.BlockAndSeekContainer; import hdvtdev.blockAndSeek.Keys;
import me.libraryaddict.disguise.DisguiseAPI; import me.libraryaddict.disguise.DisguiseAPI;
import me.libraryaddict.disguise.disguisetypes.Disguise; import me.libraryaddict.disguise.disguisetypes.Disguise;
import org.bukkit.Bukkit; import me.libraryaddict.disguise.disguisetypes.DisguiseType;
import me.libraryaddict.disguise.disguisetypes.MiscDisguise;
import org.bukkit.Location; import org.bukkit.Location;
import org.bukkit.Material;
import org.bukkit.block.Block; import org.bukkit.block.Block;
import org.bukkit.block.data.BlockData; import org.bukkit.block.data.BlockData;
import org.bukkit.entity.ArmorStand; import org.bukkit.entity.ArmorStand;
import org.bukkit.entity.Player; import org.bukkit.entity.Player;
import org.bukkit.persistence.PersistentDataType;
import org.bukkit.util.Vector; import org.bukkit.util.Vector;
import java.util.Map; import java.util.Map;
@@ -18,26 +19,58 @@ import java.util.concurrent.ConcurrentHashMap;
public class FreezeManager { public class FreezeManager {
private static final Map<Player, FreezeData> frozenPlayers = new ConcurrentHashMap<>(); private static final Map<Player, FreezeData> frozenPlayers = new ConcurrentHashMap<>();
private static final Map<Player, BlockData> playerDisguise = new ConcurrentHashMap<>();
private static final Map<BlockData, Player> disguisePlayer = new ConcurrentHashMap<>();
private static final Vector velocity = new Vector(0, 0, 0); private static final Disguise hideDisguise = new MiscDisguise(DisguiseType.LLAMA_SPIT);
private static final Vector zeroVelocity = new Vector(0, 0, 0);
public static boolean freeze(Player player, Material material) { public static void addPlayerDisguise(Player player, BlockData blockData) {
Location location = player.getLocation(); disguisePlayer.put(blockData, player);
if (frozenPlayers.containsKey(player)) { playerDisguise.put(player, blockData);
FreezeData data = frozenPlayers.remove(player);
Location blockLocation = location.getBlock().getLocation();
for (Player p : Bukkit.getOnlinePlayers()) {
p.sendBlockChange(blockLocation, data.blockData);
} }
ArmorStand armorStand = data.armorStand;
armorStand.removePassenger(player); public static void removePlayerDisguise(Player player) {
armorStand.remove(); disguisePlayer.remove(playerDisguise.remove(player));
}
public static void unfreezeIfFrozen(Player player) {
Location location = player.getLocation();
FreezeData data = frozenPlayers.remove(player);
if (data != null) {
unfreeze(player, location, data);
}
}
public static boolean unfreeze(BlockData blockData) {
Player player = disguisePlayer.get(blockData);
if (player != null) {
freeze(player);
return true;
} else return false;
}
private static void unfreeze(Player player, Location location, FreezeData data) {
Location blockLocation = location.getBlock().getLocation();
location.getWorld().setBlockData(blockLocation, data.blockData);
player.getPersistentDataContainer().remove(Keys.FROZEN_PLAYER);
data.armorStand.remove();
player.setInvulnerable(false); player.setInvulnerable(false);
BlockAndSeekContainer.NO_COLLIDE_TEAM.removeEntry(player.getName()); Keys.NO_COLLIDE_TEAM.removeEntry(player.getName());
if (data.disguise() != null) DisguiseAPI.disguiseToAll(player, data.disguise); if (data.disguise != null) DisguiseAPI.disguiseToAll(player, data.disguise);
}
public static boolean freeze(Player player) {
Location location = player.getLocation();
FreezeData data = frozenPlayers.remove(player);
if (data != null) {
unfreeze(player, location, data);
} else { } else {
Block block = location.getBlock(); Block block = location.getBlock();
@@ -45,35 +78,37 @@ public class FreezeManager {
Location blockLocation = block.getLocation(); Location blockLocation = block.getLocation();
Location centerLocation = blockLocation.toCenterLocation(); Location centerLocation = blockLocation.toCenterLocation();
Location upperBlockLocation = centerLocation.clone(); Location upperBlockLocation = centerLocation.clone();
upperBlockLocation.setY(upperBlockLocation.getY() + 1); upperBlockLocation.setY(upperBlockLocation.getY() + 0.25);
if (!upperBlockLocation.getBlock().isSolid() && !blockLocation.getBlock().isSolid()) { if (!upperBlockLocation.getBlock().isSolid() && !blockLocation.getBlock().isSolid()) {
for (Player p : Bukkit.getOnlinePlayers()) {
p.sendBlockChange(blockLocation, material.createBlockData());
}
location.getWorld().setBlockData(blockLocation, playerDisguise.get(player));
centerLocation.setY(centerLocation.getY() - 0.5); centerLocation.setY(centerLocation.getY() - 0.85);
player.setVelocity(velocity); player.setVelocity(zeroVelocity);
player.setInvulnerable(true); player.setInvulnerable(true);
BlockAndSeekContainer.NO_COLLIDE_TEAM.addEntry(player.getName()); player.getPersistentDataContainer().set(Keys.FROZEN_PLAYER, PersistentDataType.BOOLEAN, true);
Keys.NO_COLLIDE_TEAM.addEntry(player.getName());
ArmorStand armorStand = location.getWorld().spawn(centerLocation, ArmorStand.class); ArmorStand armorStand = location.getWorld().spawn(centerLocation, ArmorStand.class, stand -> {
armorStand.setInvulnerable(true); stand.setVisible(false);
armorStand.setSmall(true); stand.setVisible(false);
armorStand.setGravity(true); stand.setCollidable(false);
armorStand.setCanMove(false); stand.setGravity(true);
armorStand.setInvisible(true); stand.setSmall(true);
armorStand.setCollidable(false); stand.setCanMove(false);
armorStand.addPassenger(player); stand.addPassenger(player);
stand.getPersistentDataContainer().set(Keys.FROZEN_PLAYER, PersistentDataType.BOOLEAN, true);
stand.setInvulnerable(true);
});
Disguise disguise = DisguiseAPI.getDisguise(player); Disguise disguise = DisguiseAPI.getDisguise(player);
DisguiseAPI.undisguiseToAll(player); DisguiseAPI.disguiseToAll(player, hideDisguise);
frozenPlayers.put(player, new FreezeData(armorStand, blockData, disguise)); frozenPlayers.put(player, new FreezeData(armorStand, blockData, disguise));

View File

@@ -11,6 +11,7 @@ import org.bukkit.Bukkit;
import org.bukkit.Location; import org.bukkit.Location;
import org.bukkit.WorldCreator; import org.bukkit.WorldCreator;
import org.bukkit.entity.Player; import org.bukkit.entity.Player;
import org.bukkit.inventory.PlayerInventory;
import org.bukkit.scheduler.BukkitRunnable; import org.bukkit.scheduler.BukkitRunnable;
import org.bukkit.scoreboard.Criteria; import org.bukkit.scoreboard.Criteria;
import org.bukkit.scoreboard.DisplaySlot; import org.bukkit.scoreboard.DisplaySlot;
@@ -43,19 +44,21 @@ public class GamesManager {
} else return 2; } else return 2;
} }
BlockAndSeekMap map = ConfigManager.getMap(name); BlockAndSeekMap map = MapsManager.getMap(name);
BlockAndSeekGame game = new BlockAndSeekGame(name, map.maxPlayers()); System.out.println(map);
List<Integer> spawnCords = map.spawn(); BlockAndSeekGame game = new BlockAndSeekGame(name, map.getMaxPlayers(), map.getLobby());
List<Integer> lobbyCords = map.lobby(); List<Integer> spawnCords = map.getSpawn();
List<Integer> lobbyCords = map.getLobby();
games.put(name, game); games.put(name, game);
new BukkitRunnable() { new BukkitRunnable() {
int duration = map.duration(); int duration = map.getDuration() + 10;
final int seekerSpawn = duration - 15;
int gameEnd = duration - 10;
int waitTime = 30; int waitTime = 30;
final Location spawn = new Location(Bukkit.getWorld(name), spawnCords.getFirst(), spawnCords.get(1), spawnCords.get(2)); final Location spawn = new Location(Bukkit.getWorld(name), spawnCords.getFirst(), spawnCords.get(1), spawnCords.get(2));
final Location lobby = new Location(Bukkit.getWorld(name), lobbyCords.getFirst(), lobbyCords.get(1), lobbyCords.get(2)); Player seeker;
@Override @Override
public void run() { public void run() {
@@ -67,15 +70,18 @@ public class GamesManager {
player.sendActionBar(Component.text("Игроков " + playerCount + "/12")); //TODO! player.sendActionBar(Component.text("Игроков " + playerCount + "/12")); //TODO!
} }
if (playerCount >= map.minPlayers()) { if (playerCount >= map.getMinPlayers()) {
if (waitTime == 0 || playerCount == map.maxPlayers()) { if (waitTime == 0 || playerCount == map.getMaxPlayers()) {
game.start(); game.start();
Player seeker = game.selectRandomSeeker(); seeker = game.selectRandomSeeker();
seeker.teleport(spawn);
for (Player player : game.getHiders()) { for (Player player : game.getHiders()) {
player.teleport(spawn); player.teleport(spawn);
RouletteCreator.createRoulette(player, null, true, map.blocks()); PlayerInventory inventory = player.getInventory();
inventory.clear();
inventory.addItem(ItemManager.getFreezeItem());
RouletteCreator.createRoulette(player, null, true, map.getBlocks());
} }
} else { } else {
@@ -91,25 +97,31 @@ public class GamesManager {
} else { } else {
if (seekerSpawn == gameEnd) {
seeker.teleport(spawn);
PlayerInventory seekerInventory = seeker.getInventory();
seekerInventory.setArmorContents(ItemManager.getSeekerArmor());
}
if (game.hidersCount() == 0) { if (game.hidersCount() == 0) {
for (Player player : game.getPlayers()) { for (Player player : game.getPlayers()) {
player.showTitle(Title.title(Localization.getComponent("seekers-won"), Component.text(""))); player.showTitle(Title.title(Localization.getComponent("seekers-won"), Component.text("")));
} }
game.end(); game.preEnd();
games.remove(name); games.remove(name);
this.cancel();
} }
for (Player player : game.getPlayers()) { for (Player player : game.getPlayers()) {
player.sendActionBar(Localization.getComponent("game-time-left", "{time}", String.valueOf(duration))); player.sendActionBar(Localization.getComponent("game-time-left", "{time}", String.valueOf(gameEnd)));
} }
if (duration == 0) { if (gameEnd == 0) {
if (game.hidersCount() == 1) { if (game.hidersCount() == 1) {
for (Player player : game.getPlayers()) { for (Player player : game.getPlayers()) {
player.showTitle(Title.title(Localization.getComponent("hiders-solo-win", "{player}", player.getName()), Component.text(""))); player.showTitle(Title.title(Localization.getComponent("hiders-solo-win", "{player}", game.getLastHider().getName()), Component.text("")));
} }
} else { } else {
for (Player player : game.getPlayers()) { for (Player player : game.getPlayers()) {
@@ -117,11 +129,14 @@ public class GamesManager {
} }
} }
game.end(); game.preEnd();
games.remove(name); games.remove(name);
this.cancel();
} else duration--;
} else gameEnd--;
if (duration == 0) {
this.cancel();
}
} }

View File

@@ -0,0 +1,106 @@
package hdvtdev.blockAndSeek.managers;
import hdvtdev.blockAndSeek.Keys;
import hdvtdev.blockAndSeek.Localization;
import org.bukkit.Bukkit;
import org.bukkit.Material;
import org.bukkit.entity.Player;
import org.bukkit.inventory.Inventory;
import org.bukkit.inventory.InventoryHolder;
import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.meta.ItemMeta;
import org.bukkit.persistence.PersistentDataType;
import org.jetbrains.annotations.NotNull;
public class GuiManager {
private static final ItemStack filler1 = new ItemStack(Material.ORANGE_STAINED_GLASS_PANE);
private static final ItemStack filler2 = new ItemStack(Material.BLUE_STAINED_GLASS_PANE);
private static final ItemStack filler3 = new ItemStack(Material.GREEN_STAINED_GLASS_PANE);
private GuiManager() {
}
public static void fill(Inventory inventory) {
int size = inventory.getSize();
for (int i = 0; i < size; i++) {
inventory.setItem(i, i % 2 == 0 ? filler1 : filler2);
}
}
public static void fillAlt(Inventory inventory) {
int size = inventory.getSize();
for (int i = 0; i < size; i++) {
inventory.setItem(i, i % 2 == 0 ? filler3 : filler2);
}
}
public static class Menu implements InventoryHolder {
public static final Menu instance = new Menu();
private static final Inventory mainMenu = Bukkit.createInventory(instance, 27, Localization.getComponent("menu-item"));
static {
fill(mainMenu);
mainMenu.setItem(13, ItemManager.getGamesPageItem());
}
private Menu() {
}
public static void open(Player player) {
player.openInventory(mainMenu);
}
@Override
public @NotNull Inventory getInventory() {
return mainMenu;
}
public static class Games implements InventoryHolder {
private static final ItemStack defaultGameItem = new ItemStack(Material.CLOCK);
private Games() {
}
public static void open(Player player) {
Inventory gamesMenu = Bukkit.createInventory(new Games(), 45, Localization.getComponent("menu-item"));
for (String game : GamesManager.getAvailableGames()) {
ItemStack gameItem = defaultGameItem.clone();
ItemMeta meta = gameItem.getItemMeta();
meta.getPersistentDataContainer().set(Keys.GAME, PersistentDataType.STRING, game);
meta.displayName(Localization.getComponent("game-name", "{name}", game));
gameItem.setItemMeta(meta);
gamesMenu.addItem(gameItem);
}
if (player.hasPermission("blockandseek.manage")) {
gamesMenu.setItem(44, ItemManager.getCreateGameButton());
}
player.openInventory(gamesMenu);
}
@Override
public @NotNull Inventory getInventory() {
return Bukkit.createInventory(null, 9);
}
public static abstract class Maps implements InventoryHolder {
}
}
}
}

View File

@@ -0,0 +1,98 @@
package hdvtdev.blockAndSeek.managers;
import hdvtdev.blockAndSeek.Keys;
import hdvtdev.blockAndSeek.Localization;
import org.bukkit.Color;
import org.bukkit.Material;
import org.bukkit.enchantments.Enchantment;
import org.bukkit.entity.Player;
import org.bukkit.inventory.ItemFlag;
import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.PlayerInventory;
import org.bukkit.inventory.meta.ItemMeta;
import org.bukkit.inventory.meta.LeatherArmorMeta;
import org.bukkit.persistence.PersistentDataType;
public class ItemManager {
private static final ItemStack freezeItem = new ItemStack(Material.HEART_OF_THE_SEA);
private static final ItemStack menuItem = new ItemStack(Material.COMPASS);
private static final ItemStack games = new ItemStack(Material.BOOKSHELF);
private static final ItemStack createGameButton = new ItemStack(Material.SLIME_BALL);
private static final ItemStack[] seekerSet;
static {
ItemMeta freezeMeta = freezeItem.getItemMeta();
freezeMeta.displayName(Localization.getComponent("freeze-item"));
freezeMeta.getPersistentDataContainer().set(Keys.FREEZE_ITEM, PersistentDataType.BOOLEAN, true);
freezeItem.setItemMeta(freezeMeta);
ItemMeta menuMeta = menuItem.getItemMeta();
menuMeta.displayName(Localization.getComponent("menu-item"));
menuMeta.getPersistentDataContainer().set(Keys.MENU_ITEM, PersistentDataType.BOOLEAN, true);
menuMeta.addEnchant(Enchantment.ARROW_INFINITE, 1, true);
menuMeta.addItemFlags(ItemFlag.HIDE_ENCHANTS);
menuItem.setItemMeta(menuMeta);
ItemMeta gamesMeta = games.getItemMeta();
gamesMeta.displayName(Localization.getComponent("games-page-item"));
games.setItemMeta(gamesMeta);
ItemMeta createGameButtonMeta = createGameButton.getItemMeta();
createGameButtonMeta.displayName(Localization.getComponent("create-game-item"));
createGameButton.setItemMeta(createGameButtonMeta);
ItemStack seekerHelmet = new ItemStack(Material.LEATHER_HELMET);
ItemStack seekerChestplate = new ItemStack(Material.LEATHER_CHESTPLATE);
ItemStack seekerLeggings = new ItemStack(Material.LEATHER_LEGGINGS);
ItemStack seekerBoots = new ItemStack(Material.LEATHER_BOOTS);
seekerHelmet.setItemMeta(color(seekerHelmet));
seekerBoots.setItemMeta(color(seekerBoots));
seekerChestplate.setItemMeta(color(seekerChestplate));
seekerLeggings.setItemMeta(color(seekerLeggings));
seekerSet = new ItemStack[]{seekerBoots, seekerLeggings, seekerChestplate, seekerHelmet};
}
private static ItemMeta color(ItemStack item) {
LeatherArmorMeta meta = (LeatherArmorMeta) item.getItemMeta();
meta.setColor(Color.RED);
meta.setUnbreakable(true);
meta.addEnchant(Enchantment.PROTECTION_ENVIRONMENTAL, 10, true);
meta.displayName(Localization.getComponent("seeker-armor"));
return meta;
}
public static void defaultInventory(Player player) {
PlayerInventory inventory = player.getInventory();
inventory.clear();
inventory.addItem(menuItem);
}
public static ItemStack getCreateGameButton() {
return createGameButton;
}
public static ItemStack getGamesPageItem() {
return games;
}
public static ItemStack getMenuItem() {
return menuItem;
}
public static ItemStack[] getSeekerArmor() {
return seekerSet;
}
public static ItemStack getFreezeItem() {
return freezeItem;
}
}

View File

@@ -1,11 +1,60 @@
package hdvtdev.blockAndSeek.managers; package hdvtdev.blockAndSeek.managers;
import hdvtdev.blockAndSeek.BlockAndSeek;
import hdvtdev.blockAndSeek.BlockAndSeekMap; import hdvtdev.blockAndSeek.BlockAndSeekMap;
import org.bukkit.configuration.file.YamlConfiguration;
import java.io.File;
import java.io.IOException;
import java.util.Map; import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
public class MapsManager { public class MapsManager {
private static final Map<String, BlockAndSeekMap> maps = null; private static volatile Map<String, BlockAndSeekMap> allMaps = new ConcurrentHashMap<>();
private static final Map<String, BlockAndSeekMap> readyMaps = new ConcurrentHashMap<>();
private static final File mapsFile = new File(BlockAndSeek.getPluginDataFolder(), "maps.yml");
public static Set<String> getAllMaps() {
return allMaps.keySet();
}
public static void test() {
System.out.println("all maps");
allMaps.forEach((k, v) -> System.out.println(k + ": " + v));
System.out.println("ready maps");
readyMaps.forEach((k, v) -> System.out.println(k + ": " + v));
}
public static BlockAndSeekMap getMap(String name) {
return allMaps.get(name);
}
public static void saveMap(String name, BlockAndSeekMap map) throws IOException {
var conf = YamlConfiguration.loadConfiguration(mapsFile);
if (conf.contains(name)) conf.set(name, null);
conf.set(name, map);
conf.save(mapsFile);
}
public static void loadMaps() {
Map<String, BlockAndSeekMap> confMap = new ConcurrentHashMap<>();
YamlConfiguration configuration = YamlConfiguration.loadConfiguration(mapsFile);
for (String map : configuration.getKeys(false)) {
BlockAndSeekMap blockAndSeekMap = configuration.getSerializable(map, BlockAndSeekMap.class, BlockAndSeekMap.defaultMap());
if (blockAndSeekMap.isReady()) readyMaps.put(map, blockAndSeekMap);
confMap.put(map, blockAndSeekMap);
}
allMaps = confMap;
}
} }

View File

@@ -9,7 +9,6 @@ import java.util.List;
public class RouletteGenerator { public class RouletteGenerator {
private final ProbabilityCollection<ItemStack> probabilityCollection = new ProbabilityCollection<>(); private final ProbabilityCollection<ItemStack> probabilityCollection = new ProbabilityCollection<>();
public RouletteGenerator(List<BlockAndSeekMap.Block> blocks) { public RouletteGenerator(List<BlockAndSeekMap.Block> blocks) {

View File

@@ -19,3 +19,12 @@ en-US:
game-title: "<bold><gold>{title}" game-title: "<bold><gold>{title}"
wait-time-left: "<gold>Game starts in: <yellow><bold>{time}<reset><gold>s" wait-time-left: "<gold>Game starts in: <yellow><bold>{time}<reset><gold>s"
#items
freeze-item: "<gradient:#084CFB:#ADF3FD><bold>Freeze"
seeker-armor: "<gradient:#8B0000:#B22222:#DC143C><bold>Seeker armor"
menu-item: "<gradient:#FFD700:#FFF200:#FFFF00><bold>BlockAndSeek Menu"
games-page-item: "<gradient:#006400:#228B22:#00FF7F><bold>Games"
create-game-item: "<green><bold>Create new game"
game-name: "<green>{name}"