Telesphoreo 2022-05-19 13:39:19 -05:00
parent 15089ffd61
commit 476a9d3ff3
12 changed files with 323 additions and 251 deletions

View File

@ -1,24 +1,36 @@
For those who are wanting to contribute, we fully encourage doing so. There are a few rules we require following when contributing however. For those who are wanting to contribute, we fully encourage doing so. There are a few rules we require following when
contributing however.
## Steps ## Steps
1. Make an issue and get feedback. It's important to know if your idea will be accepted before writing any code. 1. Make an issue and get feedback. It's important to know if your idea will be accepted before writing any code.
- If it is a feature request, describe the feature and be extremely specific. - If it is a feature request, describe the feature and be extremely specific.
- If it is a bug report, ensure you include how to reproduce the bug and the expected outcome - If it is a bug report, ensure you include how to reproduce the bug and the expected outcome
- If it is an enhancement, describe your proposed changes. Ensure you are extremely specific. - If it is an enhancement, describe your proposed changes. Ensure you are extremely specific.
2. Fork this project 2. Fork this project
3. Create a new branch that describes the new feature, enhancement, or bug fix. For example, this is good: `feature/add-xyz`. This is bad: `fix-this-lol`. 3. Create a new branch that describes the new feature, enhancement, or bug fix. For example, this is
good: `feature/add-xyz`. This is bad: `fix-this-lol`.
4. Write the code that addresses your change. 4. Write the code that addresses your change.
- Keep in mind that it **must** be formatted correctly. If you are using IntelliJ, there is a `codeStyle.xml` file that tells IntelliJ how to format your code. Check this link for information on how to use the file: https://www.jetbrains.com/help/idea/configuring-code-style.html#import-export-schemes
- Keep in mind that it **must** be formatted correctly. If you are using IntelliJ, there is a `codeStyle.xml` file that
tells IntelliJ how to format your code. Check this link for information on how to use the
file: https://www.jetbrains.com/help/idea/configuring-code-style.html#import-export-schemes
- If you are not using IntelliJ, that is fine. We use Allman style so please format your code accordingly. - If you are not using IntelliJ, that is fine. We use Allman style so please format your code accordingly.
6. Push your changes to your new branch and make a PR based off of that branch. 6. Push your changes to your new branch and make a PR based off of that branch.
## Requirements for a PR ## Requirements for a PR
- The issue must be marked as approved - The issue must be marked as approved
- It must only address each specific issue. Don't make one PR for multiple issues. - It must only address each specific issue. Don't make one PR for multiple issues.
- Your PR must compile and work. If it does not compile or work, your PR will most likely be rejected. - Your PR must compile and work. If it does not compile or work, your PR will most likely be rejected.
## Code requirements ## Code requirements
- Most importantly, your code must be efficient. Your pull request may be rejected if your code is deemed inefficient or sloppy.
- Most importantly, your code must be efficient. Your pull request may be rejected if your code is deemed inefficient or
sloppy.
- Do not repeat yourself. Create functions as needed if you're using large blocks of code over and over again. - Do not repeat yourself. Create functions as needed if you're using large blocks of code over and over again.
- Do not use an excessive amount of commits when making your PR. It makes the master branch look messy. - Do not use an excessive amount of commits when making your PR. It makes the master branch look messy.
- Your code must be consistent with Plex's codebase. If a function already exists, use it. - Your code must be consistent with Plex's codebase. If a function already exists, use it.

View File

@ -7,8 +7,9 @@ import net.kyori.adventure.text.Component;
@Data @Data
@AllArgsConstructor @AllArgsConstructor
public class Message { public class Message
{
UUID sender; UUID sender;
Component message; Component message;
} }

View File

