From a9fdb858fd10665b4709628c1c73cd23176395b2 Mon Sep 17 00:00:00 2001 From: JvstvsHD <79066214+JvstvsHD@users.noreply.github.com> Date: Sat, 13 Jul 2024 15:57:39 +0200 Subject: [PATCH] Implement events II - Implemented event calling - fix mutes not working properly with the paper-extension This closes #12. --- .../java/de/jvstvshd/necrify/api/Necrify.java | 41 ++++++++++-- .../necrify/api/event/NecrifyEvent.java | 23 +++++++ .../api/event/origin/ClassEventOrigin.java | 33 +++++++++ .../necrify/api/event/origin/EventOrigin.java | 38 +++++++++++ .../api/event/origin/StringEventOrigin.java | 33 +++++++++ .../punishment/PunishmentChangedEvent.java | 4 +- .../api/event/user/UserDeletedEvent.java | 25 ++----- .../necrify/api/punishment/Punishment.java | 17 +++-- .../api/punishment/PunishmentManager.java | 2 +- .../api/punishment/util/PlayerResolver.java | 2 +- .../necrify/api/user/NecrifyUser.java | 29 ++++++-- .../necrify/api/user/UserDeletionReason.java | 36 ++++++++++ .../necrify/paper/listeners/ChatListener.java | 16 ++++- .../listeners/MessagingChannelListener.java | 3 + .../necrify/common/AbstractNecrifyPlugin.java | 52 ++++++++++++++ .../necrify/common/plugin/MuteData.java | 1 + .../common/punishment/AbstractPunishment.java | 67 ++++++++++++++----- .../AbstractTemporalPunishment.java | 30 ++++----- .../necrify/common/punishment/NecrifyBan.java | 16 ++--- .../common/punishment/NecrifyKick.java | 10 ++- .../common/punishment/NecrifyMute.java | 42 ++---------- plugin/build.gradle.kts | 3 +- .../MessagingChannelCommunicator.java | 50 +++++++++++++- ...Plugin.java => NecrifyVelocityPlugin.java} | 59 +++++++++++----- .../necrify/velocity/commands/BanCommand.java | 6 +- .../velocity/commands/KickCommand.java | 6 +- .../velocity/commands/MuteCommand.java | 10 +-- .../velocity/commands/PunishmentCommand.java | 8 +-- .../commands/PunishmentRemovalCommand.java | 15 +++-- .../velocity/commands/TempbanCommand.java | 6 +- .../velocity/commands/TempmuteCommand.java | 8 +-- .../velocity/commands/WhitelistCommand.java | 6 +- .../impl/DefaultPunishmentManager.java | 14 ++-- .../necrify/velocity/impl/VelocityKick.java | 10 ++- .../velocity/internal/PunishmentHelper.java | 8 +-- .../necrify/velocity/internal/Util.java | 8 +-- .../velocity/listener/ConnectListener.java | 8 +-- .../ResourceBundleMessageProvider.java | 6 +- .../necrify/velocity/user/VelocityUser.java | 57 ++++++++-------- .../velocity/user/VelocityUserManager.java | 63 ++++++++++++++--- 40 files changed, 632 insertions(+), 239 deletions(-) create mode 100644 api/src/main/java/de/jvstvshd/necrify/api/event/origin/ClassEventOrigin.java create mode 100644 api/src/main/java/de/jvstvshd/necrify/api/event/origin/EventOrigin.java create mode 100644 api/src/main/java/de/jvstvshd/necrify/api/event/origin/StringEventOrigin.java create mode 100644 api/src/main/java/de/jvstvshd/necrify/api/user/UserDeletionReason.java create mode 100644 plugin-common/src/main/java/de/jvstvshd/necrify/common/AbstractNecrifyPlugin.java rename plugin/src/main/java/de/jvstvshd/necrify/velocity/{NecrifyPlugin.java => NecrifyVelocityPlugin.java} (84%) diff --git a/api/src/main/java/de/jvstvshd/necrify/api/Necrify.java b/api/src/main/java/de/jvstvshd/necrify/api/Necrify.java index 3a6c454c..7645615e 100644 --- a/api/src/main/java/de/jvstvshd/necrify/api/Necrify.java +++ b/api/src/main/java/de/jvstvshd/necrify/api/Necrify.java @@ -24,6 +24,7 @@ package de.jvstvshd.necrify.api; +import de.jvstvshd.necrify.api.event.EventDispatcher; import de.jvstvshd.necrify.api.message.MessageProvider; import de.jvstvshd.necrify.api.punishment.Punishment; import de.jvstvshd.necrify.api.punishment.PunishmentManager; @@ -68,33 +69,50 @@ public interface Necrify { * @deprecated Will be removed with {@link PunishmentManager}. */ @Deprecated(since = "1.2.0", forRemoval = true) - @ApiStatus.ScheduledForRemoval(inVersion = "1.2.0") + @ApiStatus.ScheduledForRemoval(inVersion = "1.3.0") PunishmentManager getPunishmentManager(); /** * @deprecated Will be removed with {@link PunishmentManager}. */ @Deprecated(since = "1.2.0", forRemoval = true) - @ApiStatus.ScheduledForRemoval(inVersion = "1.2.0") + @ApiStatus.ScheduledForRemoval(inVersion = "1.3.0") void setPunishmentManager(PunishmentManager punishmentManager); /** * @deprecated Will be removed with {@link PunishmentManager}. */ @Deprecated(since = "1.2.0", forRemoval = true) - @ApiStatus.ScheduledForRemoval(inVersion = "1.2.0") + @ApiStatus.ScheduledForRemoval(inVersion = "1.3.0") PlayerResolver getPlayerResolver(); /** * @deprecated Will be removed with {@link PunishmentManager}. */ @Deprecated(since = "1.2.0", forRemoval = true) - @ApiStatus.ScheduledForRemoval(inVersion = "1.2.0") + @ApiStatus.ScheduledForRemoval(inVersion = "1.3.0") void setPlayerResolver(PlayerResolver playerResolver); + /** + * Returns the executor service used by the plugin. + * + * @return the executor service. + * @deprecated Rename in favor of {@link #getExecutor()}. + */ + @ApiStatus.ScheduledForRemoval(inVersion = "1.3.0") + @Deprecated(since = "1.2.0", forRemoval = true) @NotNull ExecutorService getService(); + /** + * Returns the executor service used by the plugin. This {@link ExecutorService} is used for asynchronous operations, + * such as database queries, event dispatching or time-consuming network/IO operations. + * + * @return the executor service. + */ + @NotNull + ExecutorService getExecutor(); + @NotNull MessageProvider getMessageProvider(); @@ -116,4 +134,19 @@ public interface Necrify { default CompletableFuture> getPunishment(@NotNull UUID punishmentId) { return getPunishmentManager().getPunishment(punishmentId, getService()); } + + /** + * Returns the system's event dispatcher. + * + * @return the event dispatcher. + */ + @NotNull + EventDispatcher getEventDispatcher(); + + /** + * Sets the event dispatcher. + * + * @param eventDispatcher the event dispatcher to set. + */ + void setEventDispatcher(@NotNull EventDispatcher eventDispatcher); } diff --git a/api/src/main/java/de/jvstvshd/necrify/api/event/NecrifyEvent.java b/api/src/main/java/de/jvstvshd/necrify/api/event/NecrifyEvent.java index 521d1f2f..4dc74c46 100644 --- a/api/src/main/java/de/jvstvshd/necrify/api/event/NecrifyEvent.java +++ b/api/src/main/java/de/jvstvshd/necrify/api/event/NecrifyEvent.java @@ -24,6 +24,8 @@ package de.jvstvshd.necrify.api.event; +import de.jvstvshd.necrify.api.event.origin.EventOrigin; + /** * Represents an event that can be dispatched by the {@link EventDispatcher}. * All events must extend this class. @@ -33,6 +35,7 @@ public abstract class NecrifyEvent { private final String name; + private EventOrigin origin = null; private EventDispatcher executingDispatcher = null; public NecrifyEvent(String name) { @@ -62,4 +65,24 @@ NecrifyEvent setExecutingDispatcher(EventDispatcher executingDispatcher) { this.executingDispatcher = executingDispatcher; return this; } + + /** + * Gets the origin of this event. + * + * @return the origin of this event. + */ + public EventOrigin getOrigin() { + return origin; + } + + /** + * Sets the origin of this event. + * + * @param origin the origin of this event. + * @return this event. + */ + public NecrifyEvent setOrigin(EventOrigin origin) { + this.origin = origin; + return this; + } } diff --git a/api/src/main/java/de/jvstvshd/necrify/api/event/origin/ClassEventOrigin.java b/api/src/main/java/de/jvstvshd/necrify/api/event/origin/ClassEventOrigin.java new file mode 100644 index 00000000..025c5bae --- /dev/null +++ b/api/src/main/java/de/jvstvshd/necrify/api/event/origin/ClassEventOrigin.java @@ -0,0 +1,33 @@ +/* + * This file is part of Necrify (formerly Velocity Punishment), which is licensed under the MIT license. + * + * Copyright (c) 2022-2024 JvstvsHD + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +package de.jvstvshd.necrify.api.event.origin; + +public record ClassEventOrigin(Class origin) implements EventOrigin { + + @Override + public boolean originatesFrom(Object object) { + return origin.isInstance(object); + } +} diff --git a/api/src/main/java/de/jvstvshd/necrify/api/event/origin/EventOrigin.java b/api/src/main/java/de/jvstvshd/necrify/api/event/origin/EventOrigin.java new file mode 100644 index 00000000..bdcf8c2d --- /dev/null +++ b/api/src/main/java/de/jvstvshd/necrify/api/event/origin/EventOrigin.java @@ -0,0 +1,38 @@ +/* + * This file is part of Necrify (formerly Velocity Punishment), which is licensed under the MIT license. + * + * Copyright (c) 2022-2024 JvstvsHD + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +package de.jvstvshd.necrify.api.event.origin; + +public interface EventOrigin { + + static EventOrigin ofString(String name) { + return new StringEventOrigin(name); + } + + static EventOrigin ofClass(Class clazz) { + return new ClassEventOrigin(clazz); + } + + boolean originatesFrom(Object object); +} diff --git a/api/src/main/java/de/jvstvshd/necrify/api/event/origin/StringEventOrigin.java b/api/src/main/java/de/jvstvshd/necrify/api/event/origin/StringEventOrigin.java new file mode 100644 index 00000000..4eb80c53 --- /dev/null +++ b/api/src/main/java/de/jvstvshd/necrify/api/event/origin/StringEventOrigin.java @@ -0,0 +1,33 @@ +/* + * This file is part of Necrify (formerly Velocity Punishment), which is licensed under the MIT license. + * + * Copyright (c) 2022-2024 JvstvsHD + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +package de.jvstvshd.necrify.api.event.origin; + +public record StringEventOrigin(String origin) implements EventOrigin { + + @Override + public boolean originatesFrom(Object object) { + return object instanceof String string && string.equals(origin); + } +} diff --git a/api/src/main/java/de/jvstvshd/necrify/api/event/punishment/PunishmentChangedEvent.java b/api/src/main/java/de/jvstvshd/necrify/api/event/punishment/PunishmentChangedEvent.java index 48c70ed6..102777d6 100644 --- a/api/src/main/java/de/jvstvshd/necrify/api/event/punishment/PunishmentChangedEvent.java +++ b/api/src/main/java/de/jvstvshd/necrify/api/event/punishment/PunishmentChangedEvent.java @@ -36,8 +36,8 @@ public class PunishmentChangedEvent extends PunishmentEvent { private final Punishment oldPunishment; - public PunishmentChangedEvent(String name, Punishment punishment, Punishment oldPunishment) { - super(name, punishment); + public PunishmentChangedEvent(Punishment punishment, Punishment oldPunishment) { + super("punishment_changed", punishment); this.oldPunishment = oldPunishment; } diff --git a/api/src/main/java/de/jvstvshd/necrify/api/event/user/UserDeletedEvent.java b/api/src/main/java/de/jvstvshd/necrify/api/event/user/UserDeletedEvent.java index 3fa4b01b..9f339925 100644 --- a/api/src/main/java/de/jvstvshd/necrify/api/event/user/UserDeletedEvent.java +++ b/api/src/main/java/de/jvstvshd/necrify/api/event/user/UserDeletedEvent.java @@ -25,6 +25,7 @@ package de.jvstvshd.necrify.api.event.user; import de.jvstvshd.necrify.api.user.NecrifyUser; +import de.jvstvshd.necrify.api.user.UserDeletionReason; /** * Event that is fired when a user is deleted. @@ -33,7 +34,7 @@ */ public class UserDeletedEvent extends UserEvent { - private final Reason reason; + private final UserDeletionReason reason; /** * Creates a new UserDeletedEvent. @@ -41,30 +42,12 @@ public class UserDeletedEvent extends UserEvent { * @param user The user that was deleted. * @param reason The reason why the user was deleted. */ - public UserDeletedEvent(NecrifyUser user, Reason reason) { + public UserDeletedEvent(NecrifyUser user, UserDeletionReason reason) { super("user_deleted", user); this.reason = reason; } - public Reason getReason() { + public UserDeletionReason getReason() { return reason; } - - /** - * The reason why the user was deleted. - * - * @since 1.2.0 - */ - public enum Reason { - - /** - * The user was deleted because the user requested it. This may due to data protection regulation. - */ - USER_REQUESTED, - - /** - * The user was deleted by the system or a team member. - */ - USER_DELETED - } } diff --git a/api/src/main/java/de/jvstvshd/necrify/api/punishment/Punishment.java b/api/src/main/java/de/jvstvshd/necrify/api/punishment/Punishment.java index cf87a517..cc17d6cc 100644 --- a/api/src/main/java/de/jvstvshd/necrify/api/punishment/Punishment.java +++ b/api/src/main/java/de/jvstvshd/necrify/api/punishment/Punishment.java @@ -28,6 +28,8 @@ import de.jvstvshd.necrify.api.punishment.util.ReasonHolder; import de.jvstvshd.necrify.api.user.NecrifyUser; import net.kyori.adventure.text.Component; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; import java.time.LocalDateTime; import java.util.UUID; @@ -51,7 +53,7 @@ public interface Punishment extends ReasonHolder { * Punishes the player finally. * * @return a {@link CompletableFuture} containing the exerted punishment - * @throws PunishmentException if the punishment could not be exerted + * @throws PunishmentException if the punishment could not be exerted (inside the future) */ CompletableFuture punish(); @@ -59,19 +61,19 @@ public interface Punishment extends ReasonHolder { * Cancels this punishment thus allowing the player e.g. to join the server * * @return a {@link CompletableFuture} containing the cancelled punishment - * @throws PunishmentException if the punishment could not be cancelled + * @throws PunishmentException if the punishment could not be cancelled (inside the future) */ CompletableFuture cancel(); /** * Changes the duration and reason of this punishment. This method can be used if a player created an appeal an it was accepted. * - * @param newReason the new reason which should be displayed to the player + * @param newReason the new reason which should be displayed to the player or null if the reason should not be changed * @return a {@link CompletableFuture} containing the new punishment * @throws PunishmentException if the punishment could not be changed * @see #cancel() */ - CompletableFuture change(Component newReason); + CompletableFuture change(@Nullable Component newReason); /** * Returns the type of this punishment. By default, this is a field from {@link StandardPunishmentType}. @@ -79,23 +81,28 @@ public interface Punishment extends ReasonHolder { * @return the type of this punishment * @see StandardPunishmentType */ + @NotNull PunishmentType getType(); /** * @return the id of this punishment. */ + @NotNull UUID getPunishmentUuid(); /** + * This will return the value of {@link NecrifyUser#getUuid()} from {@link #getUser()}. + * * @return the uuid of the punished player. * @since 1.0.1 - * @deprecated Consider using {@link #getUser()} instead. */ + @NotNull UUID getUuid(); /** * @return the user this punishment is affecting * @since 1.2.0 */ + @NotNull NecrifyUser getUser(); } diff --git a/api/src/main/java/de/jvstvshd/necrify/api/punishment/PunishmentManager.java b/api/src/main/java/de/jvstvshd/necrify/api/punishment/PunishmentManager.java index 79e1aa77..4b3e89a5 100644 --- a/api/src/main/java/de/jvstvshd/necrify/api/punishment/PunishmentManager.java +++ b/api/src/main/java/de/jvstvshd/necrify/api/punishment/PunishmentManager.java @@ -43,7 +43,7 @@ * NecrifyUser. */ @Deprecated(since = "1.2.0", forRemoval = true) -@ApiStatus.ScheduledForRemoval(inVersion = "1.2.0") +@ApiStatus.ScheduledForRemoval(inVersion = "1.3.0") public interface PunishmentManager { /** diff --git a/api/src/main/java/de/jvstvshd/necrify/api/punishment/util/PlayerResolver.java b/api/src/main/java/de/jvstvshd/necrify/api/punishment/util/PlayerResolver.java index b10c9c9d..35c2176f 100644 --- a/api/src/main/java/de/jvstvshd/necrify/api/punishment/util/PlayerResolver.java +++ b/api/src/main/java/de/jvstvshd/necrify/api/punishment/util/PlayerResolver.java @@ -43,7 +43,7 @@ * NecrifyUser. */ @Deprecated(since = "1.2.0", forRemoval = true) -@ApiStatus.ScheduledForRemoval(inVersion = "1.2.0") +@ApiStatus.ScheduledForRemoval(inVersion = "1.3.0") public interface PlayerResolver { /** diff --git a/api/src/main/java/de/jvstvshd/necrify/api/user/NecrifyUser.java b/api/src/main/java/de/jvstvshd/necrify/api/user/NecrifyUser.java index 02376952..ba2b9137 100644 --- a/api/src/main/java/de/jvstvshd/necrify/api/user/NecrifyUser.java +++ b/api/src/main/java/de/jvstvshd/necrify/api/user/NecrifyUser.java @@ -32,6 +32,7 @@ import org.jetbrains.annotations.Nullable; import java.util.List; +import java.util.Optional; import java.util.UUID; import java.util.concurrent.CompletableFuture; @@ -133,6 +134,7 @@ public interface NecrifyUser extends CommandSender { /** * This method queries all punishments with the given {@link UUID} of a player and returns them in a list. + * All punishments that are returned are still running, i.e. they are not expired or revoked. * * @param the type of punishment(s), matching them in type * @param types the types of punishments to query. If no type is given, all punishments that are stored as running @@ -173,26 +175,39 @@ public interface NecrifyUser extends CommandSender { /** * Deletes this user from the system. This will also delete all punishments associated with this user. */ - void delete(); + void delete(@NotNull UserDeletionReason reason); /** - * Method to add punishments to users. This method is only meant to be used until events are implemented. + * Gets a punishment by its UUID. This punishment has to be valid, i.e. it is still running. A punishment that + * was revoked or expired is not returned by this method. * - * @param punishment the punishment to add. + * @param punishmentUuid the UUID of the punishment. + * @return the punishment with the given UUID, if it exists. */ + default Optional getPunishment(@NotNull UUID punishmentUuid) { + return getPunishments().stream().filter(punishment -> punishment.getPunishmentUuid().equals(punishmentUuid)).findFirst(); + } + + /* *//** + * Method to add punishments to users. This method is only meant to be used until events are implemented and all + * other components can be used so this method will not be used. + * + * @param punishment the punishment to add. + *//* @Deprecated(forRemoval = true) @ApiStatus.ScheduledForRemoval(inVersion = "1.2.0") default void addPunishment(Punishment punishment) { } - /** - * Method to remove punishments from users. This method is only meant to be used until events are implemented. + *//** + * Method to remove punishments from users. This method is only meant to be used until events are implemented and all + * other components can be used so this method will not be used. * This does not cancel the punishment, it only removes it from the user's punishment list. * * @param punishment the punishment to remove. - */ + *//* @Deprecated(forRemoval = true) @ApiStatus.ScheduledForRemoval(inVersion = "1.2.0") default void removePunishment(Punishment punishment) { - } + }*/ } diff --git a/api/src/main/java/de/jvstvshd/necrify/api/user/UserDeletionReason.java b/api/src/main/java/de/jvstvshd/necrify/api/user/UserDeletionReason.java new file mode 100644 index 00000000..3caeead3 --- /dev/null +++ b/api/src/main/java/de/jvstvshd/necrify/api/user/UserDeletionReason.java @@ -0,0 +1,36 @@ +/* + * This file is part of Necrify (formerly Velocity Punishment), which is licensed under the MIT license. + * + * Copyright (c) 2022-2024 JvstvsHD + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +package de.jvstvshd.necrify.api.user; + +public interface UserDeletionReason { + + UserDeletionReason USER_REQUESTED = new UserDeletionReasonImpl("User requested deletion."); + UserDeletionReason USER_DELETED = new UserDeletionReasonImpl("User was deleted by the system or a team member."); + + String reason(); + + record UserDeletionReasonImpl(String reason) implements UserDeletionReason { + } +} diff --git a/paper-extension/src/main/java/de/jvstvshd/necrify/paper/listeners/ChatListener.java b/paper-extension/src/main/java/de/jvstvshd/necrify/paper/listeners/ChatListener.java index eacf39eb..9c83b8e7 100644 --- a/paper-extension/src/main/java/de/jvstvshd/necrify/paper/listeners/ChatListener.java +++ b/paper-extension/src/main/java/de/jvstvshd/necrify/paper/listeners/ChatListener.java @@ -29,6 +29,8 @@ import org.bukkit.event.EventHandler; import org.bukkit.event.Listener; +import java.time.LocalDateTime; +import java.util.ArrayDeque; import java.util.Comparator; import java.util.stream.Collectors; @@ -45,8 +47,16 @@ public void onChat(AsyncChatEvent event) { var mutes = plugin.cachedMutes().stream().filter(muteData -> event.getPlayer().getUniqueId().equals(muteData.getPlayer().getUniqueId())).collect(Collectors.toList()); if (mutes.isEmpty()) return; mutes.sort(Comparator.comparing(MuteInformation::getDuration)); - var mute = mutes.get(0); - event.setCancelled(true); - event.getPlayer().sendMessage(mute.getReason()); + var queue = new ArrayDeque<>(mutes); + while (!queue.isEmpty()) { + var mute = queue.poll(); + if (!mute.getDuration().isPermanent() && mute.getDuration().expiration().isBefore(LocalDateTime.now())) { + plugin.cachedMutes().remove(mute); + continue; + } + event.setCancelled(true); + event.getPlayer().sendMessage(mute.getReason()); + break; + } } } diff --git a/paper-extension/src/main/java/de/jvstvshd/necrify/paper/listeners/MessagingChannelListener.java b/paper-extension/src/main/java/de/jvstvshd/necrify/paper/listeners/MessagingChannelListener.java index 8df74c54..f5340730 100644 --- a/paper-extension/src/main/java/de/jvstvshd/necrify/paper/listeners/MessagingChannelListener.java +++ b/paper-extension/src/main/java/de/jvstvshd/necrify/paper/listeners/MessagingChannelListener.java @@ -43,6 +43,7 @@ public MessagingChannelListener(NecrifyPaperPlugin plugin) { @SuppressWarnings("UnstableApiUsage") @Override public void onPluginMessageReceived(@NotNull String channel, @NotNull Player player, byte @NotNull [] message) { + if (message.length == 0) return; var input = ByteStreams.newDataInput(message); var content = input.readUTF(); MuteData data; @@ -59,6 +60,8 @@ public void onPluginMessageReceived(@NotNull String channel, @NotNull Player pla plugin.cachedMutes().removeIf(muteInformation -> muteInformation.getPunishmentUUID().equals(mute.getPunishmentUUID())); case MuteData.UPDATE -> plugin.cachedMutes().stream().filter(muteInformation -> muteInformation.getPunishmentUUID().equals(mute.getPunishmentUUID())).findFirst().ifPresent(muteInformation -> muteInformation.updateTo(mute)); + case MuteData.RESET -> + plugin.cachedMutes().stream().filter(muteInformation -> muteInformation.getPlayer().getUniqueId().equals(mute.getPlayer().getUniqueId())).forEach(plugin.cachedMutes()::remove); } } } diff --git a/plugin-common/src/main/java/de/jvstvshd/necrify/common/AbstractNecrifyPlugin.java b/plugin-common/src/main/java/de/jvstvshd/necrify/common/AbstractNecrifyPlugin.java new file mode 100644 index 00000000..a06864df --- /dev/null +++ b/plugin-common/src/main/java/de/jvstvshd/necrify/common/AbstractNecrifyPlugin.java @@ -0,0 +1,52 @@ +/* + * This file is part of Necrify (formerly Velocity Punishment), which is licensed under the MIT license. + * + * Copyright (c) 2022-2024 JvstvsHD + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +package de.jvstvshd.necrify.common; + +import de.jvstvshd.necrify.api.Necrify; +import org.jetbrains.annotations.NotNull; + +import java.util.concurrent.ExecutorService; + +public abstract class AbstractNecrifyPlugin implements Necrify { + + protected ExecutorService executorService; + + public AbstractNecrifyPlugin(ExecutorService executorService) { + this.executorService = executorService; + } + + public AbstractNecrifyPlugin() { + } + + @Override + public @NotNull ExecutorService getExecutor() { + return executorService; + } + + @Override + public @NotNull ExecutorService getService() { + return getExecutor(); + } +} diff --git a/plugin-common/src/main/java/de/jvstvshd/necrify/common/plugin/MuteData.java b/plugin-common/src/main/java/de/jvstvshd/necrify/common/plugin/MuteData.java index d9e5416d..a9ba0511 100644 --- a/plugin-common/src/main/java/de/jvstvshd/necrify/common/plugin/MuteData.java +++ b/plugin-common/src/main/java/de/jvstvshd/necrify/common/plugin/MuteData.java @@ -39,6 +39,7 @@ public class MuteData { public static final int ADD = 0; public static final int REMOVE = 1; public static final int UPDATE = 2; + public static final int RESET = 3; public static final int UNKNOWN = -1; private final UUID uuid; diff --git a/plugin-common/src/main/java/de/jvstvshd/necrify/common/punishment/AbstractPunishment.java b/plugin-common/src/main/java/de/jvstvshd/necrify/common/punishment/AbstractPunishment.java index 07065efb..1171593b 100644 --- a/plugin-common/src/main/java/de/jvstvshd/necrify/common/punishment/AbstractPunishment.java +++ b/plugin-common/src/main/java/de/jvstvshd/necrify/common/punishment/AbstractPunishment.java @@ -25,15 +25,18 @@ package de.jvstvshd.necrify.common.punishment; +import de.jvstvshd.necrify.api.event.EventDispatcher; +import de.jvstvshd.necrify.api.event.punishment.PunishmentCancelledEvent; +import de.jvstvshd.necrify.api.event.punishment.PunishmentPersecutedEvent; import de.jvstvshd.necrify.api.message.MessageProvider; import de.jvstvshd.necrify.api.punishment.Punishment; import de.jvstvshd.necrify.api.user.NecrifyUser; +import de.jvstvshd.necrify.common.AbstractNecrifyPlugin; import net.kyori.adventure.text.Component; import net.kyori.adventure.text.minimessage.MiniMessage; import org.intellij.lang.annotations.Language; import org.jetbrains.annotations.NotNull; -import javax.sql.DataSource; import java.util.UUID; import java.util.concurrent.Callable; import java.util.concurrent.CompletableFuture; @@ -42,11 +45,12 @@ public abstract class AbstractPunishment implements Punishment { private final Component reason; - private final DataSource dataSource; private final ExecutorService service; private final NecrifyUser user; private final UUID punishmentUuid; private final MessageProvider messageProvider; + private final EventDispatcher eventDispatcher; + private final AbstractNecrifyPlugin plugin; @Language("sql") protected final static String APPLY_PUNISHMENT = "INSERT INTO punishment.necrify_punishment" + @@ -58,22 +62,19 @@ public abstract class AbstractPunishment implements Punishment { protected final static String APPLY_CHANGE = "UPDATE necrify_punishment SET reason = ?, expiration = ?, permanent = ? WHERE punishment_id = ?"; private final boolean validity; - public AbstractPunishment(NecrifyUser user, Component reason, DataSource dataSource, ExecutorService service, MessageProvider messageProvider) { - this(user, reason, dataSource, service, UUID.randomUUID(), messageProvider); + public AbstractPunishment(@NotNull NecrifyUser user, @NotNull Component reason, @NotNull AbstractNecrifyPlugin plugin) { + this(user, reason, UUID.randomUUID(), plugin); } - public AbstractPunishment(NecrifyUser user, Component reason, DataSource dataSource, ExecutorService service, UUID punishmentUuid, MessageProvider messageProvider) { + public AbstractPunishment(@NotNull NecrifyUser user, @NotNull Component reason, @NotNull UUID punishmentUuid, @NotNull AbstractNecrifyPlugin plugin) { this.reason = reason; - this.dataSource = dataSource; - this.service = service; + this.service = plugin.getService(); this.user = user; this.punishmentUuid = punishmentUuid; this.validity = true; - this.messageProvider = messageProvider; - } - - public DataSource getDataSource() { - return dataSource; + this.messageProvider = plugin.getMessageProvider(); + this.eventDispatcher = plugin.getEventDispatcher(); + this.plugin = plugin; } public @NotNull Component getReason() { @@ -96,11 +97,11 @@ protected CompletableFuture executeAsync(Callable task, ExecutorServic return future; } - public NecrifyUser getUser() { + public @NotNull NecrifyUser getUser() { return user; } - public UUID getPunishmentUuid() { + public @NotNull UUID getPunishmentUuid() { return punishmentUuid; } @@ -113,11 +114,34 @@ public boolean isValid() { return validity; } + @Override + public final CompletableFuture punish() { + return applyPunishment().whenCompleteAsync((punishment, throwable) -> { + if (punishment != null) { + plugin.getEventDispatcher().dispatch(new PunishmentPersecutedEvent(punishment)); + } + }); + } + + @Override + public final CompletableFuture cancel() { + return applyCancellation().whenCompleteAsync((punishment, throwable) -> { + if (punishment != null) { + plugin.getEventDispatcher().dispatch(new PunishmentCancelledEvent(punishment)); + } + }); + } + + protected abstract CompletableFuture applyPunishment(); + + protected CompletableFuture applyCancellation() { + throw new UnsupportedOperationException("cancellation is not supported for this punishment"); + } + @Override public String toString() { return "AbstractPunishment{" + "reason=" + reason + - ", dataSource=" + dataSource + ", service=" + service + ", user=" + user + ", punishmentUuid=" + punishmentUuid + @@ -145,12 +169,23 @@ protected void checkValidity() { } } + @NotNull public MessageProvider getMessageProvider() { return messageProvider; } @Override - public UUID getUuid() { + public @NotNull UUID getUuid() { return punishmentUuid; } + + @NotNull + public EventDispatcher getEventDispatcher() { + return eventDispatcher; + } + + @NotNull + public AbstractNecrifyPlugin getPlugin() { + return plugin; + } } diff --git a/plugin-common/src/main/java/de/jvstvshd/necrify/common/punishment/AbstractTemporalPunishment.java b/plugin-common/src/main/java/de/jvstvshd/necrify/common/punishment/AbstractTemporalPunishment.java index 7fa5f144..34758ce3 100644 --- a/plugin-common/src/main/java/de/jvstvshd/necrify/common/punishment/AbstractTemporalPunishment.java +++ b/plugin-common/src/main/java/de/jvstvshd/necrify/common/punishment/AbstractTemporalPunishment.java @@ -28,31 +28,30 @@ import de.chojo.sadu.queries.api.query.Query; import de.jvstvshd.necrify.api.PunishmentException; import de.jvstvshd.necrify.api.duration.PunishmentDuration; -import de.jvstvshd.necrify.api.message.MessageProvider; +import de.jvstvshd.necrify.api.event.punishment.PunishmentChangedEvent; import de.jvstvshd.necrify.api.punishment.Punishment; import de.jvstvshd.necrify.api.punishment.StandardPunishmentType; import de.jvstvshd.necrify.api.punishment.TemporalPunishment; import de.jvstvshd.necrify.api.user.NecrifyUser; +import de.jvstvshd.necrify.common.AbstractNecrifyPlugin; import de.jvstvshd.necrify.common.io.Adapters; import net.kyori.adventure.text.Component; import org.jetbrains.annotations.NotNull; -import javax.sql.DataSource; import java.util.UUID; import java.util.concurrent.CompletableFuture; -import java.util.concurrent.ExecutorService; public abstract class AbstractTemporalPunishment extends AbstractPunishment implements TemporalPunishment { private final PunishmentDuration duration; - public AbstractTemporalPunishment(NecrifyUser user, Component reason, DataSource dataSource, ExecutorService service, PunishmentDuration duration, MessageProvider messageProvider) { - super(user, reason, dataSource, service, messageProvider); + public AbstractTemporalPunishment(NecrifyUser user, Component reason, PunishmentDuration duration, AbstractNecrifyPlugin plugin) { + super(user, reason, plugin); this.duration = duration; } - public AbstractTemporalPunishment(NecrifyUser user, Component reason, DataSource dataSource, ExecutorService service, UUID punishmentUuid, PunishmentDuration duration, MessageProvider messageProvider) { - super(user, reason, dataSource, service, punishmentUuid, messageProvider); + public AbstractTemporalPunishment(NecrifyUser user, Component reason, UUID punishmentUuid, PunishmentDuration duration, AbstractNecrifyPlugin plugin) { + super(user, reason, punishmentUuid, plugin); this.duration = duration; } @@ -80,7 +79,7 @@ protected void checkValidity() { } @Override - public CompletableFuture change(@NotNull PunishmentDuration newDuration, Component newReason) throws PunishmentException { + public final CompletableFuture change(@NotNull PunishmentDuration newDuration, Component newReason) throws PunishmentException { if (!getType().isBan() && !getType().isMute()) { throw new IllegalStateException("only bans and mutes can be changed"); } @@ -92,32 +91,34 @@ public CompletableFuture change(@NotNull PunishmentDuration newDurat .bind(newDuration.isPermanent()) .bind(getPunishmentUuid(), Adapters.UUID_ADAPTER)) .update(); + Punishment punishment; if (getType().isBan()) { - return new NecrifyBan(getUser(), newReason, getDataSource(), getService(), newDuration, getMessageProvider()); + punishment = new NecrifyBan(getUser(), newReason, newDuration, getPlugin()); } else if (getType().isMute()) { - return new NecrifyMute(getUser(), newReason, getDataSource(), getService(), newDuration, getMessageProvider()); + punishment = new NecrifyMute(getUser(), newReason, newDuration, getPlugin()); } else { throw new IllegalStateException("punishment type is not a ban or mute"); } + getPlugin().getEventDispatcher().dispatch(new PunishmentChangedEvent(punishment, this)); + return punishment; }, getService()); } @Override - public CompletableFuture cancel() throws PunishmentException { + protected CompletableFuture applyCancellation() throws PunishmentException { return executeAsync(() -> { Query.query(APPLY_CANCELLATION) .single(Call.of().bind(getPunishmentUuid(), Adapters.UUID_ADAPTER)) .delete(); - getUser().removePunishment(this); return this; }, getService()); } @Override - public abstract StandardPunishmentType getType(); + public abstract @NotNull StandardPunishmentType getType(); @Override - public CompletableFuture punish() throws PunishmentException { + protected CompletableFuture applyPunishment() throws PunishmentException { checkValidity(); var duration = getDuration().absolute(); return executeAsync(() -> { @@ -129,7 +130,6 @@ public CompletableFuture punish() throws PunishmentException { .bind(convertReason(getReason())) .bind(getPunishmentUuid(), Adapters.UUID_ADAPTER)) .insert(); - getUser().addPunishment(this); return this; }, getService()); } diff --git a/plugin-common/src/main/java/de/jvstvshd/necrify/common/punishment/NecrifyBan.java b/plugin-common/src/main/java/de/jvstvshd/necrify/common/punishment/NecrifyBan.java index a6602915..3be0940e 100644 --- a/plugin-common/src/main/java/de/jvstvshd/necrify/common/punishment/NecrifyBan.java +++ b/plugin-common/src/main/java/de/jvstvshd/necrify/common/punishment/NecrifyBan.java @@ -26,33 +26,31 @@ import de.jvstvshd.necrify.api.PunishmentException; import de.jvstvshd.necrify.api.duration.PunishmentDuration; -import de.jvstvshd.necrify.api.message.MessageProvider; import de.jvstvshd.necrify.api.punishment.Ban; import de.jvstvshd.necrify.api.punishment.Punishment; import de.jvstvshd.necrify.api.punishment.StandardPunishmentType; import de.jvstvshd.necrify.api.user.NecrifyUser; +import de.jvstvshd.necrify.common.AbstractNecrifyPlugin; import net.kyori.adventure.text.Component; import net.kyori.adventure.text.format.NamedTextColor; import net.kyori.adventure.text.format.TextDecoration; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; -import javax.sql.DataSource; import java.time.LocalDateTime; import java.time.format.DateTimeFormatter; import java.util.Locale; import java.util.UUID; import java.util.concurrent.CompletableFuture; -import java.util.concurrent.ExecutorService; public class NecrifyBan extends AbstractTemporalPunishment implements Ban { - public NecrifyBan(NecrifyUser user, Component reason, DataSource dataSource, ExecutorService service, PunishmentDuration duration, MessageProvider messageProvider) { - super(user, reason, dataSource, service, duration, messageProvider); + public NecrifyBan(NecrifyUser user, Component reason, PunishmentDuration duration, AbstractNecrifyPlugin plugin) { + super(user, reason, duration, plugin); } - public NecrifyBan(NecrifyUser user, Component reason, DataSource dataSource, ExecutorService service, UUID punishmentUuid, PunishmentDuration duration, MessageProvider messageProvider) { - super(user, reason, dataSource, service, punishmentUuid, duration, messageProvider); + public NecrifyBan(NecrifyUser user, Component reason, UUID punishmentUuid, PunishmentDuration duration, AbstractNecrifyPlugin plugin) { + super(user, reason, punishmentUuid, duration, plugin); } @Override @@ -61,7 +59,7 @@ public boolean isOngoing() { } @Override - public CompletableFuture punish() throws PunishmentException { + public CompletableFuture applyPunishment() throws PunishmentException { return super.punish().whenComplete((p, throwable) -> { tryKick(); }); @@ -93,7 +91,7 @@ public boolean isPermanent() { } @Override - public StandardPunishmentType getType() { + public @NotNull StandardPunishmentType getType() { return getDuration().isPermanent() ? StandardPunishmentType.PERMANENT_BAN : StandardPunishmentType.BAN; } } diff --git a/plugin-common/src/main/java/de/jvstvshd/necrify/common/punishment/NecrifyKick.java b/plugin-common/src/main/java/de/jvstvshd/necrify/common/punishment/NecrifyKick.java index 8fbe5469..9b9c7d18 100644 --- a/plugin-common/src/main/java/de/jvstvshd/necrify/common/punishment/NecrifyKick.java +++ b/plugin-common/src/main/java/de/jvstvshd/necrify/common/punishment/NecrifyKick.java @@ -24,27 +24,25 @@ package de.jvstvshd.necrify.common.punishment; -import de.jvstvshd.necrify.api.message.MessageProvider; import de.jvstvshd.necrify.api.punishment.Kick; import de.jvstvshd.necrify.api.punishment.PunishmentType; import de.jvstvshd.necrify.api.punishment.StandardPunishmentType; import de.jvstvshd.necrify.api.user.NecrifyUser; +import de.jvstvshd.necrify.common.AbstractNecrifyPlugin; import net.kyori.adventure.text.Component; import org.jetbrains.annotations.NotNull; -import javax.sql.DataSource; import java.util.Locale; import java.util.UUID; -import java.util.concurrent.ExecutorService; public abstract class NecrifyKick extends AbstractPunishment implements Kick { - public NecrifyKick(NecrifyUser user, Component reason, DataSource dataSource, ExecutorService service, UUID punishmentUuid, MessageProvider messageProvider) { - super(user, reason, dataSource, service, punishmentUuid, messageProvider); + public NecrifyKick(NecrifyUser user, Component reason, UUID punishmentUuid, AbstractNecrifyPlugin plugin) { + super(user, reason, punishmentUuid, plugin); } @Override - public PunishmentType getType() { + public @NotNull PunishmentType getType() { return StandardPunishmentType.KICK; } diff --git a/plugin-common/src/main/java/de/jvstvshd/necrify/common/punishment/NecrifyMute.java b/plugin-common/src/main/java/de/jvstvshd/necrify/common/punishment/NecrifyMute.java index 5fab23ac..684540c6 100644 --- a/plugin-common/src/main/java/de/jvstvshd/necrify/common/punishment/NecrifyMute.java +++ b/plugin-common/src/main/java/de/jvstvshd/necrify/common/punishment/NecrifyMute.java @@ -24,35 +24,30 @@ package de.jvstvshd.necrify.common.punishment; -import de.jvstvshd.necrify.api.PunishmentException; import de.jvstvshd.necrify.api.duration.PunishmentDuration; -import de.jvstvshd.necrify.api.message.MessageProvider; import de.jvstvshd.necrify.api.punishment.Mute; -import de.jvstvshd.necrify.api.punishment.Punishment; import de.jvstvshd.necrify.api.punishment.StandardPunishmentType; import de.jvstvshd.necrify.api.user.NecrifyUser; +import de.jvstvshd.necrify.common.AbstractNecrifyPlugin; import net.kyori.adventure.text.Component; import net.kyori.adventure.text.format.NamedTextColor; import net.kyori.adventure.text.format.TextDecoration; import org.jetbrains.annotations.NotNull; -import javax.sql.DataSource; import java.time.LocalDateTime; import java.time.format.DateTimeFormatter; import java.util.Locale; import java.util.UUID; -import java.util.concurrent.CompletableFuture; -import java.util.concurrent.ExecutorService; public class NecrifyMute extends AbstractTemporalPunishment implements Mute { - public NecrifyMute(NecrifyUser user, Component reason, DataSource dataSource, ExecutorService service, PunishmentDuration duration, MessageProvider messageProvider) { - super(user, reason, dataSource, service, duration, messageProvider); + public NecrifyMute(NecrifyUser user, Component reason, PunishmentDuration duration, AbstractNecrifyPlugin plugin) { + super(user, reason, duration, plugin); } - public NecrifyMute(NecrifyUser user, Component reason, DataSource dataSource, ExecutorService service, UUID punishmentUuid, PunishmentDuration duration, MessageProvider messageProvider) { - super(user, reason, dataSource, service, punishmentUuid, duration, messageProvider); + public NecrifyMute(NecrifyUser user, Component reason, UUID punishmentUuid, PunishmentDuration duration, AbstractNecrifyPlugin plugin) { + super(user, reason, punishmentUuid, duration, plugin); } @Override @@ -61,21 +56,7 @@ public boolean isOngoing() { } @Override - public CompletableFuture punish() throws PunishmentException { - var punishment = super.punish(); - //queueMute(MuteData.ADD); - return punishment; - } - - @Override - public CompletableFuture cancel() throws PunishmentException { - var punishment = super.cancel(); - //queueMute(MuteData.REMOVE); - return punishment; - } - - @Override - public StandardPunishmentType getType() { + public @NotNull StandardPunishmentType getType() { return isPermanent() ? StandardPunishmentType.PERMANENT_MUTE : StandardPunishmentType.MUTE; } @@ -97,13 +78,4 @@ public boolean isPermanent() { return getMessageProvider().provide("punishment.mute.temp.full-reason", Component.text(getDuration().remainingDuration()).color(NamedTextColor.YELLOW), getReason(), until); } } - - /*void queueMute(int type) { - try { - getPunishmentManager().plugin().communicator().queueMute((Mute) this, type); - } catch (Exception e) { - getPunishmentManager().plugin().getLogger().error("Could not queue mute", e); - } - }*/ - -} +} \ No newline at end of file diff --git a/plugin/build.gradle.kts b/plugin/build.gradle.kts index c21a9292..6db4e670 100644 --- a/plugin/build.gradle.kts +++ b/plugin/build.gradle.kts @@ -43,7 +43,8 @@ tasks { val prefix: (String) -> String = { "de.jvstvshd.necrify.lib.$it" } relocate("com.fasterxml.jackson", prefix("jackson")) relocate("com.github.benmanes.caffeine", prefix("caffeine")) - relocate("com.google", prefix("google")) + relocate("com.google.errorprone", prefix("google.errorprone")) + relocate("com.google.protobuf", prefix("google.protobuf")) relocate("com.mysql", prefix("mysql")) relocate("com.sun.jna", "sun.jna") relocate("com.zaxxer.hikari", prefix("hikari")) diff --git a/plugin/src/main/java/de/jvstvshd/necrify/velocity/MessagingChannelCommunicator.java b/plugin/src/main/java/de/jvstvshd/necrify/velocity/MessagingChannelCommunicator.java index 57c87f30..e372edfa 100644 --- a/plugin/src/main/java/de/jvstvshd/necrify/velocity/MessagingChannelCommunicator.java +++ b/plugin/src/main/java/de/jvstvshd/necrify/velocity/MessagingChannelCommunicator.java @@ -27,10 +27,14 @@ import com.fasterxml.jackson.core.JsonProcessingException; import com.google.common.io.ByteStreams; import com.velocitypowered.api.event.Subscribe; +import com.velocitypowered.api.event.connection.DisconnectEvent; import com.velocitypowered.api.event.player.ServerPostConnectEvent; import com.velocitypowered.api.proxy.Player; import com.velocitypowered.api.proxy.ProxyServer; import com.velocitypowered.api.proxy.server.RegisteredServer; +import de.jvstvshd.necrify.api.event.punishment.PunishmentCancelledEvent; +import de.jvstvshd.necrify.api.event.punishment.PunishmentChangedEvent; +import de.jvstvshd.necrify.api.event.punishment.PunishmentPersecutedEvent; import de.jvstvshd.necrify.api.punishment.Mute; import de.jvstvshd.necrify.api.punishment.util.ReasonHolder; import de.jvstvshd.necrify.common.plugin.MuteData; @@ -110,7 +114,7 @@ public void onChooseInitialServer(ServerPostConnectEvent event) { } private boolean sendMessage(RegisteredServer server, MuteData muteData) throws JsonProcessingException { - return server.sendPluginMessage(NecrifyPlugin.MUTE_DATA_CHANNEL_IDENTIFIER, serializeMuteData(muteData)); + return server.sendPluginMessage(NecrifyVelocityPlugin.MUTE_DATA_CHANNEL_IDENTIFIER, serializeMuteData(muteData)); } @SuppressWarnings("UnstableApiUsage") @@ -125,7 +129,7 @@ public synchronized List testRecipients() { byte[] message = new byte[]{0x00}; supportingServers.clear(); for (RegisteredServer allServer : server.getAllServers()) { - if (allServer.sendPluginMessage(NecrifyPlugin.MUTE_DATA_CHANNEL_IDENTIFIER, message)) { + if (allServer.sendPluginMessage(NecrifyVelocityPlugin.MUTE_DATA_CHANNEL_IDENTIFIER, message)) { supportingServers.add(allServer); } else { supportedEverywhere = false; @@ -143,4 +147,46 @@ public boolean isSupportedEverywhere() { public boolean isPlayerReachable(Player player) { return player.getCurrentServer().map(serverConnection -> supportingServers.contains(serverConnection.getServer())).orElse(false); } + + @Subscribe + public void onPlayerDisconnect(DisconnectEvent event) { + try { + queueMute(new MuteData(event.getPlayer().getUniqueId(), null, null, MuteData.RESET, null)); + } catch (Exception e) { + logger.error("Could not queue mute for player {}", event.getPlayer().getUniqueId(), e); + } + } + + @org.greenrobot.eventbus.Subscribe + public void onPunishmentPersecution(PunishmentPersecutedEvent event) { + if (event.getPunishment() instanceof Mute mute) { + try { + queueMute(mute, MuteData.ADD); + } catch (Exception e) { + logger.error("Could not queue mute for player {}", mute.getUser().getUuid(), e); + } + } + } + + @org.greenrobot.eventbus.Subscribe + public void onPunishmentChange(PunishmentChangedEvent event) { + if (event.getPunishment() instanceof Mute mute) { + try { + queueMute(mute, MuteData.UPDATE); + } catch (Exception e) { + logger.error("Could not queue mute for player {}", mute.getUser().getUuid(), e); + } + } + } + + @org.greenrobot.eventbus.Subscribe + public void onPunishmentRemoved(PunishmentCancelledEvent event) { + if (event.getPunishment() instanceof Mute mute) { + try { + queueMute(mute, MuteData.REMOVE); + } catch (Exception e) { + logger.error("Could not queue mute for player {}", mute.getUser().getUuid(), e); + } + } + } } diff --git a/plugin/src/main/java/de/jvstvshd/necrify/velocity/NecrifyPlugin.java b/plugin/src/main/java/de/jvstvshd/necrify/velocity/NecrifyVelocityPlugin.java similarity index 84% rename from plugin/src/main/java/de/jvstvshd/necrify/velocity/NecrifyPlugin.java rename to plugin/src/main/java/de/jvstvshd/necrify/velocity/NecrifyVelocityPlugin.java index d1083707..40ed5604 100644 --- a/plugin/src/main/java/de/jvstvshd/necrify/velocity/NecrifyPlugin.java +++ b/plugin/src/main/java/de/jvstvshd/necrify/velocity/NecrifyVelocityPlugin.java @@ -48,12 +48,16 @@ import de.chojo.sadu.queries.configuration.QueryConfiguration; import de.chojo.sadu.sqlite.databases.SqLite; import de.chojo.sadu.updater.SqlUpdater; -import de.jvstvshd.necrify.api.Necrify; +import de.jvstvshd.necrify.api.event.EventDispatcher; +import de.jvstvshd.necrify.api.event.Slf4jLogger; +import de.jvstvshd.necrify.api.event.origin.EventOrigin; +import de.jvstvshd.necrify.api.event.user.UserLoadedEvent; import de.jvstvshd.necrify.api.message.MessageProvider; import de.jvstvshd.necrify.api.punishment.Punishment; import de.jvstvshd.necrify.api.punishment.PunishmentManager; import de.jvstvshd.necrify.api.punishment.util.PlayerResolver; import de.jvstvshd.necrify.api.user.UserManager; +import de.jvstvshd.necrify.common.AbstractNecrifyPlugin; import de.jvstvshd.necrify.common.io.Adapters; import de.jvstvshd.necrify.common.plugin.MuteData; import de.jvstvshd.necrify.velocity.commands.*; @@ -76,11 +80,10 @@ import java.util.Optional; import java.util.UUID; import java.util.concurrent.CompletableFuture; -import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; @Plugin(id = "necrify", name = "Necrify", version = "1.2.0-SNAPSHOT", description = "A simple punishment plugin for Velocity", authors = {"JvstvsHD"}) -public class NecrifyPlugin implements Necrify { +public class NecrifyVelocityPlugin extends AbstractNecrifyPlugin { private final ProxyServer server; private final Logger logger; @@ -96,8 +99,8 @@ public class NecrifyPlugin implements Necrify { private PlayerResolver playerResolver; private MessageProvider messageProvider; private UserManager userManager; - private final ExecutorService service; private final MessagingChannelCommunicator communicator; + private EventDispatcher eventDispatcher; /** * Since 1.19.1, cancelling chat messages on proxy is not possible anymore. Therefore, we have to listen to the chat event on the actual game server. This means @@ -108,16 +111,20 @@ public class NecrifyPlugin implements Necrify { public static final Component MUTES_DISABLED = Component.text(MUTES_DISABLED_STRING); @Inject - public NecrifyPlugin(ProxyServer server, Logger logger, @DataDirectory Path dataDirectory) { + public NecrifyVelocityPlugin(ProxyServer server, Logger logger, @DataDirectory Path dataDirectory) { + super(Executors.newCachedThreadPool(new ThreadFactoryBuilder() + .setUncaughtExceptionHandler((t, e) -> logger.error("An error occurred in thread {}", t.getName(), e)) + .build())); this.server = server; this.logger = logger; + this.dataDirectory = dataDirectory; this.configurationManager = new ConfigurationManager(dataDirectory.resolve("config.yml")); - this.playerResolver = new DefaultPlayerResolver(server); this.communicator = new MessagingChannelCommunicator(server, logger); - this.dataDirectory = dataDirectory; - this.service = Executors.newCachedThreadPool(new ThreadFactoryBuilder().setUncaughtExceptionHandler((t, e) -> logger.error("An error occurred in thread {}", t.getName(), e)).build()); + this.playerResolver = new DefaultPlayerResolver(server); + this.eventDispatcher = new EventDispatcher(getExecutor(), new Slf4jLogger(logger)); } + //TODO keep changed implementations and do not override them. @Subscribe public void onProxyInitialization(ProxyInitializeEvent event) { Thread.setDefaultUncaughtExceptionHandler((t, e) -> logger.error("An error occurred in thread {}", t.getName(), e)); @@ -129,11 +136,13 @@ public void onProxyInitialization(ProxyInitializeEvent event) { this.messageProvider = new ResourceBundleMessageProvider(configurationManager.getConfiguration()); } catch (IOException e) { logger.error("Could not load configuration", e); + logger.error("Aborting start-up"); + return; } dataSource = createDataSource(); QueryConfiguration.setDefault(QueryConfiguration.builder(dataSource).setExceptionHandler(e -> logger.error("An error occurred during a database request", e)).build()); punishmentManager = new DefaultPunishmentManager(server, dataSource, this); - this.userManager = new VelocityUserManager(service, server, Caffeine.newBuilder().maximumSize(100).expireAfterWrite(Duration.ofMinutes(10)).build(), Caffeine.newBuilder().maximumSize(100).expireAfterWrite(Duration.ofMinutes(10)).build(), this); + this.userManager = new VelocityUserManager(getExecutor(), server, Caffeine.newBuilder().maximumSize(100).expireAfterWrite(Duration.ofMinutes(10)).build(), Caffeine.newBuilder().maximumSize(100).expireAfterWrite(Duration.ofMinutes(10)).build(), this); try { updateDatabase(); } catch (SQLException | IOException e) { @@ -141,10 +150,12 @@ public void onProxyInitialization(ProxyInitializeEvent event) { } setup(server.getCommandManager(), server.getEventManager()); var notSupportedServers = communicator.testRecipients(); - if (communicator.isSupportedEverywhere()) { + if (!communicator.isSupportedEverywhere()) { logger.warn("Persecution of mutes cannot be granted on the following servers as the required paper plugin is not installed: {}", Joiner.on(", ").join(notSupportedServers)); } + eventDispatcher.register(communicator); + eventDispatcher.register(userManager); logger.info("Velocity Punishment Plugin v1.2.0-SNAPSHOT has been loaded. This is only a dev build and thus may be unstable."); } @@ -218,11 +229,6 @@ public ProxyServer getServer() { return server; } - @Override - public @NotNull ExecutorService getService() { - return service; - } - public HikariDataSource getDataSource() { return dataSource; } @@ -268,8 +274,27 @@ public void setUserManager(@NotNull UserManager userManager) { @Override public CompletableFuture> getPunishment(@NotNull UUID punishmentId) { return Util.executeAsync(() -> (Optional) Query.query("SELECT u.* FROM punishment.necrify_user u " + "INNER JOIN punishment.necrify_punishment p ON u.uuid = p.uuid " + "WHERE p.punishment_id = ?;").single(Call.of().bind(punishmentId, Adapters.UUID_ADAPTER)).map(row -> { + var userId = row.getObject(1, UUID.class); + var cachedUser = getUserManager().getUser(userId); + if (cachedUser.isPresent()) { + return cachedUser.get().getPunishment(punishmentId).orElse(null); + } var user = new VelocityUser(row.getObject(1, UUID.class), row.getString(2), row.getBoolean(3), this); - return user.getPunishments().stream().filter(punishment -> punishment.getPunishmentUuid().equals(punishmentId)).findFirst().orElse(null); - }).first(), service); + getExecutor().execute(() -> { + Query.query("SELECT type, expiration, reason, punishment_id FROM punishment.necrify_punishment WHERE uuid = ?;").single(Call.of().bind(userId, Adapters.UUID_ADAPTER)).map(user::addPunishment).all(); + getEventDispatcher().dispatch(new UserLoadedEvent(user).setOrigin(EventOrigin.ofClass(getClass()))); + }); + return user.getPunishment(punishmentId).orElse(null); + }).first(), getExecutor()); + } + + @Override + public @NotNull EventDispatcher getEventDispatcher() { + return eventDispatcher; + } + + @Override + public void setEventDispatcher(@NotNull EventDispatcher eventDispatcher) { + this.eventDispatcher = eventDispatcher; } } diff --git a/plugin/src/main/java/de/jvstvshd/necrify/velocity/commands/BanCommand.java b/plugin/src/main/java/de/jvstvshd/necrify/velocity/commands/BanCommand.java index 45c4c5b2..277b4d04 100644 --- a/plugin/src/main/java/de/jvstvshd/necrify/velocity/commands/BanCommand.java +++ b/plugin/src/main/java/de/jvstvshd/necrify/velocity/commands/BanCommand.java @@ -29,7 +29,7 @@ import com.velocitypowered.api.command.BrigadierCommand; import com.velocitypowered.api.command.CommandSource; import de.jvstvshd.necrify.api.PunishmentException; -import de.jvstvshd.necrify.velocity.NecrifyPlugin; +import de.jvstvshd.necrify.velocity.NecrifyVelocityPlugin; import de.jvstvshd.necrify.velocity.internal.PunishmentHelper; import de.jvstvshd.necrify.velocity.internal.Util; import net.kyori.adventure.text.format.NamedTextColor; @@ -37,14 +37,14 @@ public class BanCommand { - public static BrigadierCommand banCommand(NecrifyPlugin plugin) { + public static BrigadierCommand banCommand(NecrifyVelocityPlugin plugin) { var node = Util.permissibleCommand("ban", "necrify.command.ban") .then(Util.playerArgument(plugin.getServer()).executes(context -> execute(context, plugin)) .then(Util.reasonArgument.executes(context -> execute(context, plugin)))); return new BrigadierCommand(node); } - private static int execute(CommandContext context, NecrifyPlugin plugin) { + private static int execute(CommandContext context, NecrifyVelocityPlugin plugin) { var source = context.getSource(); var player = context.getArgument("player", String.class); var reason = PunishmentHelper.parseReason(context); diff --git a/plugin/src/main/java/de/jvstvshd/necrify/velocity/commands/KickCommand.java b/plugin/src/main/java/de/jvstvshd/necrify/velocity/commands/KickCommand.java index 69b67058..e4ccb9f8 100644 --- a/plugin/src/main/java/de/jvstvshd/necrify/velocity/commands/KickCommand.java +++ b/plugin/src/main/java/de/jvstvshd/necrify/velocity/commands/KickCommand.java @@ -29,7 +29,7 @@ import com.velocitypowered.api.command.BrigadierCommand; import com.velocitypowered.api.command.CommandSource; import com.velocitypowered.api.proxy.Player; -import de.jvstvshd.necrify.velocity.NecrifyPlugin; +import de.jvstvshd.necrify.velocity.NecrifyVelocityPlugin; import de.jvstvshd.necrify.velocity.internal.PunishmentHelper; import de.jvstvshd.necrify.velocity.internal.Util; import net.kyori.adventure.text.Component; @@ -39,14 +39,14 @@ public class KickCommand { - public static BrigadierCommand kickCommand(NecrifyPlugin plugin) { + public static BrigadierCommand kickCommand(NecrifyVelocityPlugin plugin) { var node = Util.permissibleCommand("kick", "necrify.command.kick") .then(Util.playerArgument(plugin.getServer()).executes(context -> execute(context, plugin)) .then(Util.reasonArgument.executes(context -> execute(context, plugin)))); return new BrigadierCommand(node); } - private static int execute(CommandContext context, NecrifyPlugin plugin) { + private static int execute(CommandContext context, NecrifyVelocityPlugin plugin) { var source = context.getSource(); var playerArgument = context.getArgument("player", String.class); Optional playerOptional = plugin.getServer().getPlayer(playerArgument); diff --git a/plugin/src/main/java/de/jvstvshd/necrify/velocity/commands/MuteCommand.java b/plugin/src/main/java/de/jvstvshd/necrify/velocity/commands/MuteCommand.java index ddf3dcc8..72ba06c6 100644 --- a/plugin/src/main/java/de/jvstvshd/necrify/velocity/commands/MuteCommand.java +++ b/plugin/src/main/java/de/jvstvshd/necrify/velocity/commands/MuteCommand.java @@ -29,7 +29,7 @@ import com.velocitypowered.api.command.BrigadierCommand; import com.velocitypowered.api.command.CommandSource; import de.jvstvshd.necrify.api.PunishmentException; -import de.jvstvshd.necrify.velocity.NecrifyPlugin; +import de.jvstvshd.necrify.velocity.NecrifyVelocityPlugin; import de.jvstvshd.necrify.velocity.internal.PunishmentHelper; import de.jvstvshd.necrify.velocity.internal.Util; import net.kyori.adventure.text.Component; @@ -38,20 +38,20 @@ import net.kyori.adventure.text.minimessage.MiniMessage; /** - * @see NecrifyPlugin#MUTES_DISABLED + * @see NecrifyVelocityPlugin#MUTES_DISABLED */ public class MuteCommand { - public static BrigadierCommand muteCommand(NecrifyPlugin plugin) { + public static BrigadierCommand muteCommand(NecrifyVelocityPlugin plugin) { var node = Util.permissibleCommand("mute", "necrify.command.mute") .then(Util.playerArgument(plugin.getServer()).executes(context -> execute(context, plugin)) .then(Util.reasonArgument.executes(context -> execute(context, plugin)))); return new BrigadierCommand(node); } - private static int execute(CommandContext context, NecrifyPlugin plugin) { + private static int execute(CommandContext context, NecrifyVelocityPlugin plugin) { CommandSource source = context.getSource(); - source.sendMessage(NecrifyPlugin.MUTES_DISABLED); + source.sendMessage(NecrifyVelocityPlugin.MUTES_DISABLED); if (!plugin.communicator().isSupportedEverywhere()) { source.sendMessage(plugin.getMessageProvider() .prefixed(MiniMessage.miniMessage().deserialize("It seems that not all servers run the mentioned paper extension. " + diff --git a/plugin/src/main/java/de/jvstvshd/necrify/velocity/commands/PunishmentCommand.java b/plugin/src/main/java/de/jvstvshd/necrify/velocity/commands/PunishmentCommand.java index c101bbd7..f9363819 100644 --- a/plugin/src/main/java/de/jvstvshd/necrify/velocity/commands/PunishmentCommand.java +++ b/plugin/src/main/java/de/jvstvshd/necrify/velocity/commands/PunishmentCommand.java @@ -34,7 +34,7 @@ import com.velocitypowered.api.command.CommandSource; import de.jvstvshd.necrify.api.PunishmentException; import de.jvstvshd.necrify.api.punishment.Punishment; -import de.jvstvshd.necrify.velocity.NecrifyPlugin; +import de.jvstvshd.necrify.velocity.NecrifyVelocityPlugin; import de.jvstvshd.necrify.velocity.internal.PunishmentHelper; import de.jvstvshd.necrify.velocity.internal.Util; import net.kyori.adventure.text.Component; @@ -51,7 +51,7 @@ public class PunishmentCommand { private final static List PUNISHMENT_OPTIONS = ImmutableList.of("cancel", "remove", "info", "change"); - public static BrigadierCommand punishmentCommand(NecrifyPlugin plugin) { + public static BrigadierCommand punishmentCommand(NecrifyVelocityPlugin plugin) { var node = Util.permissibleCommand("punishment", "necrify.command.punishment") .then(LiteralArgumentBuilder.literal("playerinfo") .then(Util.punishmentRemoveArgument(plugin).executes(context -> executePlayerInfo(context, plugin)))) @@ -63,7 +63,7 @@ public static BrigadierCommand punishmentCommand(NecrifyPlugin plugin) { return new BrigadierCommand(node); } - private static int executePlayerInfo(CommandContext context, NecrifyPlugin plugin) { + private static int executePlayerInfo(CommandContext context, NecrifyVelocityPlugin plugin) { CommandSource source = context.getSource(); var punishmentManager = plugin.getPunishmentManager(); PunishmentHelper.getPlayerUuid(context, plugin).whenCompleteAsync((uuid, throwable) -> { @@ -87,7 +87,7 @@ private static int executePlayerInfo(CommandContext context, Necr return Command.SINGLE_SUCCESS; } - private static int execute(CommandContext context, NecrifyPlugin plugin) { + private static int execute(CommandContext context, NecrifyVelocityPlugin plugin) { var source = context.getSource(); var uuidString = context.getArgument("punishment ID", String.class); UUID uuid; diff --git a/plugin/src/main/java/de/jvstvshd/necrify/velocity/commands/PunishmentRemovalCommand.java b/plugin/src/main/java/de/jvstvshd/necrify/velocity/commands/PunishmentRemovalCommand.java index a832822b..1c5d6bc4 100644 --- a/plugin/src/main/java/de/jvstvshd/necrify/velocity/commands/PunishmentRemovalCommand.java +++ b/plugin/src/main/java/de/jvstvshd/necrify/velocity/commands/PunishmentRemovalCommand.java @@ -29,10 +29,11 @@ import com.velocitypowered.api.command.BrigadierCommand; import com.velocitypowered.api.command.CommandSource; import de.jvstvshd.necrify.api.PunishmentException; +import de.jvstvshd.necrify.api.event.punishment.PunishmentCancelledEvent; import de.jvstvshd.necrify.api.punishment.Punishment; import de.jvstvshd.necrify.api.punishment.PunishmentType; import de.jvstvshd.necrify.api.punishment.StandardPunishmentType; -import de.jvstvshd.necrify.velocity.NecrifyPlugin; +import de.jvstvshd.necrify.velocity.NecrifyVelocityPlugin; import de.jvstvshd.necrify.velocity.internal.PunishmentHelper; import de.jvstvshd.necrify.velocity.internal.Util; import net.kyori.adventure.text.Component; @@ -45,19 +46,19 @@ public class PunishmentRemovalCommand { - public static BrigadierCommand unmuteCommand(NecrifyPlugin plugin) { + public static BrigadierCommand unmuteCommand(NecrifyVelocityPlugin plugin) { var node = Util.permissibleCommand("unmute", "necrify.command.unmute") .then(Util.punishmentRemoveArgument(plugin).executes(context -> execute(context, plugin, "unmute", StandardPunishmentType.MUTE, StandardPunishmentType.PERMANENT_MUTE))); return new BrigadierCommand(node); } - public static BrigadierCommand unbanCommand(NecrifyPlugin plugin) { + public static BrigadierCommand unbanCommand(NecrifyVelocityPlugin plugin) { var node = Util.permissibleCommand("unban", "necrify.command.unban") .then(Util.punishmentRemoveArgument(plugin).executes(context -> execute(context, plugin, "unban", StandardPunishmentType.BAN, StandardPunishmentType.PERMANENT_BAN))); return new BrigadierCommand(node); } - public static int execute(CommandContext context, NecrifyPlugin plugin, String commandName, PunishmentType... types) { + public static int execute(CommandContext context, NecrifyVelocityPlugin plugin, String commandName, PunishmentType... types) { var source = context.getSource(); PunishmentHelper.getPlayerUuid(context, plugin).whenCompleteAsync((uuid, throwable) -> { if (Util.sendErrorMessageIfErrorOccurred(context, uuid, throwable, plugin)) return; @@ -77,7 +78,7 @@ public static int execute(CommandContext context, NecrifyPlugin p source.sendMessage(buildComponent(PunishmentHelper.buildPunishmentData(punishment, plugin.getMessageProvider()), punishment)); } } else { - Punishment punishment = punishments.get(0); + Punishment punishment = punishments.getFirst(); try { punishment.cancel().whenCompleteAsync((unused, th) -> { if (th != null) { @@ -85,10 +86,12 @@ public static int execute(CommandContext context, NecrifyPlugin p source.sendMessage(plugin.getMessageProvider().internalError()); return; } + plugin.getEventDispatcher().dispatch(new PunishmentCancelledEvent(punishment)); + //plugin.getUserManager().getUser(uuid).ifPresentOrElse(user -> user.removePunishment(punishment), () -> plugin.getLogger().warn("User {} not found in cache", uuid)); source.sendMessage(plugin.getMessageProvider().provide("command." + commandName + ".success").color(NamedTextColor.GREEN)); }, plugin.getService()); } catch (PunishmentException e) { - plugin.getLogger().error("An error occurred while removing punishment " + punishment.getPunishmentUuid() + " for player " + uuid, e); + plugin.getLogger().error("An error occurred while removing punishment {} for player {}", punishment.getPunishmentUuid(), uuid, e); Util.sendErrorMessage(context, e); } } diff --git a/plugin/src/main/java/de/jvstvshd/necrify/velocity/commands/TempbanCommand.java b/plugin/src/main/java/de/jvstvshd/necrify/velocity/commands/TempbanCommand.java index b9aab2cd..5e25354a 100644 --- a/plugin/src/main/java/de/jvstvshd/necrify/velocity/commands/TempbanCommand.java +++ b/plugin/src/main/java/de/jvstvshd/necrify/velocity/commands/TempbanCommand.java @@ -29,7 +29,7 @@ import com.velocitypowered.api.command.BrigadierCommand; import com.velocitypowered.api.command.CommandSource; import de.jvstvshd.necrify.api.duration.PunishmentDuration; -import de.jvstvshd.necrify.velocity.NecrifyPlugin; +import de.jvstvshd.necrify.velocity.NecrifyVelocityPlugin; import de.jvstvshd.necrify.velocity.internal.PunishmentHelper; import de.jvstvshd.necrify.velocity.internal.Util; import net.kyori.adventure.text.Component; @@ -42,7 +42,7 @@ public class TempbanCommand { - public static BrigadierCommand tempbanCommand(NecrifyPlugin plugin) { + public static BrigadierCommand tempbanCommand(NecrifyVelocityPlugin plugin) { var node = Util.permissibleCommand("tempban", "necrify.command.tempban") .then(Util.playerArgument(plugin.getServer()) .then(Util.durationArgument.executes(context -> execute(context, plugin)) @@ -50,7 +50,7 @@ public static BrigadierCommand tempbanCommand(NecrifyPlugin plugin) { return new BrigadierCommand(node); } - private static int execute(CommandContext context, NecrifyPlugin plugin) { + private static int execute(CommandContext context, NecrifyVelocityPlugin plugin) { CommandSource source = context.getSource(); var player = context.getArgument("player", String.class); plugin.getPlayerResolver().getOrQueryPlayerUuid(player, plugin.getService()).whenCompleteAsync((uuid, throwable) -> { diff --git a/plugin/src/main/java/de/jvstvshd/necrify/velocity/commands/TempmuteCommand.java b/plugin/src/main/java/de/jvstvshd/necrify/velocity/commands/TempmuteCommand.java index 73457186..3fdd8f89 100644 --- a/plugin/src/main/java/de/jvstvshd/necrify/velocity/commands/TempmuteCommand.java +++ b/plugin/src/main/java/de/jvstvshd/necrify/velocity/commands/TempmuteCommand.java @@ -30,7 +30,7 @@ import com.velocitypowered.api.command.CommandSource; import de.jvstvshd.necrify.api.PunishmentException; import de.jvstvshd.necrify.api.duration.PunishmentDuration; -import de.jvstvshd.necrify.velocity.NecrifyPlugin; +import de.jvstvshd.necrify.velocity.NecrifyVelocityPlugin; import de.jvstvshd.necrify.velocity.internal.PunishmentHelper; import de.jvstvshd.necrify.velocity.internal.Util; import net.kyori.adventure.text.Component; @@ -41,11 +41,11 @@ import java.util.Optional; /** - * @see NecrifyPlugin#MUTES_DISABLED + * @see NecrifyVelocityPlugin#MUTES_DISABLED */ public class TempmuteCommand { - public static BrigadierCommand tempmuteCommand(NecrifyPlugin plugin) { + public static BrigadierCommand tempmuteCommand(NecrifyVelocityPlugin plugin) { var node = Util.permissibleCommand("tempmute", "necrify.command.tempmute") .then(Util.playerArgument(plugin.getServer()) .then(Util.durationArgument.executes(context -> execute(context, plugin)) @@ -53,7 +53,7 @@ public static BrigadierCommand tempmuteCommand(NecrifyPlugin plugin) { return new BrigadierCommand(node); } - private static int execute(CommandContext context, NecrifyPlugin plugin) { + private static int execute(CommandContext context, NecrifyVelocityPlugin plugin) { CommandSource source = context.getSource(); var player = context.getArgument("player", String.class); plugin.getPlayerResolver().getOrQueryPlayerUuid(player, plugin.getService()).whenCompleteAsync((uuid, throwable) -> { diff --git a/plugin/src/main/java/de/jvstvshd/necrify/velocity/commands/WhitelistCommand.java b/plugin/src/main/java/de/jvstvshd/necrify/velocity/commands/WhitelistCommand.java index b06f60f1..2b8c3bad 100644 --- a/plugin/src/main/java/de/jvstvshd/necrify/velocity/commands/WhitelistCommand.java +++ b/plugin/src/main/java/de/jvstvshd/necrify/velocity/commands/WhitelistCommand.java @@ -31,7 +31,7 @@ import com.mojang.brigadier.context.CommandContext; import com.velocitypowered.api.command.BrigadierCommand; import com.velocitypowered.api.command.CommandSource; -import de.jvstvshd.necrify.velocity.NecrifyPlugin; +import de.jvstvshd.necrify.velocity.NecrifyVelocityPlugin; import de.jvstvshd.necrify.velocity.internal.Util; import net.kyori.adventure.text.Component; import net.kyori.adventure.text.format.NamedTextColor; @@ -45,7 +45,7 @@ public class WhitelistCommand { public static final List options = ImmutableList.of("add", "remove", "on", "off"); - public static BrigadierCommand whitelistCommand(NecrifyPlugin plugin) { + public static BrigadierCommand whitelistCommand(NecrifyVelocityPlugin plugin) { var node = Util.permissibleCommand("whitelist", "necrify.command.whitelist") .then(RequiredArgumentBuilder.argument("option", StringArgumentType.word()) .executes(context -> execute(context, plugin)).suggests((context, builder) -> { @@ -60,7 +60,7 @@ public static BrigadierCommand whitelistCommand(NecrifyPlugin plugin) { return new BrigadierCommand(node); } - private static int execute(CommandContext context, NecrifyPlugin plugin) { + private static int execute(CommandContext context, NecrifyVelocityPlugin plugin) { var source = context.getSource(); String player; if (context.getArguments().containsKey("player")) { diff --git a/plugin/src/main/java/de/jvstvshd/necrify/velocity/impl/DefaultPunishmentManager.java b/plugin/src/main/java/de/jvstvshd/necrify/velocity/impl/DefaultPunishmentManager.java index ec274f2a..56e31bcc 100644 --- a/plugin/src/main/java/de/jvstvshd/necrify/velocity/impl/DefaultPunishmentManager.java +++ b/plugin/src/main/java/de/jvstvshd/necrify/velocity/impl/DefaultPunishmentManager.java @@ -31,7 +31,7 @@ import de.jvstvshd.necrify.api.user.NecrifyUser; import de.jvstvshd.necrify.common.punishment.NecrifyBan; import de.jvstvshd.necrify.common.punishment.NecrifyMute; -import de.jvstvshd.necrify.velocity.NecrifyPlugin; +import de.jvstvshd.necrify.velocity.NecrifyVelocityPlugin; import de.jvstvshd.necrify.velocity.internal.Util; import net.kyori.adventure.text.Component; import org.jetbrains.annotations.ApiStatus; @@ -45,15 +45,15 @@ import java.util.concurrent.Executors; @Deprecated(since = "1.2.0", forRemoval = true) -@ApiStatus.ScheduledForRemoval(inVersion = "2.0.0") +@ApiStatus.ScheduledForRemoval(inVersion = "1.3.0") public class DefaultPunishmentManager implements PunishmentManager { private final ProxyServer proxyServer; private final HikariDataSource dataSource; private final ExecutorService service = Executors.newCachedThreadPool(); - private final NecrifyPlugin plugin; + private final NecrifyVelocityPlugin plugin; - public DefaultPunishmentManager(ProxyServer proxyServer, HikariDataSource dataSource, NecrifyPlugin plugin) { + public DefaultPunishmentManager(ProxyServer proxyServer, HikariDataSource dataSource, NecrifyVelocityPlugin plugin) { this.proxyServer = proxyServer; this.dataSource = dataSource; this.plugin = plugin; @@ -61,12 +61,12 @@ public DefaultPunishmentManager(ProxyServer proxyServer, HikariDataSource dataSo @Override public Ban createBan(UUID player, Component reason, PunishmentDuration duration) { - return new NecrifyBan(getUser(player), reason, dataSource, service, duration.absolute(), plugin.getMessageProvider()); + return new NecrifyBan(getUser(player), reason, duration.absolute(), plugin); } @Override public Mute createMute(UUID player, Component reason, PunishmentDuration duration) { - return new NecrifyMute(getUser(player), reason, dataSource, service, duration.absolute(), plugin.getMessageProvider()); + return new NecrifyMute(getUser(player), reason, duration.absolute(), plugin); } //temporary workaround so that this class still functions @@ -95,7 +95,7 @@ public ProxyServer getServer() { return proxyServer; } - public NecrifyPlugin plugin() { + public NecrifyVelocityPlugin plugin() { return plugin; } diff --git a/plugin/src/main/java/de/jvstvshd/necrify/velocity/impl/VelocityKick.java b/plugin/src/main/java/de/jvstvshd/necrify/velocity/impl/VelocityKick.java index bac32810..6a697e43 100644 --- a/plugin/src/main/java/de/jvstvshd/necrify/velocity/impl/VelocityKick.java +++ b/plugin/src/main/java/de/jvstvshd/necrify/velocity/impl/VelocityKick.java @@ -24,26 +24,24 @@ package de.jvstvshd.necrify.velocity.impl; -import de.jvstvshd.necrify.api.message.MessageProvider; import de.jvstvshd.necrify.api.punishment.Punishment; import de.jvstvshd.necrify.api.user.NecrifyUser; +import de.jvstvshd.necrify.common.AbstractNecrifyPlugin; import de.jvstvshd.necrify.common.punishment.NecrifyKick; import de.jvstvshd.necrify.velocity.user.VelocityUser; import net.kyori.adventure.text.Component; -import javax.sql.DataSource; import java.util.UUID; import java.util.concurrent.CompletableFuture; -import java.util.concurrent.ExecutorService; public class VelocityKick extends NecrifyKick { - public VelocityKick(NecrifyUser user, Component reason, DataSource dataSource, ExecutorService service, UUID punishmentUuid, MessageProvider messageProvider) { - super(user, reason, dataSource, service, punishmentUuid, messageProvider); + public VelocityKick(NecrifyUser user, Component reason, UUID punishmentUuid, AbstractNecrifyPlugin plugin) { + super(user, reason, punishmentUuid, plugin); } @Override - public CompletableFuture punish() { + protected CompletableFuture applyPunishment() { if (!(getUser() instanceof VelocityUser)) throw new IllegalStateException("Cannot kick user: User is not a VelocityUser."); var player = ((VelocityUser) getUser()).getPlayer(); diff --git a/plugin/src/main/java/de/jvstvshd/necrify/velocity/internal/PunishmentHelper.java b/plugin/src/main/java/de/jvstvshd/necrify/velocity/internal/PunishmentHelper.java index 1097cf4e..91109721 100644 --- a/plugin/src/main/java/de/jvstvshd/necrify/velocity/internal/PunishmentHelper.java +++ b/plugin/src/main/java/de/jvstvshd/necrify/velocity/internal/PunishmentHelper.java @@ -32,7 +32,7 @@ import de.jvstvshd.necrify.api.punishment.Punishment; import de.jvstvshd.necrify.api.punishment.TemporalPunishment; import de.jvstvshd.necrify.api.user.NecrifyUser; -import de.jvstvshd.necrify.velocity.NecrifyPlugin; +import de.jvstvshd.necrify.velocity.NecrifyVelocityPlugin; import net.kyori.adventure.text.Component; import net.kyori.adventure.text.TextComponent; import net.kyori.adventure.text.format.NamedTextColor; @@ -91,11 +91,11 @@ public static Optional parseDuration(CommandContext getPlayerUuid(CommandContext context, NecrifyPlugin plugin) { + public static CompletableFuture getPlayerUuid(CommandContext context, NecrifyVelocityPlugin plugin) { var argument = context.getArgument("player", String.class); if (argument.length() <= 16) { return plugin.getPlayerResolver().getOrQueryPlayerUuid(argument, plugin.getService()); @@ -110,7 +110,7 @@ public static CompletableFuture getPlayerUuid(CommandContext> getUser(CommandContext context, NecrifyPlugin plugin) { + public static CompletableFuture> getUser(CommandContext context, NecrifyVelocityPlugin plugin) { var argument = context.getArgument("player", String.class); if (argument.length() <= 16) { return plugin.getUserManager().loadUser(argument); diff --git a/plugin/src/main/java/de/jvstvshd/necrify/velocity/internal/Util.java b/plugin/src/main/java/de/jvstvshd/necrify/velocity/internal/Util.java index 2846c950..90e60984 100644 --- a/plugin/src/main/java/de/jvstvshd/necrify/velocity/internal/Util.java +++ b/plugin/src/main/java/de/jvstvshd/necrify/velocity/internal/Util.java @@ -38,7 +38,7 @@ import de.jvstvshd.necrify.api.message.MessageProvider; import de.jvstvshd.necrify.api.punishment.Punishment; import de.jvstvshd.necrify.api.punishment.TemporalPunishment; -import de.jvstvshd.necrify.velocity.NecrifyPlugin; +import de.jvstvshd.necrify.velocity.NecrifyVelocityPlugin; import net.kyori.adventure.text.Component; import net.kyori.adventure.text.TextComponent; import net.kyori.adventure.text.event.ClickEvent; @@ -72,7 +72,7 @@ public static RequiredArgumentBuilder playerArgument(Prox }); } - public static RequiredArgumentBuilder punishmentRemoveArgument(NecrifyPlugin plugin) { + public static RequiredArgumentBuilder punishmentRemoveArgument(NecrifyVelocityPlugin plugin) { return RequiredArgumentBuilder.argument("player", StringArgumentType.word()).suggests((context, builder) -> Util.executeAsync(() -> { var input = builder.getRemainingLowerCase(); if (input.isBlank() || input.length() <= 2) return builder.build(); @@ -156,7 +156,7 @@ public static String trimUuid(UUID origin) { return origin.toString().toLowerCase().replace("-", ""); } - public static boolean sendErrorMessageIfErrorOccurred(CommandContext context, UUID uuid, Throwable throwable, NecrifyPlugin plugin) { + public static boolean sendErrorMessageIfErrorOccurred(CommandContext context, UUID uuid, Throwable throwable, NecrifyVelocityPlugin plugin) { var source = context.getSource(); var player = context.getArgument("player", String.class); if (throwable != null) { @@ -171,7 +171,7 @@ public static boolean sendErrorMessageIfErrorOccurred(CommandContext context, Throwable throwable, NecrifyPlugin plugin) { + public static boolean sendErrorMessageIfErrorOccurred(CommandContext context, Throwable throwable, NecrifyVelocityPlugin plugin) { var source = context.getSource(); var player = context.getArgument("player", String.class); if (throwable != null) { diff --git a/plugin/src/main/java/de/jvstvshd/necrify/velocity/listener/ConnectListener.java b/plugin/src/main/java/de/jvstvshd/necrify/velocity/listener/ConnectListener.java index e8dfc7dc..0140cc9c 100644 --- a/plugin/src/main/java/de/jvstvshd/necrify/velocity/listener/ConnectListener.java +++ b/plugin/src/main/java/de/jvstvshd/necrify/velocity/listener/ConnectListener.java @@ -33,7 +33,7 @@ import de.jvstvshd.necrify.api.punishment.Punishment; import de.jvstvshd.necrify.api.user.NecrifyUser; import de.jvstvshd.necrify.common.plugin.MuteData; -import de.jvstvshd.necrify.velocity.NecrifyPlugin; +import de.jvstvshd.necrify.velocity.NecrifyVelocityPlugin; import de.jvstvshd.necrify.velocity.internal.Util; import net.kyori.adventure.text.Component; import net.kyori.adventure.text.format.NamedTextColor; @@ -45,11 +45,11 @@ import java.util.concurrent.TimeUnit; public final class ConnectListener { - private final NecrifyPlugin plugin; + private final NecrifyVelocityPlugin plugin; private final ExecutorService service; private final ProxyServer proxyServer; - public ConnectListener(NecrifyPlugin plugin, + public ConnectListener(NecrifyVelocityPlugin plugin, ExecutorService service, ProxyServer proxyServer) { this.plugin = plugin; this.service = service; @@ -105,7 +105,7 @@ public void onConnect(LoginEvent event) { event.setResult(ResultedEvent.ComponentResult.denied(deny)); } - public NecrifyPlugin plugin() { + public NecrifyVelocityPlugin plugin() { return plugin; } diff --git a/plugin/src/main/java/de/jvstvshd/necrify/velocity/message/ResourceBundleMessageProvider.java b/plugin/src/main/java/de/jvstvshd/necrify/velocity/message/ResourceBundleMessageProvider.java index f92ecec5..353d4207 100644 --- a/plugin/src/main/java/de/jvstvshd/necrify/velocity/message/ResourceBundleMessageProvider.java +++ b/plugin/src/main/java/de/jvstvshd/necrify/velocity/message/ResourceBundleMessageProvider.java @@ -25,7 +25,7 @@ package de.jvstvshd.necrify.velocity.message; import de.jvstvshd.necrify.api.message.MessageProvider; -import de.jvstvshd.necrify.velocity.NecrifyPlugin; +import de.jvstvshd.necrify.velocity.NecrifyVelocityPlugin; import de.jvstvshd.necrify.velocity.config.ConfigData; import net.kyori.adventure.key.Key; import net.kyori.adventure.text.Component; @@ -77,14 +77,14 @@ public class ResourceBundleMessageProvider implements MessageProvider { LOGGER.error("An error occurred while loading translation file {}", path.getFileName(), e); } }); - try (JarFile jar = new JarFile(new File(NecrifyPlugin.class.getProtectionDomain().getCodeSource().getLocation().toURI()))) { + try (JarFile jar = new JarFile(new File(NecrifyVelocityPlugin.class.getProtectionDomain().getCodeSource().getLocation().toURI()))) { for (JarEntry translationEntry : jar.stream().filter(jarEntry -> jarEntry.getName().toLowerCase().contains("translations") && !jarEntry.isDirectory()).toList()) { var path = Path.of(baseDir.toString(), translationEntry.getName().split("/")[1]); if (Files.exists(path)) { continue; } System.out.println("copying translation file " + translationEntry.getName()); - Files.copy(Objects.requireNonNull(NecrifyPlugin.class.getResourceAsStream("/" + translationEntry.getName())), path); + Files.copy(Objects.requireNonNull(NecrifyVelocityPlugin.class.getResourceAsStream("/" + translationEntry.getName())), path); } } } diff --git a/plugin/src/main/java/de/jvstvshd/necrify/velocity/user/VelocityUser.java b/plugin/src/main/java/de/jvstvshd/necrify/velocity/user/VelocityUser.java index 00cebcfb..eba17633 100644 --- a/plugin/src/main/java/de/jvstvshd/necrify/velocity/user/VelocityUser.java +++ b/plugin/src/main/java/de/jvstvshd/necrify/velocity/user/VelocityUser.java @@ -32,13 +32,15 @@ import de.chojo.sadu.queries.api.call.Call; import de.chojo.sadu.queries.api.query.Query; import de.jvstvshd.necrify.api.duration.PunishmentDuration; +import de.jvstvshd.necrify.api.event.user.UserDeletedEvent; import de.jvstvshd.necrify.api.message.MessageProvider; import de.jvstvshd.necrify.api.punishment.*; import de.jvstvshd.necrify.api.user.NecrifyUser; +import de.jvstvshd.necrify.api.user.UserDeletionReason; import de.jvstvshd.necrify.common.io.Adapters; import de.jvstvshd.necrify.common.punishment.NecrifyBan; import de.jvstvshd.necrify.common.punishment.NecrifyMute; -import de.jvstvshd.necrify.velocity.NecrifyPlugin; +import de.jvstvshd.necrify.velocity.NecrifyVelocityPlugin; import de.jvstvshd.necrify.velocity.impl.VelocityKick; import de.jvstvshd.necrify.velocity.internal.Util; import net.kyori.adventure.text.Component; @@ -68,12 +70,12 @@ public class VelocityUser implements NecrifyUser { private final ExecutorService service; private final MessageProvider messageProvider; private final ProxyServer server; - private final NecrifyPlugin plugin; + private final NecrifyVelocityPlugin plugin; private boolean whitelisted; private String name; private Player player; - public VelocityUser(@NotNull UUID uuid, @Nullable String name, boolean whitelisted, @Nullable Player player, NecrifyPlugin plugin) { + public VelocityUser(@NotNull UUID uuid, @Nullable String name, boolean whitelisted, @Nullable Player player, NecrifyVelocityPlugin plugin) { this.whitelisted = whitelisted; this.plugin = plugin; this.punishments = new ArrayList<>(); @@ -86,7 +88,7 @@ public VelocityUser(@NotNull UUID uuid, @Nullable String name, boolean whitelist this.server = plugin.getServer(); } - public VelocityUser(@NotNull UUID uuid, @Nullable String name, boolean whitelisted, NecrifyPlugin plugin) { + public VelocityUser(@NotNull UUID uuid, @Nullable String name, boolean whitelisted, NecrifyVelocityPlugin plugin) { this.whitelisted = whitelisted; this.plugin = plugin; this.punishments = new ArrayList<>(); @@ -112,7 +114,7 @@ public VelocityUser(@NotNull UUID uuid, @Nullable String name, boolean whitelist @Override public @NotNull Ban ban(@Nullable Component reason, @NotNull PunishmentDuration duration) { - return punish(new NecrifyBan(this, reason, dataSource, service, duration.absolute(), messageProvider)); + return punish(new NecrifyBan(this, reason, duration.absolute(), plugin)); } @Override @@ -122,7 +124,7 @@ public VelocityUser(@NotNull UUID uuid, @Nullable String name, boolean whitelist @Override public @NotNull Mute mute(@Nullable Component reason, @NotNull PunishmentDuration duration) { - return punish(new NecrifyMute(this, reason, dataSource, service, duration.absolute(), messageProvider)); + return punish(new NecrifyMute(this, reason, duration.absolute(), plugin)); } @Override @@ -132,7 +134,7 @@ public VelocityUser(@NotNull UUID uuid, @Nullable String name, boolean whitelist @Override public @NotNull Kick kick(@Nullable Component reason) { - var kick = new VelocityKick(this, reason, dataSource, service, UUID.randomUUID(), messageProvider); + var kick = new VelocityKick(this, reason, UUID.randomUUID(), plugin); kick.punish(); return kick; } @@ -146,6 +148,7 @@ private T punish(T punishment) { @SuppressWarnings("unchecked") @Override public @NotNull List getPunishments(PunishmentType... types) { + validatePunishments(); if (types == null || types.length == 0) return (List) ImmutableList.copyOf(punishments); return (List) ImmutableList.copyOf(punishments.stream().filter(punishment -> { @@ -157,19 +160,23 @@ private T punish(T punishment) { }).toList()); } + private synchronized void validatePunishments() { + punishments.removeIf(punishment -> !punishment.isOngoing()); + } + @Override public @NotNull CompletableFuture queryUsername(boolean update) { - try (HttpClient httpClient = HttpClient.newHttpClient()) { - HttpRequest request = HttpRequest.newBuilder(URI.create("https://sessionserver.mojang.com/session/minecraft/profile/" + uuid)).GET().build(); - return httpClient - .sendAsync(request, HttpResponse.BodyHandlers.ofString()) - .thenApply(response -> JsonParser.parseString(response.body()).getAsJsonObject().get("name").getAsString()) - .thenApplyAsync(s -> { - if (update) - name = s; - return s; - }); - } + HttpClient httpClient = HttpClient.newHttpClient(); + HttpRequest request = HttpRequest.newBuilder(URI.create("https://sessionserver.mojang.com/session/minecraft/profile/" + uuid)).GET().build(); + return httpClient + .sendAsync(request, HttpResponse.BodyHandlers.ofString()) + .thenApply(response -> JsonParser.parseString(response.body()).getAsJsonObject().get("name").getAsString()) + .thenApplyAsync(s -> { + if (update) + name = s; + return s; + }); + } public Optional queryPlayer() { @@ -199,12 +206,9 @@ public Punishment addPunishment(Row row) throws SQLException { final UUID punishmentUuid = row.getObject(4, UUID.class); Punishment punishment; switch (type) { - case BAN, PERMANENT_BAN -> - punishment = new NecrifyBan(this, reason, dataSource, service, punishmentUuid, duration, messageProvider); - case MUTE, PERMANENT_MUTE -> - punishment = new NecrifyMute(this, reason, dataSource, service, punishmentUuid, duration, messageProvider); - case KICK -> - punishment = new VelocityKick(this, reason, dataSource, service, punishmentUuid, messageProvider); + case BAN, PERMANENT_BAN -> punishment = new NecrifyBan(this, reason, punishmentUuid, duration, plugin); + case MUTE, PERMANENT_MUTE -> punishment = new NecrifyMute(this, reason, punishmentUuid, duration, plugin); + case KICK -> punishment = new VelocityKick(this, reason, punishmentUuid, plugin); default -> throw new UnsupportedOperationException("unhandled punishment type: " + type.getName()); } punishments.add(punishment); @@ -236,12 +240,10 @@ public void setPlayer(Player player) { this.player = player; } - @Override public void addPunishment(Punishment punishment) { punishments.add(punishment); } - @Override public void removePunishment(Punishment punishment) { punishments.remove(punishment); } @@ -276,7 +278,8 @@ public String toString() { } @Override - public void delete() { + public void delete(@NotNull UserDeletionReason reason) { + plugin.getEventDispatcher().dispatch(new UserDeletedEvent(this, reason)); throw new UnsupportedOperationException("not implemented yet"); } } diff --git a/plugin/src/main/java/de/jvstvshd/necrify/velocity/user/VelocityUserManager.java b/plugin/src/main/java/de/jvstvshd/necrify/velocity/user/VelocityUserManager.java index 0b88b778..eb87420f 100644 --- a/plugin/src/main/java/de/jvstvshd/necrify/velocity/user/VelocityUserManager.java +++ b/plugin/src/main/java/de/jvstvshd/necrify/velocity/user/VelocityUserManager.java @@ -31,11 +31,16 @@ import com.velocitypowered.api.proxy.ProxyServer; import de.chojo.sadu.queries.api.call.Call; import de.chojo.sadu.queries.api.query.Query; +import de.jvstvshd.necrify.api.event.origin.EventOrigin; +import de.jvstvshd.necrify.api.event.punishment.PunishmentCancelledEvent; +import de.jvstvshd.necrify.api.event.punishment.PunishmentChangedEvent; +import de.jvstvshd.necrify.api.event.punishment.PunishmentPersecutedEvent; +import de.jvstvshd.necrify.api.event.user.UserLoadedEvent; import de.jvstvshd.necrify.api.user.NecrifyUser; import de.jvstvshd.necrify.api.user.UserManager; import de.jvstvshd.necrify.common.io.Adapters; import de.jvstvshd.necrify.common.user.MojangAPI; -import de.jvstvshd.necrify.velocity.NecrifyPlugin; +import de.jvstvshd.necrify.velocity.NecrifyVelocityPlugin; import de.jvstvshd.necrify.velocity.internal.Util; import org.intellij.lang.annotations.Language; import org.jetbrains.annotations.NotNull; @@ -69,9 +74,9 @@ public class VelocityUserManager implements UserManager { private final ProxyServer server; private final Cache userCache; private final Cache nameCache; - private final NecrifyPlugin plugin; + private final NecrifyVelocityPlugin plugin; - public VelocityUserManager(ExecutorService executor, ProxyServer server, Cache userCache, Cache nameCache, NecrifyPlugin plugin) { + public VelocityUserManager(ExecutorService executor, ProxyServer server, Cache userCache, Cache nameCache, NecrifyVelocityPlugin plugin) { this.executor = executor; this.server = server; this.userCache = userCache; @@ -111,8 +116,11 @@ public VelocityUserManager(ExecutorService executor, ProxyServer server, Cache cache(velocityUser)); + return user.map(velocityUser -> { + cache(velocityUser); + plugin.getEventDispatcher().dispatch(new UserLoadedEvent(velocityUser).setOrigin(EventOrigin.ofClass(getClass()))); + return velocityUser; + }); }, executor); } @@ -134,8 +142,11 @@ public VelocityUserManager(ExecutorService executor, ProxyServer server, Cache cache(velocityUser)); + return user.map(velocityUser -> { + cache(velocityUser); + plugin.getEventDispatcher().dispatch(new UserLoadedEvent(velocityUser).setOrigin(EventOrigin.ofClass(getClass()))); + return velocityUser; + }); }, executor); } @@ -170,7 +181,9 @@ private NecrifyUser createUser(UUID uuid, String name) { if (!result.changed()) { throw new IllegalStateException("user already exists"); } - return cache(new VelocityUser(uuid, name, false, plugin)); + var user = new VelocityUser(uuid, name, false, plugin); + plugin.getEventDispatcher().dispatch(new UserLoadedEvent(user)); + return cache(user); } @Override @@ -226,4 +239,38 @@ public void onPlayerJoin(LoginEvent event) { if (user == null) return; user.setPlayer(player); } + + @org.greenrobot.eventbus.Subscribe + public void onUserLoaded(UserLoadedEvent event) { + if (event.getOrigin().originatesFrom(getClass())) return; + var user = event.getUser(); + if (user instanceof VelocityUser) { + cache((VelocityUser) user); + } + } + + @org.greenrobot.eventbus.Subscribe + public void onPunishmentEnforced(PunishmentPersecutedEvent event) { + var punishment = event.getPunishment(); + if (punishment.getUser() instanceof VelocityUser user) { + user.addPunishment(punishment); + } + } + + @org.greenrobot.eventbus.Subscribe + public void onPunishmentCancelled(PunishmentCancelledEvent event) { + var punishment = event.getPunishment(); + if (punishment.getUser() instanceof VelocityUser user) { + user.removePunishment(punishment); + } + } + + @org.greenrobot.eventbus.Subscribe + public void onPunishmentChanged(PunishmentChangedEvent event) { + var punishment = event.getPunishment(); + if (punishment.getUser() instanceof VelocityUser user) { + user.removePunishment(punishment); + user.addPunishment(punishment); + } + } } \ No newline at end of file