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