@ -2,29 +2,34 @@ package dev.plex.nush;
import javax.annotation.Nullable; import javax.annotation.Nullable;
public enum NushAction { public enum NushAction
MUTE("Mute Player", 0), {
CANCEL("Cancel", 1), MUTE("Mute Player", 0),
SMITE("Smite", 2), CANCEL("Cancel", 1),
BAN("Ban Player", 3), SMITE("Smite", 2),
ACCEPT("Accept", 4); BAN("Ban Player", 3),
ACCEPT("Accept", 4);
public final String humanReadable; public final String humanReadable;
public final int ordinal; public final int ordinal;
NushAction(String humanReadable, int ordinal) { NushAction(String humanReadable, int ordinal)
this.humanReadable = humanReadable; {
this.ordinal = ordinal; this.humanReadable = humanReadable;
} this.ordinal = ordinal;
}
@Nullable @Nullable
public static NushAction fromOrdinal(int ordinal) { public static NushAction fromOrdinal(int ordinal)
for (NushAction value : NushAction.values()) { {
if (value.ordinal == ordinal) { for (NushAction value : NushAction.values())
return value; {
} if (value.ordinal == ordinal)
} {
return value;
}
}
return null; return null;
} }
} }

View File

@ -8,33 +8,38 @@ import dev.plex.nush.handler.impl.ListenerHandler;
import java.util.Map; import java.util.Map;
import java.util.Map.Entry; import java.util.Map.Entry;
public class NushModule extends PlexModule { public class NushModule extends PlexModule
{
public static final Map<String, String> messages = Map.ofEntries( public static final Map<String, String> messages = Map.ofEntries(
Map.entry("nushToggled", "<aqua>{0} - {1} NUSH."), Map.entry("nushToggled", "<aqua>{0} - {1} NUSH."),
Map.entry("nushApply", "<yellow>Applying {0} to {1}!")); Map.entry("nushApply", "<yellow>Applying {0} to {1}!"));
public static boolean enabled = false; public static boolean enabled = false;
private static NushModule INSTANCE; private static NushModule INSTANCE;
public static NushModule getInstance() { public static NushModule getInstance()
return INSTANCE; {
} return INSTANCE;
}
@Override @Override
public void enable() { public void enable()
INSTANCE = this; {
Plex plex = getPlex(); INSTANCE = this;
for (Entry<String, String> entry : messages.entrySet()) { Plex plex = getPlex();
plex.messages.addDefault(entry.getKey(), entry.getValue()); for (Entry<String, String> entry : messages.entrySet())
} {
plex.messages.addDefault(entry.getKey(), entry.getValue());
}
new ActionHandler().init(this); new ActionHandler().init(this);
new CommandHandler().init(this); new CommandHandler().init(this);
new ListenerHandler().init(this); new ListenerHandler().init(this);
} }
@Override @Override
public void disable() { public void disable()
// Unregistering listeners / commands is handled by Plex {
} // Unregistering listeners / commands is handled by Plex
}
} }

View File

