diff --git a/README.md b/README.md index e4f75a8..6f70b09 100644 --- a/README.md +++ b/README.md @@ -36,3 +36,11 @@ Updates ALL* your plugins \ ### Hardcore P Hardcore hearts by chance + +### Sleep +Sleeping doesn't skip night, but speeds it up. The more players, the faster it goes. + +### Instant sleep +One can instantly skip, but only a part of the night. \ +There's 5 players on the server. A night is 10 minutes long. \ +Each player can instantly skip 2 minutes of the night at any time, even if others aren't sleeping \ No newline at end of file diff --git a/src/main/java/eu/m724/tweaks/TweaksConfig.java b/src/main/java/eu/m724/tweaks/TweaksConfig.java index 1213c2a..a8c1197 100644 --- a/src/main/java/eu/m724/tweaks/TweaksConfig.java +++ b/src/main/java/eu/m724/tweaks/TweaksConfig.java @@ -40,7 +40,10 @@ public record TweaksConfig( boolean updaterEnabled, boolean hardcoreEnabled, - float hardcoreChance + float hardcoreChance, + + boolean sleepEnabled, + boolean sleepInstant ) { public static final int CONFIG_VERSION = 1; private static TweaksConfig config; @@ -95,6 +98,9 @@ public record TweaksConfig( boolean hardcoreEnabled = config.getBoolean("hardcore.enabled"); float hardcoreChance = (float) config.getDouble("hardcore.chance"); + boolean sleepEnabled = config.getBoolean("sleep.enabled"); + boolean sleepInstant = config.getBoolean("sleep.instant"); + TweaksConfig.config = new TweaksConfig( isProtocolLib, hideWorldBorder, @@ -105,7 +111,8 @@ public record TweaksConfig( compassEnabled, compassWidth, compassPrecision, pomodoroEnabled, pomodoroForce, updaterEnabled, - hardcoreEnabled, hardcoreChance + hardcoreEnabled, hardcoreChance, + sleepEnabled, sleepInstant ); return TweaksConfig.config; diff --git a/src/main/java/eu/m724/tweaks/TweaksPlugin.java b/src/main/java/eu/m724/tweaks/TweaksPlugin.java index b5c90d1..75aa267 100644 --- a/src/main/java/eu/m724/tweaks/TweaksPlugin.java +++ b/src/main/java/eu/m724/tweaks/TweaksPlugin.java @@ -16,6 +16,7 @@ import eu.m724.tweaks.ping.PingChecker; import eu.m724.tweaks.ping.PingCommands; import eu.m724.tweaks.pomodoro.PomodoroCommands; import eu.m724.tweaks.pomodoro.PomodoroManager; +import eu.m724.tweaks.sleep.SleepManager; import eu.m724.tweaks.updater.UpdaterManager; import eu.m724.tweaks.worldborder.WorldBorderManager; import org.bukkit.plugin.java.JavaPlugin; @@ -89,6 +90,9 @@ public class TweaksPlugin extends JavaPlugin { new HardcoreManager().init(this); } + if (config.sleepEnabled()) { + new SleepManager().init(this); + } getLogger().info("Took %.3f milliseconds".formatted((System.nanoTime() - start) / 1000000.0)); } diff --git a/src/main/java/eu/m724/tweaks/pomodoro/PlayerPomodoro.java b/src/main/java/eu/m724/tweaks/pomodoro/PlayerPomodoro.java index ba1def0..3aba1be 100644 --- a/src/main/java/eu/m724/tweaks/pomodoro/PlayerPomodoro.java +++ b/src/main/java/eu/m724/tweaks/pomodoro/PlayerPomodoro.java @@ -33,7 +33,7 @@ public class PlayerPomodoro { } public int getCycleDurationSeconds() { - return isBreak ? 300 : 1500; + return isBreak ? (pomodori < 3 ? 300 : 1200) : 1500; } public long getRemainingSeconds(long now) { @@ -66,6 +66,7 @@ public class PlayerPomodoro { public void next() { if (isBreak) { // from break to interval this.pomodori++; + this.pomodori %= 4; } this.intervalStart = System.nanoTime(); diff --git a/src/main/java/eu/m724/tweaks/pomodoro/PomodoroListener.java b/src/main/java/eu/m724/tweaks/pomodoro/PomodoroListener.java index d15cef2..9859e64 100644 --- a/src/main/java/eu/m724/tweaks/pomodoro/PomodoroListener.java +++ b/src/main/java/eu/m724/tweaks/pomodoro/PomodoroListener.java @@ -6,30 +6,35 @@ package eu.m724.tweaks.pomodoro; +import eu.m724.tweaks.TweaksConfig; import net.md_5.bungee.api.chat.ComponentBuilder; import org.bukkit.entity.Player; import org.bukkit.event.EventHandler; import org.bukkit.event.Listener; -import org.bukkit.event.player.PlayerJoinEvent; -import org.bukkit.event.player.PlayerMoveEvent; -import org.bukkit.event.player.PlayerQuitEvent; +import org.bukkit.event.player.*; public class PomodoroListener implements Listener { - @EventHandler - public void onPlayerJoin(PlayerJoinEvent event) { - Player player = event.getPlayer(); - PlayerPomodoro timer = Pomodoros.get(player); - if (timer == null) return; + private final boolean force = TweaksConfig.getConfig().pomodoroForce(); - if (timer.isBreak()) { - if (timer.isCycleComplete()) { - timer.next(); + @EventHandler + public void onPlayerLogin(PlayerLoginEvent event) { + Player player = event.getPlayer(); + PlayerPomodoro pomodoro = Pomodoros.get(player); + if (pomodoro == null) return; + + long remaining = pomodoro.getRemainingSeconds(System.nanoTime()); + + if (pomodoro.isBreak()) { + if (pomodoro.isCycleComplete()) { + pomodoro.next(); } else { - event.getPlayer().kickPlayer( - new ComponentBuilder() - .append(Pomodoros.formatTimer(timer, System.nanoTime())) - .build().toLegacyText() - ); + if (force) { + event.getPlayer().kickPlayer( + new ComponentBuilder() + .append(Pomodoros.formatTimer(pomodoro, remaining)) + .build().toLegacyText() + ); + } } } } @@ -37,11 +42,11 @@ public class PomodoroListener implements Listener { @EventHandler public void onPlayerQuit(PlayerQuitEvent event) { Player player = event.getPlayer(); - PlayerPomodoro timer = Pomodoros.timers.get(player.getUniqueId()); - if (timer == null) return; + PlayerPomodoro pomodoro = Pomodoros.get(player); + if (pomodoro == null) return; - if (!timer.isBreak() && timer.isCycleComplete()) { - timer.next(); + if (!pomodoro.isBreak() && pomodoro.isCycleComplete()) { + pomodoro.next(); } } diff --git a/src/main/java/eu/m724/tweaks/pomodoro/PomodoroManager.java b/src/main/java/eu/m724/tweaks/pomodoro/PomodoroManager.java index 5ec0683..bc1dcaf 100644 --- a/src/main/java/eu/m724/tweaks/pomodoro/PomodoroManager.java +++ b/src/main/java/eu/m724/tweaks/pomodoro/PomodoroManager.java @@ -17,6 +17,6 @@ public class PomodoroManager { public void init() { plugin.getServer().getPluginManager().registerEvents(new PomodoroListener(), plugin); - new PomodoroRunnable().runTaskTimerAsynchronously(plugin, 0, 20L); + new PomodoroRunnable(plugin).runTaskTimerAsynchronously(plugin, 0, 20L); } } diff --git a/src/main/java/eu/m724/tweaks/pomodoro/PomodoroRunnable.java b/src/main/java/eu/m724/tweaks/pomodoro/PomodoroRunnable.java index 1ddfa25..08a170c 100644 --- a/src/main/java/eu/m724/tweaks/pomodoro/PomodoroRunnable.java +++ b/src/main/java/eu/m724/tweaks/pomodoro/PomodoroRunnable.java @@ -6,12 +6,22 @@ package eu.m724.tweaks.pomodoro; +import eu.m724.tweaks.Language; +import eu.m724.tweaks.TweaksConfig; import net.md_5.bungee.api.ChatMessageType; import org.bukkit.Bukkit; import org.bukkit.Sound; +import org.bukkit.plugin.Plugin; import org.bukkit.scheduler.BukkitRunnable; public class PomodoroRunnable extends BukkitRunnable { + private final boolean force = TweaksConfig.getConfig().pomodoroForce(); + private final Plugin plugin; + + public PomodoroRunnable(Plugin plugin) { + this.plugin = plugin; // only used for kicking + } + @Override public void run() { long now = System.nanoTime(); @@ -23,8 +33,14 @@ public class PomodoroRunnable extends BukkitRunnable { // TODO make not always on player.spigot().sendMessage(ChatMessageType.ACTION_BAR, Pomodoros.formatTimer(pomodoro, remaining)); - if (remaining <= 0) + if (remaining <= 0) { player.playSound(player.getLocation(), Sound.BLOCK_ANVIL_FALL, 1.0f, 0.5f); + if (remaining < -60 && force) { + plugin.getServer().getScheduler().scheduleSyncDelayedTask(plugin, () -> { + player.kickPlayer(Language.getString("pomodoroEndKick")); + }); + } + } }); } } diff --git a/src/main/java/eu/m724/tweaks/pomodoro/Pomodoros.java b/src/main/java/eu/m724/tweaks/pomodoro/Pomodoros.java index 55d9967..2fa63e5 100644 --- a/src/main/java/eu/m724/tweaks/pomodoro/Pomodoros.java +++ b/src/main/java/eu/m724/tweaks/pomodoro/Pomodoros.java @@ -6,6 +6,7 @@ package eu.m724.tweaks.pomodoro; +import eu.m724.tweaks.TweaksConfig; import net.md_5.bungee.api.ChatColor; import net.md_5.bungee.api.chat.BaseComponent; import net.md_5.bungee.api.chat.ComponentBuilder; @@ -16,6 +17,8 @@ import java.util.Map; import java.util.UUID; public class Pomodoros { + private static final boolean force = TweaksConfig.getConfig().pomodoroForce(); + static final Map timers = new HashMap<>(); public static PlayerPomodoro get(Player player) { @@ -48,8 +51,14 @@ public class Pomodoros { .append("%02d:%02d".formatted(remaining / 60, remaining % 60)) .color(ChatColor.GRAY); } else { + // TODO I think it's bad to put this here + if (force) { + remaining += 60; + } else { + remaining = 0; + } builder - .append("%02d:%02d".formatted(-remaining / 60, -remaining % 60)) + .append("%02d:%02d".formatted(remaining / 60, remaining % 60)) .color(remaining % 2 == 0 ? ChatColor.RED : ChatColor.YELLOW); } } diff --git a/src/main/java/eu/m724/tweaks/sleep/SleepListener.java b/src/main/java/eu/m724/tweaks/sleep/SleepListener.java new file mode 100644 index 0000000..80f1f67 --- /dev/null +++ b/src/main/java/eu/m724/tweaks/sleep/SleepListener.java @@ -0,0 +1,60 @@ +/* + * Copyright (C) 2024 Minecon724 + * Tweaks724 is licensed under the GNU General Public License. See the LICENSE.md file + * in the project root for the full license text. + */ + +package eu.m724.tweaks.sleep; + +import eu.m724.tweaks.TweaksConfig; +import org.bukkit.GameRule; +import org.bukkit.World; +import org.bukkit.entity.Player; +import org.bukkit.event.EventHandler; +import org.bukkit.event.Listener; +import org.bukkit.event.player.PlayerBedEnterEvent; +import org.bukkit.event.player.PlayerBedLeaveEvent; +import org.bukkit.event.world.TimeSkipEvent; + +import java.util.HashSet; +import java.util.Set; + +public class SleepListener implements Listener { + private final boolean instant = TweaksConfig.getConfig().sleepInstant(); + + private final Set skippedCurrentNight = new HashSet<>(); + private long lastDay = 0; + + @EventHandler + public void onPlayerBedEnter(PlayerBedEnterEvent event) { + if (event.getBedEnterResult() == PlayerBedEnterEvent.BedEnterResult.OK) { + SleepState.playersSleeping++; + + if (instant) { + World world = event.getPlayer().getWorld(); + + long day = world.getFullTime() / 24000; + if (day != lastDay) skippedCurrentNight.clear(); + lastDay = day; + + if (!skippedCurrentNight.contains(event.getPlayer())) { + double onePlayerRatio = 1.0 / (event.getPlayer().getServer().getOnlinePlayers().size() * world.getGameRuleValue(GameRule.PLAYERS_SLEEPING_PERCENTAGE)); + world.setTime((long) ((23459 - world.getTime()) * onePlayerRatio)); + skippedCurrentNight.add(event.getPlayer()); + } + } + } + + } + + @EventHandler + public void onPlayerBedLeave(PlayerBedLeaveEvent event) { + SleepState.playersSleeping--; + } + + @EventHandler + public void onPlayerBedLeave(TimeSkipEvent event) { + if (event.getSkipReason() == TimeSkipEvent.SkipReason.NIGHT_SKIP) + event.setCancelled(true); + } +} diff --git a/src/main/java/eu/m724/tweaks/sleep/SleepManager.java b/src/main/java/eu/m724/tweaks/sleep/SleepManager.java new file mode 100644 index 0000000..2aec5cf --- /dev/null +++ b/src/main/java/eu/m724/tweaks/sleep/SleepManager.java @@ -0,0 +1,18 @@ +/* + * Copyright (C) 2024 Minecon724 + * Tweaks724 is licensed under the GNU General Public License. See the LICENSE.md file + * in the project root for the full license text. + */ + +package eu.m724.tweaks.sleep; + +import eu.m724.tweaks.TweaksConfig; +import org.bukkit.plugin.Plugin; + +public class SleepManager { + public void init(Plugin plugin) { + plugin.getServer().getPluginManager().registerEvents(new SleepListener(), plugin); + if (!TweaksConfig.getConfig().sleepInstant()) + new TimeForwardRunnable(plugin).runTaskTimer(plugin, 0, 1); // TODO maybe not + } +} diff --git a/src/main/java/eu/m724/tweaks/sleep/SleepState.java b/src/main/java/eu/m724/tweaks/sleep/SleepState.java new file mode 100644 index 0000000..f810e9e --- /dev/null +++ b/src/main/java/eu/m724/tweaks/sleep/SleepState.java @@ -0,0 +1,11 @@ +/* + * Copyright (C) 2024 Minecon724 + * Tweaks724 is licensed under the GNU General Public License. See the LICENSE.md file + * in the project root for the full license text. + */ + +package eu.m724.tweaks.sleep; + +public class SleepState { + static int playersSleeping; +} diff --git a/src/main/java/eu/m724/tweaks/sleep/TimeForwardRunnable.java b/src/main/java/eu/m724/tweaks/sleep/TimeForwardRunnable.java new file mode 100644 index 0000000..4b263b9 --- /dev/null +++ b/src/main/java/eu/m724/tweaks/sleep/TimeForwardRunnable.java @@ -0,0 +1,60 @@ +/* + * Copyright (C) 2024 Minecon724 + * Tweaks724 is licensed under the GNU General Public License. See the LICENSE.md file + * in the project root for the full license text. + */ + +package eu.m724.tweaks.sleep; + +import org.bukkit.GameRule; +import org.bukkit.Server; +import org.bukkit.World; +import org.bukkit.plugin.Plugin; +import org.bukkit.scheduler.BukkitRunnable; + +public class TimeForwardRunnable extends BukkitRunnable { + private final Server server; + private final World world; // TODO multi worlds + + private final double percentage; + + public TimeForwardRunnable(Plugin plugin) { + this.server = plugin.getServer(); + this.world = server.getWorld("world"); + this.percentage = world.getGameRuleValue(GameRule.PLAYERS_SLEEPING_PERCENTAGE); + } + + @Override + public void run() { + int playersSleeping = SleepState.playersSleeping; + //System.out.println(playersSleeping); + if (playersSleeping == 0) return; + + int onlinePlayers = (int) (server.getOnlinePlayers().size() / percentage); // TODO optimize remove size every tick maybe + + double sleepPercentage = (double) playersSleeping / onlinePlayers; + + // we want sleep to take 200 ticks which is 10 seconds assuming all palyres onilien + + long time = world.getTime(); + long untilDay = 23459 - time; + + if (untilDay == 0) return; + + long perSkip = 200 + (100000 / -untilDay); + perSkip = Math.clamp(perSkip, 20, 200); + perSkip = (long) (perSkip * sleepPercentage); + + /*long perSkip = (long) (Math.pow(untilDay, 2) / 10000); + perSkip = Math.clamp(perSkip, 5, 200); + perSkip = (long) (perSkip * sleepPercentage);*/ + + + /*System.out.println("asdasd"); + System.out.println(sleepPercentage); + System.out.println(untilDay); + System.out.println(perSkip);*/ + + world.setTime(world.getTime() + perSkip); + } +} diff --git a/src/main/java/eu/m724/tweaks/updater/UpdateChecker.java b/src/main/java/eu/m724/tweaks/updater/UpdateChecker.java index 5b2e958..02b07d5 100644 --- a/src/main/java/eu/m724/tweaks/updater/UpdateChecker.java +++ b/src/main/java/eu/m724/tweaks/updater/UpdateChecker.java @@ -69,7 +69,7 @@ public class UpdateChecker extends BukkitRunnable { private void alert() { int n = availableUpdates.size(); if (n == 0) return; - logger.info(Language.getString("updateAvailableNotice")); + logger.info(Language.getString("updateAvailableNotice").formatted(n)); availableUpdates.stream() .map(u -> "- %s (%s -> %s)".formatted(u.resource().name(), u.running().label(), u.latest().label())) diff --git a/src/main/resources/config.yml b/src/main/resources/config.yml index 294ac09..0b21b90 100644 --- a/src/main/resources/config.yml +++ b/src/main/resources/config.yml @@ -63,6 +63,19 @@ hardcore: # 0.0 - 1.0 decimal. This is if you want to make it like an Easter egg chance: 1.0 +# Makes sleeping +# And adds a nice animation +sleep: + enabled: true + # This gives every player a "share" of the night + # They can instantly skip it by sleeping + # For example, if 5 players online and night is 5 minutes, one can go to sleep and skip 1 minute of the night + # Leaving the bed and reentering it does nothing + instant: false + # Percentage: playersSleepingPercentage gamerule + # If instant: how much % of players to skip the night + # If not: how much % make skipping full speed + # Finally, thank you for downloading Tweaks724, I hope you enjoy! # Don't modify unless told to diff --git a/src/main/resources/strings.properties b/src/main/resources/strings.properties index 90b830d..91462d8 100644 --- a/src/main/resources/strings.properties +++ b/src/main/resources/strings.properties @@ -4,4 +4,5 @@ # in the project root for the full license text. # -updateAvailableNotice = Available updates (%d): \ No newline at end of file +updateAvailableNotice = Available updates (%d): +pomodoroEndKick = Break time! Come back in 5 minutes. \ No newline at end of file