Compare commits

..

3 commits

Author SHA1 Message Date
f534cd4c53
Alert
All checks were successful
/ deploy (push) Successful in 1m18s
2024-12-12 17:09:48 +01:00
d4f10496e9
Remove commented code 2024-12-11 15:51:54 +01:00
64d28128f8
Full 2024-12-11 15:51:43 +01:00
9 changed files with 350 additions and 52 deletions

View file

@ -12,49 +12,53 @@ Please report all suspicious behavior. You can do so on any of those:
Stuff no<sub><sup>t many</sup></sub> other plugins do. Stuff no<sub><sup>t many</sup></sub> other plugins do.
Dependencies: Dependencies:
- **1.21.1** this is mandatory as the plugin uses NMS for some stuff\ - **1.21.1**, mandatory as the plugin uses NMS for some stuff\
The focus is on [a widely used version](https://bstats.org/global/bukkit) that has [good mod support](https://modrinth.com/modpack/fabulously-optimized/versions?c=release) Why not latest? The focus is on [a widely used version](https://bstats.org/global/bukkit) that has [good mod support](https://modrinth.com/modpack/fabulously-optimized/versions?c=release)
- [ProtocolLib](https://www.spigotmc.org/resources/protocollib.1997/) (optional, but you lose a lot) - [ProtocolLib](https://www.spigotmc.org/resources/protocollib.1997/)
# Features # Features
Those with <sup>P</sup> need ProtocolLib
### Expand world border ### Expand world border
Expands the world border to 30,000,000 (from 29,999,984) Expands the world border to 30,000,000 (from 29,999,984)
### Hide world border <sup><sup><sub>P</sub></sup></sup> ### Hide world border
Hides the world border. It's still there, just invisible. Hides the world border. It's still there, just invisible.
### Server brand <sup><sup><sub>P</sub></sup></sup> ### Server brand
Modify the F3 brand, optionally include player's ping and server performance Modify the F3 brand, optionally include player's ping and server performance
### Doors ### Doors
Open two doors with one click. Knock on doors. Open two doors with one click. Knock on doors.
### MOTD <sup><sup><sub>P</sub></sup></sup> ### MOTD
Random MOTD for every ping Random MOTD for every ping
### Chat rooms ### Chat rooms
Chat rooms players can freely create and join. Alerts like death and join messages are only within the player's chat room. Chat rooms players can freely create and join. Alerts like death and join messages are only within the player's chat room.
`/chat` - switch chat room \
`/chatmanage` - create, delete, modify etc. (`tweaks724.chatmanage`)
### Compass ### Compass
Holding a compass shows a bar with 4 directions and stuff like beds, lodestones, death pos (TODO) etc. Holding a compass shows a bar with 4 directions and stuff like beds, lodestones, death pos (TODO) etc.
### Pomodoro ### Pomodoro
Self-discipline with a pomodoro timer that's actually forced Self-discipline with a pomodoro timer that's actually forced
`/pomodoro` (`tweaks724.pomodoro`)
### Updater ### Updater
Updates ALL* your plugins \ Updates ALL* your plugins \
<sub>*Those on SpigotMC and that release updates there</sub> <sub>*Those on SpigotMC and that release updates there</sub>
### Hardcore <sup><sup><sub>P</sub></sup></sup> `/updates` - shows available updates (`tweaks724.updates`)
### Hardcore
Hardcore hearts by chance Hardcore hearts by chance
### Sleep ### Sleep
Sleeping doesn't skip night, but speeds it up. The more players, the faster it goes. Sleeping doesn't skip night, but speeds it up. The more players, the faster it goes.
- Instant sleep \
### Instant sleep
One can instantly skip, but only a part of the night. \ One can instantly skip, but only a part of the night. \
There's 5 players on the server. A night is 10 minutes long. \ 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 Each player can instantly skip 2 minutes of the night at any time, even if others aren't sleeping
@ -63,29 +67,19 @@ Each player can instantly skip 2 minutes of the night at any time, even if other
Players are given a unique subdomain like "\<key>.example.com" and they must use it to join \ Players are given a unique subdomain like "\<key>.example.com" and they must use it to join \
It can be enabled that new players can't join the server without a key It can be enabled that new players can't join the server without a key
# Commands `/tauth` (`tweaks724.tauth`)
### /chat
Changes chatroom
### /chatmanage ### Full join
`tweaks724.chatmanage` \ Players with `tweaks724.bypass-full` can join even when the server is full
Manages chatroom, like create, delete etc.
### /ping ### Emergency alerts
Displays your ping. \ Issue messages that the player needs to read to keep playing, and that make an attention grabbing sound
`/emergencyalerts` (`tweaks724.emergencyalerts`)
### Utility commands
- `/ping` - displays player ping \
**Ping is calculated by the plugin**. \ **Ping is calculated by the plugin**. \
That allows for more precision (decimal places) and to get the ping immediately after a player join That allows for more precision (decimal places) and to get the ping immediately after a player join
### /pomodoro
`tweaks724.pomodoro` \
Manage your pomodoro
- `/pom start` to start
- `/pom stop` to stop
- `/pom` to skip stage
### /tauth
`tweaks724.tauth` \
Manages authentication keys.
- `/tauth <key>` to see who the key is bound to
- `/tauth new` to create a key
- `/tauth delete <key>` to delete a key

View file

@ -7,10 +7,12 @@
package eu.m724.tweaks; package eu.m724.tweaks;
import eu.m724.mstats.MStatsPlugin; import eu.m724.mstats.MStatsPlugin;
import eu.m724.tweaks.alert.AlertManager;
import eu.m724.tweaks.auth.AuthManager; import eu.m724.tweaks.auth.AuthManager;
import eu.m724.tweaks.chat.ChatCommands; import eu.m724.tweaks.chat.ChatCommands;
import eu.m724.tweaks.chat.ChatManager; import eu.m724.tweaks.chat.ChatManager;
import eu.m724.tweaks.door.DoorManager; import eu.m724.tweaks.door.DoorManager;
import eu.m724.tweaks.full.FullListener;
import eu.m724.tweaks.hardcore.HardcoreManager; import eu.m724.tweaks.hardcore.HardcoreManager;
import eu.m724.tweaks.motd.MotdManager; import eu.m724.tweaks.motd.MotdManager;
import eu.m724.tweaks.ping.F3NameListener; import eu.m724.tweaks.ping.F3NameListener;
@ -99,6 +101,10 @@ public class TweaksPlugin extends MStatsPlugin {
new AuthManager(this).init(getCommand("tauth")); new AuthManager(this).init(getCommand("tauth"));
} }
new AlertManager(this).init(getCommand("emergencyalert"));
this.getServer().getPluginManager().registerEvents(new FullListener(), this);
if (config.metrics()) if (config.metrics())
mStats(1); mStats(1);

View file

@ -0,0 +1,52 @@
/*
* 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.alert;
import org.bukkit.Bukkit;
import org.bukkit.Material;
import org.bukkit.entity.Player;
import org.bukkit.event.inventory.InventoryType;
import org.bukkit.inventory.Inventory;
import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.meta.BookMeta;
public class Alert {
public final String[] content;
public final long issued;
public final Inventory inventory;
public Alert(String... content) {
this.content = content;
this.issued = System.currentTimeMillis();
this.inventory = inventory(content);
}
public boolean isOpen(Player player) {
var item = player.getOpenInventory().getTopInventory().getItem(0);
if (item != null) {
var meta = item.getItemMeta();
return meta != null && meta.getCustomModelData() == 4198203;
}
return false;
}
private Inventory inventory(String... pages) {
var inv = Bukkit.createInventory(null, InventoryType.LECTERN);
var book = new ItemStack(Material.WRITTEN_BOOK);
var bookMeta = (BookMeta) book.getItemMeta();
bookMeta.setTitle("ALERT");
//bookMeta.setAuthor("a");
bookMeta.setCustomModelData(4198203);
for (String page : pages) {
bookMeta.addPage(page);
}
book.setItemMeta(bookMeta);
inv.setItem(0, book);
return inv;
}
}

View file

@ -0,0 +1,101 @@
/*
* 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.alert;
import org.bukkit.Material;
import org.bukkit.command.Command;
import org.bukkit.command.CommandExecutor;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player;
import org.bukkit.inventory.meta.BookMeta;
import org.jetbrains.annotations.NotNull;
import java.util.List;
public class AlertCommand implements CommandExecutor {
private List<String> pending;
private long when;
private final AlertManager manager;
public AlertCommand(AlertManager manager) {
this.manager = manager;
}
@Override
public boolean onCommand(@NotNull CommandSender sender, @NotNull Command command, @NotNull String label, @NotNull String[] args) {
if (args.length == 0) {
sender.sendMessage("/emergencyalert manages emergency alerts");
sender.sendMessage("/emergencyalert cancel - cancels a pending or an active alert");
sender.sendMessage("/emergencyalert new <content> - creates a new alert with given text");
sender.sendMessage("/emergencyalert new - creates a new alert with contents of held book");
} else {
if (args[0].equals("CONFIRM")) {
if (pending != null) {
if (System.currentTimeMillis() - when > 15 * 1000) {
sender.sendMessage("There was a pending alert, but you took too long to confirm it, please create it again");
pending = null;
return true;
}
sender.sendMessage("Alert broadcast");
manager.start(pending.toArray(String[]::new));
pending = null;
} else {
sender.sendMessage("There is no pending alert to confirm");
}
} else if (args[0].equalsIgnoreCase("confirm")) {
sender.sendMessage("CONFIRM must be in all caps");
} else if (args[0].equalsIgnoreCase("cancel")) {
if (AlertManager.current != null) {
manager.stop();
sender.sendMessage("Cancelled alert");
} else if (pending != null) {
sender.sendMessage("Cancelled pending alert");
pending = null;
} else {
sender.sendMessage("There is no alert to cancel");
}
} else if (args[0].equalsIgnoreCase("new")) {
if (pending != null) {
sender.sendMessage("Another alert already waiting for confirmation. /emergencyalert cancel?");
return true;
}
if (args.length == 1) {
if (sender instanceof Player player) {
var is = player.getInventory().getItemInMainHand();
if (is.getType() == Material.WRITTEN_BOOK) {
player.swingMainHand();
pending = ((BookMeta) is.getItemMeta()).getPages();
sender.sendMessage("Used book content as alert text");
} else {
sender.sendMessage("You must hold a written book in your hand or pass a command argument to use as alert text");
}
} else {
sender.sendMessage("You must pass some text to alert, or be a player to use a book");
}
} else {
pending = List.of(String.join(" " , args));
sender.sendMessage("Used command argument as alert text");
}
if (pending != null) {
when = System.currentTimeMillis();
if (AlertManager.current != null) {
sender.sendMessage("Broadcasting a new alert will cancel the currently active one");
}
sender.sendMessage("Please confirm broadcast with /emergencyalert CONFIRM within 15 seconds");
}
} else {
sender.sendMessage("Unknown argument \"%s\". Run this command without any arguments to see help.".formatted(args[0]));
}
}
return true;
}
}

View file

@ -0,0 +1,90 @@
/*
* 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.alert;
import com.comphenix.protocol.PacketType;
import com.comphenix.protocol.ProtocolLibrary;
import com.comphenix.protocol.events.ListenerPriority;
import com.comphenix.protocol.events.PacketAdapter;
import com.comphenix.protocol.events.PacketContainer;
import com.comphenix.protocol.events.PacketEvent;
import eu.m724.tweaks.TweaksPlugin;
import org.bukkit.command.PluginCommand;
import org.bukkit.entity.Player;
import org.bukkit.scheduler.BukkitTask;
import java.util.HashMap;
import java.util.Map;
public class AlertManager {
private final TweaksPlugin plugin;
private BukkitTask notifyTask;
static Alert current;
static Map<Player, Integer> pages = new HashMap<>();
public AlertManager(TweaksPlugin plugin) {
this.plugin = plugin;
}
public void init(PluginCommand command) {
command.setExecutor(new AlertCommand(this));
ProtocolLibrary.getProtocolManager().addPacketListener(new PacketAdapter(
plugin,
ListenerPriority.NORMAL,
PacketType.Play.Client.ENCHANT_ITEM
) {
@Override
public void onPacketReceiving(PacketEvent event) {
if (current == null) return;
if (!current.isOpen(event.getPlayer())) return;
PacketContainer packet = event.getPacket();
int windowId, buttonId;
windowId = packet.getIntegers().read(0);
buttonId = packet.getIntegers().read(1);
var page = pages.getOrDefault(event.getPlayer(),1);
if (buttonId == 1) { // prev page
page--;
} else if (buttonId == 2) { // nextc page
page++;
} else {
return;
}
pages.put(event.getPlayer(), page);
var npacket = new PacketContainer(PacketType.Play.Server.WINDOW_DATA);
npacket.getIntegers().write(0, windowId);
npacket.getIntegers().write(1, 0);
npacket.getIntegers().write(2, page);
ProtocolLibrary.getProtocolManager().sendServerPacket(event.getPlayer(), npacket);
}
});
}
public Alert start(String... content) {
stop();
current = new Alert(content);
notifyTask = new AlertRunnable(current, v -> this.stop()).runTaskTimer(plugin, 0, 10);
return current;
}
public void stop() {
if (current == null) return;
for (Player player : plugin.getServer().getOnlinePlayers()) {
if (current.isOpen(player))
player.closeInventory();
}
pages.clear();
notifyTask.cancel();
current = null;
}
}

View file

@ -0,0 +1,58 @@
/*
* 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.alert;
import net.md_5.bungee.api.ChatColor;
import net.md_5.bungee.api.ChatMessageType;
import net.md_5.bungee.api.chat.ComponentBuilder;
import org.bukkit.Bukkit;
import org.bukkit.Sound;
import org.bukkit.scheduler.BukkitRunnable;
import java.util.function.Consumer;
public class AlertRunnable extends BukkitRunnable {
private final Alert alert;
private final Consumer<Void> onEnd;
public AlertRunnable(Alert alert, Consumer<Void> onEnd) {
this.alert = alert;
this.onEnd = onEnd;
}
@Override
public void run() {
if (alert != null) {
var ago = (System.currentTimeMillis() - alert.issued) / 1000;
Bukkit.getOnlinePlayers().forEach(p -> {
if (ago < 15) {
p.playSound(p, Sound.BLOCK_PORTAL_TRIGGER, 1f, 2f);
//p.playSound(p, Sound.ENTITY_GHAST_HURT, 1f, 2f);
if (ago % 2 == 0) {
p.playSound(p, Sound.BLOCK_ANVIL_PLACE, 1f, 0.5f);
}
}
if (ago < 10) {
if (!alert.isOpen(p)) {
p.openInventory(alert.inventory);
}
}
p.spigot().sendMessage(
ChatMessageType.ACTION_BAR,
new ComponentBuilder("An important event is ongoing").color(ChatColor.YELLOW)
.append(" %d:%02d".formatted(ago / 60, ago % 60)).color(ChatColor.GRAY)
.build()
);
});
if (ago > 300)
onEnd.accept(null);
}
}
}

View file

@ -13,7 +13,7 @@ import org.bukkit.event.player.PlayerLoginEvent;
public class FullListener implements Listener { public class FullListener implements Listener {
@EventHandler @EventHandler
public void onPlayerLogin(PlayerLoginEvent event) { public void onPlayerLogin(PlayerLoginEvent event) {
if (event.getResult() == PlayerLoginEvent.Result.KICK_FULL && event.getPlayer().hasPermission("tweaks724.full.exempt")) { if (event.getResult() == PlayerLoginEvent.Result.KICK_FULL && event.getPlayer().hasPermission("tweaks724.bypass-full")) {
event.allow(); event.allow();
} }
} }

View file

@ -45,16 +45,6 @@ public class TimeForwardRunnable extends BukkitRunnable {
perSkip = Math.clamp(perSkip, 20, 200); perSkip = Math.clamp(perSkip, 20, 200);
perSkip = (long) (perSkip * sleepPercentage); 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); world.setTime(world.getTime() + perSkip);
} }
} }

View file

@ -14,7 +14,6 @@ libraries:
commands: commands:
chat: chat:
description: Chatroom user commands description: Chatroom user commands
usage: /<command> [room] [password, optional]
aliases: [c, chatroom, cr, room] aliases: [c, chatroom, cr, room]
chatmanage: chatmanage:
description: Chatroom user management commands description: Chatroom user management commands
@ -33,14 +32,22 @@ commands:
tauth: tauth:
description: Authentication management description: Authentication management
permission: tweaks724.tauth permission: tweaks724.tauth
emergencyalert:
description: Send emergency alert
permission: tweaks724.emergencyalert
permissions: permissions:
tweaks724.chatmanage: tweaks724:
default: true chatmanage:
tweaks724.pomodoro: default: true
default: true pomodoro:
tweaks724.updates: default: true
default: op updates:
tweaks724.tauth: default: op
default: op tauth:
default: op
bypass-full:
default: op
emergencyalert:
default: op