@ -18,68 +18,83 @@ import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player; import org.bukkit.entity.Player;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.Nullable;
import static dev.plex.nush.NushAction.ACCEPT; import static dev.plex.nush.NushAction.ACCEPT;
import static dev.plex.nush.NushAction.CANCEL; import static dev.plex.nush.NushAction.CANCEL;
@CommandParameters(name = "nush", aliases = "raidmode", description = "Toggle NUSH on or off.", usage = "/<command> [on | enable | off | disable | toggle]") @CommandParameters(name = "nush", aliases = "raidmode", description = "Toggle NUSH on or off.", usage = "/<command> [on | enable | off | disable | toggle]")
@CommandPermissions(level = Rank.ADMIN, permission = "plex.nush.command") @CommandPermissions(level = Rank.ADMIN, permission = "plex.nush.command")
public class NUSHCommand extends PlexCommand { public class NUSHCommand extends PlexCommand
{
@Override @Override
protected Component execute(@NotNull CommandSender commandSender, @Nullable Player player, protected Component execute(@NotNull CommandSender commandSender, @Nullable Player player,
@NotNull String[] args) { @NotNull String[] args)
if (args.length == 0) { {
NushModule.enabled = !NushModule.enabled; if (args.length == 0)
} else if (args.length == 1) { {
switch (args[0].toLowerCase()) { NushModule.enabled = !NushModule.enabled;
case "on", "enable" -> NushModule.enabled = true; }
case "off", "disable" -> NushModule.enabled = false; else if (args.length == 1)
case "toggle" -> NushModule.enabled = !NushModule.enabled; {
} switch (args[0].toLowerCase())
} else { {
if (args[0].equalsIgnoreCase("work")) { case "on", "enable" -> NushModule.enabled = true;
try { case "off", "disable" -> NushModule.enabled = false;
UUID nushIdentifier = UUID.fromString(args[1]); case "toggle" -> NushModule.enabled = !NushModule.enabled;
Message nushMessage = ActionHandler.MAP.get(nushIdentifier); }
}
else
{
if (args[0].equalsIgnoreCase("work"))
{
try
{
UUID nushIdentifier = UUID.fromString(args[1]);
Message nushMessage = ActionHandler.MAP.get(nushIdentifier);
if (nushMessage == null) { if (nushMessage == null)
return null; {
} return null;
}
NushAction action = NushAction.fromOrdinal(Integer.parseInt(args[2])); NushAction action = NushAction.fromOrdinal(Integer.parseInt(args[2]));
if (action == null) { if (action == null)
return null; {
} return null;
}
if (action == ACCEPT || action == CANCEL) { if (action == ACCEPT || action == CANCEL)
ActionHandler.resolve(nushIdentifier, action); {
return Component.text(action.humanReadable, NamedTextColor.YELLOW); ActionHandler.resolve(nushIdentifier, action);
} return Component.text(action.humanReadable, NamedTextColor.YELLOW);
}
StringBuilder command = new StringBuilder(); StringBuilder command = new StringBuilder();
command.append(action.name().toLowerCase()); command.append(action.name().toLowerCase());
command.append(" "); command.append(" ");
command.append(nushMessage.getSender()); command.append(nushMessage.getSender());
if (!command.toString().trim().isEmpty()) { if (!command.toString().trim().isEmpty())
PlexLog.debug("Dispatching command: {0}", command.toString()); {
Bukkit.dispatchCommand(commandSender, command.toString()); PlexLog.debug("Dispatching command: {0}", command.toString());
} Bukkit.dispatchCommand(commandSender, command.toString());
}
ActionHandler.resolve(nushIdentifier, action); ActionHandler.resolve(nushIdentifier, action);
return Component.text(action.humanReadable, NamedTextColor.YELLOW); return Component.text(action.humanReadable, NamedTextColor.YELLOW);
} catch (Exception ignored) { }
return null; catch (Exception ignored)
} {
} return null;
}
}
return null; return null;
} }
PlexUtils.broadcastToAdmins(messageComponent("nushToggled", commandSender.getName(), PlexUtils.broadcastToAdmins(messageComponent("nushToggled", commandSender.getName(),
NushModule.enabled ? "Enabling" : "Disabling")); NushModule.enabled ? "Enabling" : "Disabling"));
return null; return null;
} }
} }

View File

@ -2,7 +2,8 @@ package dev.plex.nush.handler;
import dev.plex.nush.NushModule; import dev.plex.nush.NushModule;
public interface Handler { public interface Handler
{
void init(NushModule module); void init(NushModule module);
} }

View File

