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

27 Commits

Author SHA1 Message Date
Shiewk 0d095c40f0 Removed unnecessary log message, 1.4.2 2025-04-11 16:30:48 +02:00
Shiewk 8df1029d42 Add a VanishToggleEvent 2025-04-02 18:29:20 +02:00
Shiewk 2f66c6f12c move SModeration for Paper to subproject 2024-12-19 15:59:20 +01:00
Shiewk 1f9758f3d0 Use main branch for development from now on (#5) 2024-12-16 14:48:39 +01:00
Shiewk c7502fd661 add missing whitespace 2024-12-06 19:41:06 +01:00
Shiewk 1a9cf76a93 1.4.1 2024-08-25 11:12:39 +02:00
Shiewk b3ec076cae Fix chat input title delay 2024-08-25 10:59:29 +02:00
Shiewk 3cb3314f4c Allow opening own ender chest 2024-08-22 15:28:25 +02:00
Shiewk fb785fb53a Improve styling 2024-08-22 13:57:31 +02:00
Shiewk e44f6489af Update main branch to 1.4.0 (#4)
- Fixed a bug where unknown players would crash the SMod menu
- SocialSpy command and permissions
- Hide death messages from vanished players
2024-08-21 18:43:41 +02:00
Shiewk faa2eb0a43 1.4.0 2024-08-21 18:40:56 +02:00
Shiewk 8c00347ef2 Hide death messages from vanished players 2024-08-21 18:40:06 +02:00
Shiewk 8de4382ec4 SocialSpy command and permissions 2024-08-21 18:32:01 +02:00
Shiewk a7c487decd Update to version 1.3.1 2024-08-04 14:48:51 +02:00
Shiewk 22f42df1da Fixed a bug where unknown players would crash the SMod menu 2024-08-04 14:47:29 +02:00
Shiewk 7e90939b84 Update main branch to version 1.3.0 (#3)
- Fixed EnderchestSee bug
- Fixed vanish bug
- Moved vanish-related methods to VanishCommand.java
- Added /vanish list command and list vanished players on join
- Added search option in SMod menu with chat input
- Refactored listeners
- Added Invsee for equipment
- Added ability to filter by type in SMod menu
- Updated docs and README to version 1.3.0
2024-07-29 17:41:04 +02:00
Shiewk 5c5eee0bca Update to version 1.3.0 2024-07-29 17:33:56 +02:00
Shiewk d7560d5ef3 Add ability to filter by type in SMod menu 2024-07-29 17:07:45 +02:00
Shiewk ce8a8a44cd Added Invsee for equipment 2024-07-29 16:27:42 +02:00
Shiewk 7902bb9a46 Refactor listeners 2024-07-29 15:12:23 +02:00
Shiewk b40e543f9e Fixed a bug where players could not put any items in their ender chests 2024-07-29 15:10:47 +02:00
Shiewk ab037716c4 Add search option in SMod menu with chat input 2024-07-29 13:22:00 +02:00
Shiewk 56aef4a2c9 Added /vanish list command and list vanished players on join 2024-07-28 16:10:22 +02:00
Shiewk 755b758b2f Move vanish-related methods to VanishCommand.java 2024-07-28 15:29:41 +02:00
Shiewk 4392456b15 Add missing docs, update to 1.2.1 2024-07-26 18:39:14 +02:00
Shiewk 0db57042af Fix vanish bug 2024-07-26 18:38:42 +02:00
Shiewk 57b21c2e1f Fix EnderchestSee bug 2024-07-26 18:36:57 +02:00
47 changed files with 1065 additions and 453 deletions
+2 -1
View File
@@ -14,7 +14,7 @@ SModeration provides a nice user interface that can be used instead of chat comm
![SMod Menu Sort](https://github.com/Shiewk/SModeration/assets/152653291/23e3862d-0915-47bd-9c47-6d8d10f8ab69)
It has helpful functions like filtering and sorting options.
It has helpful functions like filtering, searching and sorting options.
## Commands
This plugin has many commands, for a complete list of commands and their usage, please see [the commands list](https://github.com/Shiewk/SModeration/blob/main/docs/commands.md).
@@ -25,6 +25,7 @@ The most important ones are:
- /smod
- /unmute & /unban
- /invsee & /enderchestsee
- /vanish
## Permissions
This plugin uses Bukkit permissions for commands and other actions.
+12 -22
View File
@@ -5,21 +5,20 @@ plugins {
group = 'de.shiewk'
version = pluginVersion
repositories {
mavenCentral()
maven {
name = "papermc-repo"
url = "https://repo.papermc.io/repository/maven-public/"
}
maven {
name = "sonatype"
url = "https://oss.sonatype.org/content/groups/public/"
subprojects {
repositories {
mavenCentral()
maven {
name = "papermc-repo"
url = "https://repo.papermc.io/repository/maven-public/"
}
maven {
name = "sonatype"
url = "https://oss.sonatype.org/content/groups/public/"
}
}
}
dependencies {
compileOnly "io.papermc.paper:paper-api:1.20.4-R0.1-SNAPSHOT"
}
def targetJavaVersion = 17
java {
@@ -37,13 +36,4 @@ tasks.withType(JavaCompile).configureEach {
if (targetJavaVersion >= 10 || JavaVersion.current().isJava10Compatible()) {
options.release.set(targetJavaVersion)
}
}
processResources {
def props = [version: version]
inputs.properties props
filteringCharset 'UTF-8'
filesMatching('plugin.yml') {
expand props
}
}
}
+16 -51
View File
@@ -1,53 +1,18 @@
# SModeration commands
### /smod
The /smod command just opens the SMod menu. It takes no arguments.
### /mute
The /mute command is used to mute players.
It requires 2 arguments:
- Player name
- Duration
If you want to, you can also add a **reason**.
For example, if you want to mute a player for breaking server rules, just use **/mute playername 1h 30min Breaking server rules.**
The player will be muted for 1 hour and 30 minutes with the reason "Breaking server rules.".
Muted players can still join the server, but can't use the chat.
### /ban
The /ban command works the same as the /mute command, with one important difference:
Banned players **can't even join** the server until the ban expires.
### /kick
The /kick command is a bit different. It does not require a duration because kicks are instant. Instead, you can use the command like this: **/kick playername reason**
### /modlogs
The /modlogs command can be used when the /smod menu is unavailable. It displays information about a player in chat instead of a menu.
Example: **/modlogs playername** shows you a message in chat that tells you whether the player is muted or banned.
### /unmute & /unban
The /unmute and /unban commands only take one argument, the player name.
The specified player will then be unmuted or unbanned.
### /invsee
The /invsee command can be used to view the inventory of another player.
It takes one argument: the player name.
The player has to be online.
### /enderchestsee
The /enderchestsee command can, similarly to /invsee, be used to view the ender chest of another player.
It takes one argument: the player name.
The player has to be online.
### /vanish
The /vanish command is used to toggle vanish mode.
In vanish mode, other players (who don't have the necessary permissions) can't see that you're online.
To toggle vanish mode for yourself, use **/vanish**.
To toggle vanish mode for someone else, use **/vanish <playername>**.
Vanish status is not saved, so you re-appear when you leave the server.
| Command | Description | Permission |
|----------------------------------------|------------------------------------------------------------------------------|--------------------|
| /smod | Opens the SMod menu. | smod.menu |
| /mute \<player> \<duration> \<reason?> | Mutes a player so that they can't type in chat for the specified duration. | smod.mute |
| /ban \<player> \<duration> \<reason?> | Bans a player so that they can't join the server for the specified duration. | smod.ban |
| /kick \<player> \<reason?> | Kicks a player from the server. | smod.kick |
| /modlogs <player\|uuid> | Lists a player's active punishments in chat. | smod.logs |
| /unmute <player> | Clears a player's mute status. | smod.unmute |
| /unban <player> | Clears a player's ban status. | smod.unban |
| /invsee \<player> inventory | Views another player's inventory. | smod.invsee |
| /invsee \<player> equipment | Views another player's equipment (armor and offhand). | smod.invsee |
| /enderchestsee <player> | Views another player's ender chest. | smod.enderchestsee |
| /vanish | Toggles vanish mode so that other players can't see you're online. | smod.vanish |
| /vanish toggle \<player> | Toggles vanish mode for another player. | smod.vanish |
| /vanish list | Lists all vanished players. | smod.vanish.see |
| /socialspy | Enables SocialSpy mode where you can see other player's private messages. | smod.socialspy |
+21 -16
View File
@@ -1,19 +1,24 @@
# SModeration permissions
- **smod.mute**: Allows the player to mute other players.
- **smod.preventmute**: Prevents the player from being muted (if they are online).
- **smod.ban**: Allows the player to ban and kick other players.
- **smod.preventban**: Prevents the player from being banned (if they are online).
- **smod.kick**: Allows the player to kick other players.
- **smod.preventkick**: Prevents the player from being kicked (if they are online).
- **smod.menu**: Allows the player to use the SModeration menu.
- **smod.notifications**: Allows the player to be notified when a punishment is issued.
- **smod.unmute**: Allows the player to unmute other players.
- **smod.unban**: Allows the player to unban other players.
- **smod.logs**: Allows the player to view mod logs.
- **smod.invsee**: Allows the player to view other players inventories.
- **smod.invsee.modify**: Allows the player to view and modify other players inventories.
- **smod.invsee.preventmodify**: When giving this permission to a player, prevents their inventory from being modified.
- **smod.enderchestsee**: Allows the player to view other players ender chests.
- **smod.enderchestsee.modify**: Allows the player to view and modify other players ender chests.
| Permission | Description |
|---------------------------|------------------------------------------------------------------|
| smod.mute | Allows the player to mute other players. |
| smod.preventmute | Prevents the player from being muted (if they are online). |
| smod.ban | Allows the player to ban and kick other players. |
| smod.preventban | Prevents the player from being banned (if they are online). |
| smod.kick | Allows the player to kick other players. |
| smod.preventkick | Prevents the player from being kicked (if they are online). |
| smod.menu | Allows the player to use the SModeration menu. |
| smod.notifications | Allows the player to be notified when a punishment is issued. |
| smod.unmute | Allows the player to unmute other players. |
| smod.unban | Allows the player to unban other players. |
| smod.logs | Allows the player to view mod logs. |
| smod.invsee | Allows the player to view other players inventories. |
| smod.invsee.modify | Allows the player to view and modify other players inventories. |
| smod.invsee.preventmodify | Prevents the player's inventory from being modified. |
| smod.enderchestsee | Allows the player to view other players ender chests. |
| smod.enderchestsee.modify | Allows the player to view and modify other players ender chests. |
| smod.vanish | Allows the player to enter and leave vanish mode. |
| smod.vanish.see | Allows the player to see vanished players |
| smod.socialspy | Allows the player to enable SocialSpy |
All of these permissions are granted by default if the player is a server operator.
+1 -1
View File
@@ -1 +1 @@
pluginVersion = 1.2.0
pluginVersion = 1.4.2
+1
View File
@@ -1 +1,2 @@
rootProject.name = 'SModeration'
include 'smoderation-paper'
+19
View File
@@ -0,0 +1,19 @@
apply plugin: 'java'
dependencies {
compileOnly "io.papermc.paper:paper-api:1.20.4-R0.1-SNAPSHOT"
}
jar {
archiveBaseName.set('SModeration-Paper')
archiveVersion.set(pluginVersion)
}
processResources {
def props = [version: version]
inputs.properties props
filteringCharset 'UTF-8'
filesMatching('plugin.yml') {
expand props
}
}
@@ -0,0 +1,92 @@
package de.shiewk.smoderation.paper;
import de.shiewk.smoderation.paper.command.*;
import de.shiewk.smoderation.paper.config.SModerationConfig;
import de.shiewk.smoderation.paper.input.ChatInputListener;
import de.shiewk.smoderation.paper.listener.*;
import de.shiewk.smoderation.paper.storage.PunishmentContainer;
import net.kyori.adventure.text.TextComponent;
import net.kyori.adventure.text.format.NamedTextColor;
import net.kyori.adventure.text.format.TextColor;
import net.kyori.adventure.text.logger.slf4j.ComponentLogger;
import org.bukkit.Bukkit;
import org.bukkit.command.PluginCommand;
import org.bukkit.command.TabExecutor;
import org.bukkit.entity.Player;
import org.bukkit.plugin.java.JavaPlugin;
import java.io.File;
import static de.shiewk.smoderation.paper.command.VanishCommand.isVanished;
import static de.shiewk.smoderation.paper.command.VanishCommand.toggleVanish;
import static net.kyori.adventure.text.Component.text;
import static org.bukkit.Bukkit.getPluginManager;
public final class SModerationPaper extends JavaPlugin {
public static final PunishmentContainer container = new PunishmentContainer();
public static ComponentLogger LOGGER = null;
public static SModerationPaper PLUGIN = null;
public static SModerationConfig CONFIG = null;
public static File SAVE_FILE = null;
public static final TextColor PRIMARY_COLOR = TextColor.color(212, 0, 255);
public static final TextColor SECONDARY_COLOR = TextColor.color(52, 143, 255);
public static final TextColor INACTIVE_COLOR = NamedTextColor.GRAY;
public static final TextColor FAIL_COLOR = NamedTextColor.RED;
public static final TextComponent CHAT_PREFIX = text("SM \u00BB ").color(PRIMARY_COLOR);
@Override
public void onLoad() {
LOGGER = getComponentLogger();
PLUGIN = this;
CONFIG = new SModerationConfig(this.getConfig(), this);
SAVE_FILE = new File(this.getDataFolder().getAbsolutePath() + "/container.gz");
}
@Override
public void onEnable() {
getPluginManager().registerEvents(new PunishmentListener(), this);
getPluginManager().registerEvents(new CustomInventoryListener(), this);
getPluginManager().registerEvents(new InvSeeListener(), this);
getPluginManager().registerEvents(new EnderchestSeeListener(), this);
getPluginManager().registerEvents(new VanishListener(), this);
getPluginManager().registerEvents(new ChatInputListener(), this);
getPluginManager().registerEvents(new SocialSpyListener(), this);
registerCommand("mute", new MuteCommand());
registerCommand("ban", new BanCommand());
registerCommand("kick", new KickCommand());
registerCommand("smod", new SModCommand());
registerCommand("modlogs", new ModLogsCommand());
registerCommand("unmute", new UnmuteCommand());
registerCommand("unban", new UnbanCommand());
registerCommand("invsee", new InvseeCommand());
registerCommand("enderchestsee", new EnderchestSeeCommand());
registerCommand("vanish", new VanishCommand());
registerCommand("socialspy", new SocialSpyCommand());
container.load(SAVE_FILE);
}
private void registerCommand(String label, TabExecutor executor){
final PluginCommand command = getCommand(label);
if (command != null) {
command.setExecutor(executor);
command.setTabCompleter(executor);
} else {
LOGGER.warn("Command %s failed to register: This command does not exist".formatted(label));
}
}
@Override
public void onDisable() {
SModerationPaper.container.save(SModerationPaper.SAVE_FILE);
for (Player player : Bukkit.getOnlinePlayers()) {
// in case players are still vanished when the server shuts down
if (isVanished(player)){
toggleVanish(player);
}
}
}
}
@@ -1,9 +1,9 @@
package de.shiewk.smoderation.command;
package de.shiewk.smoderation.paper.command;
import de.shiewk.smoderation.SModeration;
import de.shiewk.smoderation.punishments.Punishment;
import de.shiewk.smoderation.util.PlayerUtil;
import de.shiewk.smoderation.util.TimeUtil;
import de.shiewk.smoderation.paper.SModerationPaper;
import de.shiewk.smoderation.paper.punishments.Punishment;
import de.shiewk.smoderation.paper.util.PlayerUtil;
import de.shiewk.smoderation.paper.util.TimeUtil;
import net.kyori.adventure.text.Component;
import net.kyori.adventure.text.format.NamedTextColor;
import org.bukkit.Bukkit;
@@ -81,7 +81,7 @@ public class BanCommand implements TabExecutor {
reason.append(args[i]);
}
final Punishment punishment = Punishment.ban(System.currentTimeMillis(), System.currentTimeMillis() + duration, senderUUID, uuid, reason.isEmpty() ? Punishment.DEFAULT_REASON : reason.toString());
Punishment.issue(punishment, SModeration.container);
Punishment.issue(punishment, SModerationPaper.container);
return true;
}
}
@@ -1,6 +1,6 @@
package de.shiewk.smoderation.command;
package de.shiewk.smoderation.paper.command;
import de.shiewk.smoderation.util.PlayerUtil;
import de.shiewk.smoderation.paper.util.PlayerUtil;
import net.kyori.adventure.text.Component;
import org.bukkit.Bukkit;
import org.bukkit.command.Command;
@@ -15,7 +15,7 @@ import org.jetbrains.annotations.Nullable;
import java.util.ArrayList;
import java.util.List;
import static de.shiewk.smoderation.SModeration.*;
import static de.shiewk.smoderation.paper.SModerationPaper.*;
public class EnderchestSeeCommand implements TabExecutor {
@@ -28,16 +28,12 @@ public class EnderchestSeeCommand implements TabExecutor {
if (sender instanceof HumanEntity human){
final Player player = PlayerUtil.findOnlinePlayer(args[0]);
if (player != null) {
if (human.getUniqueId().equals(player.getUniqueId())){
human.sendMessage(Component.text("You can't open your own ender chest.").color(FAIL_COLOR));
} else {
human.sendMessage(CHAT_PREFIX.append(
Component.text("Opening ender chest of ").color(PRIMARY_COLOR)
.append(Component.text(player.getName()).color(SECONDARY_COLOR))
.append(Component.text("."))
));
human.openInventory(player.getEnderChest());
}
human.sendMessage(CHAT_PREFIX.append(
Component.text("Opening ender chest of ").color(PRIMARY_COLOR)
.append(Component.text(player.getName()).color(SECONDARY_COLOR))
.append(Component.text("."))
));
human.openInventory(player.getEnderChest());
} else {
human.sendMessage(Component.text("This player is not online.").color(FAIL_COLOR));
}
@@ -1,6 +1,7 @@
package de.shiewk.smoderation.command;
package de.shiewk.smoderation.paper.command;
import de.shiewk.smoderation.util.PlayerUtil;
import de.shiewk.smoderation.paper.inventory.InvSeeEquipmentInventory;
import de.shiewk.smoderation.paper.util.PlayerUtil;
import net.kyori.adventure.text.Component;
import org.bukkit.Bukkit;
import org.bukkit.command.Command;
@@ -15,20 +16,34 @@ import org.jetbrains.annotations.Nullable;
import java.util.ArrayList;
import java.util.List;
import static de.shiewk.smoderation.SModeration.*;
import static de.shiewk.smoderation.paper.SModerationPaper.*;
public class InvseeCommand implements TabExecutor {
private enum InvseeType {
INVENTORY,
EQUIPMENT
}
@Override
public boolean onCommand(@NotNull CommandSender sender, @NotNull Command command, @NotNull String label, @NotNull String[] args) {
if (args.length < 1) {
return false;
}
final InvseeType type;
if (args.length > 1){
switch (args[1].toLowerCase()){
case "armor", "equipment" -> type = InvseeType.EQUIPMENT;
default -> type = InvseeType.INVENTORY;
}
} else {
type = InvseeType.INVENTORY;
}
if (sender instanceof HumanEntity human){
final Player player = PlayerUtil.findOnlinePlayer(args[0]);
if (player != null) {
if (human.getUniqueId().equals(player.getUniqueId())){
if (human.getUniqueId().equals(player.getUniqueId()) && type != InvseeType.EQUIPMENT){
human.sendMessage(Component.text("You can't open your own inventory.").color(FAIL_COLOR));
} else {
human.sendMessage(CHAT_PREFIX.append(
@@ -36,7 +51,10 @@ public class InvseeCommand implements TabExecutor {
.append(Component.text(player.getName()).color(SECONDARY_COLOR))
.append(Component.text("."))
));
human.openInventory(player.getInventory());
switch (type){
case INVENTORY -> human.openInventory(player.getInventory());
case EQUIPMENT -> new InvSeeEquipmentInventory(human, player).open();
}
}
} else {
human.sendMessage(Component.text("This player is not online.").color(FAIL_COLOR));
@@ -49,8 +67,10 @@ public class InvseeCommand implements TabExecutor {
@Override
public @Nullable List<String> onTabComplete(@NotNull CommandSender sender, @NotNull Command command, @NotNull String label, @NotNull String[] args) {
if (args.length > 1){
if (args.length > 2){
return List.of();
} else if (args.length > 1){
return List.of("armor", "equipment", "inventory");
}
List<String> available = new ArrayList<>();
for (Player onlinePlayer : Bukkit.getOnlinePlayers()) {
@@ -1,8 +1,8 @@
package de.shiewk.smoderation.command;
package de.shiewk.smoderation.paper.command;
import de.shiewk.smoderation.SModeration;
import de.shiewk.smoderation.punishments.Punishment;
import de.shiewk.smoderation.util.PlayerUtil;
import de.shiewk.smoderation.paper.SModerationPaper;
import de.shiewk.smoderation.paper.punishments.Punishment;
import de.shiewk.smoderation.paper.util.PlayerUtil;
import net.kyori.adventure.text.Component;
import net.kyori.adventure.text.format.NamedTextColor;
import org.bukkit.Bukkit;
@@ -59,7 +59,7 @@ public class KickCommand implements TabExecutor {
reason.append(args[i]);
}
final Punishment punishment = Punishment.kick(System.currentTimeMillis(), senderUUID, uuid, reason.isEmpty() ? Punishment.DEFAULT_REASON : reason.toString());
Punishment.issue(punishment, SModeration.container);
Punishment.issue(punishment, SModerationPaper.container);
return true;
}
}
@@ -1,10 +1,10 @@
package de.shiewk.smoderation.command;
package de.shiewk.smoderation.paper.command;
import de.shiewk.smoderation.SModeration;
import de.shiewk.smoderation.punishments.Punishment;
import de.shiewk.smoderation.punishments.PunishmentType;
import de.shiewk.smoderation.util.PlayerUtil;
import de.shiewk.smoderation.util.TimeUtil;
import de.shiewk.smoderation.paper.SModerationPaper;
import de.shiewk.smoderation.paper.punishments.Punishment;
import de.shiewk.smoderation.paper.punishments.PunishmentType;
import de.shiewk.smoderation.paper.util.PlayerUtil;
import de.shiewk.smoderation.paper.util.TimeUtil;
import net.kyori.adventure.text.Component;
import net.kyori.adventure.text.format.NamedTextColor;
import org.bukkit.Bukkit;
@@ -20,7 +20,7 @@ import java.util.ArrayList;
import java.util.List;
import java.util.UUID;
import static de.shiewk.smoderation.SModeration.*;
import static de.shiewk.smoderation.paper.SModerationPaper.*;
public class ModLogsCommand implements TabExecutor {
@Override
@@ -45,7 +45,7 @@ public class ModLogsCommand implements TabExecutor {
.append(Component.text(name).color(SECONDARY_COLOR))
.append(Component.text(" (%s)".formatted(uuid)).color(INACTIVE_COLOR))));
UUID finalUuid = uuid;
final List<Punishment> punishments = SModeration.container.findAll(p -> p.to.equals(finalUuid) && p.isActive());
final List<Punishment> punishments = SModerationPaper.container.findAll(p -> p.to.equals(finalUuid) && p.isActive());
for (Punishment punishment : punishments) {
sender.sendMessage(Component.text("- is currently ").color(PRIMARY_COLOR)
.append(Component.text(punishment.type == PunishmentType.BAN ? "banned" : "muted").color(SECONDARY_COLOR))
@@ -1,9 +1,9 @@
package de.shiewk.smoderation.command;
package de.shiewk.smoderation.paper.command;
import de.shiewk.smoderation.SModeration;
import de.shiewk.smoderation.punishments.Punishment;
import de.shiewk.smoderation.util.PlayerUtil;
import de.shiewk.smoderation.util.TimeUtil;
import de.shiewk.smoderation.paper.SModerationPaper;
import de.shiewk.smoderation.paper.punishments.Punishment;
import de.shiewk.smoderation.paper.util.PlayerUtil;
import de.shiewk.smoderation.paper.util.TimeUtil;
import net.kyori.adventure.text.format.NamedTextColor;
import org.bukkit.Bukkit;
import org.bukkit.command.*;
@@ -80,7 +80,7 @@ public class MuteCommand implements TabExecutor {
reason.append(args[i]);
}
final Punishment punishment = Punishment.mute(System.currentTimeMillis(), System.currentTimeMillis() + duration, senderUUID, uuid, reason.isEmpty() ? Punishment.DEFAULT_REASON : reason.toString());
Punishment.issue(punishment, SModeration.container);
Punishment.issue(punishment, SModerationPaper.container);
return true;
}
}
@@ -1,7 +1,7 @@
package de.shiewk.smoderation.command;
package de.shiewk.smoderation.paper.command;
import de.shiewk.smoderation.SModeration;
import de.shiewk.smoderation.inventory.SModMenu;
import de.shiewk.smoderation.paper.SModerationPaper;
import de.shiewk.smoderation.paper.inventory.SModMenu;
import org.bukkit.command.Command;
import org.bukkit.command.CommandSender;
import org.bukkit.command.TabExecutor;
@@ -15,7 +15,7 @@ public class SModCommand implements TabExecutor {
@Override
public boolean onCommand(@NotNull CommandSender commandSender, @NotNull Command command, @NotNull String s, @NotNull String[] strings) {
if (commandSender instanceof Player player){
new SModMenu(player, SModeration.container).open();
new SModMenu(player, SModerationPaper.container).open();
}
return true;
}
@@ -0,0 +1,32 @@
package de.shiewk.smoderation.paper.command;
import de.shiewk.smoderation.paper.listener.SocialSpyListener;
import net.kyori.adventure.text.format.NamedTextColor;
import org.bukkit.command.Command;
import org.bukkit.command.CommandSender;
import org.bukkit.command.TabExecutor;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.List;
import static de.shiewk.smoderation.paper.SModerationPaper.CHAT_PREFIX;
import static net.kyori.adventure.text.Component.text;
public class SocialSpyCommand implements TabExecutor {
@Override
public boolean onCommand(@NotNull CommandSender sender, @NotNull Command command, @NotNull String label, @NotNull String[] args) {
final boolean enabled = SocialSpyListener.toggle(sender);
sender.sendMessage(CHAT_PREFIX.append(text("SocialSpy ").append(
enabled ?
text("enabled").color(NamedTextColor.GREEN) :
text("disabled").color(NamedTextColor.RED)
).append(text("."))));
return true;
}
@Override
public @Nullable List<String> onTabComplete(@NotNull CommandSender sender, @NotNull Command command, @NotNull String label, @NotNull String[] args) {
return List.of();
}
}
@@ -1,9 +1,9 @@
package de.shiewk.smoderation.command;
package de.shiewk.smoderation.paper.command;
import de.shiewk.smoderation.SModeration;
import de.shiewk.smoderation.punishments.Punishment;
import de.shiewk.smoderation.punishments.PunishmentType;
import de.shiewk.smoderation.util.PlayerUtil;
import de.shiewk.smoderation.paper.SModerationPaper;
import de.shiewk.smoderation.paper.punishments.Punishment;
import de.shiewk.smoderation.paper.punishments.PunishmentType;
import de.shiewk.smoderation.paper.util.PlayerUtil;
import net.kyori.adventure.text.Component;
import net.kyori.adventure.text.format.NamedTextColor;
import org.bukkit.command.*;
@@ -46,10 +46,10 @@ public class UnbanCommand implements TabExecutor {
return true;
}
UUID finalUuid = uuid;
final Punishment punishment = SModeration.container.find(p -> p.to.equals(finalUuid) && p.isActive() && p.type == PunishmentType.BAN);
final Punishment punishment = SModerationPaper.container.find(p -> p.to.equals(finalUuid) && p.isActive() && p.type == PunishmentType.BAN);
if (punishment != null) {
punishment.undo(senderUUID);
punishment.broadcastUndo(SModeration.container);
punishment.broadcastUndo(SModerationPaper.container);
} else {
sender.sendMessage(Component.text("This player is not banned.").color(NamedTextColor.RED));
}
@@ -1,9 +1,9 @@
package de.shiewk.smoderation.command;
package de.shiewk.smoderation.paper.command;
import de.shiewk.smoderation.SModeration;
import de.shiewk.smoderation.punishments.Punishment;
import de.shiewk.smoderation.punishments.PunishmentType;
import de.shiewk.smoderation.util.PlayerUtil;
import de.shiewk.smoderation.paper.SModerationPaper;
import de.shiewk.smoderation.paper.punishments.Punishment;
import de.shiewk.smoderation.paper.punishments.PunishmentType;
import de.shiewk.smoderation.paper.util.PlayerUtil;
import net.kyori.adventure.text.Component;
import net.kyori.adventure.text.format.NamedTextColor;
import org.bukkit.command.*;
@@ -46,10 +46,10 @@ public class UnmuteCommand implements TabExecutor {
return true;
}
UUID finalUuid = uuid;
final Punishment punishment = SModeration.container.find(p -> p.to.equals(finalUuid) && p.isActive() && p.type == PunishmentType.MUTE);
final Punishment punishment = SModerationPaper.container.find(p -> p.to.equals(finalUuid) && p.isActive() && p.type == PunishmentType.MUTE);
if (punishment != null) {
punishment.undo(senderUUID);
punishment.broadcastUndo(SModeration.container);
punishment.broadcastUndo(SModerationPaper.container);
} else {
sender.sendMessage(Component.text("This player is not muted.").color(NamedTextColor.RED));
}
@@ -0,0 +1,139 @@
package de.shiewk.smoderation.paper.command;
import de.shiewk.smoderation.paper.SModerationPaper;
import de.shiewk.smoderation.paper.event.VanishToggleEvent;
import de.shiewk.smoderation.paper.util.PlayerUtil;
import it.unimi.dsi.fastutil.objects.ObjectArrayList;
import it.unimi.dsi.fastutil.objects.ObjectListIterator;
import net.kyori.adventure.text.Component;
import net.kyori.adventure.text.format.NamedTextColor;
import org.bukkit.Bukkit;
import org.bukkit.command.Command;
import org.bukkit.command.CommandSender;
import org.bukkit.command.TabExecutor;
import org.bukkit.entity.Player;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.List;
import static de.shiewk.smoderation.paper.SModerationPaper.*;
import static net.kyori.adventure.text.Component.text;
public class VanishCommand implements TabExecutor {
@Override
public boolean onCommand(@NotNull CommandSender sender, @NotNull Command command, @NotNull String label, @NotNull String[] args) {
if (args.length == 0 || args[0].equalsIgnoreCase("toggle")){
Player player = null;
if (args.length > 1){
player = PlayerUtil.findOnlinePlayer(args[1]);
} else if (sender instanceof Player){
player = (Player) sender;
}
if (player != null){
toggleVanish(player);
return true;
} else {
return false;
}
} else if (args[0].equalsIgnoreCase("list")) {
if (sender.hasPermission("smod.vanish.see")){
listVanishedPlayersTo(sender);
} else {
sender.sendMessage(text().color(NamedTextColor.RED).content("You do not have permission to list all vanished players."));
}
return true;
} else {
return false;
}
}
@Override
public @Nullable List<String> onTabComplete(@NotNull CommandSender sender, @NotNull Command command, @NotNull String label, @NotNull String[] args) {
if (args.length < 2){
return List.of("list", "toggle");
}
if (args.length < 3 && args[0].equalsIgnoreCase("toggle")){
return PlayerUtil.listPlayerNames(args[1]);
}
return List.of();
}
private static final ObjectArrayList<Player> vanishedPlayers = new ObjectArrayList<>();
public static void toggleVanish(Player player){
final boolean newStatus = !isVanished(player);
VanishToggleEvent event = new VanishToggleEvent(player, newStatus);
Bukkit.getPluginManager().callEvent(event);
if (event.isCancelled()){
return;
}
if (newStatus){
vanishedPlayers.add(player);
for (CommandSender sender : SModerationPaper.container.collectBroadcastTargets()) {
sender.sendMessage(CHAT_PREFIX.append(
player.displayName()
.colorIfAbsent(SECONDARY_COLOR)
).append(
text()
.content(" vanished.")
.color(PRIMARY_COLOR)
));
}
player.sendMessage(CHAT_PREFIX.append(text("You are now vanished.").color(PRIMARY_COLOR)));
player.setVisibleByDefault(false);
for (Player onlinePlayer : Bukkit.getOnlinePlayers()) {
if (onlinePlayer.hasPermission("smod.vanish.see")){
onlinePlayer.showEntity(PLUGIN, player);
}
}
} else {
vanishedPlayers.remove(player);
for (CommandSender sender : container.collectBroadcastTargets()) {
sender.sendMessage(CHAT_PREFIX.append(
player.displayName()
.colorIfAbsent(SECONDARY_COLOR)
).append(
text()
.content(" re-appeared.")
.color(PRIMARY_COLOR)
));
}
player.sendMessage(CHAT_PREFIX.append(text("You are no longer vanished.").color(PRIMARY_COLOR)));
player.setVisibleByDefault(true);
}
}
public static boolean isVanished(Player player){
return vanishedPlayers.contains(player);
}
public static ObjectArrayList<Player> getVanishedPlayers() {
return vanishedPlayers.clone();
}
public static void listVanishedPlayersTo(CommandSender receiver){
if (vanishedPlayers.isEmpty()){
receiver.sendMessage(CHAT_PREFIX.append(
text().content("No players are currently vanished.").color(PRIMARY_COLOR)
));
} else {
Component vanishList = CHAT_PREFIX.append(
text().content("The following players are currently vanished: ").color(PRIMARY_COLOR)
);
for (ObjectListIterator<Player> iterator = vanishedPlayers.iterator(); iterator.hasNext(); ) {
Player vanishedPlayer = iterator.next();
vanishList = vanishList.append(
vanishedPlayer.displayName().colorIfAbsent(SECONDARY_COLOR)
);
if (iterator.hasNext()){
vanishList = vanishList.append(
text().content(", ").color(PRIMARY_COLOR)
);
}
}
receiver.sendMessage(vanishList);
}
}
}
@@ -0,0 +1,30 @@
package de.shiewk.smoderation.paper.config;
import de.shiewk.smoderation.paper.SModerationPaper;
import org.bukkit.configuration.file.FileConfiguration;
import java.util.List;
public class SModerationConfig {
private final FileConfiguration config;
private final SModerationPaper plugin;
public SModerationConfig(FileConfiguration config, SModerationPaper plugin) {
this.config = config;
this.plugin = plugin;
}
public List<String> getSocialSpyCommands(List<String> default_){
final String path = "socialspy-commands";
if (!config.contains(path)){
config.set(path, default_);
plugin.saveConfig();
}
return config.getStringList(path);
}
public FileConfiguration getConfig() {
return config;
}
}
@@ -1,7 +1,7 @@
package de.shiewk.smoderation.event;
package de.shiewk.smoderation.paper.event;
import de.shiewk.smoderation.punishments.Punishment;
import de.shiewk.smoderation.storage.PunishmentContainer;
import de.shiewk.smoderation.paper.punishments.Punishment;
import de.shiewk.smoderation.paper.storage.PunishmentContainer;
import org.bukkit.event.Cancellable;
import org.bukkit.event.Event;
import org.bukkit.event.HandlerList;
@@ -0,0 +1,42 @@
package de.shiewk.smoderation.paper.event;
import org.bukkit.entity.Player;
import org.bukkit.event.Cancellable;
import org.bukkit.event.HandlerList;
import org.bukkit.event.player.PlayerEvent;
import org.jetbrains.annotations.NotNull;
public class VanishToggleEvent extends PlayerEvent implements Cancellable {
private static final HandlerList handlerList = new HandlerList();
private final boolean state;
private boolean cancelled;
public VanishToggleEvent(Player player, boolean state) {
super(player);
this.state = state;
}
public boolean getState() {
return state;
}
@Override
public @NotNull HandlerList getHandlers() {
return handlerList;
}
public static HandlerList getHandlerList() {
return handlerList;
}
@Override
public boolean isCancelled() {
return cancelled;
}
@Override
public void setCancelled(boolean cancelled) {
this.cancelled = cancelled;
}
}
@@ -0,0 +1,70 @@
package de.shiewk.smoderation.paper.input;
import net.kyori.adventure.text.Component;
import net.kyori.adventure.title.Title;
import org.bukkit.entity.Player;
import org.jetbrains.annotations.NotNull;
import java.time.Duration;
import java.util.Objects;
import java.util.concurrent.ConcurrentHashMap;
import java.util.function.Consumer;
import static de.shiewk.smoderation.paper.SModerationPaper.CHAT_PREFIX;
import static net.kyori.adventure.text.Component.text;
import static net.kyori.adventure.text.format.NamedTextColor.GRAY;
public class ChatInput {
private final Player player;
private final Component prompt;
private final Consumer<Component> action;
private int remainingTicks;
private ChatInput(@NotNull Player player, @NotNull Component prompt, @NotNull Consumer<Component> action, int remainingSeconds){
Objects.requireNonNull(action);
Objects.requireNonNull(prompt);
Objects.requireNonNull(player);
this.player = player;
this.prompt = prompt;
this.action = action;
this.remainingTicks = remainingSeconds * 20 + 1;
}
static void tickAll() {
runningInputs.values().forEach(ChatInput::tick);
}
void tick(){
remainingTicks--;
if (remainingTicks <= 0){
runningInputs.remove(player);
return;
}
if (remainingTicks % 20 == 0){
player.showTitle(Title.title(
text().content(getRemainingTicks() / 20 + " seconds").color(GRAY).build(),
getPrompt(),
Title.Times.times(Duration.ZERO, Duration.ofSeconds(2), Duration.ZERO)
));
}
}
final static ConcurrentHashMap<Player, ChatInput> runningInputs = new ConcurrentHashMap<>();
public static void prompt(Player player, Consumer<Component> consumer, Component prompt, int timeSeconds){
runningInputs.put(player, new ChatInput(player, prompt, consumer, timeSeconds));
player.sendMessage(CHAT_PREFIX.append(prompt));
}
public Component getPrompt() {
return prompt;
}
public Consumer<Component> getAction() {
return action;
}
public int getRemainingTicks() {
return remainingTicks;
}
}
@@ -0,0 +1,32 @@
package de.shiewk.smoderation.paper.input;
import com.destroystokyo.paper.event.server.ServerTickStartEvent;
import io.papermc.paper.event.player.AsyncChatEvent;
import org.bukkit.event.EventHandler;
import org.bukkit.event.EventPriority;
import org.bukkit.event.Listener;
import org.bukkit.event.player.PlayerQuitEvent;
import static de.shiewk.smoderation.paper.input.ChatInput.runningInputs;
public class ChatInputListener implements Listener {
@EventHandler
public void onAsyncChat(AsyncChatEvent event){
final ChatInput input = runningInputs.remove(event.getPlayer());
if (input != null){
event.setCancelled(true);
input.getAction().accept(event.message());
}
}
@EventHandler public void onPlayerQuit(PlayerQuitEvent event){
runningInputs.remove(event.getPlayer());
}
@EventHandler(priority = EventPriority.MONITOR) public void onServerTickStart(ServerTickStartEvent event){
ChatInput.tickAll();
}
}
@@ -0,0 +1,3 @@
package de.shiewk.smoderation.paper.inventory;
public interface AutoUpdatingCustomInventory extends CustomInventory { }
@@ -1,4 +1,4 @@
package de.shiewk.smoderation.inventory;
package de.shiewk.smoderation.paper.inventory;
import net.kyori.adventure.text.Component;
import net.kyori.adventure.text.format.NamedTextColor;
@@ -1,4 +1,4 @@
package de.shiewk.smoderation.inventory;
package de.shiewk.smoderation.paper.inventory;
import net.kyori.adventure.text.Component;
import net.kyori.adventure.text.format.TextDecoration;
@@ -0,0 +1,66 @@
package de.shiewk.smoderation.paper.inventory;
import de.shiewk.smoderation.paper.SModerationPaper;
import org.bukkit.Bukkit;
import org.bukkit.entity.HumanEntity;
import org.bukkit.event.inventory.InventoryClickEvent;
import org.bukkit.event.inventory.InventoryType;
import org.bukkit.inventory.EntityEquipment;
import org.bukkit.inventory.Inventory;
import org.bukkit.inventory.ItemStack;
import org.jetbrains.annotations.NotNull;
import static net.kyori.adventure.text.Component.text;
public class InvSeeEquipmentInventory implements AutoUpdatingCustomInventory {
private final HumanEntity viewer;
private final HumanEntity subject;
private final Inventory inventory = Bukkit.createInventory(this, InventoryType.HOPPER, text("Player equipment"));
private boolean changing = false;
public InvSeeEquipmentInventory(HumanEntity viewer, HumanEntity subject) {
this.viewer = viewer;
this.subject = subject;
}
@Override
public void refresh() {
if (!changing){
final EntityEquipment equipment = subject.getEquipment();
inventory.setItem(0, equipment.getHelmet());
inventory.setItem(1, equipment.getChestplate());
inventory.setItem(2, equipment.getLeggings());
inventory.setItem(3, equipment.getBoots());
inventory.setItem(4, equipment.getItemInOffHand());
}
}
@Override
public void open() {
refresh();
viewer.openInventory(getInventory());
}
@Override
public void click(ItemStack stack, InventoryClickEvent event) {
if (viewer.hasPermission("smod.invsee.modify") && !subject.hasPermission("smod.invsee.preventmodify")){
event.setCancelled(false);
changing = true;
Bukkit.getScheduler().scheduleSyncDelayedTask(SModerationPaper.PLUGIN, () -> {
changing = false;
final EntityEquipment equipment = subject.getEquipment();
equipment.setHelmet(inventory.getItem(0));
equipment.setChestplate(inventory.getItem(1));
equipment.setLeggings(inventory.getItem(2));
equipment.setBoots(inventory.getItem(3));
equipment.setItemInOffHand(inventory.getItem(4));
});
}
}
@Override
public @NotNull Inventory getInventory() {
return inventory;
}
}
@@ -1,4 +1,4 @@
package de.shiewk.smoderation.inventory;
package de.shiewk.smoderation.paper.inventory;
import net.kyori.adventure.text.Component;
import net.kyori.adventure.text.format.NamedTextColor;
@@ -1,11 +1,13 @@
package de.shiewk.smoderation.inventory;
package de.shiewk.smoderation.paper.inventory;
import de.shiewk.smoderation.punishments.Punishment;
import de.shiewk.smoderation.punishments.PunishmentType;
import de.shiewk.smoderation.storage.PunishmentContainer;
import de.shiewk.smoderation.util.PlayerUtil;
import de.shiewk.smoderation.util.TimeUtil;
import de.shiewk.smoderation.paper.input.ChatInput;
import de.shiewk.smoderation.paper.punishments.Punishment;
import de.shiewk.smoderation.paper.punishments.PunishmentType;
import de.shiewk.smoderation.paper.storage.PunishmentContainer;
import de.shiewk.smoderation.paper.util.PlayerUtil;
import de.shiewk.smoderation.paper.util.TimeUtil;
import net.kyori.adventure.text.Component;
import net.kyori.adventure.text.TextComponent;
import net.kyori.adventure.text.format.NamedTextColor;
import net.kyori.adventure.text.format.TextDecoration;
import org.bukkit.Bukkit;
@@ -15,6 +17,7 @@ import org.bukkit.Sound;
import org.bukkit.entity.Player;
import org.bukkit.event.inventory.InventoryClickEvent;
import org.bukkit.inventory.Inventory;
import org.bukkit.inventory.ItemFlag;
import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.meta.ItemMeta;
import org.bukkit.inventory.meta.SkullMeta;
@@ -25,9 +28,11 @@ import org.jetbrains.annotations.NotNull;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;
import java.util.function.Consumer;
import java.util.function.Predicate;
import static de.shiewk.smoderation.SModeration.*;
import static de.shiewk.smoderation.paper.SModerationPaper.*;
import static net.kyori.adventure.text.Component.text;
public class SModMenu extends PageableCustomInventory {
@@ -70,13 +75,17 @@ public class SModMenu extends PageableCustomInventory {
private List<Punishment> punishments;
private ItemStack sortStack = null;
private ItemStack filterStack = null;
private ItemStack searchStack = null;
private ItemStack typeStack = null;
private int sort = 0;
private int filter = 0;
private int type = -1;
private String searchQuery = null;
public SModMenu(Player player, PunishmentContainer container) {
this.player = player;
this.container = container;
this.inventory = Bukkit.createInventory(this, 54, Component.text("SMod Menu"));
this.inventory = Bukkit.createInventory(this, 54, text("SMod Menu"));
reload();
}
@@ -88,8 +97,27 @@ public class SModMenu extends PageableCustomInventory {
return Filter.values()[filter];
}
public PunishmentType getType(){
return type == -1 ? null : PunishmentType.values()[type];
}
private void reload(){
this.punishments = container.copy().stream().filter(getFilter().filter).sorted(getSort().comparator).toList();
this.punishments = container.copy().stream()
.filter(getFilter().filter)
.filter(p -> getType() == null || p.type == getType())
.filter(p -> p.matchesSearchQuery(searchQuery))
.sorted(getSort().comparator).toList();
}
public void promptSearchQuery(){
Bukkit.getScheduler().scheduleSyncDelayedTask(PLUGIN, player::closeInventory);
ChatInput.prompt(player, component -> {
if (component instanceof TextComponent text){
this.searchQuery = text.content();
// chat event is async
Bukkit.getScheduler().scheduleSyncDelayedTask(PLUGIN, this::open);
}
}, text("Enter your search query in chat").color(SECONDARY_COLOR), 30);
}
@Override
@@ -135,6 +163,25 @@ public class SModMenu extends PageableCustomInventory {
refresh();
}
public void cycleType(boolean backwards){
player.playSound(player, Sound.UI_BUTTON_CLICK, 1f, backwards ? 0.8f : 2f);
if (backwards){
if (type <= -1){
type = PunishmentType.values().length-1;
} else {
type--;
}
} else {
if (type >= PunishmentType.values().length-1){
type = -1;
} else {
type++;
}
}
reload();
refresh();
}
@Override
public void switchPage() {
player.playSound(player, Sound.BLOCK_STONE_HIT, 0.75f, 1f);
@@ -144,55 +191,101 @@ public class SModMenu extends PageableCustomInventory {
final Filter filter = getFilter();
final ItemStack stack = new ItemStack(Filter.ICON);
stack.editMeta(meta -> {
meta.displayName(applyFormatting(Component.text("Filter: " + filter.name).color(SECONDARY_COLOR)));
meta.displayName(applyFormatting(text("Filter: " + filter.name).color(PRIMARY_COLOR)));
ArrayList<Component> lore = new ArrayList<>();
lore.add(Component.empty());
for (Filter value : Filter.values()) {
final boolean selected = filter == value;
Component filterText = applyFormatting(Component.text((selected ? "\u00BB " : "") + value.name).color(selected ? PRIMARY_COLOR : INACTIVE_COLOR));
Component filterText = applyFormatting(text((selected ? "\u00BB " : "") + value.name).color(selected ? SECONDARY_COLOR : INACTIVE_COLOR));
lore.add(filterText);
}
lore.add(Component.empty());
lore.add(applyFormatting(Component.text("\u00BB Click to switch filter").color(NamedTextColor.GOLD)));
lore.add(applyFormatting(text("\u00BB Click to switch filter").color(NamedTextColor.GOLD)));
meta.lore(lore);
});
filterStack = stack;
return stack;
}
private ItemStack createTypeItem(){
final PunishmentType type = getType();
final ItemStack stack = new ItemStack(Material.CHEST);
stack.editMeta(meta -> {
meta.displayName(applyFormatting(text("Type: " + (type == null ? "All" : type.name)).color(PRIMARY_COLOR)));
ArrayList<Component> lore = new ArrayList<>();
lore.add(Component.empty());
final Consumer<PunishmentType> addToLore = value -> {
final boolean selected = type == value;
Component typeText = applyFormatting(text((selected ? "\u00BB " : "") + (value == null ? "All" : value.name)).color(selected ? SECONDARY_COLOR : INACTIVE_COLOR));
lore.add(typeText);
};
addToLore.accept(null);
for (PunishmentType value : PunishmentType.values()) {
addToLore.accept(value);
}
lore.add(Component.empty());
lore.add(applyFormatting(text("\u00BB Click to switch type").color(NamedTextColor.GOLD)));
meta.lore(lore);
});
return typeStack = stack;
}
private ItemStack createSortItem(){
final Sort sort = getSort();
final ItemStack stack = new ItemStack(Sort.ICON);
stack.editMeta(meta -> {
meta.displayName(applyFormatting(Component.text("Sort by: " + sort.name).color(PRIMARY_COLOR)));
meta.displayName(applyFormatting(text("Sort by: " + sort.name).color(PRIMARY_COLOR)));
ArrayList<Component> lore = new ArrayList<>();
lore.add(Component.empty());
for (Sort value : Sort.values()) {
final boolean selected = sort == value;
Component sortText = applyFormatting(Component.text((selected ? "\u00BB " : "") + value.name).color(selected ? SECONDARY_COLOR : INACTIVE_COLOR));
Component sortText = applyFormatting(text((selected ? "\u00BB " : "") + value.name).color(selected ? SECONDARY_COLOR : INACTIVE_COLOR));
lore.add(sortText);
}
lore.add(Component.empty());
lore.add(applyFormatting(Component.text("\u00BB Click to switch sorting option").color(NamedTextColor.GOLD)));
lore.add(applyFormatting(text("\u00BB Click to switch sorting option").color(NamedTextColor.GOLD)));
meta.lore(lore);
});
sortStack = stack;
return stack;
}
private ItemStack createSearchItem(){
final ItemStack stack = new ItemStack(Material.FLOWER_BANNER_PATTERN);
stack.editMeta(meta -> {
meta.addItemFlags(ItemFlag.HIDE_ITEM_SPECIFICS);
meta.displayName(applyFormatting(text("Search").color(PRIMARY_COLOR)));
final ArrayList<Component> lore = new ArrayList<>(List.of(
Component.empty(),
applyFormatting(text("Current search query: %s".formatted(searchQuery == null ? "None" : "\"" + searchQuery + "\"")).color(SECONDARY_COLOR)),
Component.empty(),
applyFormatting(text("\u00BB Click to enter new search query").color(NamedTextColor.GOLD))
));
if (searchQuery != null){
lore.add(applyFormatting(text("\u00BB Right click to remove search query").color(NamedTextColor.GOLD)));
}
meta.lore(lore);
});
return searchStack = stack;
}
private ItemStack createPunishmentItem(Punishment punishment){
ItemStack stack = new ItemStack(Material.PLAYER_HEAD);
stack.editMeta(meta -> {
if (meta instanceof SkullMeta skullMeta){
skullMeta.setOwningPlayer(Bukkit.getOfflinePlayer(punishment.to));
try {
skullMeta.setOwningPlayer(Bukkit.getOfflinePlayer(punishment.to));
} catch (NullPointerException e) {
LOGGER.warn("Player {} has a punishment but was never on this server!", punishment.to);
}
}
meta.displayName(applyFormatting(Component.text(punishment.type.name).color(NamedTextColor.RED).decorate(TextDecoration.BOLD)));
meta.displayName(applyFormatting(text(punishment.type.name).color(NamedTextColor.RED).decorate(TextDecoration.BOLD)));
ArrayList<Component> lore = new ArrayList<>();
lore.add(applyFormatting(Component.text("Player: ").color(SECONDARY_COLOR).append(Component.text(PlayerUtil.offlinePlayerName(punishment.to)).color(PRIMARY_COLOR))));
lore.add(applyFormatting(Component.text("Punished by: ").color(SECONDARY_COLOR).append(Component.text(PlayerUtil.offlinePlayerName(punishment.by)).color(PRIMARY_COLOR))));
lore.add(applyFormatting(Component.text("Timestamp: ").color(SECONDARY_COLOR).append(Component.text(TimeUtil.calendarTimestamp(punishment.time)).color(PRIMARY_COLOR))));
lore.add(applyFormatting(text("Player: ").color(SECONDARY_COLOR).append(text(PlayerUtil.offlinePlayerName(punishment.to)).color(PRIMARY_COLOR))));
lore.add(applyFormatting(text("Punished by: ").color(SECONDARY_COLOR).append(text(PlayerUtil.offlinePlayerName(punishment.by)).color(PRIMARY_COLOR))));
lore.add(applyFormatting(text("Timestamp: ").color(SECONDARY_COLOR).append(text(TimeUtil.calendarTimestamp(punishment.time)).color(PRIMARY_COLOR))));
if (punishment.type != PunishmentType.KICK){
lore.add(applyFormatting(Component.text("Duration: ").color(SECONDARY_COLOR).append(Component.text(TimeUtil.formatTimeLong(punishment.until - punishment.time)).color(PRIMARY_COLOR))));
lore.add(applyFormatting(text("Duration: ").color(SECONDARY_COLOR).append(text(TimeUtil.formatTimeLong(punishment.until - punishment.time)).color(PRIMARY_COLOR))));
long remainingTime = punishment.until - System.currentTimeMillis();
final String expires;
if (remainingTime > 0){
@@ -201,15 +294,15 @@ public class SModMenu extends PageableCustomInventory {
remainingTime *= -1;
expires = TimeUtil.formatTimeLong(remainingTime) + " ago";
}
lore.add(applyFormatting(Component.text("Expires: ").color(SECONDARY_COLOR).append(Component.text(expires).color(PRIMARY_COLOR))));
lore.add(applyFormatting(text("Expires: ").color(SECONDARY_COLOR).append(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(text("Reason: ").color(SECONDARY_COLOR).append(text(punishment.reason).color(PRIMARY_COLOR))));
if (punishment.wasUndone()){
lore.add(applyFormatting(Component.text("Undone by: ").color(NamedTextColor.RED).append(Component.text(PlayerUtil.offlinePlayerName(punishment.undoneBy())).color(NamedTextColor.GOLD))));
lore.add(applyFormatting(text("Undone by: ").color(NamedTextColor.RED).append(text(PlayerUtil.offlinePlayerName(punishment.undoneBy())).color(NamedTextColor.GOLD))));
} else if (punishment.isActive()) {
if ((punishment.type == PunishmentType.BAN && player.hasPermission("smod.unban")) || (punishment.type == PunishmentType.MUTE && player.hasPermission("smod.unmute"))){
lore.add(Component.empty());
lore.add(applyFormatting(Component.text("\u00BB Click to undo punishment").color(NamedTextColor.GOLD)));
lore.add(applyFormatting(text("\u00BB Click to undo punishment").color(NamedTextColor.GOLD)));
}
}
meta.lore(lore);
@@ -224,8 +317,10 @@ public class SModMenu extends PageableCustomInventory {
}
inventory.setItem(45, createPreviousPageStack());
inventory.setItem(53, createNextPageStack());
inventory.setItem(47, createSearchItem());
inventory.setItem(48, createTypeItem());
inventory.setItem(50, createFilterItem());
inventory.setItem(48, createSortItem());
inventory.setItem(51, createSortItem());
for (int i = 0; i < 45; i++) {
int ci = i + (getPage() * 45);
@@ -252,6 +347,18 @@ public class SModMenu extends PageableCustomInventory {
cycleFilter(event.isRightClick());
} else if (stack.equals(sortStack)){
cycleSort(event.isRightClick());
} else if (stack.equals(searchStack)){
if (event.isRightClick() && searchQuery != null){
player.playSound(player, Sound.UI_BUTTON_CLICK, 1f, 0.8f);
searchQuery = null;
reload();
refresh();
} else {
player.playSound(player, Sound.UI_BUTTON_CLICK, 1f, 2f);
promptSearchQuery();
}
} else if (stack.equals(typeStack)) {
cycleType(event.isRightClick());
}
final ItemMeta itemMeta = stack.getItemMeta();
if (itemMeta != null) {
@@ -0,0 +1,37 @@
package de.shiewk.smoderation.paper.listener;
import com.destroystokyo.paper.event.server.ServerTickEndEvent;
import de.shiewk.smoderation.paper.inventory.AutoUpdatingCustomInventory;
import de.shiewk.smoderation.paper.inventory.CustomInventory;
import org.bukkit.Bukkit;
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
import org.bukkit.event.EventPriority;
import org.bukkit.event.Listener;
import org.bukkit.event.inventory.InventoryClickEvent;
import org.bukkit.event.inventory.InventoryDragEvent;
public class CustomInventoryListener implements Listener {
@EventHandler(priority = EventPriority.HIGH, ignoreCancelled = true)
public void onInventoryClick(InventoryClickEvent event){
if (event.getInventory().getHolder() instanceof CustomInventory customInventory){
event.setCancelled(true);
customInventory.click(event.getCurrentItem(), event);
}
}
@EventHandler(priority = EventPriority.HIGH, ignoreCancelled = true)
public void onInventoryDrag(InventoryDragEvent event){
if (event.getInventory().getHolder() instanceof CustomInventory){
event.setCancelled(true);
}
}
@EventHandler(priority = EventPriority.LOWEST)
public void onServerTickEnd(ServerTickEndEvent event){
for (Player onlinePlayer : Bukkit.getOnlinePlayers()) {
if (onlinePlayer.getOpenInventory().getTopInventory().getHolder() instanceof AutoUpdatingCustomInventory ci) {
ci.refresh();
}
}
}
}
@@ -1,4 +1,4 @@
package de.shiewk.smoderation.event;
package de.shiewk.smoderation.paper.listener;
import org.bukkit.entity.HumanEntity;
import org.bukkit.event.EventHandler;
@@ -8,14 +8,14 @@ import org.bukkit.inventory.Inventory;
import org.bukkit.inventory.InventoryHolder;
import org.bukkit.inventory.PlayerInventory;
public class EnderchestSeeEvents implements Listener {
public class EnderchestSeeListener implements Listener {
@EventHandler
public void onInventoryClick(InventoryClickEvent event){
final Inventory clicked = event.getView().getTopInventory();
if (!(clicked instanceof PlayerInventory)){
final InventoryHolder holder = clicked.getHolder();
if (holder instanceof HumanEntity humanHolder){
if (holder instanceof HumanEntity humanHolder && humanHolder.getEnderChest().equals(clicked) && !humanHolder.equals(event.getWhoClicked())){
if (!event.getWhoClicked().hasPermission("smod.enderchestsee.modify")){
event.setCancelled(true);
}
@@ -1,4 +1,4 @@
package de.shiewk.smoderation.event;
package de.shiewk.smoderation.paper.listener;
import org.bukkit.entity.HumanEntity;
import org.bukkit.event.EventHandler;
@@ -9,7 +9,7 @@ import org.bukkit.inventory.PlayerInventory;
import java.util.Objects;
public class InvSeeEvents implements Listener {
public class InvSeeListener implements Listener {
@EventHandler
public void onInventoryClick(InventoryClickEvent event){
@@ -1,10 +1,10 @@
package de.shiewk.smoderation.listener;
package de.shiewk.smoderation.paper.listener;
import de.shiewk.smoderation.SModeration;
import de.shiewk.smoderation.event.PunishmentIssueEvent;
import de.shiewk.smoderation.punishments.Punishment;
import de.shiewk.smoderation.punishments.PunishmentType;
import de.shiewk.smoderation.storage.PunishmentContainer;
import de.shiewk.smoderation.paper.SModerationPaper;
import de.shiewk.smoderation.paper.event.PunishmentIssueEvent;
import de.shiewk.smoderation.paper.punishments.Punishment;
import de.shiewk.smoderation.paper.punishments.PunishmentType;
import de.shiewk.smoderation.paper.storage.PunishmentContainer;
import io.papermc.paper.event.player.AsyncChatEvent;
import org.bukkit.Bukkit;
import org.bukkit.entity.Player;
@@ -14,13 +14,13 @@ import org.bukkit.event.Listener;
import org.bukkit.event.player.PlayerLoginEvent;
import org.bukkit.event.world.WorldSaveEvent;
import static de.shiewk.smoderation.SModeration.CHAT_PREFIX;
import static de.shiewk.smoderation.paper.SModerationPaper.CHAT_PREFIX;
public class PunishmentListener implements Listener {
@EventHandler(priority = EventPriority.LOW)
public void onPlayerLogin(PlayerLoginEvent event){
Punishment punishment = SModeration.container.find(p ->
Punishment punishment = SModerationPaper.container.find(p ->
p.type == PunishmentType.BAN
&& p.to.equals(event.getPlayer().getUniqueId())
&& p.isActive());
@@ -32,7 +32,7 @@ public class PunishmentListener implements Listener {
@EventHandler(priority = EventPriority.LOW, ignoreCancelled = true)
public void onPlayerChat(AsyncChatEvent event){
final Player player = event.getPlayer();
final Punishment punishment = SModeration.container.find(p ->
final Punishment punishment = SModerationPaper.container.find(p ->
p.type == PunishmentType.MUTE
&& p.to.equals(player.getUniqueId())
&& p.isActive());
@@ -64,7 +64,7 @@ public class PunishmentListener implements Listener {
@EventHandler
public void onWorldSave(WorldSaveEvent event){
if (event.getWorld().equals(Bukkit.getServer().getWorlds().get(0))){
SModeration.container.save(SModeration.SAVE_FILE);
SModerationPaper.container.save(SModerationPaper.SAVE_FILE);
}
}
}
@@ -0,0 +1,97 @@
package de.shiewk.smoderation.paper.listener;
import de.shiewk.smoderation.paper.SModerationPaper;
import it.unimi.dsi.fastutil.objects.ObjectArrayList;
import org.bukkit.NamespacedKey;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
import org.bukkit.event.EventPriority;
import org.bukkit.event.Listener;
import org.bukkit.event.player.PlayerCommandPreprocessEvent;
import org.bukkit.event.player.PlayerJoinEvent;
import org.bukkit.event.player.PlayerQuitEvent;
import org.bukkit.persistence.PersistentDataContainer;
import org.bukkit.persistence.PersistentDataType;
import java.util.List;
import static de.shiewk.smoderation.paper.SModerationPaper.PRIMARY_COLOR;
import static de.shiewk.smoderation.paper.SModerationPaper.SECONDARY_COLOR;
import static net.kyori.adventure.text.Component.text;
public class SocialSpyListener implements Listener {
private static final List<String> defaultCommands = List.of(
"w",
"tell",
"msg",
"teammsg",
"tm",
"minecraft:w",
"minecraft:tell",
"minecraft:msg",
"minecraft:teammsg",
"minecraft:tm"
);
private static final NamespacedKey SAVE_KEY = new NamespacedKey("smoderation", "socialspy");
private static final ObjectArrayList<CommandSender> targets = new ObjectArrayList<>();
public static boolean toggle(CommandSender sender) {
boolean enabledNow = isEnabled(sender);
if (enabledNow){
targets.remove(sender);
if (sender instanceof Player player){
player.getPersistentDataContainer().set(SAVE_KEY, PersistentDataType.BOOLEAN, false);
}
return false;
} else {
targets.add(sender);
if (sender instanceof Player player){
player.getPersistentDataContainer().set(SAVE_KEY, PersistentDataType.BOOLEAN, true);
}
return true;
}
}
@EventHandler public void onPlayerJoin(PlayerJoinEvent event){
final PersistentDataContainer pdc = event.getPlayer().getPersistentDataContainer();
if (Boolean.TRUE.equals(pdc.get(SAVE_KEY, PersistentDataType.BOOLEAN))){
targets.add(event.getPlayer());
}
}
@EventHandler public void onPlayerQuit(PlayerQuitEvent event){
targets.remove(event.getPlayer());
}
public static boolean isEnabled(CommandSender sender){
return targets.contains(sender);
}
@EventHandler(ignoreCancelled = true, priority = EventPriority.NORMAL)
public void onPlayerSendCommand(PlayerCommandPreprocessEvent event){
List<String> ssCommands = SModerationPaper.CONFIG.getSocialSpyCommands(defaultCommands);
final String message = event.getMessage();
if (ssCommands.stream().anyMatch(str ->
message.startsWith("/"+str+" ")
|| message.startsWith(str+" ")
)){
SocialSpyListener.command(event.getPlayer(), message);
}
}
public static void command(Player player, String command){
for (CommandSender target : targets) {
target.sendMessage(text("[", PRIMARY_COLOR)
.append(text("SocialSpy", SECONDARY_COLOR))
.append(text("] "))
.append(player.displayName().colorIfAbsent(PRIMARY_COLOR))
.append(text(": ", PRIMARY_COLOR))
.append(text(command, SECONDARY_COLOR))
);
}
}
}
@@ -0,0 +1,58 @@
package de.shiewk.smoderation.paper.listener;
import de.shiewk.smoderation.paper.SModerationPaper;
import de.shiewk.smoderation.paper.command.VanishCommand;
import net.kyori.adventure.text.Component;
import org.bukkit.Bukkit;
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
import org.bukkit.event.EventPriority;
import org.bukkit.event.Listener;
import org.bukkit.event.entity.PlayerDeathEvent;
import org.bukkit.event.player.PlayerJoinEvent;
import org.bukkit.event.player.PlayerQuitEvent;
import static de.shiewk.smoderation.paper.SModerationPaper.SECONDARY_COLOR;
import static net.kyori.adventure.text.Component.text;
public class VanishListener implements Listener {
@EventHandler public void onPlayerQuit(PlayerQuitEvent event){
final Player player = event.getPlayer();
if (VanishCommand.isVanished(player)){
VanishCommand.toggleVanish(player);
}
for (Player vanishedPlayer : VanishCommand.getVanishedPlayers()) {
// to clean up visibility status
player.hideEntity(SModerationPaper.PLUGIN, vanishedPlayer);
}
}
@EventHandler(priority = EventPriority.MONITOR) public void onPlayerJoin(PlayerJoinEvent event){
Bukkit.getScheduler().scheduleSyncDelayedTask(SModerationPaper.PLUGIN, () -> {
final Player player = event.getPlayer().getPlayer();
assert player != null;
if (player.hasPermission("smod.vanish.see")){
for (Player vanishedPlayer : VanishCommand.getVanishedPlayers()) {
// to show visible vanished players
player.showEntity(SModerationPaper.PLUGIN, vanishedPlayer);
}
VanishCommand.listVanishedPlayersTo(player);
}
});
}
@EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true)
public void onPlayerDeath(PlayerDeathEvent event){
final Component message = event.deathMessage();
if (VanishCommand.isVanished(event.getPlayer()) && message != null){
event.deathMessage(null);
for (Player onlinePlayer : Bukkit.getOnlinePlayers()) {
if (onlinePlayer.hasPermission("smod.vanish.see")){
onlinePlayer.sendMessage(text("[VANISH] ").color(SECONDARY_COLOR).append(message));
}
}
}
}
}
@@ -1,10 +1,10 @@
package de.shiewk.smoderation.punishments;
package de.shiewk.smoderation.paper.punishments;
import de.shiewk.smoderation.event.PunishmentIssueEvent;
import de.shiewk.smoderation.storage.PunishmentContainer;
import de.shiewk.smoderation.util.ByteUtil;
import de.shiewk.smoderation.util.PlayerUtil;
import de.shiewk.smoderation.util.TimeUtil;
import de.shiewk.smoderation.paper.event.PunishmentIssueEvent;
import de.shiewk.smoderation.paper.storage.PunishmentContainer;
import de.shiewk.smoderation.paper.util.ByteUtil;
import de.shiewk.smoderation.paper.util.PlayerUtil;
import de.shiewk.smoderation.paper.util.TimeUtil;
import net.kyori.adventure.text.Component;
import org.bukkit.Bukkit;
import org.bukkit.command.CommandSender;
@@ -15,7 +15,7 @@ import java.io.InputStream;
import java.io.OutputStream;
import java.util.UUID;
import static de.shiewk.smoderation.SModeration.*;
import static de.shiewk.smoderation.paper.SModerationPaper.*;
public class Punishment {
public static final String DEFAULT_REASON = "No reason provided.";
@@ -239,4 +239,23 @@ public class Punishment {
default -> throw new IllegalStateException("Unknown punishment type " + type);
}
}
public boolean matchesSearchQuery(String searchQuery) {
if (searchQuery == null) return true;
searchQuery = searchQuery.toLowerCase();
return reason.toLowerCase().contains(searchQuery)
|| by.toString().equalsIgnoreCase(searchQuery)
|| to.toString().equalsIgnoreCase(searchQuery)
|| getPlayerName().toLowerCase().contains(searchQuery)
|| getModeratorName().toLowerCase().contains(searchQuery);
}
private String getPlayerName() {
return PlayerUtil.offlinePlayerName(to);
}
private String getModeratorName() {
return PlayerUtil.offlinePlayerName(by);
}
}
@@ -1,4 +1,4 @@
package de.shiewk.smoderation.punishments;
package de.shiewk.smoderation.paper.punishments;
public enum PunishmentType {
MUTE("Mute"),
@@ -1,7 +1,7 @@
package de.shiewk.smoderation.storage;
package de.shiewk.smoderation.paper.storage;
import de.shiewk.smoderation.SModeration;
import de.shiewk.smoderation.punishments.Punishment;
import de.shiewk.smoderation.paper.SModerationPaper;
import de.shiewk.smoderation.paper.punishments.Punishment;
import net.kyori.adventure.text.logger.slf4j.ComponentLogger;
import org.bukkit.Bukkit;
import org.bukkit.command.CommandSender;
@@ -75,7 +75,7 @@ public class PunishmentContainer {
}
public void load(File file){
final ComponentLogger logger = SModeration.LOGGER;
final ComponentLogger logger = SModerationPaper.LOGGER;
try {
logger.info("Loading from {}", file.getPath());
if (!file.isFile()){
@@ -100,9 +100,8 @@ public class PunishmentContainer {
}
public void save(File file) {
final ComponentLogger logger = SModeration.LOGGER;
final ComponentLogger logger = SModerationPaper.LOGGER;
try {
logger.info("Saving to {}", file.getPath());
if (!file.isFile()){
file.mkdirs();
file.delete();
@@ -115,7 +114,6 @@ public class PunishmentContainer {
}
gzout.close();
}
logger.info("Successfully saved.");
} catch (IOException e){
logger.error("An error occurred while saving: {}", e.toString());
for (StackTraceElement stackTraceElement : e.getStackTrace()) {
@@ -1,4 +1,4 @@
package de.shiewk.smoderation.util;
package de.shiewk.smoderation.paper.util;
import java.nio.ByteBuffer;
import java.util.UUID;
@@ -1,11 +1,12 @@
package de.shiewk.smoderation.util;
package de.shiewk.smoderation.paper.util;
import de.shiewk.smoderation.SModeration;
import de.shiewk.smoderation.punishments.Punishment;
import de.shiewk.smoderation.paper.SModerationPaper;
import de.shiewk.smoderation.paper.punishments.Punishment;
import org.bukkit.Bukkit;
import org.bukkit.OfflinePlayer;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player;
import org.bukkit.util.StringUtil;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -24,7 +25,7 @@ public abstract class PlayerUtil {
return "CONSOLE";
}
OfflinePlayer player = Bukkit.getOfflinePlayer(uuid);
return player.getName() == null ? uuid.toString() : player.getName();
return player.getName() == null ? "Unknown Player " + uuid : player.getName();
}
public static @Nullable UUID offlinePlayerUUIDByName(String name){
@@ -33,7 +34,7 @@ public abstract class PlayerUtil {
return offlinePlayer.getUniqueId();
} else {
// try to find uuid by searching through punishments
final Punishment punishment = SModeration.container.find(p -> offlinePlayerName(p.to).equalsIgnoreCase(name));
final Punishment punishment = SModerationPaper.container.find(p -> offlinePlayerName(p.to).equalsIgnoreCase(name));
if (punishment != null) {
return punishment.to;
}
@@ -71,4 +72,8 @@ public abstract class PlayerUtil {
}
return List.copyOf(names);
}
public static List<String> listPlayerNames(String search) {
return StringUtil.copyPartialMatches(search, listPlayerNames(), new ArrayList<>());
}
}
@@ -1,4 +1,4 @@
package de.shiewk.smoderation.util;
package de.shiewk.smoderation.paper.util;
import org.jetbrains.annotations.Range;
@@ -1,6 +1,6 @@
name: SModeration
version: '${version}'
main: de.shiewk.smoderation.SModeration
version: '1.4.2'
main: de.shiewk.smoderation.paper.SModerationPaper
api-version: '1.20'
load: STARTUP
authors:
@@ -72,11 +72,23 @@ commands:
permission: smod.enderchestsee
description: Views the ender chest of another player.
vanish:
usage: "§cUsage: /vanish <player>"
usage: "§cUsage: /vanish list or /vanish toggle <player>"
aliases:
- smvanish
- smodvanish
- v
- smv
permission: smod.vanish
description: Toggles vanish mode which prevents other players from seeing you're online
socialspy:
usage: "§cUsage: /socialspy"
description: Enables socialspy mode (you can see private messages of other players)
permission: smod.socialspy
aliases:
- smodsocialspy
- smsocialspy
- smss
- ss
permissions:
smod.mute:
default: op
@@ -137,4 +149,7 @@ permissions:
description: Allows the player to use /vanish
smod.vanish.see:
default: op
description: Allows the player to see vanished players
description: Allows the player to see vanished players
smod.socialspy:
default: op
description: Allows the player to enable SocialSpy
@@ -1,137 +0,0 @@
package de.shiewk.smoderation;
import de.shiewk.smoderation.command.*;
import de.shiewk.smoderation.event.CustomInventoryEvents;
import de.shiewk.smoderation.event.EnderchestSeeEvents;
import de.shiewk.smoderation.event.InvSeeEvents;
import de.shiewk.smoderation.listener.PunishmentListener;
import de.shiewk.smoderation.listener.VanishListener;
import de.shiewk.smoderation.storage.PunishmentContainer;
import it.unimi.dsi.fastutil.objects.ObjectArrayList;
import net.kyori.adventure.text.TextComponent;
import net.kyori.adventure.text.format.NamedTextColor;
import net.kyori.adventure.text.format.TextColor;
import net.kyori.adventure.text.logger.slf4j.ComponentLogger;
import org.bukkit.Bukkit;
import org.bukkit.command.CommandSender;
import org.bukkit.command.PluginCommand;
import org.bukkit.command.TabExecutor;
import org.bukkit.entity.Player;
import org.bukkit.plugin.java.JavaPlugin;
import java.io.File;
import static net.kyori.adventure.text.Component.text;
import static org.bukkit.Bukkit.getPluginManager;
public final class SModeration extends JavaPlugin {
public static final PunishmentContainer container = new PunishmentContainer();
public static ComponentLogger LOGGER = null;
public static SModeration PLUGIN = null;
public static File SAVE_FILE = null;
public static final TextColor PRIMARY_COLOR = TextColor.color(212, 0, 255);
public static final TextColor SECONDARY_COLOR = TextColor.color(52, 143, 255);
public static final TextColor INACTIVE_COLOR = NamedTextColor.GRAY;
public static final TextColor FAIL_COLOR = NamedTextColor.RED;
public static final TextComponent CHAT_PREFIX = text("SM \u00BB ").color(PRIMARY_COLOR);
@Override
public void onLoad() {
LOGGER = getComponentLogger();
PLUGIN = this;
SAVE_FILE = new File(this.getDataFolder().getAbsolutePath() + "/container.gz");
}
@Override
public void onEnable() {
getPluginManager().registerEvents(new PunishmentListener(), this);
getPluginManager().registerEvents(new CustomInventoryEvents(), this);
getPluginManager().registerEvents(new InvSeeEvents(), this);
getPluginManager().registerEvents(new EnderchestSeeEvents(), this);
getPluginManager().registerEvents(new VanishListener(), this);
registerCommand("mute", new MuteCommand());
registerCommand("ban", new BanCommand());
registerCommand("kick", new KickCommand());
registerCommand("smod", new SModCommand());
registerCommand("modlogs", new ModLogsCommand());
registerCommand("unmute", new UnmuteCommand());
registerCommand("unban", new UnbanCommand());
registerCommand("invsee", new InvseeCommand());
registerCommand("enderchestsee", new EnderchestSeeCommand());
registerCommand("vanish", new VanishCommand());
container.load(SAVE_FILE);
}
private void registerCommand(String label, TabExecutor executor){
final PluginCommand command = getCommand(label);
if (command != null) {
command.setExecutor(executor);
command.setTabCompleter(executor);
} else {
LOGGER.warn("Command %s failed to register: This command does not exist".formatted(label));
}
}
@Override
public void onDisable() {
SModeration.container.save(SModeration.SAVE_FILE);
for (Player player : Bukkit.getOnlinePlayers()) {
// in case players are still vanished when the server shuts down
if (isVanished(player)){
toggleVanish(player);
}
}
}
private static final ObjectArrayList<Player> vanishedPlayers = new ObjectArrayList<>();
public static void toggleVanish(Player player){
final boolean newStatus = !isVanished(player);
if (newStatus){
vanishedPlayers.add(player);
for (CommandSender sender : container.collectBroadcastTargets()) {
sender.sendMessage(CHAT_PREFIX.append(
player.displayName()
.colorIfAbsent(SECONDARY_COLOR)
).append(
text()
.content(" vanished.")
.color(PRIMARY_COLOR)
));
}
player.sendMessage(CHAT_PREFIX.append(text("You are now vanished.").color(PRIMARY_COLOR)));
player.setVisibleByDefault(false);
for (Player onlinePlayer : Bukkit.getOnlinePlayers()) {
if (onlinePlayer.hasPermission("smod.vanish.see")){
onlinePlayer.showEntity(PLUGIN, player);
}
}
} else {
vanishedPlayers.remove(player);
for (CommandSender sender : container.collectBroadcastTargets()) {
sender.sendMessage(CHAT_PREFIX.append(
player.displayName()
.colorIfAbsent(SECONDARY_COLOR)
).append(
text()
.content(" re-appeared.")
.color(PRIMARY_COLOR)
));
}
player.sendMessage(CHAT_PREFIX.append(text("You are no longer vanished.").color(PRIMARY_COLOR)));
player.setVisibleByDefault(true);
}
}
public static boolean isVanished(Player player){
return vanishedPlayers.contains(player);
}
public static ObjectArrayList<Player> getVanishedPlayers() {
return vanishedPlayers.clone();
}
}
@@ -1,39 +0,0 @@
package de.shiewk.smoderation.command;
import de.shiewk.smoderation.SModeration;
import de.shiewk.smoderation.util.PlayerUtil;
import org.bukkit.command.Command;
import org.bukkit.command.CommandSender;
import org.bukkit.command.TabExecutor;
import org.bukkit.entity.Player;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.List;
public class VanishCommand implements TabExecutor {
@Override
public boolean onCommand(@NotNull CommandSender sender, @NotNull Command command, @NotNull String label, @NotNull String[] args) {
Player player = null;
if (args.length > 0){
player = PlayerUtil.findOnlinePlayer(args[0]);
} else if (sender instanceof Player){
player = (Player) sender;
}
if (player != null){
SModeration.toggleVanish(player);
return true;
} else {
return false;
}
}
@Override
public @Nullable List<String> onTabComplete(@NotNull CommandSender sender, @NotNull Command command, @NotNull String label, @NotNull String[] args) {
if (args.length < 2){
return PlayerUtil.listPlayerNames();
}
return List.of();
}
}
@@ -1,17 +0,0 @@
package de.shiewk.smoderation.event;
import de.shiewk.smoderation.inventory.CustomInventory;
import org.bukkit.event.EventHandler;
import org.bukkit.event.EventPriority;
import org.bukkit.event.Listener;
import org.bukkit.event.inventory.InventoryClickEvent;
public class CustomInventoryEvents implements Listener {
@EventHandler(priority = EventPriority.HIGH, ignoreCancelled = true)
public void onInventoryClick(InventoryClickEvent event){
if (event.getInventory().getHolder() instanceof CustomInventory customInventory){
customInventory.click(event.getCurrentItem(), event);
event.setCancelled(true);
}
}
}
@@ -1,34 +0,0 @@
package de.shiewk.smoderation.listener;
import de.shiewk.smoderation.SModeration;
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
import org.bukkit.event.EventPriority;
import org.bukkit.event.Listener;
import org.bukkit.event.player.PlayerJoinEvent;
import org.bukkit.event.player.PlayerQuitEvent;
public class VanishListener implements Listener {
@EventHandler public void onPlayerQuit(PlayerQuitEvent event){
final Player player = event.getPlayer();
if (SModeration.isVanished(player)){
SModeration.toggleVanish(player);
}
for (Player vanishedPlayer : SModeration.getVanishedPlayers()) {
// to clean up visibility status
player.hideEntity(SModeration.PLUGIN, vanishedPlayer);
}
}
@EventHandler(priority = EventPriority.HIGHEST) public void onPlayerJoin(PlayerJoinEvent event){
final Player player = event.getPlayer();
if (player.hasPermission("smod.vanish.see")){
for (Player vanishedPlayer : SModeration.getVanishedPlayers()) {
// to show visible vanished players
player.showEntity(SModeration.PLUGIN, vanishedPlayer);
}
}
}
}