Skip to content

Commit

Permalink
Provide more information on mutes synchronized to sub-servers
Browse files Browse the repository at this point in the history
  • Loading branch information
JvstvsHD committed Aug 15, 2024
1 parent b4642dd commit 19ee04d
Show file tree
Hide file tree
Showing 19 changed files with 274 additions and 129 deletions.
4 changes: 2 additions & 2 deletions build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -8,13 +8,13 @@ plugins {
`maven-publish`
signing
id("io.papermc.hangar-publish-plugin") version "0.1.2"
id("io.github.goooler.shadow") version "8.1.8" apply false
id("com.gradleup.shadow") version "8.3.0" apply false
id("net.kyori.indra.licenser.spotless") version "2.2.0"
java
}

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

subprojects {
apply {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -144,6 +144,16 @@ public String getDefaultReason(StandardPunishmentType type) {
} + "</red>";
}

@SuppressWarnings("ConstantValue")
public static String buildInfo() {
var buildInfo = "v" + VERSION + " (running on commit " + GIT_COMMIT;
//build number is only available when built by the CI (GitHub Actions or Jenkins)
if (!BUILD_NUMBER.equalsIgnoreCase("-1")) {
buildInfo += " build " + BUILD_NUMBER;
}
return buildInfo + ")";
}

public abstract NecrifyKick createKick(Component reason, NecrifyUser user, UUID punishmentUuid);

public abstract Logger getLogger();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -186,6 +186,7 @@ public void tempmuteCommand(
return;
}
sender.sendMessage("command.tempmute.success",
NamedTextColor.GRAY,
miniMessage(target.getUsername()).color(NamedTextColor.YELLOW),
copyComponent(target.getUuid().toString()).color(NamedTextColor.YELLOW),
finalReason,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,11 +16,10 @@
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/

package de.jvstvshd.necrify.velocity.message;
package de.jvstvshd.necrify.common.message;

import de.jvstvshd.necrify.api.message.MessageProvider;
import de.jvstvshd.necrify.velocity.NecrifyVelocityPlugin;
import de.jvstvshd.necrify.velocity.config.ConfigData;
import de.jvstvshd.necrify.common.AbstractNecrifyPlugin;
import net.kyori.adventure.key.Key;
import net.kyori.adventure.text.Component;
import net.kyori.adventure.text.format.NamedTextColor;
Expand All @@ -35,7 +34,6 @@

import java.io.File;
import java.io.IOException;
import java.net.URISyntaxException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.ArrayList;
Expand Down Expand Up @@ -66,14 +64,14 @@ public class ResourceBundleMessageProvider implements MessageProvider {
}
try (Stream<Path> paths = Files.list(baseDir)) {
List<Path> registeredPaths = new ArrayList<>();
try (JarFile jar = new JarFile(new File(NecrifyVelocityPlugin.class.getProtectionDomain().getCodeSource().getLocation().toURI()))) {
try (JarFile jar = new JarFile(new File(AbstractNecrifyPlugin.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;
}
LOGGER.info("copying translation file {}", translationEntry.getName());
Files.copy(Objects.requireNonNull(NecrifyVelocityPlugin.class.getResourceAsStream("/" + translationEntry.getName())), path);
Files.copy(Objects.requireNonNull(AbstractNecrifyPlugin.class.getResourceAsStream("/" + translationEntry.getName())), path);
registeredPaths.add(path);
}
}
Expand Down Expand Up @@ -106,16 +104,15 @@ private static Locale locale(String fileName) {
}



private final ConfigData configData;
private final Locale defaultLocale;
private final boolean autoPrefixed;

public ResourceBundleMessageProvider(@NotNull ConfigData configData) {
this(configData, true);
public ResourceBundleMessageProvider(@NotNull Locale defaultLocale) {
this(defaultLocale, true);
}

private ResourceBundleMessageProvider(@NotNull ConfigData configData, boolean autoPrefixed) {
this.configData = configData;
private ResourceBundleMessageProvider(@NotNull Locale defaultLocale, boolean autoPrefixed) {
this.defaultLocale = defaultLocale;
this.autoPrefixed = autoPrefixed;
}

Expand Down Expand Up @@ -152,14 +149,14 @@ public boolean autoPrefixed() {

@NotNull
private Locale orDefault(@Nullable Locale input) {
return input == null ? configData.getDefaultLanguage() : input;
return input == null ? defaultLocale : input;
}

@Override
public MessageProvider unprefixedProvider() {
if (!autoPrefixed) {
return this;
}
return new ResourceBundleMessageProvider(configData, false);
return new ResourceBundleMessageProvider(defaultLocale, false);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -20,35 +20,87 @@

import com.fasterxml.jackson.annotation.JsonIgnore;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.core.JsonFactory;
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
import org.jetbrains.annotations.ApiStatus;

import java.time.LocalDateTime;
import java.util.UUID;

/**
* Represents a data object that is used to transfer mute data between sub-servers. This is used to synchronize mute data between sub-servers
* and this proxy. Since Minecraft 1.19.1, chat messages cannot be cancelled on the proxy, so this must be done on the sub-servers.
* <p>Mute information status updates are sent to the sub-servers using their plugin messaging channels.</p>
*
* <b>Deprecation notice:</b> The fields {@link MuteData#ADD}, {@link MuteData#REMOVE} and {@link MuteData#UPDATE} are deprecated in favor
* of usage of {@link MuteData#RECALCULATION} and {@link MuteData#RESET}. The former ones are only used for compatibility reasons.
*/
public class MuteData {

public static final String MUTE_DATA_CHANNEL_IDENTIFIER = "necrify:mutedata";
public static final ObjectMapper OBJECT_MAPPER = new ObjectMapper().registerModule(new JavaTimeModule());
public static final ObjectMapper OBJECT_MAPPER = new ObjectMapper()
.registerModule(new JavaTimeModule())
.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
@Deprecated(forRemoval = true)
@ApiStatus.ScheduledForRemoval(inVersion = "1.3.0")
public static final int ADD = 0;
@Deprecated(forRemoval = true)
@ApiStatus.ScheduledForRemoval(inVersion = "1.3.0")
public static final int REMOVE = 1;
@Deprecated(forRemoval = true)
@ApiStatus.ScheduledForRemoval(inVersion = "1.3.0")
public static final int UPDATE = 2;

/**
* The protocol version of the mute data. This is used to ensure that the data is correctly interpreted by the sub-servers.
* Unexpected results may occur if the version of incoming data does not match.
*/
public static final int PROTOCOL_VERSION = 1;

/**
* Starting from 1.2.0-rc.1, this and {@link #RECALCULATION} are the only type that is actively used. All other ones exist merely for compatibility reasons.
* <p>Used to indicate that all mute data for a user should be reset. This requires only the field {@link MuteData#getUuid()} to be set.</p>
*/
public static final int RESET = 3;
/**
* Starting from 1.2.0-rc.1, this and {@link #RESET} are the only type that is actively used. All other ones exist merely for compatibility reasons.
* <p>Used to let sub-servers know that the mute status of a user has changed. This requires all fields of
* {@link MuteData#MuteData(int, UUID, String, LocalDateTime, UUID, int)} to be set, though {@link MuteData#getPunishmentId()}
* may be omitted.</p>
*/
public static final int RECALCULATION = 4;
public static final int UNKNOWN = -1;

private final UUID uuid;
private final String reason;
private final LocalDateTime expiration;
private final int type;
private final UUID punishmentId;
private final int version;

public MuteData(@JsonProperty("uuid") UUID uuid, @JsonProperty("reason") String reason,
@JsonProperty("expiration") LocalDateTime expiration, @JsonProperty("type") int type, @JsonProperty("punishment_id") UUID punishmentId) {
public MuteData(@JsonProperty("type") int type,
@JsonProperty("uuid") UUID uuid,
@JsonProperty("reason") String reason,
@JsonProperty("expiration") LocalDateTime expiration,
@JsonProperty("punishment_id") UUID punishmentId,
@JsonProperty("version") int version) {
this.uuid = uuid;
this.reason = reason;
this.expiration = expiration;
this.type = type;
this.punishmentId = punishmentId;
this.version = version;
}

public MuteData(UUID uuid, String reason, LocalDateTime expiration, int type, UUID punishmentId) {
this.uuid = uuid;
this.reason = reason;
this.expiration = expiration;
this.type = type;
this.punishmentId = punishmentId;
this.version = PROTOCOL_VERSION;
}

public UUID getUuid() {
Expand All @@ -67,16 +119,23 @@ public int getType() {
return type;
}

public int getVersion() {
return version;
}

@Deprecated
@JsonIgnore
public boolean isAdd() {
return type == ADD;
}

@Deprecated
@JsonIgnore
public boolean isRemove() {
return type == REMOVE;
}

@Deprecated
@JsonIgnore
public boolean isUpdate() {
return type == UPDATE;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
/*
* 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.common.punishment;

import de.jvstvshd.necrify.api.punishment.StandardPunishmentType;
import de.jvstvshd.necrify.api.punishment.TemporalPunishment;
import de.jvstvshd.necrify.common.AbstractNecrifyPlugin;
import net.kyori.adventure.text.Component;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;

import java.util.ArrayList;
import java.util.List;
import java.util.Locale;

public class ChainedPunishment extends AbstractTemporalPunishment {

private final List<TemporalPunishment> bans;

private ChainedPunishment(List<TemporalPunishment> bans, AbstractNecrifyPlugin plugin) {
this(bans.getFirst(), bans, plugin);
}

private ChainedPunishment(TemporalPunishment tp, List<TemporalPunishment> bans, AbstractNecrifyPlugin plugin) {
super(tp.getUser(), tp.getReason(), tp.getPunishmentUuid(), tp.getDuration(), plugin, tp.getSuccessorOrNull(), tp.getCreationTime());
this.bans = bans;
}

@Override
public @NotNull Component getReason() {
return bans.stream().map(TemporalPunishment::getReason).reduce(Component.empty(), (a, b) -> a.append(Component.newline()).append(b));
}

public static ChainedPunishment of(TemporalPunishment last, AbstractNecrifyPlugin plugin) {
List<TemporalPunishment> bans = new ArrayList<>();
TemporalPunishment current = last;
while (current.getPredecessor() != null) {
bans.add(current);
current = (TemporalPunishment) current.getPredecessor();
}
bans.add(current);
return new ChainedPunishment(bans, plugin);
}

@Override
public @NotNull StandardPunishmentType getType() {
return bans.getFirst().getType().standard();
}

@Override
public boolean isPermanent() {
return bans.stream().anyMatch(TemporalPunishment::isPermanent);
}

@SuppressWarnings("OptionalGetWithoutIsPresent")
@Override
public @NotNull Component createFullReason(@Nullable Locale locale) {
return bans.stream().max((a, b) -> b.getDuration().expiration().compareTo(a.getDuration().expiration()))
.get() //list will never be empty
.createFullReason(locale);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ private void tryKick() {
var until = Component.text(getDuration().expiration().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")))
.color(NamedTextColor.YELLOW);
return getMessageProvider().provide("punishment.ban.temp.full-reason",
Component.text(getDuration().remainingDuration()).color(NamedTextColor.YELLOW), getReason(), until);
Component.text(getDuration().remainingDuration()).color(NamedTextColor.YELLOW), getReason(), until).color(NamedTextColor.GRAY);
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,8 @@ public boolean isPermanent() {
} else {
var until = Component.text(getDuration().expiration().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")))
.color(NamedTextColor.YELLOW);
return getMessageProvider().provide("punishment.mute.temp.full-reason", Component.text(getDuration().remainingDuration()).color(NamedTextColor.YELLOW), getReason(), until);
return getMessageProvider().provide("punishment.mute.temp.full-reason",
Component.text(getDuration().remainingDuration()).color(NamedTextColor.YELLOW), getReason(), until).color(NamedTextColor.GRAY);
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
/*
* 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.common.util;

import org.slf4j.Logger;

public class Updater {

public static void updateInformation(Logger logger) {
logger.info("Check here for updates:");
logger.info("https://hangar.papermc.io/JvstvsHD/Necrify/");
logger.info("https://github.com/JvstvsHD/necrify/releases");
logger.info("Dev builds: https://ci.jvstvshd.de/job/Necrify/ (Proceed with caution, these builds may be unstable! Do not use these in production!)");
}
}
7 changes: 5 additions & 2 deletions necrify-paper/build.gradle.kts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
plugins {
java
`java-library`
id("io.github.goooler.shadow")
id("com.gradleup.shadow")
id("net.minecrell.plugin-yml.paper") version "0.6.0"
id("io.papermc.hangar-publish-plugin")
}
Expand All @@ -16,6 +16,9 @@ dependencies {
}

tasks {
jar {
archiveFileName.set("Necrify-Paper-${project.buildVersion()}.jar")
}
shadowJar {
archiveFileName.set("Necrify-Paper-${project.buildVersion()}.jar")
dependencies {
Expand Down Expand Up @@ -55,7 +58,7 @@ tasks.getByName<Test>("test") {
}

paper {
main = "de.jvstvshd.necrify.paper.NecrifyPaperPlugin"
main = "de.jvstvshd.necrify.paper.NecrifyPaperJavaPlugin"
name = "necrify-paper"
version = rootProject.version.toString()
description = "A paper plugin complementing the Necrify plugin for velocity for imposing mutes."
Expand Down
Loading

0 comments on commit 19ee04d

Please sign in to comment.