@ -12,7 +12,6 @@ import dev.plex.util.minimessage.SafeMiniMessage;
import java.util.HashMap; import java.util.HashMap;
import java.util.Map; import java.util.Map;
import java.util.UUID; import java.util.UUID;
import net.kyori.adventure.audience.Audience;
import net.kyori.adventure.identity.Identity; import net.kyori.adventure.identity.Identity;
import net.kyori.adventure.text.Component; import net.kyori.adventure.text.Component;
import net.kyori.adventure.text.TextReplacementConfig; import net.kyori.adventure.text.TextReplacementConfig;
@ -24,58 +23,67 @@ import net.kyori.adventure.text.minimessage.tag.standard.StandardTags;
import org.bukkit.Bukkit; import org.bukkit.Bukkit;
import org.bukkit.entity.Player; import org.bukkit.entity.Player;
public class ActionHandler implements Handler { public class ActionHandler implements Handler
{
public static final Map<UUID, Message> MAP = new HashMap<>(); public static final Map<UUID, Message> MAP = new HashMap<>();
private final static TextReplacementConfig URL_REPLACEMENT_CONFIG = TextReplacementConfig.builder() private final static TextReplacementConfig URL_REPLACEMENT_CONFIG = TextReplacementConfig.builder()
.match("(https?|ftp|file)://[-a-zA-Z0-9+&@#/%?=~_|!:,.;]*[-a-zA-Z0-9+&@#/%=~_|]") .match("(https?|ftp|file)://[-a-zA-Z0-9+&@#/%?=~_|!:,.;]*[-a-zA-Z0-9+&@#/%=~_|]")
.replacement( .replacement(
(matchResult, builder) -> Component.empty().content(matchResult.group()).clickEvent( (matchResult, builder) -> Component.empty().content(matchResult.group()).clickEvent(
ClickEvent.openUrl(matchResult.group()))).build(); ClickEvent.openUrl(matchResult.group()))).build();
private static NushModule MODULE; private static NushModule MODULE;
public static void resolve(UUID uuid, NushAction action) { public static void resolve(UUID uuid, NushAction action)
Message message = MAP.get(uuid); {
if (message == null) { Message message = MAP.get(uuid);
return; if (message == null)
} {
if (action == NushAction.ACCEPT) { return;
for (Player player : Bukkit.getOnlinePlayers()) { }
if (player.getUniqueId() != message.getSender()) { if (action == NushAction.ACCEPT)
player.sendMessage(Identity.identity(message.getSender()), getMessage(message)); {
} for (Player player : Bukkit.getOnlinePlayers())
} {
} if (player.getUniqueId() != message.getSender())
MAP.remove(uuid); {
} player.sendMessage(Identity.identity(message.getSender()), getMessage(message));
}
}
}
MAP.remove(uuid);
}
public static Component getMessage(Message message) { public static Component getMessage(Message message)
String text = PlexUtils.getTextFromComponent(message.getMessage()); {
Plex plex = MODULE.getPlex(); String text = PlexUtils.getTextFromComponent(message.getMessage());
PlexPlayer plexPlayer = DataUtils.getPlayer(message.getSender()); Plex plex = MODULE.getPlex();
Component prefix = plex.getRankManager().getPrefix(plexPlayer); PlexPlayer plexPlayer = DataUtils.getPlayer(message.getSender());
Component component = Component.empty(); Component prefix = plex.getRankManager().getPrefix(plexPlayer);
Component component = Component.empty();
if (prefix != null) { if (prefix != null)
component = component.append(prefix); {
} component = component.append(prefix);
}
return component.append(Component.space()).append( return component.append(Component.space()).append(
PlexUtils.mmDeserialize(plex.config.getString("chat.name-color", "<white>") + PlexUtils.mmDeserialize(plex.config.getString("chat.name-color", "<white>") +
MiniMessage.builder().tags( MiniMessage.builder().tags(
TagResolver.resolver(StandardTags.color(), StandardTags.rainbow(), TagResolver.resolver(StandardTags.color(), StandardTags.rainbow(),
StandardTags.decorations(), StandardTags.gradient(), StandardTags.decorations(), StandardTags.gradient(),
StandardTags.transition() StandardTags.transition()
)).build().serialize(plexPlayer.getPlayer().displayName()))) )).build().serialize(plexPlayer.getPlayer().displayName())))
.append(Component.space()) .append(Component.space())
.append(Component.text("»").color(NamedTextColor.GRAY)).append(Component.space()) .append(Component.text("»").color(NamedTextColor.GRAY)).append(Component.space())
.append( .append(
SafeMiniMessage.mmDeserializeWithoutEvents(text)) SafeMiniMessage.mmDeserializeWithoutEvents(text))
.replaceText(URL_REPLACEMENT_CONFIG); .replaceText(URL_REPLACEMENT_CONFIG);
} }
@Override @Override
public void init(NushModule module) { public void init(NushModule module)
MODULE = NushModule.getInstance(); {
} MODULE = NushModule.getInstance();
}
} }

View File

@ -4,10 +4,12 @@ import dev.plex.nush.NushModule;
import dev.plex.nush.command.impl.NUSHCommand; import dev.plex.nush.command.impl.NUSHCommand;
import dev.plex.nush.handler.Handler; import dev.plex.nush.handler.Handler;
public class CommandHandler implements Handler { public class CommandHandler implements Handler
{
@Override @Override
public void init(NushModule module) { public void init(NushModule module)
module.registerCommand(new NUSHCommand()); {
} module.registerCommand(new NUSHCommand());
}
} }

