Signed-off-by: Minecon724 <minecon724@noreply.git.m724.eu>
This commit is contained in:
parent
a8e67dbe26
commit
e3f34ec46f
8 changed files with 244 additions and 158 deletions
|
@ -6,70 +6,77 @@
|
|||
|
||||
package eu.m724.tweaks.module.pomodoro;
|
||||
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
public class PlayerPomodoro {
|
||||
private int pomodori = 0;
|
||||
private int intervalsDone = 0;
|
||||
|
||||
private boolean isBreak = false;
|
||||
// this is for both break and not break
|
||||
private long intervalStart = -1;
|
||||
private boolean breaktime = false;
|
||||
private long currentIntervalStartedAtNanos = -1;
|
||||
|
||||
/**
|
||||
* A "pomodoro" is the 25-minute cycle you take breaks after<br>
|
||||
* This returns how many cycles already elapsed, so if this is the first cycle this is 0<br>
|
||||
* The break after the "pomodoro," so if it's breaktime after the first "pomodoro" it stays at 0
|
||||
*/
|
||||
public int getPomodori() {
|
||||
return pomodori;
|
||||
public int getIntervalsDone() {
|
||||
return intervalsDone;
|
||||
}
|
||||
|
||||
public boolean isBreaktime() {
|
||||
return breaktime;
|
||||
}
|
||||
|
||||
public boolean isLongBreak() {
|
||||
return (intervalsDone + 1) % PomodoroModule.INTERVALS_BEFORE_LONG_BREAK == 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* When did the current interval start<br>
|
||||
* Or when did the break start
|
||||
*
|
||||
* @see PlayerPomodoro#isBreak()
|
||||
* @return The time the current interval or break started, in milliseconds
|
||||
*/
|
||||
public long getIntervalStart() {
|
||||
return intervalStart;
|
||||
public long getCurrentIntervalStartedAtNanos() {
|
||||
return currentIntervalStartedAtNanos;
|
||||
}
|
||||
|
||||
public int getCycleDurationSeconds() {
|
||||
return isBreak ? (pomodori < 3 ? 300 : 1200) : 1500;
|
||||
public int getCurrentIntervalDurationSeconds() {
|
||||
if (breaktime) {
|
||||
if (isLongBreak()) {
|
||||
return PomodoroModule.LONG_BREAK_DURATION_SECONDS;
|
||||
}
|
||||
|
||||
return PomodoroModule.SHORT_BREAK_DURATION_SECONDS;
|
||||
} else {
|
||||
return PomodoroModule.INTERVAL_DURATION_SECONDS;
|
||||
}
|
||||
}
|
||||
|
||||
public long getRemainingSeconds(long now) {
|
||||
return getCycleDurationSeconds() - (now - getIntervalStart()) / 1000000000;
|
||||
public long getCurrentIntervalDurationNanos() {
|
||||
return TimeUnit.SECONDS.toNanos(getCurrentIntervalDurationSeconds());
|
||||
}
|
||||
|
||||
/**
|
||||
* Is it a break currently
|
||||
*/
|
||||
public boolean isBreak() {
|
||||
return isBreak;
|
||||
public long getCurrentIntervalRemainingNanos(long nowNanos) {
|
||||
long elapsed = nowNanos - getCurrentIntervalStartedAtNanos();
|
||||
return getCurrentIntervalDurationNanos() - elapsed;
|
||||
}
|
||||
|
||||
public boolean isCycleComplete() {
|
||||
return intervalStart + getCycleDurationSeconds() * 1000000000L < System.nanoTime();
|
||||
public boolean isIntervalComplete(long nowNanos) {
|
||||
return currentIntervalStartedAtNanos + getCurrentIntervalDurationNanos() < nowNanos;
|
||||
}
|
||||
|
||||
/**
|
||||
* Resets and starts the timer
|
||||
*/
|
||||
public void start() {
|
||||
this.pomodori = 0;
|
||||
this.isBreak = false;
|
||||
this.intervalStart = System.nanoTime();
|
||||
this.intervalsDone = 0;
|
||||
this.breaktime = false;
|
||||
this.currentIntervalStartedAtNanos = System.nanoTime();
|
||||
}
|
||||
|
||||
/**
|
||||
* Completes a cycle
|
||||
*/
|
||||
public void next() {
|
||||
if (isBreak) { // from break to interval
|
||||
this.pomodori++;
|
||||
this.pomodori %= 4;
|
||||
public void startBreakOrNextInterval() {
|
||||
if (breaktime) { // from break to interval
|
||||
this.intervalsDone++;
|
||||
this.intervalsDone %= PomodoroModule.INTERVALS_BEFORE_LONG_BREAK;
|
||||
}
|
||||
|
||||
this.intervalStart = System.nanoTime();
|
||||
isBreak = !isBreak;
|
||||
this.currentIntervalStartedAtNanos = System.nanoTime();
|
||||
breaktime = !breaktime;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,29 @@
|
|||
/*
|
||||
* Copyright (C) 2025 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.module.pomodoro;
|
||||
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.UUID;
|
||||
|
||||
public class PlayerPomodoroTracker {
|
||||
static final Map<UUID, PlayerPomodoro> timers = new HashMap<>();
|
||||
|
||||
public static PlayerPomodoro get(Player player) {
|
||||
return timers.get(player.getUniqueId());
|
||||
}
|
||||
|
||||
public static PlayerPomodoro create(Player player) {
|
||||
return timers.computeIfAbsent(player.getUniqueId(), (k) -> new PlayerPomodoro());
|
||||
}
|
||||
|
||||
public static boolean remove(Player player) {
|
||||
return timers.remove(player.getUniqueId()) != null;
|
||||
}
|
||||
}
|
|
@ -6,6 +6,9 @@
|
|||
|
||||
package eu.m724.tweaks.module.pomodoro;
|
||||
|
||||
import eu.m724.tweaks.Language;
|
||||
import eu.m724.tweaks.config.TweaksConfig;
|
||||
import net.md_5.bungee.api.ChatColor;
|
||||
import org.bukkit.command.Command;
|
||||
import org.bukkit.command.CommandExecutor;
|
||||
import org.bukkit.command.CommandSender;
|
||||
|
@ -18,25 +21,34 @@ public class PomodoroCommands implements CommandExecutor {
|
|||
Player player = (Player) sender;
|
||||
String action = args.length > 0 ? args[0] : null;
|
||||
|
||||
PlayerPomodoro pomodoro = Pomodoros.get(player);
|
||||
PlayerPomodoro pomodoro = PlayerPomodoroTracker.get(player);
|
||||
|
||||
long now = System.nanoTime();
|
||||
|
||||
if (pomodoro != null) {
|
||||
if ("stop".equals(action)) {
|
||||
Pomodoros.remove(player);
|
||||
sender.sendMessage("Pomodoro disabled");
|
||||
PlayerPomodoroTracker.remove(player);
|
||||
sender.spigot().sendMessage(Language.getComponent("pomodoroStopped", ChatColor.GREEN, label));
|
||||
} else {
|
||||
if (pomodoro.isCycleComplete()) {
|
||||
pomodoro.next();
|
||||
if (pomodoro.isIntervalComplete(now)) {
|
||||
pomodoro.startBreakOrNextInterval();
|
||||
|
||||
if (pomodoro.isBreaktime() && TweaksConfig.getConfig().pomodoroForce()) {
|
||||
player.kickPlayer(PomodoroModule.formatTimer(pomodoro, now).toLegacyText());
|
||||
}
|
||||
}
|
||||
sender.spigot().sendMessage(Pomodoros.formatTimer(pomodoro, pomodoro.getRemainingSeconds(System.nanoTime())));
|
||||
|
||||
sender.spigot().sendMessage(PomodoroModule.formatTimer(pomodoro, now));
|
||||
}
|
||||
} else {
|
||||
if ("start".equals(action)) {
|
||||
pomodoro = Pomodoros.create(player);
|
||||
pomodoro = PlayerPomodoroTracker.create(player);
|
||||
pomodoro.start();
|
||||
sender.spigot().sendMessage(Pomodoros.formatTimer(pomodoro, pomodoro.getCycleDurationSeconds()));
|
||||
|
||||
sender.spigot().sendMessage(PomodoroModule.formatTimer(pomodoro, now));
|
||||
} else {
|
||||
sender.sendMessage("Start pomodoro with /pom start");
|
||||
// TODO help?
|
||||
sender.spigot().sendMessage(Language.getComponent("pomodoroStart", ChatColor.GOLD, label));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -7,56 +7,68 @@
|
|||
package eu.m724.tweaks.module.pomodoro;
|
||||
|
||||
import eu.m724.tweaks.config.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.*;
|
||||
import org.bukkit.event.player.PlayerLoginEvent;
|
||||
import org.bukkit.event.player.PlayerQuitEvent;
|
||||
import org.bukkit.event.player.PlayerToggleSneakEvent;
|
||||
|
||||
public class PomodoroListener implements Listener {
|
||||
private final boolean force = TweaksConfig.getConfig().pomodoroForce();
|
||||
private final TweaksConfig config = TweaksConfig.getConfig();
|
||||
|
||||
@EventHandler
|
||||
public void onPlayerLogin(PlayerLoginEvent event) {
|
||||
// Joining ends break
|
||||
Player player = event.getPlayer();
|
||||
PlayerPomodoro pomodoro = Pomodoros.get(player);
|
||||
PlayerPomodoro pomodoro = PlayerPomodoroTracker.get(player);
|
||||
if (pomodoro == null) return;
|
||||
|
||||
long remaining = pomodoro.getRemainingSeconds(System.nanoTime());
|
||||
long now = System.nanoTime();
|
||||
long remaining = pomodoro.getCurrentIntervalRemainingNanos(now);
|
||||
|
||||
if (pomodoro.isBreak()) {
|
||||
if (pomodoro.isCycleComplete()) {
|
||||
pomodoro.next();
|
||||
if (pomodoro.isBreaktime()) {
|
||||
if (remaining > 0 && config.pomodoroForce()) {
|
||||
player.kickPlayer(PomodoroModule.formatTimer(pomodoro, now).toLegacyText());
|
||||
} else {
|
||||
if (force) {
|
||||
event.getPlayer().kickPlayer(
|
||||
new ComponentBuilder()
|
||||
.append(Pomodoros.formatTimer(pomodoro, remaining))
|
||||
.build().toLegacyText()
|
||||
);
|
||||
}
|
||||
pomodoro.startBreakOrNextInterval();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@EventHandler
|
||||
public void onPlayerQuit(PlayerQuitEvent event) {
|
||||
// Quitting starts break
|
||||
Player player = event.getPlayer();
|
||||
PlayerPomodoro pomodoro = Pomodoros.get(player);
|
||||
PlayerPomodoro pomodoro = PlayerPomodoroTracker.get(player);
|
||||
if (pomodoro == null) return;
|
||||
|
||||
if (!pomodoro.isBreak() && pomodoro.isCycleComplete()) {
|
||||
pomodoro.next();
|
||||
if (pomodoro.isBreaktime()) return;
|
||||
|
||||
long now = System.nanoTime();
|
||||
long remaining = pomodoro.getCurrentIntervalRemainingNanos(now);
|
||||
|
||||
if (remaining <= 0) {
|
||||
pomodoro.startBreakOrNextInterval();
|
||||
}
|
||||
}
|
||||
|
||||
@EventHandler
|
||||
public void onPlayerMove(PlayerMoveEvent event) {
|
||||
Player player = event.getPlayer();
|
||||
PlayerPomodoro timer = Pomodoros.get(player);
|
||||
if (timer == null) return;
|
||||
public void onPlayerToggleSneak(PlayerToggleSneakEvent event) {
|
||||
// Sneaking ends break
|
||||
if (!event.isSneaking()) return;
|
||||
|
||||
if (timer.isBreak() && timer.getRemainingSeconds(System.nanoTime()) <= 0)
|
||||
timer.next(); // resume timer if break ended
|
||||
Player player = event.getPlayer();
|
||||
PlayerPomodoro pomodoro = PlayerPomodoroTracker.get(player);
|
||||
if (pomodoro == null) return;
|
||||
|
||||
if (!pomodoro.isBreaktime()) return;
|
||||
|
||||
long now = System.nanoTime();
|
||||
long remaining = pomodoro.getCurrentIntervalRemainingNanos(now);
|
||||
|
||||
if (remaining <= 0) {
|
||||
pomodoro.startBreakOrNextInterval();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -6,9 +6,23 @@
|
|||
|
||||
package eu.m724.tweaks.module.pomodoro;
|
||||
|
||||
import eu.m724.tweaks.Language;
|
||||
import eu.m724.tweaks.config.TweaksConfig;
|
||||
import eu.m724.tweaks.module.TweaksModule;
|
||||
import net.md_5.bungee.api.ChatColor;
|
||||
import net.md_5.bungee.api.chat.BaseComponent;
|
||||
import net.md_5.bungee.api.chat.ComponentBuilder;
|
||||
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
public class PomodoroModule extends TweaksModule {
|
||||
static final int INTERVAL_DURATION_SECONDS = 10;
|
||||
static final int SHORT_BREAK_DURATION_SECONDS = (int) TimeUnit.MINUTES.toSeconds(5);
|
||||
static final int LONG_BREAK_DURATION_SECONDS = (int) TimeUnit.MINUTES.toSeconds(20);
|
||||
static final int INTERVALS_BEFORE_LONG_BREAK = 4;
|
||||
|
||||
static final int KICK_DELAY_SECONDS = 60;
|
||||
|
||||
@Override
|
||||
protected void onInit() {
|
||||
registerEvents(new PomodoroListener());
|
||||
|
@ -16,4 +30,66 @@ public class PomodoroModule extends TweaksModule {
|
|||
|
||||
registerCommand("pomodoro", new PomodoroCommands());
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a formatted timer for a player.
|
||||
*
|
||||
* @param pomodoro the player's {@link PlayerPomodoro} instance
|
||||
* @param nowNanos unix now timestamp in nanoseconds
|
||||
* @return the timer as {@link BaseComponent}
|
||||
*/
|
||||
static BaseComponent formatTimer(PlayerPomodoro pomodoro, long nowNanos) {
|
||||
ComponentBuilder builder = new ComponentBuilder();
|
||||
|
||||
long remainingNanos = pomodoro.getCurrentIntervalRemainingNanos(nowNanos);
|
||||
long remainingSeconds = TimeUnit.NANOSECONDS.toSeconds(remainingNanos);
|
||||
|
||||
if (pomodoro.isBreaktime()) {
|
||||
if (pomodoro.isLongBreak()) {
|
||||
builder.append(Language.getComponent("pomodoroLongBreak", ChatColor.LIGHT_PURPLE));
|
||||
} else {
|
||||
builder.append(Language.getComponent("pomodoroShortBreak", ChatColor.LIGHT_PURPLE));
|
||||
}
|
||||
|
||||
if (remainingNanos > 0) {
|
||||
builder.append(" %02d:%02d".formatted(remainingSeconds / 60, remainingSeconds % 60))
|
||||
.color(ChatColor.GOLD);
|
||||
} else {
|
||||
builder.append(" 00:00")
|
||||
.color(ChatColor.GREEN);
|
||||
|
||||
if (!TweaksConfig.getConfig().pomodoroForce()) {
|
||||
builder.append( "/pom").color(ChatColor.GOLD);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (remainingNanos > 0) {
|
||||
builder
|
||||
.append("%02d:%02d".formatted(remainingSeconds / 60, remainingSeconds % 60))
|
||||
.color(ChatColor.GRAY);
|
||||
} else {
|
||||
builder
|
||||
.append("00:00")
|
||||
.color(remainingSeconds % 2 == 0 ? ChatColor.RED : ChatColor.GRAY);
|
||||
|
||||
if (!TweaksConfig.getConfig().pomodoroForce()) {
|
||||
builder.append( "/pom").color(ChatColor.GOLD);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
for (int i=0; i<INTERVALS_BEFORE_LONG_BREAK; i++) {
|
||||
ChatColor color = ChatColor.GRAY;
|
||||
if (i == pomodoro.getIntervalsDone()) {
|
||||
color = ChatColor.LIGHT_PURPLE;
|
||||
} else if (i > pomodoro.getIntervalsDone()) {
|
||||
color = ChatColor.DARK_GRAY;
|
||||
}
|
||||
|
||||
builder.append(" o").color(color);
|
||||
}
|
||||
|
||||
return builder.build();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -9,34 +9,49 @@ package eu.m724.tweaks.module.pomodoro;
|
|||
import eu.m724.tweaks.TweaksPlugin;
|
||||
import eu.m724.tweaks.config.TweaksConfig;
|
||||
import net.md_5.bungee.api.ChatMessageType;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.Sound;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.plugin.Plugin;
|
||||
import org.bukkit.scheduler.BukkitRunnable;
|
||||
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
public class PomodoroRunnable extends BukkitRunnable {
|
||||
private final boolean force = TweaksConfig.getConfig().pomodoroForce();
|
||||
private final TweaksConfig config = TweaksConfig.getConfig();
|
||||
private final Plugin plugin = TweaksPlugin.getInstance(); // used only to kick
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
long now = System.nanoTime();
|
||||
|
||||
Bukkit.getOnlinePlayers().forEach(player -> {
|
||||
PlayerPomodoro pomodoro = Pomodoros.get(player);
|
||||
if (pomodoro == null) return;
|
||||
PlayerPomodoroTracker.timers.forEach((uuid, pomodoro) -> {
|
||||
long remainingNanos = pomodoro.getCurrentIntervalRemainingNanos(now);
|
||||
long remainingSecs = TimeUnit.NANOSECONDS.toSeconds(remainingNanos);
|
||||
|
||||
long remaining = pomodoro.getRemainingSeconds(now);
|
||||
// TODO make not always on
|
||||
player.spigot().sendMessage(ChatMessageType.ACTION_BAR, Pomodoros.formatTimer(pomodoro, remaining));
|
||||
// TODO optimize?
|
||||
Player player = plugin.getServer().getPlayer(uuid);
|
||||
|
||||
if (remaining <= 0) {
|
||||
player.playSound(player.getLocation(), Sound.BLOCK_ANVIL_FALL, 1.0f, 0.5f);
|
||||
if (remaining < -60 && force) {
|
||||
plugin.getServer().getScheduler().scheduleSyncDelayedTask(plugin, () -> {
|
||||
pomodoro.next();
|
||||
player.kickPlayer(Pomodoros.formatTimer(pomodoro, pomodoro.getRemainingSeconds(now)).toLegacyText());
|
||||
});
|
||||
if (player != null && player.isOnline()) {
|
||||
// TODO make not always on
|
||||
player.spigot().sendMessage(ChatMessageType.ACTION_BAR, PomodoroModule.formatTimer(pomodoro, now));
|
||||
|
||||
if (remainingNanos <= 0) {
|
||||
player.playSound(player.getLocation(), Sound.BLOCK_ANVIL_FALL, 1.0f, 0.5f);
|
||||
|
||||
if (remainingSecs < -PomodoroModule.KICK_DELAY_SECONDS && config.pomodoroForce()) {
|
||||
pomodoro.startBreakOrNextInterval();
|
||||
|
||||
plugin.getServer().getScheduler().scheduleSyncDelayedTask(plugin, () ->
|
||||
player.kickPlayer(PomodoroModule.formatTimer(pomodoro, now).toLegacyText())
|
||||
);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (remainingNanos <= 0) {
|
||||
// Start break automatically if the player is offline
|
||||
if (!pomodoro.isBreaktime()) {
|
||||
pomodoro.startBreakOrNextInterval();
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
|
|
@ -1,71 +0,0 @@
|
|||
/*
|
||||
* Copyright (C) 2025 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.module.pomodoro;
|
||||
|
||||
import net.md_5.bungee.api.ChatColor;
|
||||
import net.md_5.bungee.api.chat.BaseComponent;
|
||||
import net.md_5.bungee.api.chat.ComponentBuilder;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.UUID;
|
||||
|
||||
public class Pomodoros {
|
||||
static final Map<UUID, PlayerPomodoro> timers = new HashMap<>();
|
||||
|
||||
public static PlayerPomodoro get(Player player) {
|
||||
return timers.get(player.getUniqueId());
|
||||
}
|
||||
|
||||
public static PlayerPomodoro create(Player player) {
|
||||
return timers.computeIfAbsent(player.getUniqueId(), (k) -> new PlayerPomodoro());
|
||||
}
|
||||
|
||||
public static boolean remove(Player player) {
|
||||
return timers.remove(player.getUniqueId()) != null;
|
||||
}
|
||||
|
||||
static BaseComponent formatTimer(PlayerPomodoro pomodoro, long remaining) {
|
||||
ComponentBuilder builder = new ComponentBuilder();
|
||||
|
||||
if (pomodoro.isBreak()) {
|
||||
builder.append("Break ").color(ChatColor.LIGHT_PURPLE);
|
||||
if (remaining > 0) {
|
||||
builder.append("%02d:%02d".formatted(remaining / 60, remaining % 60))
|
||||
.color(ChatColor.GOLD);
|
||||
} else {
|
||||
builder.append("00:00")
|
||||
.color(ChatColor.GREEN);
|
||||
}
|
||||
} else {
|
||||
if (remaining > 0) {
|
||||
builder
|
||||
.append("%02d:%02d".formatted(remaining / 60, remaining % 60))
|
||||
.color(ChatColor.GRAY);
|
||||
} else {
|
||||
builder
|
||||
.append("00:00")
|
||||
.color(remaining % 2 == 0 ? ChatColor.RED : ChatColor.YELLOW);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
for (int i=0; i<4; i++) {
|
||||
ChatColor color = ChatColor.GRAY;
|
||||
if (i == pomodoro.getPomodori()) {
|
||||
color = ChatColor.LIGHT_PURPLE;
|
||||
} else if (i > pomodoro.getPomodori()) {
|
||||
color = ChatColor.DARK_GRAY;
|
||||
}
|
||||
|
||||
builder.append(" o").color(color);
|
||||
}
|
||||
|
||||
return builder.build();
|
||||
}
|
||||
}
|
|
@ -30,7 +30,7 @@ chatAlreadyHere = You're already in this room.
|
|||
authKickWrongKey = You're connecting to the wrong server address. You must connect to the one you're registered to.
|
||||
# If force is enabled and player is not registered. Changing this reveals you're using this plugin
|
||||
authKickUnregistered = You are not whitelisted on this server!
|
||||
authKickError = An error occured. Please try again. If this persists, contact an administrator.
|
||||
authKickError = An error occurred. Please try again. If this persists, contact an administrator.
|
||||
|
||||
redstoneGatewayItem = Redstone gateway
|
||||
|
||||
|
@ -44,4 +44,10 @@ durabilityDisabled = Disabled durability alert
|
|||
wordCoordsPlayerOnly = Only players can execute this command without arguments.
|
||||
wordCoordsOutOfRange = Those coordinates are invalid.
|
||||
wordCoordsInvalidWord = Invalid word: "%s"
|
||||
wordCoordsNoWords = Please provide the Z coordinate.
|
||||
wordCoordsNoWords = Please provide the Z coordinate.
|
||||
|
||||
# /pomodoro
|
||||
pomodoroStopped = Pomodoro stopped. Restart it with /%s start
|
||||
pomodoroStart = Start pomodoro with /%s start
|
||||
pomodoroShortBreak = Short break
|
||||
pomodoroLongBreak = Long break
|
Loading…
Add table
Add a link
Reference in a new issue