idk some "cool" stuff

This commit is contained in:
hdvt
2025-06-26 01:18:01 +03:00
parent 15aca87742
commit 54eb07cc86
24 changed files with 1072 additions and 195 deletions

6
.idea/ant.xml generated Normal file
View File

@@ -0,0 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="AntConfiguration">
<buildFile url="file://$PROJECT_DIR$/build.xml" />
</component>
</project>

2
.idea/compiler.xml generated
View File

@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<project version="4"> <project version="4">
<component name="CompilerConfiguration"> <component name="CompilerConfiguration">
<bytecodeTargetLevel target="17" /> <bytecodeTargetLevel target="21" />
</component> </component>
</project> </project>

2
.idea/misc.xml generated
View File

@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<project version="4"> <project version="4">
<component name="ExternalStorageConfigurationManager" enabled="true" /> <component name="ExternalStorageConfigurationManager" enabled="true" />
<component name="ProjectRootManager" version="2" languageLevel="JDK_17" project-jdk-name="21" project-jdk-type="JavaSDK"> <component name="ProjectRootManager" version="2" languageLevel="JDK_21" default="true" project-jdk-name="21" project-jdk-type="JavaSDK">
<output url="file://$PROJECT_DIR$/out" /> <output url="file://$PROJECT_DIR$/out" />
</component> </component>
</project> </project>

16
.idea/saveactions_settings.xml generated Normal file
View File

@@ -0,0 +1,16 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="SaveActionSettings">
<option name="actions">
<set>
<option value="activate" />
<option value="activateOnShortcut" />
<option value="noActionIfCompileErrors" />
<option value="organizeImports" />
<option value="reformat" />
<option value="reload" />
</set>
</option>
<option name="configurationPath" value="" />
</component>
</project>

6
.idea/vcs.xml generated Normal file
View File

@@ -0,0 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="VcsDirectoryMappings">
<mapping directory="$PROJECT_DIR$" vcs="Git" />
</component>
</project>

View File