View File

@ -5,11 +5,13 @@ import dev.plex.nush.handler.Handler;
import dev.plex.nush.listener.impl.ChatListener; import dev.plex.nush.listener.impl.ChatListener;
import dev.plex.nush.listener.impl.JoinListener; import dev.plex.nush.listener.impl.JoinListener;
public class ListenerHandler implements Handler { public class ListenerHandler implements Handler
{
@Override @Override
public void init(NushModule module) { public void init(NushModule module)
module.registerListener(new ChatListener()); {
module.registerListener(new JoinListener()); module.registerListener(new ChatListener());
} module.registerListener(new JoinListener());
}
} }

View File

@ -22,52 +22,60 @@ import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler; import org.bukkit.event.EventHandler;
import org.bukkit.event.EventPriority; import org.bukkit.event.EventPriority;
public class ChatListener extends PlexListener { public class ChatListener extends PlexListener
{
@EventHandler(priority = EventPriority.HIGHEST) @EventHandler(priority = EventPriority.HIGHEST)
public void onChat(AsyncChatEvent event) { public void onChat(AsyncChatEvent event)
if(event.isCancelled()) return; {
Player player = event.getPlayer(); if (event.isCancelled())
Instant firstJoined = Instant.ofEpochMilli(player.getFirstPlayed()); {
Instant rightNow = Instant.now(); return;
long difference = (Duration.between(firstJoined, rightNow).getSeconds() / 60); }
if (difference >= 15) { Player player = event.getPlayer();
PlexLog.debug("{0} has been on the server for {1} minutes, so Nush will skip them.", player.getName(), difference); Instant firstJoined = Instant.ofEpochMilli(player.getFirstPlayed());
return; Instant rightNow = Instant.now();
} long difference = (Duration.between(firstJoined, rightNow).getSeconds() / 60);
if (difference >= 15)
{
PlexLog.debug("{0} has been on the server for {1} minutes, so Nush will skip them.", player.getName(), difference);
return;
}
NushModule module = NushModule.getInstance(); NushModule module = NushModule.getInstance();
Plex plex = module.getPlex(); Plex plex = module.getPlex();
PlexPlayer plexPlayer = DataUtils.getPlayer(player.getUniqueId()); PlexPlayer plexPlayer = DataUtils.getPlayer(player.getUniqueId());
RankManager rankManager = plex.getRankManager(); RankManager rankManager = plex.getRankManager();
if (rankManager.isAdmin(plexPlayer)) { if (rankManager.isAdmin(plexPlayer))
PlexLog.debug("{0} is an admin so Nush will skip them.", player.getName()); {
return; // we needn't process the chat message if they're an admin PlexLog.debug("{0} is an admin so Nush will skip them.", player.getName());
} return; // we needn't process the chat message if they're an admin
}
event.setCancelled(true); event.setCancelled(true);
UUID key = UUID.randomUUID(); UUID key = UUID.randomUUID();
Message message = new Message(event.getPlayer().getUniqueId(), event.originalMessage()); Message message = new Message(event.getPlayer().getUniqueId(), event.originalMessage());
ActionHandler.MAP.put(key, message); ActionHandler.MAP.put(key, message);
Component component = ActionHandler.getMessage(message); Component component = ActionHandler.getMessage(message);
// Send the user the message so they think it got sent // Send the user the message so they think it got sent
player.sendMessage(component); player.sendMessage(component);
component = component.append(Component.text("\n")); component = component.append(Component.text("\n"));
for (NushAction value : NushAction.values()) { for (NushAction value : NushAction.values())
String command = String.format("/nush work %s %d", key, value.ordinal); {
component = component.append( String command = String.format("/nush work %s %d", key, value.ordinal);
Component.text(String.format("[%s] ", value.humanReadable)) component = component.append(
.clickEvent(ClickEvent.runCommand(command)) Component.text(String.format("[%s] ", value.humanReadable))
.hoverEvent( .clickEvent(ClickEvent.runCommand(command))
Component.text(command, NamedTextColor.YELLOW) .hoverEvent(
) Component.text(command, NamedTextColor.YELLOW)
); )
} );
}
PlexUtils.broadcastToAdmins(component); PlexUtils.broadcastToAdmins(component);
} }
} }

