commit c411e35ea2a088fd0d3e77d5ec391ef8e45810cf Author: Xelara Networks Date: Tue Jun 9 16:22:22 2026 -0400 first commit diff --git a/README.md b/README.md new file mode 100644 index 0000000..e69de29 diff --git a/pom.xml b/pom.xml new file mode 100644 index 0000000..a0aea61 --- /dev/null +++ b/pom.xml @@ -0,0 +1,47 @@ + + 4.0.0 + + com.bitnix + DirtSleep + 1.0-SNAPSHOT + jar + + DirtSleep + Simple sleep vote / night speedup plugin for Paper + + + UTF-8 + 21 + + + + + papermc-repo + https://repo.papermc.io/repository/maven-public/ + + + + + + io.papermc.paper + paper-api + 1.21.1-R0.1-SNAPSHOT + provided + + + + + DirtSleep + + + maven-compiler-plugin + 3.13.0 + + 21 + + + + + diff --git a/src/main/java/com/bitnix/dirtsleep/DirtSleepPlugin.java b/src/main/java/com/bitnix/dirtsleep/DirtSleepPlugin.java new file mode 100644 index 0000000..972bebb --- /dev/null +++ b/src/main/java/com/bitnix/dirtsleep/DirtSleepPlugin.java @@ -0,0 +1,225 @@ +package com.bitnix.dirtsleep; + +import org.bukkit.Bukkit; +import org.bukkit.ChatColor; +import org.bukkit.GameMode; +import org.bukkit.World; +import org.bukkit.command.Command; +import org.bukkit.command.CommandSender; +import org.bukkit.command.TabExecutor; +import org.bukkit.entity.Player; +import org.bukkit.plugin.java.JavaPlugin; + +import java.util.*; +import java.util.stream.Collectors; + +public final class DirtSleepPlugin extends JavaPlugin implements TabExecutor { + + private final Map> worldVotes = new HashMap<>(); + + @Override + public void onEnable() { + saveDefaultConfig(); + + Objects.requireNonNull(getCommand("voteday")).setExecutor(this); + Objects.requireNonNull(getCommand("voteday")).setTabCompleter(this); + + Objects.requireNonNull(getCommand("dirtsleep")).setExecutor(this); + Objects.requireNonNull(getCommand("dirtsleep")).setTabCompleter(this); + } + + @Override + public void onDisable() { + worldVotes.clear(); + } + + @Override + public boolean onCommand(CommandSender sender, Command command, String label, String[] args) { + if (command.getName().equalsIgnoreCase("voteday")) { + if (!(sender instanceof Player player)) { + sender.sendMessage(color("&cOnly players can use /voteday.")); + return true; + } + + handleVoteDay(player); + return true; + } + + if (command.getName().equalsIgnoreCase("dirtsleep")) { + if (args.length == 1 && args[0].equalsIgnoreCase("reload")) { + if (!sender.hasPermission("dirtsleep.admin")) { + sender.sendMessage(message("messages.no-permission")); + return true; + } + + reloadConfig(); + worldVotes.clear(); + sender.sendMessage(message("messages.reloaded")); + return true; + } + + sender.sendMessage(message("messages.usage")); + return true; + } + + return false; + } + + private void handleVoteDay(Player player) { + if (!getConfig().getBoolean("vote-day.enabled", true)) { + player.sendMessage(message("messages.disabled")); + return; + } + + World world = player.getWorld(); + + if (!isWorldEnabled(world)) { + player.sendMessage(message("messages.world-disabled")); + return; + } + + if (!canVoteInWorld(world)) { + player.sendMessage(message("messages.not-night")); + clearVotes(world); + return; + } + + String worldKey = world.getName().toLowerCase(Locale.ROOT); + Set votes = worldVotes.computeIfAbsent(worldKey, k -> new HashSet<>()); + + if (votes.contains(player.getUniqueId())) { + player.sendMessage(message("messages.already-voted")); + return; + } + + votes.add(player.getUniqueId()); + + int currentVotes = countValidVotes(world, votes); + int requiredVotes = getRequiredVotes(world); + + String voteMessage = message("messages.vote-added") + .replace("%player%", player.getName()) + .replace("%votes%", String.valueOf(currentVotes)) + .replace("%required%", String.valueOf(requiredVotes)) + .replace("%remaining%", String.valueOf(Math.max(0, requiredVotes - currentVotes))); + + broadcast(world, voteMessage); + + if (currentVotes >= requiredVotes) { + makeDay(world); + clearVotes(world); + broadcast(world, message("messages.vote-passed")); + } + } + + private void makeDay(World world) { + world.setTime(1000); + world.setStorm(false); + world.setThundering(false); + } + + private void clearVotes(World world) { + worldVotes.remove(world.getName().toLowerCase(Locale.ROOT)); + } + + private int countValidVotes(World world, Set votes) { + votes.removeIf(uuid -> { + Player p = Bukkit.getPlayer(uuid); + return p == null || !p.isOnline() || !p.getWorld().equals(world); + }); + return votes.size(); + } + + private boolean isWorldEnabled(World world) { + List worlds = getConfig().getStringList("vote-day.worlds"); + return worlds.isEmpty() || worlds.contains(world.getName()); + } + + private boolean canVoteInWorld(World world) { + if (world.getEnvironment() != World.Environment.NORMAL) { + return false; + } + + if (!getConfig().getBoolean("vote-day.only-during-night", true)) { + return true; + } + + long time = world.getTime(); + int nightStartsAt = getConfig().getInt("vote-day.night-starts-at", 12542); + return time >= nightStartsAt && time < 24000; + } + + private int getRequiredVotes(World world) { + int eligible = 0; + boolean excludeBypass = getConfig().getBoolean("vote-day.exclude-bypass", true); + + for (Player player : world.getPlayers()) { + if (player.getGameMode() == GameMode.SPECTATOR) { + continue; + } + + if (excludeBypass && player.hasPermission("dirtsleep.bypass")) { + continue; + } + + eligible++; + } + + if (eligible <= 0) { + return 1; + } + + String raw = getConfig().getString("vote-day.required-votes", "50%"); + if (raw == null) { + return 1; + } + + raw = raw.trim(); + + if (raw.endsWith("%")) { + String percentText = raw.substring(0, raw.length() - 1).trim(); + try { + double percent = Double.parseDouble(percentText); + int required = (int) Math.ceil(eligible * (percent / 100.0)); + return Math.max(1, required); + } catch (NumberFormatException ignored) { + return 1; + } + } + + try { + return Math.max(1, Integer.parseInt(raw)); + } catch (NumberFormatException ignored) { + return 1; + } + } + + private void broadcast(World world, String message) { + for (Player player : world.getPlayers()) { + player.sendMessage(message); + } + } + + private String message(String path) { + String prefix = color(getConfig().getString("messages.prefix", "&8[&bDirtSleep&8] &7")); + String text = getConfig().getString(path, ""); + return color(text.replace("%prefix%", prefix)); + } + + private String color(String text) { + return ChatColor.translateAlternateColorCodes('&', text == null ? "" : text); + } + + @Override + public List onTabComplete(CommandSender sender, Command command, String alias, String[] args) { + if (command.getName().equalsIgnoreCase("dirtsleep")) { + if (args.length == 1) { + return Arrays.asList("reload").stream() + .filter(s -> s.toLowerCase(Locale.ROOT).startsWith(args[0].toLowerCase(Locale.ROOT))) + .collect(Collectors.toList()); + } + } + + return Collections.emptyList(); + } +} diff --git a/src/main/resources/config.yml b/src/main/resources/config.yml new file mode 100644 index 0000000..1b0313f --- /dev/null +++ b/src/main/resources/config.yml @@ -0,0 +1,31 @@ +vote-day: + enabled: true + + # Empty list = all worlds + worlds: [] + + # Only allow /voteday during night + only-during-night: true + + # Tick time where night starts + night-starts-at: 12542 + + # Required votes before changing to day + # Examples: "1", "2", "50%", "75%" + required-votes: "50%" + + # Ignore players with this permission from vote requirement: + # dirtsleep.bypass + exclude-bypass: true + +messages: + prefix: "&8[&bDirtSleep&8] &7" + vote-added: "%prefix%&e%player% &7voted for day. &f(%votes%/%required% votes, %remaining% remaining)" + vote-passed: "%prefix%&aVote passed! Skipping to day." + already-voted: "%prefix%&cYou already voted." + not-night: "%prefix%&cYou can only use this at night." + disabled: "%prefix%&cVote day is disabled." + world-disabled: "%prefix%&cVote day is disabled in this world." + reloaded: "%prefix%&aConfig reloaded." + no-permission: "%prefix%&cYou do not have permission." + usage: "%prefix%&7Use: &f/dirtsleep reload" diff --git a/src/main/resources/plugin.yml b/src/main/resources/plugin.yml new file mode 100644 index 0000000..3968048 --- /dev/null +++ b/src/main/resources/plugin.yml @@ -0,0 +1,21 @@ +name: DirtSleep +version: 1.0 +main: com.bitnix.dirtsleep.DirtSleepPlugin +api-version: '1.21' +author: bitnix +description: Simple vote day plugin +commands: + voteday: + description: Vote to make it day + usage: /voteday + dirtsleep: + description: DirtSleep admin command + usage: /dirtsleep reload + permission: dirtsleep.admin +permissions: + dirtsleep.admin: + description: Allows reloading DirtSleep + default: op + dirtsleep.bypass: + description: Excludes player from required vote calculations + default: false diff --git a/target/DirtSleep.jar b/target/DirtSleep.jar new file mode 100644 index 0000000..91bcab9 Binary files /dev/null and b/target/DirtSleep.jar differ diff --git a/target/classes/com/bitnix/dirtsleep/DirtSleepPlugin.class b/target/classes/com/bitnix/dirtsleep/DirtSleepPlugin.class new file mode 100644 index 0000000..a3ba49f Binary files /dev/null and b/target/classes/com/bitnix/dirtsleep/DirtSleepPlugin.class differ diff --git a/target/classes/config.yml b/target/classes/config.yml new file mode 100644 index 0000000..1b0313f --- /dev/null +++ b/target/classes/config.yml @@ -0,0 +1,31 @@ +vote-day: + enabled: true + + # Empty list = all worlds + worlds: [] + + # Only allow /voteday during night + only-during-night: true + + # Tick time where night starts + night-starts-at: 12542 + + # Required votes before changing to day + # Examples: "1", "2", "50%", "75%" + required-votes: "50%" + + # Ignore players with this permission from vote requirement: + # dirtsleep.bypass + exclude-bypass: true + +messages: + prefix: "&8[&bDirtSleep&8] &7" + vote-added: "%prefix%&e%player% &7voted for day. &f(%votes%/%required% votes, %remaining% remaining)" + vote-passed: "%prefix%&aVote passed! Skipping to day." + already-voted: "%prefix%&cYou already voted." + not-night: "%prefix%&cYou can only use this at night." + disabled: "%prefix%&cVote day is disabled." + world-disabled: "%prefix%&cVote day is disabled in this world." + reloaded: "%prefix%&aConfig reloaded." + no-permission: "%prefix%&cYou do not have permission." + usage: "%prefix%&7Use: &f/dirtsleep reload" diff --git a/target/classes/plugin.yml b/target/classes/plugin.yml new file mode 100644 index 0000000..3968048 --- /dev/null +++ b/target/classes/plugin.yml @@ -0,0 +1,21 @@ +name: DirtSleep +version: 1.0 +main: com.bitnix.dirtsleep.DirtSleepPlugin +api-version: '1.21' +author: bitnix +description: Simple vote day plugin +commands: + voteday: + description: Vote to make it day + usage: /voteday + dirtsleep: + description: DirtSleep admin command + usage: /dirtsleep reload + permission: dirtsleep.admin +permissions: + dirtsleep.admin: + description: Allows reloading DirtSleep + default: op + dirtsleep.bypass: + description: Excludes player from required vote calculations + default: false diff --git a/target/maven-archiver/pom.properties b/target/maven-archiver/pom.properties new file mode 100644 index 0000000..abcd92c --- /dev/null +++ b/target/maven-archiver/pom.properties @@ -0,0 +1,5 @@ +#Generated by Maven +#Tue Jun 09 16:14:06 EDT 2026 +artifactId=DirtSleep +groupId=com.bitnix +version=1.0-SNAPSHOT diff --git a/target/maven-status/maven-compiler-plugin/compile/default-compile/createdFiles.lst b/target/maven-status/maven-compiler-plugin/compile/default-compile/createdFiles.lst new file mode 100644 index 0000000..52b0b9a --- /dev/null +++ b/target/maven-status/maven-compiler-plugin/compile/default-compile/createdFiles.lst @@ -0,0 +1 @@ +com/bitnix/dirtsleep/DirtSleepPlugin.class diff --git a/target/maven-status/maven-compiler-plugin/compile/default-compile/inputFiles.lst b/target/maven-status/maven-compiler-plugin/compile/default-compile/inputFiles.lst new file mode 100644 index 0000000..3dca2aa --- /dev/null +++ b/target/maven-status/maven-compiler-plugin/compile/default-compile/inputFiles.lst @@ -0,0 +1 @@ +/home/bitnix/Desktop/DirtSleep/src/main/java/com/bitnix/dirtsleep/DirtSleepPlugin.java