some improvments, bugs and bugfixed )

This commit is contained in:
hdvt
2025-07-15 16:36:46 +03:00
parent 9f36ac3e4b
commit 66a77bd59a
13 changed files with 272 additions and 80 deletions

View File

@@ -74,11 +74,11 @@ public class BlockAndSeek extends JavaPlugin {
manager.registerEvents(ConfigManager.getConfig().forceControl() ? new ForceControlEventListener() : new EventListener(), this);
manager.registerEvents(new DefaultEventListener(), this);
}
@Override
public void onDisable() {
}
}

View File

@@ -1,9 +1,9 @@
package hdvtdev.blockAndSeek;
import hdvtdev.blockAndSeek.managers.ConfigManager;
import hdvtdev.blockAndSeek.managers.FreezeManager;
import hdvtdev.blockAndSeek.managers.GamesManager;
import hdvtdev.blockAndSeek.managers.ItemManager;
import hdvtdev.blockAndSeek.managers.PropManager;
import hdvtdev.blockAndSeek.roulette.RouletteCreator;
import me.libraryaddict.disguise.DisguiseAPI;
import org.bukkit.*;
@@ -16,13 +16,13 @@ import org.jetbrains.annotations.Nullable;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.atomic.AtomicBoolean;
public class BlockAndSeekGame {
private final ConcurrentHashMap<Player, PlayerType> players = new ConcurrentHashMap<>();
private final Map<Player, PlayerType> players = new ConcurrentHashMap<>();
private final Map<Player, RouletteCreator> hiderRoulette = new HashMap<>();
private final AtomicBoolean started = new AtomicBoolean(false);
private volatile boolean started = false;
private final BlockAndSeekMap map;
private final Location lobby;
private final Location spawn;
@@ -45,12 +45,16 @@ public class BlockAndSeekGame {
return players.size();
}
public boolean isStarted() {
return started;
}
public int maxPlayers() {
return map.getMaxPlayers();
}
public boolean addPlayer(Player player) {
if (!started.get()) {
if (!started) {
players.put(player, PlayerType.HIDER);
player.getPersistentDataContainer().set(Keys.GAME, PersistentDataType.STRING, name);
player.teleport(lobby);
@@ -88,7 +92,7 @@ public class BlockAndSeekGame {
true,
"player-leave",
"{player}", player.getName(),
"{players}", started.get() ? "" : players.size() + "/" + map.getMaxPlayers()
"{players}", started ? "" : players.size() + "/" + map.getMaxPlayers()
);
}
@@ -127,7 +131,7 @@ public class BlockAndSeekGame {
}
private void start() {
started.set(true);
started = true;
selectRandomSeekers((int) Math.round(players.size() * 0.25));
List<Player> hiders = getHiders();
for (Player hider : hiders) {
@@ -137,26 +141,27 @@ public class BlockAndSeekGame {
PlayerInventory inventory = hider.getInventory();
inventory.clear();
inventory.addItem(Localization.translateItem(hider, ItemManager.getFreezeItem()));
new RouletteCreator(hider, map.getBlocks());
inventory.addItem(Localization.translateItem(hider, ItemManager.getFaceChangingItem()));
hiderRoulette.put(hider, new RouletteCreator(hider, map.getBlocks()));
}
}
private void end(boolean force) {
GamesManager.remove(name);
if (!force) {
Location serverLobby = ConfigManager.getConfig().defaultSpawn();
boolean defaultInventory = ConfigManager.getConfig().forceControl();
Config config = ConfigManager.getConfig();
Location serverLobby = config.defaultSpawn();
boolean defaultInventory = config.forceControl();
for (Player player : players.keySet()) {
PersistentDataContainer container = player.getPersistentDataContainer();
container.remove(Keys.HIDER);
container.remove(Keys.SEEKER);
container.remove(Keys.GAME);
DisguiseAPI.undisguiseToAll(player);
if (defaultInventory) ItemManager.defaultInventory(player);
player.setGlowing(false);
player.setInvulnerable(false);
Utils.setLevelWithBar(player, 0);
player.setVisibleByDefault(true);
player.setHealth(20);
player.setGameMode(GameMode.SURVIVAL);
player.teleport(serverLobby);
@@ -166,16 +171,23 @@ public class BlockAndSeekGame {
private void preEnd() {
for (Player player : players.keySet()) {
PersistentDataContainer container = player.getPersistentDataContainer();
player.setInvulnerable(true);
container.remove(Keys.HIDER);
container.remove(Keys.SEEKER);
container.remove(Keys.GAME);
}
for (Player hider : getHiders()) {
hider.getInventory().clear();
FreezeManager.unfreezeIfFrozen(hider);
PropManager.unfreezeIfFrozen(hider);
hider.setGlowing(true);
RouletteCreator rouletteCreator = hiderRoulette.get(hider);
rouletteCreator.getTask().cancelBoth();
rouletteCreator.closeInventory();
}
}
public void selectRandomSeekers(int count) {
private void selectRandomSeekers(int count) {
ArrayList<Player> rawSeekers = new ArrayList<>();
Set<Player> playerSet = players.keySet();
for (Player player : playerSet) {
@@ -224,11 +236,15 @@ public class BlockAndSeekGame {
waitTime = defaultWaitTime;
}
} else {
if (!started.get()) {
if (!started) {
start();
} else {
if (players.isEmpty()) end(false);
if (players.isEmpty()) {
end(false);
this.cancel();
return;
}
if (duration > 0 && getHidersCount() == 0) {
Localization.sendTitle(
@@ -236,6 +252,7 @@ public class BlockAndSeekGame {
false,
"seekers-won"
);
preEnd();
duration = -1;
}
@@ -245,7 +262,7 @@ public class BlockAndSeekGame {
}
}
if (getSeekersCount() == 0) duration = 0;
if (duration > 0 && getSeekersCount() == 0) duration = 0;
if (duration == 0) {
@@ -274,8 +291,8 @@ public class BlockAndSeekGame {
);
duration--;
} else if (duration == -10) {
this.cancel();
end(false);
this.cancel();
} else {
duration--;
}

View File

@@ -20,6 +20,7 @@ import org.bukkit.command.TabExecutor;
import org.bukkit.entity.Player;
import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.meta.ItemMeta;
import org.bukkit.persistence.PersistentDataContainer;
import org.bukkit.persistence.PersistentDataType;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -45,15 +46,12 @@ public class CommandListener implements TabExecutor {
switch (args[0]) {
case "test" -> {
switch (GamesManager.createGame("dust2")) {
case 1 -> {
sender.sendMessage("Game already exist");
GamesManager.get("dust2").addPlayer((Player) sender);
}
case 2 -> sender.sendMessage("Could not find world");
default -> GamesManager.get("dust2").addPlayer((Player) sender);
if (sender instanceof Player player) {
GamesManager.createGame("dust2");
GamesManager.get("dust2").addPlayer(player);
}
}
case "locale" -> {
if (sender instanceof Player player) {
@@ -72,7 +70,7 @@ public class CommandListener implements TabExecutor {
if (sender instanceof Player player && args.length == 2) {
Material material = Material.valueOf(args[1].toUpperCase());
FreezeManager.addPlayerDisguise(player, material.createBlockData());
PropManager.addPlayerDisguise(player, material.createBlockData());
DisguiseAPI.disguiseToAll(player, new MiscDisguise(DisguiseType.FALLING_BLOCK, new ItemStack(material)));
}
}
@@ -115,9 +113,16 @@ public class CommandListener implements TabExecutor {
player.getInventory().addItem(foo);
}
}
case "bbb" -> {
if (sender instanceof Player player) {
PropManager.changePropDirection(player);
}
}
case "container" -> {
if (sender instanceof Player player) {
player.sendMessage(String.valueOf(player.getPersistentDataContainer().has(Keys.GAME)));
var container = player.getPersistentDataContainer();
player.sendMessage("containers: " + container.getKeys());
}
}
case "def" -> {
@@ -130,8 +135,12 @@ public class CommandListener implements TabExecutor {
player.clearActivePotionEffects();
player.setHealth(player.getAttribute(Attribute.GENERIC_MAX_HEALTH).getDefaultValue());
player.setFoodLevel(20);
Utils.setLevelWithBar(player, 0);
DisguiseAPI.undisguiseToAll(player);
PersistentDataContainer dataContainer = player.getPersistentDataContainer();
for (var key : dataContainer.getKeys()) {
dataContainer.remove(key);
}
}
}
case "map" -> {

View File

@@ -9,6 +9,7 @@ public class Keys {
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 FACE_CHANGING_ITEM = new NamespacedKey(BlockAndSeek.getInstance(), "BlockAndSeekFaceChangingItem");
public static final NamespacedKey MENU_ITEM = new NamespacedKey(BlockAndSeek.getInstance(), "BlockAndSeekMenuItem");
public static final NamespacedKey LEAVE_ITEM = new NamespacedKey(BlockAndSeek.getInstance(), "BlockAndSeekLeaveItem");
public static final NamespacedKey GAME_PAGE = new NamespacedKey(BlockAndSeek.getInstance(), "BlockAndSeekGamePage");

View File

@@ -1,11 +1,12 @@
package hdvtdev.blockAndSeek;
import hdvtdev.blockAndSeek.managers.FreezeManager;
import hdvtdev.blockAndSeek.managers.PropManager;
import me.libraryaddict.disguise.DisguiseAPI;
import me.libraryaddict.disguise.disguisetypes.DisguiseType;
import me.libraryaddict.disguise.disguisetypes.MiscDisguise;
import org.bukkit.entity.Player;
import org.bukkit.inventory.ItemStack;
import org.bukkit.persistence.PersistentDataContainer;
public final class Utils {
@@ -29,7 +30,13 @@ public final class Utils {
public static void firstDisguise(Player player, ItemStack prop) {
DisguiseAPI.disguiseToAll(player, new MiscDisguise(DisguiseType.FALLING_BLOCK, prop));
FreezeManager.addPlayerDisguise(player, prop.getType().createBlockData());
PropManager.addPlayerDisguise(player, prop.getType().createBlockData());
}
public static boolean hasPermsToDamage(Player p1, Player p2) {
PersistentDataContainer c1 = p1.getPersistentDataContainer();
PersistentDataContainer c2 = p2.getPersistentDataContainer();
return (c1.has(Keys.SEEKER) || c1.has(Keys.HIDER)) && (c2.has(Keys.SEEKER) || c2.has(Keys.HIDER));
}
}

View File

@@ -3,9 +3,9 @@ package hdvtdev.blockAndSeek.eventListeners;
import hdvtdev.blockAndSeek.BlockAndSeek;
import hdvtdev.blockAndSeek.Keys;
import hdvtdev.blockAndSeek.Utils;
import hdvtdev.blockAndSeek.managers.FreezeManager;
import hdvtdev.blockAndSeek.managers.GamesManager;
import hdvtdev.blockAndSeek.managers.GuiManager;
import hdvtdev.blockAndSeek.managers.PropManager;
import hdvtdev.blockAndSeek.roulette.RouletteCreator;
import org.bukkit.Bukkit;
import org.bukkit.entity.ArmorStand;
@@ -75,7 +75,7 @@ public class DefaultEventListener implements Listener {
public void onBlockDamage(BlockDamageEvent event) {
Player player = event.getPlayer();
if (player.getPersistentDataContainer().has(Keys.SEEKER)) {
if (FreezeManager.unfreeze(event.getBlock().getBlockData())) {
if (PropManager.unfreeze(event.getBlock().getBlockData())) {
event.setCancelled(true);
} else {
player.damage(2);
@@ -100,7 +100,7 @@ public class DefaultEventListener implements Listener {
if (itemData.has(Keys.FREEZE_ITEM) && playerInGame(player)) {
coolDown.add(player);
scheduler.runTaskLater(BlockAndSeek.getInstance(), () -> coolDown.remove(player), 3L);
FreezeManager.freeze(player);
PropManager.freeze(player);
event.setCancelled(true);
} else if (itemData.has(Keys.MENU_ITEM)) {
GuiManager.Menu.open(player);
@@ -109,6 +109,9 @@ public class DefaultEventListener implements Listener {
String game = player.getPersistentDataContainer().get(Keys.GAME, PersistentDataType.STRING);
GamesManager.get(game).removePlayer(player);
event.setCancelled(true);
} else if (itemData.has(Keys.FACE_CHANGING_ITEM)) {
PropManager.changePropDirection(player);
event.setCancelled(true);
}
}
@@ -121,7 +124,7 @@ public class DefaultEventListener implements Listener {
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);
PropManager.freeze(player);
}
}
@@ -133,7 +136,7 @@ public class DefaultEventListener implements Listener {
String arena = container.get(Keys.GAME, PersistentDataType.STRING);
if (arena != null) {
GamesManager.get(arena).removePlayer(player);
FreezeManager.removePlayerDisguise(player);
PropManager.removePlayerDisguise(player);
}
}
@@ -158,15 +161,20 @@ public class DefaultEventListener implements Listener {
if (holder instanceof RouletteCreator rouletteCreator) {
if (rouletteCreator.isClosedByPlayer()) {
Boolean isClosedByPlayer = rouletteCreator.isClosedByPlayer();
if (isClosedByPlayer != null) {
RouletteCreator.Task task = rouletteCreator.getTask();
if (isClosedByPlayer) {
if (!task.rouletteTask().isCancelled()) {
task.cancelBoth();
Utils.firstDisguise(player, rouletteCreator.randomPropItem());
} else Utils.firstDisguise(player, rouletteCreator.randomMidPropItem()); //FIXME THIS FUCKING LINE AAAA
} else Utils.firstDisguise(player, rouletteCreator.randomMidPropItem());
task.cancelBoth();
} else Utils.firstDisguise(player, rouletteCreator.randomMidPropItem());
}
}
@@ -191,13 +199,13 @@ public class DefaultEventListener implements Listener {
if (slot == 21 || slot == 23 || slot == 25) {
task.autoCloseTask().cancel();
Utils.firstDisguise(player, inventory.getItem(slot));
rouletteCreator.closeInventoryByPlayer();
rouletteCreator.closeInventory();
}
event.setCancelled(true);
return;
} else {
if (slot == 36) {
task.rouletteTask().cancel();
task.cancelBoth();
Utils.firstDisguise(player, rouletteCreator.randomPropItem());
rouletteCreator.closeInventory();
event.setCancelled(true);
@@ -240,13 +248,15 @@ public class DefaultEventListener implements Listener {
@EventHandler
public void onRegainHealth(EntityRegainHealthEvent event) {
if (event.getEntity() instanceof Player player) {
if (player.getPersistentDataContainer().has(Keys.SEEKER)) {
PersistentDataContainer container = player.getPersistentDataContainer();
if (container.has(Keys.SEEKER)) {
event.setCancelled(true);
} else if (container.has(Keys.HIDER)) {
if (!PropManager.isPlayerDisguised(player)) event.setCancelled(true);
}
}
}
@EventHandler
public void onPlayerDamage(EntityDamageByEntityEvent event) {
if (event.getDamager() instanceof Player damager && event.getEntity() instanceof Player victim) {

View File

@@ -1,6 +1,6 @@
package hdvtdev.blockAndSeek.eventListeners;
import hdvtdev.blockAndSeek.Keys;
import hdvtdev.blockAndSeek.Utils;
import hdvtdev.blockAndSeek.managers.ItemManager;
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
@@ -13,15 +13,9 @@ import org.bukkit.event.player.PlayerDropItemEvent;
import org.bukkit.event.player.PlayerJoinEvent;
import org.bukkit.event.weather.WeatherChangeEvent;
import org.bukkit.event.world.TimeSkipEvent;
import org.bukkit.persistence.PersistentDataContainer;
public class ForceControlEventListener implements Listener {
private static boolean hasPermsToDamage(Player p1, Player p2) {
PersistentDataContainer c1 = p1.getPersistentDataContainer();
PersistentDataContainer c2 = p2.getPersistentDataContainer();
return (c1.has(Keys.SEEKER) || c1.has(Keys.HIDER)) && (c2.has(Keys.SEEKER) || c2.has(Keys.HIDER));
}
@EventHandler
public void onPlayerJoin(PlayerJoinEvent event) {
@@ -65,7 +59,7 @@ public class ForceControlEventListener implements Listener {
@EventHandler
public void onPlayerDamage(EntityDamageByEntityEvent event) {
if (event.getDamager() instanceof Player damager && event.getEntity() instanceof Player victim) {
if (!hasPermsToDamage(damager, victim)) {
if (!Utils.hasPermsToDamage(damager, victim)) {
event.setCancelled(true);
}
}

View File

@@ -6,6 +6,7 @@ import hdvtdev.blockAndSeek.BlockAndSeekMap;
import org.bukkit.Bukkit;
import org.bukkit.WorldCreator;
import org.bukkit.entity.Player;
import org.jetbrains.annotations.Nullable;
import java.io.File;
import java.util.Set;
@@ -28,20 +29,20 @@ public class GamesManager {
return games.keySet();
}
public static int createGame(String name) {
if (games.containsKey(name)) return 1;
public static @Nullable String createGame(String name) {
if (games.containsKey(name)) return name; //TODO use copy or create copy
if (Bukkit.getWorld(name) == null) {
if (new File(BlockAndSeek.getServerDataFolder(), name).exists()) {
Bukkit.createWorld(new WorldCreator(name));
} else return 2;
} else return null;
}
BlockAndSeekMap map = MapsManager.getMap(name);
BlockAndSeekGame game = new BlockAndSeekGame(name, map);
games.put(name, game);
return 0;
return null;
}
public static void remove(String name) {
@@ -52,4 +53,5 @@ public class GamesManager {
return games.get(name);
}
}

View File

@@ -17,6 +17,7 @@ import org.bukkit.persistence.PersistentDataType;
public class ItemManager {
private static final ItemStack freezeItem = new ItemStack(Material.HEART_OF_THE_SEA);
private static final ItemStack faceChangingItem = new ItemStack(Material.NETHER_STAR);
private static final ItemStack seekerSword = new ItemStack(Material.WOODEN_SWORD);
private static final ItemStack seekerHelmet = new ItemStack(Material.LEATHER_HELMET);
@@ -37,6 +38,11 @@ public class ItemManager {
freezeMeta.getPersistentDataContainer().set(Keys.FREEZE_ITEM, PersistentDataType.BOOLEAN, true);
freezeItem.setItemMeta(freezeMeta);
ItemMeta faceChangingMeta = faceChangingItem.getItemMeta();
faceChangingMeta.displayName(Component.text("face-changing-item"));
faceChangingMeta.getPersistentDataContainer().set(Keys.FACE_CHANGING_ITEM, PersistentDataType.BOOLEAN, true);
faceChangingItem.setItemMeta(faceChangingMeta);
ItemMeta swordMeta = seekerSword.getItemMeta();
swordMeta.displayName(Component.text("seeker-sword"));
swordMeta.addEnchant(Enchantment.DAMAGE_ALL, 2, false);
@@ -106,6 +112,10 @@ public class ItemManager {
inventory.addItem(Localization.translateItem(player, menuItem));
}
public static ItemStack getFaceChangingItem() {
return faceChangingItem;
}
public static ItemStack getLeaveItem() {
return leaveItem;
}

View File

@@ -7,7 +7,9 @@ import me.libraryaddict.disguise.disguisetypes.DisguiseType;
import me.libraryaddict.disguise.disguisetypes.MiscDisguise;
import org.bukkit.Location;
import org.bukkit.block.Block;
import org.bukkit.block.BlockFace;
import org.bukkit.block.data.BlockData;
import org.bukkit.block.data.Directional;
import org.bukkit.entity.ArmorStand;
import org.bukkit.entity.Player;
import org.bukkit.persistence.PersistentDataType;
@@ -16,7 +18,7 @@ import org.bukkit.util.Vector;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
public class FreezeManager {
public class PropManager {
private static final Map<Player, FreezeData> frozenPlayers = new ConcurrentHashMap<>();
private static final Map<Player, BlockData> playerDisguise = new ConcurrentHashMap<>();
@@ -25,6 +27,10 @@ public class FreezeManager {
private static final Disguise hideDisguise = new MiscDisguise(DisguiseType.LLAMA_SPIT);
private static final Vector zeroVelocity = new Vector(0, 0, 0);
public static boolean isPlayerDisguised(Player player) {
return frozenPlayers.containsKey(player);
}
public static void addPlayerDisguise(Player player, BlockData blockData) {
disguisePlayer.put(blockData, player);
playerDisguise.put(player, blockData);
@@ -34,6 +40,30 @@ public class FreezeManager {
disguisePlayer.remove(playerDisguise.remove(player));
}
public static void changePropDirection(Player player) {
if (frozenPlayers.containsKey(player)) {
Block block = player.getLocation().getBlock();
BlockData blockData = block.getBlockData();
if (blockData instanceof Directional directional) {
BlockFace face = switch (directional.getFacing()) {
case NORTH -> BlockFace.EAST;
case EAST -> BlockFace.SOUTH;
case SOUTH -> BlockFace.WEST;
case WEST -> directional.getFaces().contains(BlockFace.UP) ? BlockFace.UP : BlockFace.NORTH;
case UP -> BlockFace.DOWN;
case DOWN -> BlockFace.NORTH;
default -> null;
};
if (face != null && directional.getFaces().contains(face)) {
directional.setFacing(face);
block.setBlockData(blockData);
}
}
}
}
public static void unfreezeIfFrozen(Player player) {
Location location = player.getLocation();
FreezeData data = frozenPlayers.remove(player);

View File

@@ -0,0 +1,113 @@
package hdvtdev.blockAndSeek.managers;
import hdvtdev.blockAndSeek.BlockAndSeek;
import io.papermc.paper.threadedregions.scheduler.AsyncScheduler;
import org.bukkit.Bukkit;
import org.bukkit.World;
import org.bukkit.WorldCreator;
import org.bukkit.scheduler.BukkitRunnable;
import org.codehaus.plexus.util.FileUtils;
import org.jetbrains.annotations.ApiStatus;
import org.jetbrains.annotations.Nullable;
import java.io.File;
import java.io.IOException;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentLinkedQueue;
import java.util.concurrent.atomic.AtomicInteger;
@ApiStatus.Experimental
public final class WorldManager {
private static final File serverFolder = BlockAndSeek.getServerDataFolder();
private static final AsyncScheduler asyncScheduler = Bukkit.getAsyncScheduler();
private static final ConcurrentHashMap<String, WorldManager> worldManagers = new ConcurrentHashMap<>();
static {
//TODO
}
private final File originalWorld;
private final ConcurrentLinkedQueue<World> freeCopies = new ConcurrentLinkedQueue<>();
private final AtomicInteger copyIndex = new AtomicInteger(1);
private final int reservedCopies;
private WorldManager(String worldName, int reservedCopies) {
this.originalWorld = new File(serverFolder, worldName + "_copy");
this.reservedCopies = reservedCopies;
new BukkitRunnable() {
boolean unloading = false;
@Override
public void run() {
if (!Bukkit.isTickingWorlds() && !unloading) {
unloading = true;
Bukkit.unloadWorld(worldName, true);
asyncScheduler.runNow(BlockAndSeek.getInstance(), task -> {
try {
FileUtils.copyDirectoryStructure(new File(serverFolder, worldName), originalWorld);
createCopy();
} catch (IOException e) {
BlockAndSeek.getPluginLogger().severe("Failed to copy world \"" + worldName + "\": " + e.getMessage());
this.cancel();
}
});
this.cancel();
}
}
}.runTaskTimer(BlockAndSeek.getInstance(), 0, 1);
}
public static void createWorldManager(String existingWorld, int reservedCopies) {
worldManagers.put(existingWorld, new WorldManager(existingWorld, reservedCopies));
}
public static @Nullable WorldManager get(String worldName) {
return worldManagers.get(worldName);
}
/**
* @return {@link World} if a free copy is available or a new one has been created.
* Returns {@code null} if there are currently no free copies and a new copy is still being created.
*/
public @Nullable World acquire() {
if (freeCopies.size() <= 1) {
createCopy(); //TODO
}
return freeCopies.poll();
}
public void release() {
}
private void createCopy() {
String worldName = originalWorld.getName() + copyIndex.incrementAndGet();
try {
File worldCopy = new File(serverFolder, worldName);
if (!worldCopy.exists()) copyDirectoryToDirectory(originalWorld, worldCopy);
freeCopies.add(Bukkit.createWorld(WorldCreator.name(worldName)));
} catch (IOException e) {
BlockAndSeek.getPluginLogger().severe("Failed to copy world \"" + worldName + "\": " + e.getMessage());
}
}
private static void copyDirectoryToDirectory(File source, File destination) throws IOException {
File finalDestination = new File(destination, source.getName());
finalDestination.mkdirs();
FileUtils.copyDirectory(source, finalDestination);
}
}

View File

@@ -13,6 +13,7 @@ import org.bukkit.scheduler.BukkitRunnable;
import org.bukkit.scheduler.BukkitTask;
import org.jetbrains.annotations.ApiStatus;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.ArrayList;
import java.util.List;
@@ -27,7 +28,7 @@ public final class RouletteCreator implements InventoryHolder {
private final Inventory roulette;
private Task task;
private volatile boolean closedByPlayer = true;
private volatile Boolean closedByPlayer = true;
public RouletteCreator(@NotNull Player player, List<BlockAndSeekMap.Block> blocks) {
roulette = Bukkit.createInventory(this, 45, Localization.getComponent(player, "roulette-title"));
@@ -38,7 +39,7 @@ public final class RouletteCreator implements InventoryHolder {
return task;
}
public boolean isClosedByPlayer() {
public @Nullable Boolean isClosedByPlayer() {
return closedByPlayer;
}
@@ -47,13 +48,13 @@ public final class RouletteCreator implements InventoryHolder {
return roulette;
}
public void closeInventory() {
public void closeInventoryBySystem() {
closedByPlayer = false;
roulette.close();
}
public void closeInventoryByPlayer() {
closedByPlayer = true;
public void closeInventory() {
closedByPlayer = null;
roulette.close();
}
@@ -104,23 +105,21 @@ public final class RouletteCreator implements InventoryHolder {
long now = System.currentTimeMillis();
double elapsed = (now - startTime) / 1000.0;
if (elapsed >= 9.5) {
if (elapsed >= 5) {
this.cancel();
}
double speed;
if (elapsed < 3.0) speed = 1.0;
else if (elapsed < 3.5) speed = 0.8;
else if (elapsed < 4.0) speed = 0.6;
else if (elapsed < 4.5) speed = 0.5;
else if (elapsed < 5.0) speed = 0.4;
else if (elapsed < 5.5) speed = 0.33;
else if (elapsed < 6.0) speed = 0.28;
else if (elapsed < 6.5) speed = 0.25;
else if (elapsed < 7.0) speed = 0.22;
else if (elapsed < 7.5) speed = 0.2;
else if (elapsed < 8.0) speed = 0.12;
else speed = 0.05;
if (elapsed < 2) speed = 1.0;
else if (elapsed < 2.2) speed = 0.8;
else if (elapsed < 2.4) speed = 0.6;
else if (elapsed < 2.6) speed = 0.5;
else if (elapsed < 2.8) speed = 0.4;
else if (elapsed < 3) speed = 0.33;
else if (elapsed < 3.2) speed = 0.28;
else if (elapsed < 3.5) speed = 0.22;
else if (elapsed < 3.8) speed = 0.15;
else speed = 0.1;
task(speed);
@@ -154,7 +153,7 @@ public final class RouletteCreator implements InventoryHolder {
}.runTaskTimer(BlockAndSeek.getInstance(), 0, 1);
task = new Task(rouletteTask, Bukkit.getScheduler().runTaskLater(BlockAndSeek.getInstance(), this::closeInventory, 300));
task = new Task(rouletteTask, Bukkit.getScheduler().runTaskLater(BlockAndSeek.getInstance(), this::closeInventoryBySystem, 300));
player.openInventory(gui);
}