1
mirror of https://github.com/Shiewk/SModeration.git synced 2026-04-28 05:54:16 +02:00

Ability to cancel punishments from the SMod Menu

This commit is contained in:
Shy
2024-06-08 17:40:53 +02:00
parent c65781b7bd
commit cd5777a0ee
5 changed files with 150 additions and 8 deletions
@@ -0,0 +1,68 @@
package de.shiewk.smoderation.inventory;
import net.kyori.adventure.text.Component;
import net.kyori.adventure.text.format.NamedTextColor;
import org.bukkit.Bukkit;
import org.bukkit.Material;
import org.bukkit.entity.Player;
import org.bukkit.event.inventory.InventoryClickEvent;
import org.bukkit.event.inventory.InventoryType;
import org.bukkit.inventory.Inventory;
import org.bukkit.inventory.ItemStack;
import org.jetbrains.annotations.NotNull;
public class ConfirmationInventory implements CustomInventory {
private final Inventory inventory;
private final Player player;
private final String prompt;
private final ItemStack yesStack;
private final ItemStack noStack;
private final Runnable onAccept;
private final Runnable onReject;
private final boolean reversed;
public ConfirmationInventory(Player player, String prompt, Runnable onAccept, Runnable onReject, boolean reversed) {
this.player = player;
this.prompt = prompt;
this.onAccept = onAccept;
this.onReject = onReject;
this.reversed = reversed;
inventory = Bukkit.createInventory(this, InventoryType.HOPPER, Component.text(this.prompt));
yesStack = new ItemStack(Material.LIME_STAINED_GLASS_PANE);
noStack = new ItemStack(Material.RED_STAINED_GLASS_PANE);
}
@Override
public void refresh() {
yesStack.editMeta(meta -> meta.displayName(applyFormatting(Component.text("Yes").color(NamedTextColor.GREEN))));
noStack.editMeta(meta -> meta.displayName(applyFormatting(Component.text("No").color(NamedTextColor.RED))));
ItemStack confirmation = new ItemStack(Material.PAPER);
confirmation.editMeta(meta -> meta.displayName(applyFormatting(Component.text(prompt).color(NamedTextColor.GOLD))));
inventory.setItem(reversed ? 4 : 0, noStack);
inventory.setItem(2, confirmation);
inventory.setItem(reversed ? 0 : 4, yesStack);
}
@Override
public void open() {
refresh();
player.openInventory(getInventory());
}
@Override
public void click(ItemStack stack, InventoryClickEvent event) {
if (yesStack.equals(stack)){
inventory.close();
onAccept.run();
} else if (noStack.equals(stack)) {
inventory.close();
onReject.run();
}
}
@Override
public @NotNull Inventory getInventory() {
return inventory;
}
}
@@ -10,12 +10,16 @@ import net.kyori.adventure.text.format.NamedTextColor;
import net.kyori.adventure.text.format.TextDecoration; import net.kyori.adventure.text.format.TextDecoration;
import org.bukkit.Bukkit; import org.bukkit.Bukkit;
import org.bukkit.Material; import org.bukkit.Material;
import org.bukkit.NamespacedKey;
import org.bukkit.Sound; import org.bukkit.Sound;
import org.bukkit.entity.Player; import org.bukkit.entity.Player;
import org.bukkit.event.inventory.InventoryClickEvent; import org.bukkit.event.inventory.InventoryClickEvent;
import org.bukkit.inventory.Inventory; import org.bukkit.inventory.Inventory;
import org.bukkit.inventory.ItemStack; import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.meta.ItemMeta;
import org.bukkit.inventory.meta.SkullMeta; import org.bukkit.inventory.meta.SkullMeta;
import org.bukkit.persistence.PersistentDataContainer;
import org.bukkit.persistence.PersistentDataType;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import java.util.ArrayList; import java.util.ArrayList;
@@ -26,8 +30,8 @@ import java.util.function.Predicate;
public class SModMenu extends PageableCustomInventory { public class SModMenu extends PageableCustomInventory {
public enum Filter { public enum Filter {
ACTIVE("Active punishments", p -> p.until > System.currentTimeMillis()), ACTIVE("Active punishments", Punishment::isActive),
OLD("Expired punishments", p -> p.until < System.currentTimeMillis()), OLD("Old punishments", p -> !p.isActive()),
ALL("All punishments", p -> true); ALL("All punishments", p -> true);
public static final Material ICON = Material.HOPPER; public static final Material ICON = Material.HOPPER;
@@ -60,6 +64,7 @@ public class SModMenu extends PageableCustomInventory {
public static final NamedTextColor PRIMARY_COLOR = NamedTextColor.AQUA; public static final NamedTextColor PRIMARY_COLOR = NamedTextColor.AQUA;
public static final NamedTextColor SECONDARY_COLOR = NamedTextColor.GREEN; public static final NamedTextColor SECONDARY_COLOR = NamedTextColor.GREEN;
public static final NamedTextColor INACTIVE_COLOR = NamedTextColor.GRAY; public static final NamedTextColor INACTIVE_COLOR = NamedTextColor.GRAY;
private static final NamespacedKey PUNISHMENT_STORE_KEY = new NamespacedKey("smod", "punishmentid");
private final Inventory inventory; private final Inventory inventory;
private final Player player; private final Player player;
@@ -201,6 +206,14 @@ public class SModMenu extends PageableCustomInventory {
lore.add(applyFormatting(Component.text("Expires: ").color(SECONDARY_COLOR).append(Component.text(expires).color(PRIMARY_COLOR)))); lore.add(applyFormatting(Component.text("Expires: ").color(SECONDARY_COLOR).append(Component.text(expires).color(PRIMARY_COLOR))));
} }
lore.add(applyFormatting(Component.text("Reason: ").color(SECONDARY_COLOR).append(Component.text(punishment.reason).color(PRIMARY_COLOR)))); lore.add(applyFormatting(Component.text("Reason: ").color(SECONDARY_COLOR).append(Component.text(punishment.reason).color(PRIMARY_COLOR))));
if (punishment.wasCancelled()){
lore.add(applyFormatting(Component.text("Cancelled by: ").color(NamedTextColor.RED).append(Component.text(PlayerUtil.offlinePlayerName(punishment.cancelledBy())).color(NamedTextColor.GOLD))));
} else if (punishment.isActive()) {
if ((punishment.type == PunishmentType.BAN && player.hasPermission("smod.cancelBan")) || (punishment.type == PunishmentType.MUTE && player.hasPermission("smod.cancelMute"))){
lore.add(Component.empty());
lore.add(applyFormatting(Component.text("\u00BB Click to cancel punishment").color(NamedTextColor.GOLD)));
}
}
meta.lore(lore); meta.lore(lore);
}); });
return stack; return stack;
@@ -219,7 +232,16 @@ public class SModMenu extends PageableCustomInventory {
for (int i = 0; i < 45; i++) { for (int i = 0; i < 45; i++) {
int ci = i + (getPage() * 45); int ci = i + (getPage() * 45);
if (punishments.size() > ci){ if (punishments.size() > ci){
inventory.setItem(i, createPunishmentItem(punishments.get(ci))); final Punishment punishment = punishments.get(ci);
final ItemStack item = createPunishmentItem(punishment);
if (punishment.isActive()){
if ((punishment.type == PunishmentType.BAN && player.hasPermission("smod.cancelBan")) || (punishment.type == PunishmentType.MUTE && player.hasPermission("smod.cancelMute"))) {
item.editMeta(meta -> meta.getPersistentDataContainer().set(PUNISHMENT_STORE_KEY, PersistentDataType.LONG, punishment.time));
} else {
System.out.println("asd");
}
}
inventory.setItem(i, item);
} else { } else {
inventory.setItem(i, new ItemStack(Material.AIR)); inventory.setItem(i, new ItemStack(Material.AIR));
} }
@@ -235,6 +257,25 @@ public class SModMenu extends PageableCustomInventory {
} else if (stack.equals(sortStack)){ } else if (stack.equals(sortStack)){
cycleSort(event.isRightClick()); cycleSort(event.isRightClick());
} }
final ItemMeta itemMeta = stack.getItemMeta();
if (itemMeta != null) {
final PersistentDataContainer persistentDataContainer = itemMeta.getPersistentDataContainer();
final Long timestamp = persistentDataContainer.get(PUNISHMENT_STORE_KEY, PersistentDataType.LONG);
if (timestamp != null) {
final Punishment punishment = container.findByTimestamp(timestamp);
if (punishment != null) {
new ConfirmationInventory(player, "Do you want to cancel this punishment?", () -> {
punishment.cancel(player.getUniqueId());
player.playSound(player, Sound.BLOCK_NOTE_BLOCK_PLING, 1f, 2f);
this.open();
}, this::open, false).open();
} else {
System.out.println("kalsjkdaklsjd");
}
} else {
System.out.println("asasdasd");
}
}
} }
} }
@@ -20,7 +20,7 @@ public class PunishmentListener implements Listener {
Punishment punishment = SModeration.container.find(p -> Punishment punishment = SModeration.container.find(p ->
p.type == PunishmentType.BAN p.type == PunishmentType.BAN
&& p.to.equals(event.getPlayer().getUniqueId()) && p.to.equals(event.getPlayer().getUniqueId())
&& p.until >= System.currentTimeMillis()); && p.isActive());
if (punishment != null){ if (punishment != null){
event.disallow(PlayerLoginEvent.Result.KICK_BANNED, punishment.playerMessage()); event.disallow(PlayerLoginEvent.Result.KICK_BANNED, punishment.playerMessage());
} }
@@ -32,7 +32,7 @@ public class PunishmentListener implements Listener {
final Punishment punishment = SModeration.container.find(p -> final Punishment punishment = SModeration.container.find(p ->
p.type == PunishmentType.MUTE p.type == PunishmentType.MUTE
&& p.to.equals(player.getUniqueId()) && p.to.equals(player.getUniqueId())
&& p.until >= System.currentTimeMillis()); && p.isActive());
if (punishment != null) { if (punishment != null) {
event.setCancelled(true); event.setCancelled(true);
player.sendMessage(punishment.playerMessage()); player.sendMessage(punishment.playerMessage());
@@ -43,7 +43,7 @@ public class PunishmentListener implements Listener {
public void onPunishmentIssue(PunishmentIssueEvent event){ public void onPunishmentIssue(PunishmentIssueEvent event){
final Punishment punishment = event.getPunishment(); final Punishment punishment = event.getPunishment();
final PunishmentContainer container = event.getContainer(); final PunishmentContainer container = event.getContainer();
final Punishment duplicate = container.find(p -> p.to.equals(punishment.to) && p.type == punishment.type && p.until >= punishment.time); final Punishment duplicate = container.find(p -> p.to.equals(punishment.to) && p.type == punishment.type && p.isActive());
if (duplicate != null){ if (duplicate != null){
container.remove(duplicate); container.remove(duplicate);
container.add(new Punishment(duplicate.type, duplicate.time, System.currentTimeMillis(), duplicate.by, duplicate.to, duplicate.reason)); container.add(new Punishment(duplicate.type, duplicate.time, System.currentTimeMillis(), duplicate.by, duplicate.to, duplicate.reason));
@@ -25,6 +25,7 @@ public class Punishment {
public final UUID by; public final UUID by;
public final UUID to; public final UUID to;
public final String reason; public final String reason;
private UUID cancelledBy;
public Punishment(PunishmentType type, long time, long until, UUID by, UUID to, String reason) { public Punishment(PunishmentType type, long time, long until, UUID by, UUID to, String reason) {
this.type = type; this.type = type;
@@ -35,6 +36,25 @@ public class Punishment {
this.reason = reason; this.reason = reason;
} }
public boolean wasCancelled(){
return cancelledBy != null;
}
public UUID cancelledBy() {
return cancelledBy;
}
public void cancel(UUID cancelledBy){
if (this.cancelledBy != null){
throw new IllegalArgumentException("This punishment is already cancelled.");
}
this.cancelledBy = cancelledBy;
}
public boolean isActive(){
return until > System.currentTimeMillis() && !wasCancelled();
}
public static Punishment mute(long time, long until, UUID by, UUID to, String reason){ public static Punishment mute(long time, long until, UUID by, UUID to, String reason){
return new Punishment(PunishmentType.MUTE, time, until, by, to, reason); return new Punishment(PunishmentType.MUTE, time, until, by, to, reason);
} }
@@ -51,7 +71,7 @@ public class Punishment {
public byte[] toBytes(){ public byte[] toBytes(){
final byte[] reasonBytes = reason.getBytes(); final byte[] reasonBytes = reason.getBytes();
ByteBuffer buffer = ByteBuffer.allocate(BUFFER_LENGTH + reasonBytes.length); ByteBuffer buffer = ByteBuffer.allocate(BUFFER_LENGTH + reasonBytes.length + (cancelledBy != null ? 17 : 1));
buffer.putInt(0, type.ordinal()); buffer.putInt(0, type.ordinal());
buffer.putLong(4, time); buffer.putLong(4, time);
buffer.putLong(12, until); buffer.putLong(12, until);
@@ -59,6 +79,10 @@ public class Punishment {
buffer.put(36, ByteUtil.uuidToBytes(to)); buffer.put(36, ByteUtil.uuidToBytes(to));
buffer.putInt(40, reason.length()); buffer.putInt(40, reason.length());
buffer.put(44, reasonBytes); buffer.put(44, reasonBytes);
buffer.put(44+reasonBytes.length, cancelledBy != null ? (byte) 1 : (byte) 0);
if (cancelledBy != null){
buffer.put(44+reasonBytes.length+1, ByteUtil.uuidToBytes(cancelledBy));
}
return buffer.array(); return buffer.array();
} }
+10 -1
View File
@@ -3,6 +3,9 @@ version: '${version}'
main: de.shiewk.smoderation.SModeration main: de.shiewk.smoderation.SModeration
api-version: '1.20' api-version: '1.20'
load: STARTUP load: STARTUP
authors:
- Shiewk
description: "SModeration is an easy-to-use minecraft plugin for moderating your server."
commands: commands:
mute: mute:
usage: "§cUsage: /mute <player> <duration> <reason>" usage: "§cUsage: /mute <player> <duration> <reason>"
@@ -47,4 +50,10 @@ permissions:
description: Allows the player to use the SModeration menu. description: Allows the player to use the SModeration menu.
smod.notifications: smod.notifications:
default: op default: op
description: Allows the player to be notified when a punishment is issued. description: Allows the player to be notified when a punishment is issued.
smod.cancelMute:
default: op
description: Allows the player to unmute other players.
smod.cancelBan:
default: op
description: Allows the player to unban other players.