View File

@ -10,22 +10,25 @@ import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler; import org.bukkit.event.EventHandler;
import org.bukkit.event.player.PlayerJoinEvent; import org.bukkit.event.player.PlayerJoinEvent;
public class JoinListener extends PlexListener { public class JoinListener extends PlexListener
{
@EventHandler @EventHandler
public void onPlayerJoin(PlayerJoinEvent event) { public void onPlayerJoin(PlayerJoinEvent event)
Player player = event.getPlayer(); {
NushModule module = NushModule.getInstance(); Player player = event.getPlayer();
Plex plex = module.getPlex(); NushModule module = NushModule.getInstance();
PlexPlayer plexPlayer = DataUtils.getPlayer(player.getUniqueId()); Plex plex = module.getPlex();
RankManager rankManager = plex.getRankManager(); PlexPlayer plexPlayer = DataUtils.getPlayer(player.getUniqueId());
RankManager rankManager = plex.getRankManager();
if (!rankManager.isAdmin(plexPlayer)) { if (!rankManager.isAdmin(plexPlayer))
return; // we only want to add admins {
} return; // we only want to add admins
}
/*if (ChatListener.work.containsKey()) /*if (ChatListener.work.containsKey())
{ {
}*/ }*/
} }
} }

View File

@ -10,42 +10,52 @@ import java.util.Collections;
import java.util.HashSet; import java.util.HashSet;
import java.util.Set; import java.util.Set;
public class ReflectionsUtil { public class ReflectionsUtil
{
@SuppressWarnings("UnstableApiUsage") @SuppressWarnings("UnstableApiUsage")
public static Set<Class<?>> getClassesFrom(String packageName) { public static Set<Class<?>> getClassesFrom(String packageName)
Set<Class<?>> classes = new HashSet<>(); {
try { Set<Class<?>> classes = new HashSet<>();
ClassPath path = ClassPath.from(Plex.class.getClassLoader()); try
ImmutableSet<ClassPath.ClassInfo> infoSet = path.getTopLevelClasses(packageName); {
infoSet.forEach(info -> ClassPath path = ClassPath.from(Plex.class.getClassLoader());
{ ImmutableSet<ClassPath.ClassInfo> infoSet = path.getTopLevelClasses(packageName);
try { infoSet.forEach(info ->
Class<?> clazz = Class.forName(info.getName()); {
classes.add(clazz); try
} catch (ClassNotFoundException ex) { {
PlexLog.error("Unable to find class " + info.getName() + " in " + packageName); Class<?> clazz = Class.forName(info.getName());
} classes.add(clazz);
}); }
} catch (IOException ex) { catch (ClassNotFoundException ex)
PlexLog.error("Something went wrong while fetching classes from " + packageName); {
throw new RuntimeException(ex); PlexLog.error("Unable to find class " + info.getName() + " in " + packageName);
} }
return Collections.unmodifiableSet(classes); });
} }
catch (IOException ex)
{
PlexLog.error("Something went wrong while fetching classes from " + packageName);
throw new RuntimeException(ex);
}
return Collections.unmodifiableSet(classes);
}
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
public static <T> Set<Class<? extends T>> getClassesBySubType(String packageName, public static <T> Set<Class<? extends T>> getClassesBySubType(String packageName,
Class<T> subType) { Class<T> subType)
Set<Class<?>> loadedClasses = getClassesFrom(packageName); {
Set<Class<? extends T>> classes = new HashSet<>(); Set<Class<?>> loadedClasses = getClassesFrom(packageName);
loadedClasses.forEach(clazz -> Set<Class<? extends T>> classes = new HashSet<>();
{ loadedClasses.forEach(clazz ->
if (clazz.getSuperclass() == subType || Arrays.asList(clazz.getInterfaces()) {
.contains(subType)) { if (clazz.getSuperclass() == subType || Arrays.asList(clazz.getInterfaces())
classes.add((Class<? extends T>) clazz); .contains(subType))
} {
}); classes.add((Class<? extends T>)clazz);
return Collections.unmodifiableSet(classes); }
} });
return Collections.unmodifiableSet(classes);
}
} }