diff --git a/api/src/main/java/net/momirealms/customfishing/api/mechanic/competition/CompetitionManager.java b/api/src/main/java/net/momirealms/customfishing/api/mechanic/competition/CompetitionManager.java index b3ae4e3c..679a4158 100644 --- a/api/src/main/java/net/momirealms/customfishing/api/mechanic/competition/CompetitionManager.java +++ b/api/src/main/java/net/momirealms/customfishing/api/mechanic/competition/CompetitionManager.java @@ -21,6 +21,7 @@ import net.momirealms.customfishing.common.plugin.feature.Reloadable; import org.jetbrains.annotations.Nullable; import java.util.Collection; +import java.util.UUID; /** * Interface for managing fishing competitions. @@ -84,4 +85,17 @@ public interface CompetitionManager extends Reloadable { * @return a collection of competition IDs. */ Collection getCompetitionIDs(); + + /** + * Count the online players. + */ + int onlinePlayerCountProvider(); + + /** + * Updates the player count for a specific UUID. + * + * @param uuid the UUID of the server. + * @param count the new player count. + */ + void updatePlayerCount(UUID uuid, int count); } diff --git a/core/src/main/java/net/momirealms/customfishing/bukkit/BukkitCustomFishingPluginImpl.java b/core/src/main/java/net/momirealms/customfishing/bukkit/BukkitCustomFishingPluginImpl.java index 9f08357c..6f2d790b 100644 --- a/core/src/main/java/net/momirealms/customfishing/bukkit/BukkitCustomFishingPluginImpl.java +++ b/core/src/main/java/net/momirealms/customfishing/bukkit/BukkitCustomFishingPluginImpl.java @@ -116,9 +116,9 @@ public class BukkitCustomFishingPluginImpl extends BukkitCustomFishingPlugin { this.senderFactory = new BukkitSenderFactory(this); this.placeholderManager = new BukkitPlaceholderManager(this); this.itemManager = new BukkitItemManager(this); - this.competitionManager = new BukkitCompetitionManager(this); this.marketManager = new BukkitMarketManager(this); this.storageManager = new BukkitStorageManager(this); + this.competitionManager = new BukkitCompetitionManager(this); this.lootManager = new BukkitLootManager(this); this.coolDownManager = new CoolDownManager(this); this.entityManager = new BukkitEntityManager(this); diff --git a/core/src/main/java/net/momirealms/customfishing/bukkit/competition/BukkitCompetitionManager.java b/core/src/main/java/net/momirealms/customfishing/bukkit/competition/BukkitCompetitionManager.java index 2fe480b5..37067e97 100644 --- a/core/src/main/java/net/momirealms/customfishing/bukkit/competition/BukkitCompetitionManager.java +++ b/core/src/main/java/net/momirealms/customfishing/bukkit/competition/BukkitCompetitionManager.java @@ -35,6 +35,7 @@ import java.time.LocalDateTime; import java.util.Arrays; import java.util.Collection; import java.util.HashMap; +import java.util.UUID; import java.util.concurrent.TimeUnit; public class BukkitCompetitionManager implements CompetitionManager { @@ -45,14 +46,22 @@ public class BukkitCompetitionManager implements CompetitionManager { private Competition currentCompetition; private SchedulerTask timerCheckTask; private int nextCompetitionSeconds; + private boolean hasRedis; + private int interval; + private final UUID identifier; + private final HashMap playerCountMap; public BukkitCompetitionManager(BukkitCustomFishingPlugin plugin) { this.plugin = plugin; + this.identifier = UUID.randomUUID(); this.timeConfigMap = new HashMap<>(); this.commandConfigMap = new HashMap<>(); + this.playerCountMap = new HashMap<>(); } public void load() { + this.interval = 10; + this.hasRedis = plugin.getStorageManager().isRedisEnabled(); this.timerCheckTask = plugin.getScheduler().asyncRepeating( this::timerCheck, 1, @@ -60,6 +69,10 @@ public class BukkitCompetitionManager implements CompetitionManager { TimeUnit.SECONDS ); plugin.debug("Loaded " + commandConfigMap.size() + " competitions"); + + if (hasRedis) { + new RedisPlayerCount(this.interval); + } } public void unload() { @@ -139,7 +152,7 @@ public class BukkitCompetitionManager implements CompetitionManager { @Override public boolean startCompetition(CompetitionConfig config, boolean force, @Nullable String serverGroup) { if (!force) { - int players = Bukkit.getOnlinePlayers().size(); + int players = onlinePlayerCountProvider(); if (players < config.minPlayersToStart()) { ActionManager.trigger(Context.player(null), config.skipActions()); return false; @@ -198,4 +211,50 @@ public class BukkitCompetitionManager implements CompetitionManager { public Collection getCompetitionIDs() { return commandConfigMap.keySet(); } + + @Override + public int onlinePlayerCountProvider() { + int count = Bukkit.getOnlinePlayers().size(); + if (hasRedis) { + for (UUID uuid : playerCountMap.keySet()) { + PlayerCount playerCount = playerCountMap.get(uuid); + if ((System.currentTimeMillis() - playerCount.time) < interval * 1000L + 1000L) { + count += playerCount.count; + } else { + playerCountMap.remove(uuid); + } + } + } + return count; + } + + @Override + public void updatePlayerCount(UUID uuid, int count) { + playerCountMap.put(uuid, new PlayerCount(count, System.currentTimeMillis())); + } + + private class RedisPlayerCount implements Runnable { + public RedisPlayerCount(int interval) { + plugin.getScheduler().asyncRepeating(this, 0, interval, TimeUnit.SECONDS); + } + + @Override + public void run() { + ByteArrayDataOutput out = ByteStreams.newDataOutput(); + out.writeUTF("online"); + out.writeUTF(String.valueOf(identifier)); + out.writeUTF(String.valueOf(Bukkit.getOnlinePlayers().size())); + RedisManager.getInstance().publishRedisMessage(Arrays.toString(out.toByteArray())); + } + } + + private static class PlayerCount { + int count; + long time; + + public PlayerCount(int count, long time) { + this.count = count; + this.time = time; + } + } } diff --git a/core/src/main/java/net/momirealms/customfishing/bukkit/storage/method/database/nosql/RedisManager.java b/core/src/main/java/net/momirealms/customfishing/bukkit/storage/method/database/nosql/RedisManager.java index 0773ca6d..6c1af6d8 100644 --- a/core/src/main/java/net/momirealms/customfishing/bukkit/storage/method/database/nosql/RedisManager.java +++ b/core/src/main/java/net/momirealms/customfishing/bukkit/storage/method/database/nosql/RedisManager.java @@ -205,6 +205,12 @@ public class RedisManager extends AbstractStorage { } } } + if (type.equals("online")) { + plugin.getCompetitionManager().updatePlayerCount( + UUID.fromString(input.readUTF()), + Integer.parseInt(input.readUTF()) + ); + } } @Override