@@ -1,7 +1,6 @@
plugins { plugins {
id 'java' id 'java'
id("xyz.jpenilla.run-paper") version "2.3.1" id("xyz.jpenilla.run-paper") version "2.3.1"
id 'com.rikonardo.papermake' version '1.0.6'
} }
group = 'hdvtdev' group = 'hdvtdev'
@@ -10,6 +9,7 @@ version = '0.0.1-a'
repositories { repositories {
mavenCentral() mavenCentral()
maven { url 'https://repo.md-5.net/content/groups/public/' } maven { url 'https://repo.md-5.net/content/groups/public/' }
maven { url 'https://jitpack.io' }
maven { maven {
name = "papermc-repo" name = "papermc-repo"
url = "https://repo.papermc.io/repository/maven-public/" url = "https://repo.papermc.io/repository/maven-public/"
@@ -22,17 +22,10 @@ repositories {
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'
} }
tasks {
runServer {
// Configure the Minecraft version for our task.
// This is the only required configuration besides applying the plugin.
// Your plugin's jar (or shadowJar if present) will be used automatically.
minecraftVersion("1.20")
}
}
def targetJavaVersion = 21 def targetJavaVersion = 21
java { java {
@@ -62,6 +55,10 @@ 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 { configurations.runtimeClasspath.findAll { it.name.startsWith('Java-Probability-Collection') }.collect { zipTree(it) } }
duplicatesStrategy = DuplicatesStrategy.EXCLUDE
} }

18
build.xml Normal file
View File

@@ -0,0 +1,18 @@
<?xml version="1.0" ?>
<!DOCTYPE xml>
<project name="BlockAndSeek" default="Build">
<target name="Build">
<jar jarfile="/home/hadvart/Documents/Minecraft/Pufferfish 1.20.4/plugins/${ant.project.name}.jar">
<fileset dir="./build/classes/" 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>
</target>
</project>

View File

@@ -3,34 +3,63 @@ package hdvtdev.blockAndSeek;
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.CommandExecutor;
import org.bukkit.plugin.Plugin;
import org.bukkit.plugin.java.JavaPlugin; import org.bukkit.plugin.java.JavaPlugin;
import java.io.File; import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.util.Objects; import java.util.Objects;
import java.util.logging.Logger;
public class BlockAndSeek extends JavaPlugin implements CommandExecutor { public class BlockAndSeek extends JavaPlugin implements CommandExecutor {
private static File dataFolder; private static Plugin javaPlugin;
public static Plugin getInstance() {
return javaPlugin;
}
public static File getPluginDataFolder() { public static File getPluginDataFolder() {
return dataFolder; return javaPlugin.getDataFolder();
}
public static InputStream getPluginResource(String resource) {
return javaPlugin.getResource(resource);
}
public static void saveResource(File file) {
saveResource(file.getAbsolutePath());
}
public static void saveResource(String file) {
javaPlugin.saveResource(file, false);
}
public static Logger getPluginLogger() {
return javaPlugin.getLogger();
} }
@Override @Override
public void onEnable() { public void onEnable() {
dataFolder = getDataFolder(); javaPlugin = this;
LibsDisguises libsDisguises = (LibsDisguises) Bukkit.getPluginManager().getPlugin("LibsDisguises"); LibsDisguises libsDisguises = (LibsDisguises) Bukkit.getPluginManager().getPlugin("LibsDisguises");
if (libsDisguises == null) { if (libsDisguises == null) {
getLogger().severe("LibsDisguises не найден!"); getLogger().severe("LibsDisguises not found! It's required for the plugin to work!");
super.onDisable(); super.onDisable();
} }
Localization.load(this); try {
ConfigManager.load(); ConfigManager.loadAll();
} catch (IOException e) {
getLogger().severe("Failed to save some .yml configs!");
}
Objects.requireNonNull(getCommand("blockandseek")).setExecutor(new CommandListener()); Objects.requireNonNull(getCommand("blockandseek")).setExecutor(new CommandListener());
getServer().getPluginManager().registerEvents(new EventListener(), this);
} }

View File

@@ -0,0 +1,24 @@
package hdvtdev.blockAndSeek;
import org.bukkit.Bukkit;
import org.bukkit.NamespacedKey;
import org.bukkit.scoreboard.Scoreboard;
import org.bukkit.scoreboard.Team;
public class BlockAndSeekContainer {
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 FROZEN_PLAYER = new NamespacedKey(BlockAndSeek.getInstance(), "BlockAndSeekFrozenPlayer");
public static final NamespacedKey PLAYER = new NamespacedKey(BlockAndSeek.getInstance(), "BlockAndSeekPlayer");
public static final Team NO_COLLIDE_TEAM;
static {
Scoreboard scoreboard = Bukkit.getScoreboardManager().getMainScoreboard();
Team team = scoreboard.getTeam("BlockAndSeekNoCollide");
if (team == null) team = scoreboard.registerNewTeam("BlockAndSeekNoCollide");
team.setOption(Team.Option.COLLISION_RULE, Team.OptionStatus.NEVER);
NO_COLLIDE_TEAM = team;
}
}

View File

@@ -1,29 +1,94 @@
package hdvtdev.blockAndSeek; package hdvtdev.blockAndSeek;
import org.bukkit.Bukkit; import me.libraryaddict.disguise.DisguiseAPI;
import org.bukkit.Location; import org.bukkit.Material;
import org.bukkit.World;
import org.bukkit.entity.Player; import org.bukkit.entity.Player;
import org.jetbrains.annotations.NotNull; import org.bukkit.persistence.PersistentDataType;
import java.util.*; import java.security.SecureRandom;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.atomic.AtomicBoolean;
public class BlockAndSeekGame { public class BlockAndSeekGame {
private final Set<Player> players = Collections.synchronizedSet(new HashSet<>()); private final ConcurrentHashMap<Player, PlayerType> players = new ConcurrentHashMap<>();
public BlockAndSeekGame(String name, List<String> players) { private AtomicBoolean started = new AtomicBoolean(false);
for (String player : players) { private final String name;
this.addPlayer(player);
public BlockAndSeekGame(String name) {
this.name = name;
}
public void end() {
for (Player player : players.keySet()) {
EventListener.unfreezePlayer(player);
player.getPersistentDataContainer().remove(BlockAndSeekContainer.PLAYER);
player.sendBlockChange(player.getLocation(), Material.AIR.createBlockData());
DisguiseAPI.undisguiseToAll(player);
} }
} }
public void addPlayer(String name) { public boolean addPlayer(Player player) {
Player p = Bukkit.getPlayerExact(name); if (started.get()) {
if (p != null) players.add(p); return false;
}
player.getPersistentDataContainer().set(BlockAndSeekContainer.PLAYER, PersistentDataType.STRING, name);
players.put(player, PlayerType.HIDER);
return true;
}
public void removePlayer(Player player) {
players.remove(player);
}
public Set<Player> getPlayers() {
return players.keySet();
}
public Player getLastHider() {
for (Map.Entry<Player, PlayerType> entry : players.entrySet()) {
if (entry.getValue() == PlayerType.HIDER) return entry.getKey();
}
return null;
}
public int seekersCount() {
return (int) players.values().stream().filter(f -> f.equals(PlayerType.SEEKER)).count();
}
public int hidersCound() {
return (int) players.values().stream().filter(f -> f.equals(PlayerType.HIDER)).count();
}
public int playerCount() {
return players.size();
}
public void start() {
started.set(true);
}
public boolean isStarted() {
return started.get();
}
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) return player;
}
return null;
}
private enum PlayerType {
SEEKER,
HIDER
} }
} }

View File

@@ -0,0 +1,13 @@
package hdvtdev.blockAndSeek;
import org.bukkit.inventory.ItemStack;
import java.util.List;
public record BlockAndSeekMap(List<Integer> spawn, List<Integer> lobby, int duration, List<Block> blocks) {
public record Block(ItemStack block, int chance) {
}
}

View File

@@ -1,38 +1,32 @@
package hdvtdev.blockAndSeek; package hdvtdev.blockAndSeek;
import me.libraryaddict.disguise.DisguiseAPI; import hdvtdev.blockAndSeek.roulette.RouletteCreator;
import me.libraryaddict.disguise.disguisetypes.Disguise;
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.Bukkit;
import org.bukkit.Location;
import org.bukkit.Material; import org.bukkit.Material;
import org.bukkit.World; import org.bukkit.command.Command;
import org.bukkit.command.*; import org.bukkit.command.CommandExecutor;
import org.bukkit.command.CommandSender;
import org.bukkit.command.TabCompleter;
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.persistence.PersistentDataType;
import org.jetbrains.annotations.NotNull; 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.ArrayList;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Set;
public class CommandListener implements CommandExecutor, TabCompleter { public class CommandListener implements CommandExecutor, TabCompleter {
public static List<String> getAllCommands() { private static final MiniMessage miniMessage = MiniMessage.miniMessage();
return List.of("tpp", "morph");
}
@Override @Override
public boolean onCommand(@NotNull CommandSender sender, @NotNull Command command, @NotNull String label, @NotNull String[] args) { public boolean onCommand(@NotNull CommandSender sender, @NotNull Command command, @NotNull String label, @NotNull String[] args) {
int argsLen = args.length; int argsLen = args.length;
if (argsLen == 0) { if (argsLen == 0) {
@@ -41,54 +35,77 @@ public class CommandListener implements CommandExecutor, TabCompleter {
} }
switch (args[0]) { switch (args[0]) {
case "test" -> {
if (sender instanceof Player player) {
RouletteCreator.createRoulette(player, null, true);
}
}
case "freeze" -> {
if (sender instanceof Player player) {
ItemStack foo = new ItemStack(Material.HEART_OF_THE_SEA);
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 "foo" -> {
if (sender instanceof Player player) {
ItemStack foo = new ItemStack(Material.BROWN_DYE);
ItemMeta fooMeta = foo.getItemMeta();
fooMeta.displayName(MiniMessage.miniMessage().deserialize("<gradient:#00FF00:#01A368><bold>SoundMaker3000"));
fooMeta.getPersistentDataContainer().set(BlockAndSeekContainer.SOUND_ITEM, PersistentDataType.BOOLEAN, true);
foo.setItemMeta(fooMeta);
player.getInventory().addItem(foo);
}
}
case "map" -> { case "map" -> {
if (argsLen > 1) { if (sender.hasPermission("blockandseek.manage")) {
switch (args[1]) { if (argsLen > 1) {
case "list" -> sender.sendMessage(Localization.get("maps-list", "{maps}", ConfigManager.createdMaps().toString())); switch (args[1]) {
case "create" -> { case "list" -> {
if (argsLen > 2) { StringBuilder buffer = new StringBuilder(Localization.get("maps-available"));
String mapName = args[2]; String listElement = Localization.get("maps-available-element");
World world = Bukkit.getWorld(mapName); Set<String> readyMaps = ConfigManager.getReadyMaps();
if (world == null) { for (String map : ConfigManager.getAllMaps()) {
sender.sendMessage(Localization.get("map-missing-world", "{world}", mapName)); buffer.append("\n").append(listElement.replace("{map}", map).replace("{color-status}",
} else { readyMaps.contains(map) ? "<green>" : "<red>"));
try {
if (ConfigManager.addMap(mapName)) sender.sendMessage(Localization.get("map-created", "{map}", mapName));
else sender.sendMessage(Localization.get("map-already-exist", "{map}", mapName));
} catch (IOException e) {
sender.sendMessage(Localization.get("map-creation-failed", "{error}", e.getMessage()));
}
} }
} else sender.sendMessage(Localization.get("not-enough-arguments", "{usage}", "<green>/blockandseek create <gold>[MAP NAME]<white>")); sender.sendMessage(miniMessage.deserialize(buffer.toString()));
}
} }
default -> { } else
if (ConfigManager.createdMaps().contains(args[1])) { sender.sendMessage(Localization.getComponent("not-enough-arguments", "{command}", "/blockandseek map", "{help}", "[MAP NAME | COMMANDS]"));
if (argsLen > 2) {
switch (args[2]) { } else sender.sendMessage(Localization.getComponent("not-enough-permissions"));
case "setspawn" -> {}
case "setlobby" -> {}
case "setduration" -> {}
default -> sender.sendMessage(Localization.get("unknown-subcommand", "{subcommand}", args[2]));
}
} else sender.sendMessage(Localization.get("not-enough-arguments", "{usage}", String.format("<green>/blockandseek create %s <gold>[SUBCOMMAND]", args[1])));
} else sender.sendMessage(Localization.get("map-not-exist", "{map}", args[1]));
}
}
} else sender.sendMessage(Localization.get("not-enough-arguments", "{usage}", "<green>/blockandseek map <gold>[MAP NAME | SUBCOMMAND]<white>"));
} }
case "reload" -> { case "reload" -> {
if (argsLen > 1) { if (sender.hasPermission("blockandseek.manage")) {
switch (args[1]) { if (argsLen > 1) {
case "messages" -> { switch (args[1]) {
Localization.reload(); case "localization" -> {
sender.sendMessage(Localization.get("messages-reload")); try {
ConfigManager.load("localization.yml");
sender.sendMessage(Localization.getPrefix().append(Localization.getComponent("successful-reload", "{config}", "localization.yml")));
} catch (IOException e) {
sender.sendMessage(Localization.getComponent("failed-reload", "{config}", "localization.yml", "{e}", e.getMessage()));
}
}
case "maps" -> {
try {
ConfigManager.load(null);
} catch (IOException e) {
throw new RuntimeException(e);
}
sender.sendMessage(Localization.get("maps-reload"));
}
} }
case "maps" -> { } else
ConfigManager.load(); sender.sendMessage(Localization.get("not-enough-arguments", "{usage}", "<green>/blockandseek reload <gold>[messages | maps]<white>"));
sender.sendMessage(Localization.get("maps-reload"));
} } else sender.sendMessage(Localization.get("not-enough-permissions"));
}
}
} }
} }
@@ -98,7 +115,6 @@ public class CommandListener implements CommandExecutor, TabCompleter {
*/ */
return true; return true;
} }
@@ -106,23 +122,41 @@ public class CommandListener implements CommandExecutor, TabCompleter {
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) {
sender.sendActionBar(MiniMessage.miniMessage().deserialize("<b><blue>" + args.length)); sender.sendActionBar(MiniMessage.miniMessage().deserialize("<b><blue>" + args.length));
return switch (args.length) { return switch (args.length) {
case 1 -> List.of("reload", "help", "map", "join"); case 1 -> {
if (sender.hasPermission("blockandseek.manage")) {
yield List.of("reload", "help", "map", "join");
} else yield List.of("help", "join");
}
case 2 -> switch (args[0]) { case 2 -> switch (args[0]) {
case "map" -> { case "map" -> {
List<String> scmds = new ArrayList<>(List.of("create", "list")); List<String> scmds = new ArrayList<>();
scmds.addAll(ConfigManager.createdMaps()); /*
if (sender.hasPermission("blockandseek.manage")) {
scmds.addAll(List.of("create", "list"));
scmds.addAll(ConfigManager.createdMaps());
}
*/
yield scmds; yield scmds;
} }
case "join" -> List.of("test"); case "join" -> List.of("test"); //TODO
case "reload" -> List.of("messages", "maps"); case "reload" -> {
if (sender.hasPermission("blockandseek.manage")) {
yield List.of("messages", "maps");
} else yield List.of();
}
default -> List.of(); default -> List.of();
}; };
case 3 -> switch (args[1]) { case 3 -> switch (args[1]) {
case "create", "list" -> List.of(); case "create", "list" -> List.of();
default -> { default -> {
if (ConfigManager.createdMaps().contains(args[1])) { /*
if (ConfigManager.createdMaps().contains(args[1]) && sender.hasPermission("blockandseek.manage")) {
yield List.of("setspawn", "setlobby", "setduration"); yield List.of("setspawn", "setlobby", "setduration");
} else yield List.of(); } else yield List.of();
*/
yield List.of();
} }
}; };
default -> List.of(); default -> List.of();

View File

@@ -1,57 +1,252 @@
package hdvtdev.blockAndSeek; package hdvtdev.blockAndSeek;
import org.bukkit.Material;
import org.bukkit.configuration.ConfigurationSection;
import org.bukkit.configuration.file.YamlConfiguration; import org.bukkit.configuration.file.YamlConfiguration;
import org.jetbrains.annotations.NotNull; 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.util.HashSet;
import java.util.List; import java.util.List;
import java.util.Map;
import java.util.Set; import java.util.Set;
import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentHashMap;
public class ConfigManager { public class ConfigManager {
private static final File mapsConfigFile = new File(BlockAndSeek.getPluginDataFolder(), "maps.yml"); private static volatile ConcurrentHashMap<String, String> localization = new ConcurrentHashMap<>();
private static final ConcurrentHashMap<String, MapConfig> mapsConfigs = new ConcurrentHashMap<>(); private static volatile ConcurrentHashMap<String, String> config = new ConcurrentHashMap<>();
private static volatile ConcurrentHashMap<String, BlockAndSeekMap> maps = new ConcurrentHashMap<>();
public static Set<String> createdMaps() { private static final File mapsFile = new File(BlockAndSeek.getPluginDataFolder(), "maps.yml");
return mapsConfigs.keySet();
public static Set<String> getAllMaps() {
return YamlConfiguration.loadConfiguration(mapsFile).getKeys(false);
} }
public static MapConfig getMapConfig(@NotNull String name) { public enum MapStatus {
return mapsConfigs.get(name); SPAWN_REQUIRED,
LOBBY_REQUIRED,
DURATION_REQUIRED,
BLOCKS_REQUIRED
} }
public static boolean addMap(String name) throws IOException { public static Set<String> getReadyMaps() {
if (mapsConfigs.containsKey(name)) return false; return maps.keySet();
mapsConfigs.put(name, MapConfig.defaults()); }
YamlConfiguration config = YamlConfiguration.loadConfiguration(mapsConfigFile);
config.set(name + ".spawn", "null");
config.set(name + ".duration", "null");
config.set(name + ".lobby", "null");
config.save(mapsConfigFile); 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);
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, 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("blocks", List.of(Map.of()));
try {
configuration.save(mapsFile);
} catch (IOException ignored) {
return false;
}
return true; return true;
} }
public static boolean setMapProperty(String map, String property, Object value) {
YamlConfiguration configuration = YamlConfiguration.loadConfiguration(mapsFile);
ConfigurationSection section = configuration.getConfigurationSection(map);
public static void load() { if (section != null) {
mapsConfigs.clear(); section.set(property, value);
YamlConfiguration config = YamlConfiguration.loadConfiguration(mapsConfigFile); try {
for (String mapKey : config.getKeys(false)) { configuration.save(mapsFile);
List<Long> spawn = config.getLongList(mapKey + ".spawn"); } catch (IOException e) {
List<Long> lobby = config.getLongList(mapKey + ".lobby"); return false;
int duration = config.getInt(mapKey + ".duration"); }
MapConfig mapConfig = new MapConfig(spawn, lobby, duration);
mapsConfigs.put(mapKey, mapConfig);
} }
return true;
} }
public record MapConfig(List<Long> spawn, List<Long> lobby, int duration) { public static void loadAll() throws IOException {
public static MapConfig defaults() { load("config.yml");
return new MapConfig(null, null, -1); load("localization.yml");
load("maps.yml");
}
public static void load(String file) throws IOException {
File conf = new File(BlockAndSeek.getPluginDataFolder(), file);
YamlConfiguration defaultConfiguration = YamlConfiguration.loadConfiguration(
new InputStreamReader(BlockAndSeek.getPluginResource(file)));
if (!conf.exists()) {
BlockAndSeek.saveResource(file);
ConcurrentHashMap<String, String> confMap = new ConcurrentHashMap<>();
switch (file) {
case "config.yml" -> {
for (String key : defaultConfiguration.getKeys(false)) {
confMap.put(key, defaultConfiguration.getString(key, "NULL"));
}
config = confMap;
}
case "localization.yml" -> {
for (String key : defaultConfiguration.getConfigurationSection("en_US").getKeys(false)) {
confMap.put(key, defaultConfiguration.getString(key, "NULL"));
}
localization = confMap;
Localization.update();
}
}
} else {
switch (file) {
case "config.yml" -> loadConfig(conf, defaultConfiguration);
case "localization.yml" -> loadLocalization(conf, defaultConfiguration);
case "maps.yml" -> loadMaps(conf);
}
} }
}
private static void loadMaps(File configurationFile) throws IOException {
ConcurrentHashMap<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");
List<BlockAndSeekMap.Block> blocks = section.getMapList("blocks").stream().map(
block -> {
try {
return new BlockAndSeekMap.Block(
new ItemStack(Material.valueOf(((String) block.get("name")).toUpperCase())),
(int) block.get("chance")
);
} catch (IllegalArgumentException | ClassCastException | NullPointerException ignored) {
return null;
}
}
).toList();
if (!spawn.isEmpty() && !lobby.isEmpty() && duration != 0 && !blocks.isEmpty()) {
confMap.put(map, new BlockAndSeekMap(spawn, lobby, duration, blocks));
}
}
maps = confMap;
}
}
private static void loadConfig(File configurationFile, YamlConfiguration defaultConfiguration) throws IOException {
ConcurrentHashMap<String, String> confMap = new ConcurrentHashMap<>();
YamlConfiguration configuration = YamlConfiguration.loadConfiguration(configurationFile);
for (String key : defaultConfiguration.getKeys(false)) {
if (configuration.isSet(key)) {
confMap.put(key, configuration.getString(key, defaultConfiguration.getString(key, "NULL")));
} else {
String value = defaultConfiguration.getString(key, "NULL");
configuration.set(key, value);
confMap.put(key, value);
}
}
configuration.save(configurationFile);
config = confMap;
}
private static void loadLocalization(File configurationFile, YamlConfiguration defaultConfiguration) throws IOException {
ConcurrentHashMap<String, String> confMap = new ConcurrentHashMap<>();
YamlConfiguration configuration = YamlConfiguration.loadConfiguration(configurationFile);
String language = config.get("language");
ConfigurationSection defaultSection = defaultConfiguration.getConfigurationSection("en_US");
ConfigurationSection configSection = configuration.getConfigurationSection(language);
if (configSection != null) {
for (String key : defaultSection.getKeys(false)) {
if (configSection.contains(key)) {
confMap.put(key, configSection.getString(key, defaultSection.getString(key, "NULL")));
} else {
String value = defaultSection.getString(key, "NULL");
configSection.set(key, value);
confMap.put(key, value);
}
}
} else {
BlockAndSeek.getPluginLogger().warning(String.format("Language \"%s\" does not exist in localization.yml! Using default language en_US.", language));
for (String key : defaultSection.getKeys(false)) {
confMap.put(key, defaultSection.getString(key, "NULL"));
}
}
configuration.save(configurationFile);
localization = confMap;
}
public static ConcurrentHashMap<String, String> getLocalization() {
return localization;
} }

View File

@@ -0,0 +1,213 @@
package hdvtdev.blockAndSeek;
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 org.bukkit.Bukkit;
import org.bukkit.Location;
import org.bukkit.Material;
import org.bukkit.Sound;
import org.bukkit.block.Block;
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
import org.bukkit.event.Listener;
import org.bukkit.event.entity.EntityDamageByEntityEvent;
import org.bukkit.event.inventory.InventoryClickEvent;
import org.bukkit.event.inventory.InventoryCloseEvent;
import org.bukkit.event.player.PlayerInteractEvent;
import org.bukkit.event.player.PlayerQuitEvent;
import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.meta.ItemMeta;
import org.bukkit.persistence.PersistentDataContainer;
import org.bukkit.persistence.PersistentDataType;
import org.bukkit.potion.PotionEffect;
import org.bukkit.potion.PotionEffectType;
import org.bukkit.scheduler.BukkitTask;
import org.bukkit.util.Vector;
import java.util.concurrent.ConcurrentHashMap;
public class EventListener implements Listener {
private static final ConcurrentHashMap<Player, BukkitTask> tasks = new ConcurrentHashMap<>();
private static final ConcurrentHashMap<Player, Long> soundCoolDown = new ConcurrentHashMap<>();
private static final ConcurrentHashMap<Player, Location> frozenPlayers = new ConcurrentHashMap<>();
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);
public static void createTask(Player player, BukkitTask bukkitTask) {
tasks.put(player, bukkitTask);
}
public static void stopTask(Player player) {
BukkitTask task = tasks.remove(player);
task.cancel();
}
@EventHandler
public void onPlayerQuit(PlayerQuitEvent event) {
Player player = event.getPlayer();
PersistentDataContainer container = player.getPersistentDataContainer();
if (frozenPlayers.remove(player) != null) {
unfreezePlayer(player);
}
String arena = container.get(BlockAndSeekContainer.PLAYER, PersistentDataType.STRING);
if (arena != null) {
container.remove(BlockAndSeekContainer.PLAYER);
GamesManager.get(arena).removePlayer(player);
}
}
@EventHandler
public void onDamage(EntityDamageByEntityEvent event) {
if (event.getEntity() instanceof Player victim) {
PersistentDataContainer container = victim.getPersistentDataContainer();
if (event.getDamager() instanceof Player && container.has(BlockAndSeekContainer.FROZEN_PLAYER)) {
BlockAndSeekGame game = GamesManager.get(container.get(BlockAndSeekContainer.PLAYER, PersistentDataType.STRING));
for (Player player : game.getPlayers()) {
player.sendBlockChange(frozenPlayers.get(victim), Material.AIR.createBlockData());
}
unfreezePlayer(victim);
}
}
}
@EventHandler
public void onRightClick(PlayerInteractEvent event) {
Player player = event.getPlayer();
ItemStack item = player.getInventory().getItemInMainHand();
ItemMeta itemMeta = item.getItemMeta();
if (itemMeta != null) {
PersistentDataContainer data = itemMeta.getPersistentDataContainer();
PersistentDataContainer playerData = player.getPersistentDataContainer();
if (data.has(BlockAndSeekContainer.SOUND_ITEM)) {
Long time = soundCoolDown.get(player);
if (time != null) {
long diff = System.currentTimeMillis() - time;
if (diff > 3000) {
soundCoolDown.remove(player);
} else {
player.sendActionBar(MiniMessage.miniMessage().deserialize("<gradient:#ff0000:#ff6666><bold>Подождите немного перед следующим использованием"));
return;
}
}
Location location = player.getLocation();
for (Player p : Bukkit.getOnlinePlayers()) {
p.playSound(location, Sound.ENTITY_CHICKEN_AMBIENT, 2f, 1.5f);
}
soundCoolDown.put(player, System.currentTimeMillis());
}
if (data.has(BlockAndSeekContainer.FREEZE_ITEM)) {
String arena = playerData.get(BlockAndSeekContainer.PLAYER, PersistentDataType.STRING);
if (arena != null) {
BlockAndSeekGame game = GamesManager.get(arena);
if (frozenPlayers.remove(player) != null) {
for (Player p : game.getPlayers()) {
p.sendBlockChange(player.getLocation(), Material.AIR.createBlockData());
}
unfreezePlayer(player);
} else {
if (game.isStarted()) {
Location playerLocation = player.getLocation();
Block block = playerLocation.getBlock();
Block upperBlock = player.getLocation().getBlock();
if (!upperBlock.isSolid()) {
Location blockLocation = block.getLocation();
blockLocation.setX(blockLocation.getX() + 0.5);
double y = Math.round(blockLocation.getY());
blockLocation.setY(block.isSolid() ? y + 1 : y);
blockLocation.setZ(blockLocation.getZ() + 0.5);
blockLocation.setPitch(playerLocation.getPitch());
blockLocation.setYaw(playerLocation.getYaw());
player.getPersistentDataContainer().set(BlockAndSeekContainer.FROZEN_PLAYER, PersistentDataType.BOOLEAN, true);
player.setWalkSpeed(0);
player.setFreezeTicks(40);
player.setVelocity(ZERO_VELOCITY);
player.setFlySpeed(0);
player.setAllowFlight(true);
player.setFlying(true);
player.setGravity(false);
player.addPotionEffect(INVISIBILITY);
BlockAndSeekContainer.NO_COLLIDE_TEAM.addEntry(player.getName());
for (Player p : Bukkit.getOnlinePlayers()) {
p.sendBlockChange(blockLocation, Material.CHORUS_PLANT.createBlockData());
}
player.teleport(blockLocation);
frozenPlayers.put(player, blockLocation);
} else
player.sendActionBar(MiniMessage.miniMessage().deserialize("<red> Could not freeze here!"));
} else
player.sendActionBar(MiniMessage.miniMessage().deserialize("<red> Could not freeze now!"));
}
} else player.sendActionBar(MiniMessage.miniMessage().deserialize("<red> Could not freeze now!"));
}
}
}
public static void unfreezePlayer(Player player) {
player.getPersistentDataContainer().remove(BlockAndSeekContainer.FROZEN_PLAYER);
player.setFlySpeed(0.2f);
player.setWalkSpeed(0.2f);
player.setAllowFlight(false);
player.setFlying(false);
BlockAndSeekContainer.NO_COLLIDE_TEAM.removeEntry(player.getName());
player.setGravity(true);
player.setFreezeTicks(0);
player.removePotionEffect(PotionEffectType.INVISIBILITY);
}
@EventHandler
public void onClick(InventoryClickEvent event) {
Player player = (Player) event.getWhoClicked();
if (player.hasMetadata("RollingMenu")) {
event.setCancelled(true);
int slot = event.getSlot();
if (slot == 21 || slot == 23 || slot == 25) {
if (!tasks.containsKey(player)) {
MiscDisguise miscDisguise = new MiscDisguise(DisguiseType.FALLING_BLOCK, event.getInventory().getItem(slot));
DisguiseAPI.disguiseToAll(player, miscDisguise);
player.closeInventory(InventoryCloseEvent.Reason.UNKNOWN);
}
}
}
}
@EventHandler
public void onClose(InventoryCloseEvent event) {
Player player = (Player) event.getPlayer();
if (player.hasMetadata("RollingMenu")) {
if (!tasks.containsKey(player)) {
player.removeMetadata("RollingMenu", BlockAndSeek.getInstance());
if (!event.getReason().equals(InventoryCloseEvent.Reason.UNKNOWN)) {
MiscDisguise miscDisguise = new MiscDisguise(DisguiseType.FALLING_BLOCK, event.getInventory().getItem(21));
DisguiseAPI.disguiseToAll(player, miscDisguise);
}
} else {
Bukkit.getScheduler().runTaskLater(BlockAndSeek.getInstance(), () -> player.openInventory(event.getInventory()), 0L);
}
}
}
}

View File

@@ -1,25 +1,106 @@
package hdvtdev.blockAndSeek; package hdvtdev.blockAndSeek;
import java.util.ArrayList; import hdvtdev.blockAndSeek.roulette.RouletteCreator;
import java.util.List; import net.kyori.adventure.text.Component;
import org.bukkit.Bukkit;
import org.bukkit.entity.Player;
import org.bukkit.scheduler.BukkitRunnable;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentHashMap;
public class GamesManager { public class GamesManager {
private static final ConcurrentHashMap<String, BlockAndSeekGame> games = new ConcurrentHashMap<>(); private static final ConcurrentHashMap<String, BlockAndSeekGame> games = new ConcurrentHashMap<>();
public static void createGame(String name, ArrayList<String> players) { public static boolean isExist(String name) {
games.put(name, new BlockAndSeekGame(name, players)); return games.containsKey(name);
} }
public static boolean joinGame(String name) { public static Set<String> getAvailableGames() {
return false; return games.keySet();
} }
public static void endGame(String name) { public static int createGame(String name) {
games.remove(name); if (games.containsKey(name)) return 1;
if (Bukkit.getWorld(name) == null) return 2;
BlockAndSeekGame game = new BlockAndSeekGame(name);
games.put(name, game);
new BukkitRunnable() {
int duration = 30;
int waitTime = 10;
@Override
public void run() {
if (!game.isStarted()) {
int playerCount = game.playerCount();
for (Player player : game.getPlayers()) {
player.sendActionBar(Component.text("Игроков " + playerCount + "/12"));
}
if (playerCount > 1) {
if (waitTime == 0) {
game.start();
for (Player player : game.getPlayers()) {
RouletteCreator.createRoulette(player, null, true);
}
} else {
for (Player player : game.getPlayers()) {
player.sendMessage(Component.text("Осталось: " + waitTime));
}
waitTime--;
}
} else waitTime = 10;
} else {
if (game.hidersCound() == 0) {
for (Player player : game.getPlayers()) {
player.sendActionBar(Component.text("Сикеры победили!"));
//TODO
}
game.end();
games.remove(name);
this.cancel();
}
for (Player player : game.getPlayers()) {
player.sendActionBar(Component.text("Осталось: " + duration));
}
if (duration == 0) {
for (Player player : game.getPlayers()) {
player.sendActionBar(Component.text("Хайдеры победили!"));
}
game.end();
games.remove(name);
this.cancel();
} else duration--;
}
}
}.runTaskTimer(BlockAndSeek.getInstance(), 0L, 20L);
return 0;
} }
public static BlockAndSeekGame get(String name) {
return games.get(name);
}
} }

View File

@@ -2,66 +2,35 @@ package hdvtdev.blockAndSeek;
import net.kyori.adventure.text.Component; import net.kyori.adventure.text.Component;
import net.kyori.adventure.text.minimessage.MiniMessage; import net.kyori.adventure.text.minimessage.MiniMessage;
import org.bukkit.ChatColor;
import org.bukkit.configuration.file.YamlConfiguration;
import org.bukkit.plugin.java.JavaPlugin;
import org.jetbrains.annotations.Nullable;
import java.io.*;
import java.util.Map; import java.util.Map;
import java.util.Objects;
import java.util.concurrent.ConcurrentHashMap;
public class Localization { public class Localization {
private static final Map<String, String> localization = new ConcurrentHashMap<>(); private static volatile Map<String, String> localization = ConfigManager.getLocalization();
private static JavaPlugin javaPlugin; private static final MiniMessage miniMessage = MiniMessage.miniMessage();
private static final Component prefix = miniMessage.deserialize("<gold>[<bold><blue>BlockAndSeek<reset><gold>] ");
public static void reload() { public static Component getPrefix() {
File localizationFile = new File(javaPlugin.getDataFolder(), "messages.yml"); return prefix;
if (!localizationFile.exists()) javaPlugin.saveResource("messages.yml", false);
YamlConfiguration locale = YamlConfiguration.loadConfiguration(localizationFile);
YamlConfiguration defaultLocale = YamlConfiguration.loadConfiguration(
new InputStreamReader(Objects.requireNonNull(javaPlugin.getResource("messages.yml"))));
String prefix = locale.getString("prefix");
prefix = prefix == null ? defaultLocale.getString("prefix") : prefix;
for (String defaultElement : defaultLocale.getKeys(false)) {
String element = locale.getString(defaultElement);
localization.put(defaultElement, String.format("%s%s", prefix, element == null ? defaultLocale.getString(defaultElement) : element));
}
} }
public static void load(JavaPlugin plugin) { public static void update() {
javaPlugin = plugin; localization = ConfigManager.getLocalization();
File localizationFile = new File(plugin.getDataFolder(), "messages.yml");
if (!localizationFile.exists()) plugin.saveResource("messages.yml", false);
YamlConfiguration locale = YamlConfiguration.loadConfiguration(localizationFile);
YamlConfiguration defaultLocale = YamlConfiguration.loadConfiguration(
new InputStreamReader(Objects.requireNonNull(plugin.getResource("messages.yml"))));
String prefix = locale.getString("prefix");
prefix = prefix == null ? defaultLocale.getString("prefix") : prefix;
for (String defaultElement : defaultLocale.getKeys(false)) {
String element = locale.getString(defaultElement);
localization.put(defaultElement, String.format("%s%s", prefix, element == null ? defaultLocale.getString(defaultElement) : element));
}
} }
public static String get(String key, String... replacements) {
public static Component get(String key, String... replacements) {
String s = localization.get(key); String s = localization.get(key);
for (int i = 0; i < replacements.length; i+=2) { if (s != null) {
s = s.replace(replacements[i], replacements[i + 1]); for (int i = 0; i < replacements.length; i += 2) {
} s = s.replace(replacements[i], replacements[i + 1]);
}
} else return "Unknown localization: " + key;
return s;
}
return MiniMessage.miniMessage().deserialize(s); public static Component getComponent(String key, String... replacements) {
return miniMessage.deserialize(get(key, replacements));
} }

View File

@@ -0,0 +1,154 @@
package hdvtdev.blockAndSeek.roulette;
import hdvtdev.blockAndSeek.BlockAndSeek;
import hdvtdev.blockAndSeek.EventListener;
import me.libraryaddict.disguise.DisguiseAPI;
import me.libraryaddict.disguise.disguisetypes.DisguiseType;
import me.libraryaddict.disguise.disguisetypes.MiscDisguise;
import net.kyori.adventure.text.Component;
import org.bukkit.Bukkit;
import org.bukkit.Material;
import org.bukkit.Sound;
import org.bukkit.entity.Player;
import org.bukkit.inventory.Inventory;
import org.bukkit.inventory.InventoryHolder;
import org.bukkit.inventory.ItemFlag;
import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.meta.ItemMeta;
import org.bukkit.metadata.FixedMetadataValue;
import org.bukkit.scheduler.BukkitRunnable;
import org.jetbrains.annotations.NotNull;
import java.util.List;
public class RouletteCreator implements InventoryHolder {
private static final int[] filledSlots = {
};
public static void createRoulette(Player player, Inventory inventory, boolean openInventory) {
Inventory gui = inventory == null ? new RouletteCreator().getInventory() : inventory;
EventListener.createTask(player, new BukkitRunnable() {
int i = 0;
final RouletteGenerator rouletteGenerator = new RouletteGenerator(List.of(
new RouletteGenerator.Block(new ItemStack(Material.FLOWER_POT), 55),
new RouletteGenerator.Block(new ItemStack(Material.GOLD_BLOCK), 25),
new RouletteGenerator.Block(new ItemStack(Material.EMERALD_BLOCK), 10),
new RouletteGenerator.Block(new ItemStack(Material.DIAMOND_BLOCK), 6),
new RouletteGenerator.Block(new ItemStack(Material.NETHERITE_BLOCK), 4)
));
final List<RouletteList<ItemStack>> rows = List.of(
new RouletteList<>(rouletteGenerator.getRandomRow(15)),
new RouletteList<>(rouletteGenerator.getRandomRow(15)),
new RouletteList<>(rouletteGenerator.getRandomRow(15))
);
final List<ItemStack[]> items = List.of(
new ItemStack[]{
rows.getFirst().next(),
rows.getFirst().next(),
rows.getFirst().next(),
rows.getFirst().next(),
rows.getFirst().next()
},
new ItemStack[]{
rows.get(1).next(),
rows.get(1).next(),
rows.get(1).next(),
rows.get(1).next(),
rows.get(1).next()
},
new ItemStack[]{
rows.get(2).next(),
rows.get(2).next(),
rows.get(2).next(),
rows.get(2).next(),
rows.get(2).next()
}
);
@Override
public void run() {
for (int j = 0; j < 5; j++) {
gui.setItem(3 + j * 9, items.getFirst()[j]);
gui.setItem(5 + j * 9, items.get(1)[j]);
gui.setItem(7 + j * 9, items.get(2)[j]);
}
player.playSound(player.getLocation(), Sound.UI_BUTTON_CLICK, 0.5f, 2f);
if (i == 30) {
player.playSound(player.getLocation(), Sound.ENTITY_PLAYER_LEVELUP, 0.5f, 0.5f);
EventListener.stopTask(player);
}
for (int j = 4; j >= 1; j--) {
items.getFirst()[j] = items.getFirst()[j - 1];
items.get(1)[j] = items.get(1)[j - 1];
items.get(2)[j] = items.get(2)[j - 1];
}
items.getFirst()[0] = rows.getFirst().next();
items.get(1)[0] = rows.get(1).next();
items.get(2)[0] = rows.get(2).next();
i++;
}
}.runTaskTimer(BlockAndSeek.getInstance(), 0, 3L));
new BukkitRunnable() {
@Override
public void run() {
Inventory inventory = player.getOpenInventory().getTopInventory();
if (inventory.getHolder() instanceof RouletteCreator) {
inventory.close();
MiscDisguise miscDisguise = new MiscDisguise(DisguiseType.FALLING_BLOCK, inventory.getItem(21));
DisguiseAPI.disguiseToAll(player, miscDisguise);
}
}
}.runTaskLater(BlockAndSeek.getInstance(), 300L);
if (openInventory) {
player.openInventory(gui);
player.setMetadata("RollingMenu", new FixedMetadataValue(BlockAndSeek.getInstance(), "RollingMenu"));
}
}
@Override
public @NotNull Inventory getInventory() {
Inventory gui = Bukkit.createInventory(this, 45, Component.text("РулетОЧКА"));
ItemStack filler = new ItemStack(Material.BLUE_STAINED_GLASS_PANE);
ItemMeta fillerMeta = filler.getItemMeta();
fillerMeta.displayName(Component.text(""));
fillerMeta.lore(null);
fillerMeta.addItemFlags(ItemFlag.HIDE_ATTRIBUTES);
filler.setItemMeta(fillerMeta);
for (int i = 0; i < 45; i++) {
gui.setItem(i, filler);
}
return gui;
}
}

View File

@@ -0,0 +1,30 @@
package hdvtdev.blockAndSeek.roulette;
import com.lewdev.probabilitylib.ProbabilityCollection;
import org.bukkit.inventory.ItemStack;
import java.util.ArrayList;
import java.util.List;
public class RouletteGenerator {
private final ProbabilityCollection<ItemStack> probabilityCollection = new ProbabilityCollection<>();
public RouletteGenerator(List<Block> blocks) {
for (Block block : blocks) {
probabilityCollection.add(block.itemStack, block.chance);
}
}
public List<ItemStack> getRandomRow(int count) {
List<ItemStack> items = new ArrayList<>(count);
for (; count > 0; --count) items.add(probabilityCollection.get());
return items;
}
public record Block(ItemStack itemStack, int chance) {
}
}

View File

@@ -0,0 +1,23 @@
package hdvtdev.blockAndSeek.roulette;
import java.util.List;
import java.util.Objects;
public class RouletteList<T> {
private final List<T> items;
private int currentIndex;
public RouletteList(List<T> items) {
this.items = Objects.requireNonNull(items);
this.currentIndex = 0;
if (items.isEmpty()) {
throw new IllegalArgumentException("List must not be empty");
}
}
public T next() {
T item = items.get(currentIndex);
currentIndex = (currentIndex + 1) % items.size();
return item;
}
}

View File

@@ -1 +1,3 @@
# # Selected language in localization.yml (en_US is used by default)
language: en_US

View File

@@ -0,0 +1,10 @@
en_US:
#Maps
maps-available: "<gold>Available maps: <white>"
maps-available-element: "- {color-status}{map}<white>"
not-enough-permissions: "<red><bold>You do not have permission to run this command."
not-enough-arguments: "<red><bold>Too few arguments to run command {command}. Arguments example: {help}"
successful-reload: "<green>Successfully reloaded <yellow><u>{config}<green>."
failed-reload: "<red>Failed to reload <yellow><u>{config}<red>. Error: {e}"

View File

@@ -0,0 +1 @@
# DO NOT edit this file manually! Use plugin commands to edit maps instead.

View File

@@ -1,15 +0,0 @@
prefix: "[<blue>BlockAndSeek<white>] "
bs-usage: "Usage: <italic>/blockandseek [SUBCOMMAND]"
messages-reload: "<green>Successfully reload messages.yml"
not-enough-arguments: "Too few args. Usage: {usage}."
unknown-subcommand: "<gold>Unknown subcommand <red>{subcommand}<white>."
#Map
maps-list: "Available maps: <gold>{maps}"
maps-reload: "<green>Successfully reload <u>maps.yml"
map-created: "<green>Successfully created map <underline><gold>{map}<white>."
map-missing-world: "<red>Could not find world <gold>{world}<red> in server folder. An existing world is required to create a map"
map-creation-failed: "<red>Failed to create map <bold><green>{map}<reset>.<red> Error: {error}."
map-already-exist: "<red>Map <gold>{map}<red> already exist!"
map-not-exist: "<red>Map <gold>{map}<red> does not exist!"

View File

@@ -2,6 +2,12 @@ name: BlockAndSeek
version: '0.0.1-a' version: '0.0.1-a'
main: hdvtdev.blockAndSeek.BlockAndSeek main: hdvtdev.blockAndSeek.BlockAndSeek
api-version: '1.20' api-version: '1.20'
permissions:
blockandseek.manage:
description: "Permission to use this subcommands: reload, map"
default: op
commands: commands:
blockandseek: blockandseek:
aliases: aliases: