Skip to content

Commit

Permalink
Release 1.2.0
Browse files Browse the repository at this point in the history
- Add configurable default reasons
- Do not show succeeding punishments twice
- Correctly update expiration for mutes when chaining punishments
  • Loading branch information
JvstvsHD committed Aug 15, 2024
1 parent 19ee04d commit a937234
Show file tree
Hide file tree
Showing 14 changed files with 143 additions and 48 deletions.
5 changes: 1 addition & 4 deletions build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ plugins {
}

group = "de.jvstvshd.necrify"
version = "1.2.0-rc.1"
version = "1.2.0"

subprojects {
apply {
Expand All @@ -24,9 +24,6 @@ subprojects {
plugin<IndraSpotlessLicenserPlugin>()
}
indraSpotlessLicenser {
//licenseHeaderFile(rootProject.files("HEADER.txt"))
//headerFormat { doubleSlash() }
languageFormatOverride("pebble") { starSlash() }
newLine(true)
}
java {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -150,15 +150,15 @@ default Punishment getSuccessorOrNull() {
* After calling this method, do not access the data of successor anymore as it may be changed. Instead, use {@link #getSuccessor()}
* or {@link #getSuccessorOrNull()} as soon as the future completes.
*
* @param successor the successor of this punishment
* @param successor the successor of this punishment or null to remove the successor
* @return a {@link CompletableFuture} containing this punishment with the successor set
* @throws UnsupportedOperationException if the underlying punishment does not support succeeding punishments (e.g. Kicks)
* @throws IllegalArgumentException if {@code successor} is not related to this punishment or if the succeeding punishment is not applied the same user
* @throws IllegalStateException if {@code successor} is in a circular chain with this punishment
* @since 1.2.0
*/
@NotNull
CompletableFuture<Punishment> setSuccessor(@NotNull Punishment successor);
CompletableFuture<Punishment> setSuccessor(Punishment successor);

/**
* Returns the creation time of this punishment.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,12 +31,19 @@
public interface ReasonHolder {

/**
* Gets the reason of this punishment.
* Gets the reason of this punishment. All placeholders will be replaced with their actual values.
* @return the reason of this punishment as as component
*
*/
@NotNull
Component getReason();

/**
* Gets the reason of this punishment. All placeholders will remain as they are.
* @return the reason of this punishment as as component
*/
@NotNull
Component getRawReason();
/**
* Creates the full reason inclusive when the ban ends (or that the ban is permanent).
*
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
import de.jvstvshd.necrify.api.Necrify;
import de.jvstvshd.necrify.api.duration.PunishmentDuration;
import de.jvstvshd.necrify.api.punishment.Punishment;
import de.jvstvshd.necrify.api.punishment.PunishmentType;
import de.jvstvshd.necrify.api.punishment.PunishmentTypeRegistry;
import de.jvstvshd.necrify.api.punishment.StandardPunishmentType;
import de.jvstvshd.necrify.api.user.NecrifyUser;
Expand Down Expand Up @@ -136,13 +137,7 @@ public final void registerCommands(CommandManager<NecrifyUser> manager, boolean
}

//TODO: Move config to necrify-common
public String getDefaultReason(StandardPunishmentType type) {
return "<red>You were " + switch (type) {
case KICK -> "kicked from the server.";
case TEMPORARY_BAN, PERMANENT_BAN -> "banned from the server.";
case TEMPORARY_MUTE, PERMANENT_MUTE -> "muted.";
} + "</red>";
}
public abstract String getDefaultReason(PunishmentType type);

@SuppressWarnings("ConstantValue")
public static String buildInfo() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -285,6 +285,9 @@ public void userCommand(
Util.copyComponent(target.getUuid().toString(), provider).color(NamedTextColor.YELLOW),
Component.text(punishments.size())).color(NamedTextColor.GRAY));
for (Punishment punishment : punishments) {
if (punishment.getPredecessor() != null) {
continue;
}
Component component = buildComponent(PunishmentHelper.buildPunishmentData(punishment, plugin.getMessageProvider()), punishment);
sender.sendMessage(component);
}
Expand Down Expand Up @@ -408,6 +411,9 @@ private void removePunishments(NecrifyUser source, List<Punishment> punishments,
if (punishments.size() > 1) {
source.sendMessage(plugin.getMessageProvider().provide("command." + values[0] + ".multiple-" + values[1] + "s").color(NamedTextColor.YELLOW));
for (Punishment punishment : punishments) {
if (punishment.getPredecessor() != null) {
continue;
}
source.sendMessage(buildComponent(PunishmentHelper.buildPunishmentData(punishment, plugin.getMessageProvider()), punishment));
}
} else {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@

import de.chojo.sadu.core.conversion.UUIDConverter;
import de.chojo.sadu.queries.api.call.adapter.Adapter;
import de.chojo.sadu.queries.api.call.adapter.AdapterMapping;
import de.chojo.sadu.queries.call.adapter.UUIDAdapter;

import java.sql.JDBCType;
Expand All @@ -38,4 +39,16 @@ public class Adapters {
default -> preparedStatement.setBytes(parameterIndex, UUIDConverter.convert(x));
}
}, Types.BINARY);

public static final Adapter<UUID> UUID_NULL_ADAPTER = new Adapter<UUID>() {
@Override
public AdapterMapping<UUID> mapping() {
return null;
}

@Override
public int type() {
return Types.NULL;
}
};
}
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
import de.jvstvshd.necrify.api.user.NecrifyUser;
import de.jvstvshd.necrify.common.AbstractNecrifyPlugin;
import net.kyori.adventure.text.Component;
import net.kyori.adventure.text.TextReplacementConfig;
import net.kyori.adventure.text.minimessage.MiniMessage;
import org.intellij.lang.annotations.Language;
import org.jetbrains.annotations.NotNull;
Expand Down Expand Up @@ -89,6 +90,11 @@ public AbstractPunishment(@NotNull NecrifyUser user,
return reason;
}

@Override
public @NotNull Component getRawReason() {
return reason;
}

public ExecutorService getExecutor() {
return executor;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,8 @@
import de.jvstvshd.necrify.common.io.Adapters;
import de.jvstvshd.necrify.common.util.Util;
import net.kyori.adventure.text.Component;
import net.kyori.adventure.text.TextReplacementConfig;
import net.kyori.adventure.text.format.NamedTextColor;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;

Expand Down Expand Up @@ -81,6 +83,15 @@ protected void checkValidity() {
}
}

@Override
public @NotNull Component getReason() {
return super.getReason().replaceText(TextReplacementConfig
.builder()
.matchLiteral("<UNTIL>")
.replacement(Component.text(getDuration().remainingDuration(), NamedTextColor.YELLOW))
.build());
}

@Override
public final @NotNull CompletableFuture<Punishment> change(@NotNull PunishmentDuration newDuration, @Nullable LocalDateTime creationTime, Component newReason) throws PunishmentException {
if (!getType().isBan() && !getType().isMute()) {
Expand All @@ -103,9 +114,9 @@ protected void checkValidity() {
.withUser(getUser())
.withReason(newReason)
.withDuration(newDuration)
.withCreationTime(newCreatedAt)
.withPunishmentUuid(getPunishmentUuid())
.withSuccessor(getSuccessorOrNull())
.withCreationTime(getCreationTime());
.withSuccessor(getSuccessorOrNull());
Punishment punishment;
if (getType().isBan()) {
punishment = builder.buildBan();
Expand All @@ -125,24 +136,12 @@ protected CompletableFuture<Punishment> applyCancellation() throws PunishmentExc
if (hasSuccessor()) {
updateSuccessor().join();
}
var predecessor = getUser().getPunishments().stream()
.filter(punishment -> punishment.getSuccessorOrNull() != null && punishment.getSuccessorOrNull().equals(this)).findFirst().orElse(null);
var predecessor = getPredecessor();
if (predecessor != null) {
Query.query(APPLY_SUCCESSOR)
.single(Call.of().bind(null, new Adapter<UUID>() {
@Override
public AdapterMapping<UUID> mapping() {
return null;
}

@Override
public int type() {
return Types.NULL;
}
}).bind(predecessor.getPunishmentUuid(), Adapters.UUID_ADAPTER))
.update();
if (hasSuccessor()) {
predecessor.setSuccessor(getSuccessor()).join();
} else {
predecessor.setSuccessor(null);
}
}
Query.query(APPLY_CANCELLATION)
Expand Down Expand Up @@ -175,7 +174,7 @@ protected CompletableFuture<Punishment> applyPunishment() throws PunishmentExcep
.bind(getUser().getUuid(), Adapters.UUID_ADAPTER)
.bind(getType().getId())
.bind(duration.expirationAsTimestamp())
.bind(convertReason(getReason()))
.bind(convertReason(getRawReason()))
.bind(getPunishmentUuid(), Adapters.UUID_ADAPTER)
.bind(Timestamp.valueOf(getCreationTime())))
.insert();
Expand All @@ -184,7 +183,15 @@ protected CompletableFuture<Punishment> applyPunishment() throws PunishmentExcep
}

@Override
public @NotNull CompletableFuture<Punishment> setSuccessor(@NotNull Punishment successor) {
public @NotNull CompletableFuture<Punishment> setSuccessor(Punishment successor) {
if (successor == null) {
return Util.executeAsync(() -> {
Query.query(APPLY_SUCCESSOR)
.single(Call.of().bind(null, Adapters.UUID_NULL_ADAPTER).bind(getPunishmentUuid(), Adapters.UUID_ADAPTER))
.update();
return this;
}, getExecutor());
}
if (!getType().getRelatedTypes().contains(successor.getType())) {
throw new IllegalArgumentException("successor punishment is not related to this punishment");
}
Expand All @@ -198,7 +205,6 @@ protected CompletableFuture<Punishment> applyPunishment() throws PunishmentExcep
Query.query(APPLY_SUCCESSOR)
.single(Call.of().bind(successor.getPunishmentUuid(), Adapters.UUID_ADAPTER).bind(getPunishmentUuid(), Adapters.UUID_ADAPTER))
.update();
setSuccessor0(successor);
LocalDateTime successorNewExpiration;
if (successor instanceof TemporalPunishment temporalSuccessor) {
var total = temporalSuccessor.totalDuration();
Expand All @@ -214,7 +220,10 @@ protected CompletableFuture<Punishment> applyPunishment() throws PunishmentExcep
.bind(successor.getPunishmentUuid(), Adapters.UUID_ADAPTER))
.update();
if (successor instanceof TemporalPunishment temporalSuccessor) {
temporalSuccessor.change(PunishmentDuration.from(successorNewExpiration), issuanceSuccessor, successor.getReason()).join();
var newSuccessor = temporalSuccessor.change(PunishmentDuration.from(successorNewExpiration), issuanceSuccessor, successor.getReason()).join();
setSuccessor0(newSuccessor);
} else {
setSuccessor0(successor);
}
return this;
}, getExecutor());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -62,16 +62,19 @@ public MessagingChannelCommunicator(ProxyServer server, AbstractNecrifyPlugin pl
/**
* Recalculates the mute information for the specified user and sends the updated mute information to all registered servers.
* This will inform those servers only about expiration and reason. The reason is a translated complete reason.
*
* @param user the user to recalculate the mute information for
*/
public void recalculateMuteInformation(NecrifyUser user) {
List<Mute> mutes = user.getPunishments(StandardPunishmentType.PERMANENT_MUTE, StandardPunishmentType.TEMPORARY_MUTE);
final Mute mute = Util.getLongestPunishment(mutes);
if (mute == null)
return;
Component deny = ChainedPunishment.of(mute, plugin).createFullReason(user.getLocale());
var serialized = MiniMessage.miniMessage().serialize(GlobalTranslator.render(deny, user.getLocale()));
public void recalculateMuteInformation(NecrifyUser user) {
try {
List<Mute> mutes = user.getPunishments(StandardPunishmentType.PERMANENT_MUTE, StandardPunishmentType.TEMPORARY_MUTE);
final Mute mute = Util.getLongestPunishment(mutes);
if (mute == null) {
queueMute(new MuteData(user.getUuid(), null, null, MuteData.RESET, null));
return;
}
Component deny = ChainedPunishment.of(mute, plugin).createFullReason(user.getLocale());
var serialized = MiniMessage.miniMessage().serialize(GlobalTranslator.render(deny, user.getLocale()));
queueMute(new MuteData(user.getUuid(), serialized, mute.getDuration().expiration(), MuteData.RECALCULATION, mute.getPunishmentUuid()));
} catch (Exception e) {
logger.error("Could not queue mute for player {}", user.getUuid(), e);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@
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.PunishmentType;
import de.jvstvshd.necrify.api.punishment.util.PlayerResolver;
import de.jvstvshd.necrify.api.user.NecrifyUser;
import de.jvstvshd.necrify.api.user.UserManager;
Expand Down Expand Up @@ -474,4 +475,9 @@ public NecrifyKick createKick(Component reason, NecrifyUser user, UUID punishmen
public Set<Pair<String, UUID>> getOnlinePlayers() {
return server.getAllPlayers().stream().map(player -> Pair.of(player.getUsername(), player.getUniqueId())).collect(Collectors.toSet());
}

@Override
public String getDefaultReason(PunishmentType type) {
return configurationManager.getConfiguration().getPunishmentConfigData().getPunishmentMessages().get(type.getId());
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,9 @@ public class ConfigData {
@JsonProperty("default-language")
private final Locale defaultLanguage;

@JsonProperty("punishment")
private final PunishmentConfigData punishmentConfigData;

@JsonProperty("whitelist-activated")
@JsonAlias("whitelistActivated")
private boolean whitelistActivated;
Expand All @@ -40,15 +43,16 @@ public class ConfigData {
@JsonAlias("allowTopLevelCommands")
private boolean allowTopLevelCommands;

public ConfigData(DataBaseData dataBaseData, Locale defaultLanguage, boolean whitelistActivated, boolean allowTopLevelCommands) {
public ConfigData(DataBaseData dataBaseData, Locale defaultLanguage, PunishmentConfigData punishmentConfigData, boolean whitelistActivated, boolean allowTopLevelCommands) {
this.dataBaseData = dataBaseData;
this.defaultLanguage = defaultLanguage;
this.punishmentConfigData = punishmentConfigData;
this.whitelistActivated = whitelistActivated;
this.allowTopLevelCommands = allowTopLevelCommands;
}

public ConfigData() {
this(new DataBaseData(), Locale.ENGLISH, false, true);
this(new DataBaseData(), Locale.ENGLISH, new PunishmentConfigData(), false, true);
}

public final DataBaseData getDataBaseData() {
Expand All @@ -74,4 +78,8 @@ public boolean isAllowTopLevelCommands() {
public void setAllowTopLevelCommands(boolean allowTopLevelCommands) {
this.allowTopLevelCommands = allowTopLevelCommands;
}

public PunishmentConfigData getPunishmentConfigData() {
return punishmentConfigData;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@
import java.util.Locale;

public class DataBaseData {

private final String host;
private final String password;
private final String username;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
/*
* This file is part of Necrify (formerly Velocity Punishment), a plugin designed to manage player's punishments for the platforms Velocity and partly Paper.
* Copyright (C) 2022-2024 JvstvsHD
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/

package de.jvstvshd.necrify.velocity.config;

import java.util.Map;

public class PunishmentConfigData {

private final Map<Integer, String> punishmentMessages;

public PunishmentConfigData(Map<Integer, String> punishmentMessages) {
this.punishmentMessages = punishmentMessages;
}

public PunishmentConfigData() {
this.punishmentMessages = Map.of(
1, "<red>You are banned.",
2, "<red>You were permanently banned.",
3, "<red>You were muted.",
4, "<red>You were permanently muted.",
5, "<red>You were kicked.");
}

public Map<Integer, String> getPunishmentMessages() {
return punishmentMessages;
}
}
Loading

0 comments on commit a937234

Please sign in to comment.