Skip to content

Commit

Permalink
Add configurable punishment broadcasts and Environment plugin support
Browse files Browse the repository at this point in the history
Signed-off-by: applenick <[email protected]>
  • Loading branch information
applenick committed Dec 8, 2023
1 parent 7107409 commit 85c193f
Show file tree
Hide file tree
Showing 12 changed files with 192 additions and 57 deletions.
8 changes: 7 additions & 1 deletion pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -92,8 +92,14 @@
<artifactId>smart-invs</artifactId>
<version>1.2.7</version>
</dependency>
</dependencies>

<!-- Environment -->
<dependency>
<groupId>tc.oc.occ</groupId>
<artifactId>Environment</artifactId>
<version>1.0.0-SNAPSHOT</version>
</dependency>
</dependencies>

<build>
<finalName>Community</finalName>
Expand Down
15 changes: 15 additions & 0 deletions src/main/java/dev/pgm/community/CommunityConfig.java
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,14 @@

import dev.pgm.community.utils.NetworkUtils;
import org.bukkit.configuration.Configuration;
import tc.oc.occ.environment.Environment;

public class CommunityConfig {

private String serverDisplayName;
private String serverId;
private boolean useEnvironment;
private String environmentServerIdKey;

public CommunityConfig(Configuration config) {
reload(config);
Expand All @@ -15,13 +18,25 @@ public CommunityConfig(Configuration config) {
public void reload(Configuration config) {
this.serverDisplayName = config.getString("general.server-name", "");
this.serverId = config.getString("general.server-id", "");
this.useEnvironment = config.getBoolean("general.use-environment");
this.environmentServerIdKey = config.getString("general.environment-server-id");
}

public String getServerDisplayName() {
return serverDisplayName;
}

public String getServerId() {
if (useEnvironment) {
String serverId = Environment.get().getString(environmentServerIdKey);
if (serverId != null && !serverId.isEmpty()) {
return serverId;
}
}
return NetworkUtils.getServerVar(serverId);
}

public boolean isEnvironmentEnabled() {
return useEnvironment && Environment.get() != null;
}
}
19 changes: 19 additions & 0 deletions src/main/java/dev/pgm/community/moderation/ModerationConfig.java
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,9 @@ public class ModerationConfig extends FeatureConfigImpl {
private static final String BAN_KEY = KEY + ".ban";
private static final String MUTE_KEY = KEY + ".mute";

private static final String GLOBAL_FORMAT_KEY = KEY + ".global-broadcast";
private static final String STAFF_FORMAT_KEY = KEY + ".staff-broadcast";

private static final String RULES_KEY = KEY + ".rules-link";
private static final String APPEAL_KEY = KEY + ".appeal-link";

Expand Down Expand Up @@ -54,6 +57,10 @@ public class ModerationConfig extends FeatureConfigImpl {
private boolean banPublic;
private boolean mutePublic;

// Broadcasts
private String globalBroadcastFormat;
private String staffBroadcastFormat;

// Messages
private String rulesLink;
private String appealMessage;
Expand Down Expand Up @@ -236,6 +243,14 @@ public int getLookupSignSlot() {
return lookupSignSlot;
}

public String getGlobalBroadcastFormat() {
return globalBroadcastFormat;
}

public String getStaffBroadcastFormat() {
return staffBroadcastFormat;
}

@Override
public void reload(Configuration config) {
super.reload(config);
Expand All @@ -253,6 +268,10 @@ public void reload(Configuration config) {
this.mutePublic = config.getBoolean(getBroadcastKey(MUTE_KEY));
this.banPublic = config.getBoolean(getBroadcastKey(BAN_KEY));

// Broadcasts
this.globalBroadcastFormat = config.getString(GLOBAL_FORMAT_KEY);
this.staffBroadcastFormat = config.getString(STAFF_FORMAT_KEY);

// Messages
this.rulesLink = config.getString(RULES_KEY);
this.appealMessage = config.getString(APPEAL_KEY);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -98,7 +98,8 @@ public void repeatPunishment(CommandAudience audience, @Argument("target") Playe
isDisguised(audience));
} else {
// No target supplied, show last punishment
PunishmentFormats.formatBroadcast(lastPunishment, null, usernames)
PunishmentFormats.formatBroadcast(
lastPunishment, null, moderation.getStaffFormat(), usernames)
.thenAcceptAsync(
lpm -> {
Component lastPunishMsg =
Expand Down Expand Up @@ -235,7 +236,8 @@ public Component format(Punishment data, int index) {
builder.append(
data.formatBroadcast(
usernames.renderUsername(data.getIssuerId(), NameStyle.FANCY).join(),
usernames.renderUsername(Optional.of(data.getTargetId()), NameStyle.FANCY).join()));
usernames.renderUsername(Optional.of(data.getTargetId()), NameStyle.FANCY).join(),
moderation.getStaffFormat()));

TextComponent.Builder hover = text();
hover
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -132,5 +132,9 @@ Punishment punish(

void recieveRefresh(UUID playerId);

String getGlobalFormat();

String getStaffFormat();

ModerationTools getTools();
}
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
import dev.pgm.community.utils.Sounds;
import java.time.Duration;
import java.time.Instant;
import java.util.List;
import java.util.Map.Entry;
import java.util.Optional;
import java.util.Set;
Expand Down Expand Up @@ -191,6 +192,16 @@ public void sendRefresh(UUID playerId) {
network.sendUpdate(new RefreshPunishmentUpdate(playerId));
}

@Override
public String getGlobalFormat() {
return getModerationConfig().getGlobalBroadcastFormat();
}

@Override
public String getStaffFormat() {
return getModerationConfig().getStaffBroadcastFormat();
}

// EVENTS
@EventHandler(priority = EventPriority.LOWEST)
public void onPunishmentEvent(PlayerPunishmentEvent event) {
Expand Down Expand Up @@ -369,30 +380,45 @@ private void banHover() {
});
}

private Audience getStaffAudience() {
List<Player> staff =
Bukkit.getOnlinePlayers().stream()
.filter(p -> p.hasPermission(CommunityPermissions.PUNISHMENT_BROADCASTS))
.collect(Collectors.toList());
return Audience.get(staff);
}

private Audience getGlobalAudience() {
List<Player> normal =
Bukkit.getOnlinePlayers().stream()
.filter(p -> !p.hasPermission(CommunityPermissions.PUNISHMENT_BROADCASTS))
.collect(Collectors.toList());
return Audience.get(normal);
}

private void broadcastPunishment(
Punishment punishment, boolean silent, @Nullable Audience audience) {
broadcastPunishment(punishment, silent, null, audience);
}

private void broadcastPunishment(
Punishment punishment, boolean silent, @Nullable String server, @Nullable Audience sender) {
PunishmentFormats.formatBroadcast(punishment, server, getUsers())

boolean global = !silent && getModerationConfig().isPunishmentPublic(punishment);

if (global) {
PunishmentFormats.formatBroadcast(punishment, server, getGlobalFormat(), users)
.thenAcceptAsync(
broadcast -> {
getGlobalAudience().sendMessage(broadcast);
});
}

PunishmentFormats.formatBroadcast(punishment, server, getStaffFormat(), users)
.thenAcceptAsync(
broadcast -> {
if (getModerationConfig().isBroadcasted()) { // Broadcast to global or staff
if (silent || !getModerationConfig().isPunishmentPublic(punishment)) {
BroadcastUtils.sendAdminChatMessage(
broadcast, server, null, CommunityPermissions.PUNISHMENT_BROADCASTS);
} else {
BroadcastUtils.sendGlobalMessage(broadcast);
}
} else { // Send feedback if not broadcast
Audience viewer = sender;
if (viewer == null) {
viewer = Audience.console();
}
viewer.sendMessage(broadcast);
}
BroadcastUtils.sendAdminChatMessage(
broadcast, CommunityPermissions.PUNISHMENT_BROADCASTS);
});
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -22,11 +22,14 @@
import dev.pgm.community.utils.Sounds;
import java.time.Duration;
import java.time.Instant;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.UUID;
import javax.annotation.Nullable;
import net.kyori.adventure.text.Component;
import net.kyori.adventure.text.TextComponent;
import net.kyori.adventure.text.format.NamedTextColor;
import net.kyori.adventure.text.format.TextDecoration;
import net.kyori.adventure.title.Title.Times;
Expand Down Expand Up @@ -203,31 +206,46 @@ public void sendWarning(Audience target, String reason) {
target.playSound(Sounds.WARN_SOUND);
}

public Component formatBroadcast(Component issuer, Component target) {
Component prefix = getType().getPunishmentPrefix();
public Component formatBroadcast(Component issuer, Component target, String formatString) {
Map<String, Component> placeholders = new HashMap<>();
placeholders.put("%issuer%", issuer);
placeholders.put("%type%", getType().getPunishmentPrefix());
placeholders.put("%full_type%", getType().getPunishmentPrefix());
if (this.getDuration() != null) {
Duration length = this.getDuration();
String time = TextTranslations.translateLegacy(duration(length));

// TODO: Clean up (There's most likely an easier way to do this)
String[] timeParts = time.split(" ");
boolean seconds = timeParts.length == 2 && timeParts[1].toLowerCase().startsWith("s");
if (!seconds && time.contains("s")) {
time = time.substring(0, time.lastIndexOf('s'));
} else if (time.lastIndexOf("s") == time.length() - 1) {
time = time.substring(0, time.length() - 1);
placeholders.put("%full_type%", formatTimeComponent(getDuration()));
}
placeholders.put("%target%", target);
placeholders.put("%reason%", text(getReason(), NamedTextColor.RED));
placeholders.put("%div%", BroadcastUtils.BROADCAST_DIV);

TextComponent.Builder builder = text();

String[] parts = formatString.split(" ");

for (String part : parts) {
if (placeholders.containsKey(part)) {
builder.append(placeholders.get(part));
} else {
builder.append(text(part));
}
prefix = getType().getPunishmentPrefix(text(time, NamedTextColor.GOLD));
}
return text()
.append(issuer)
.append(BroadcastUtils.BROADCAST_DIV)
.append(prefix)
.append(BroadcastUtils.BROADCAST_DIV)
.append(target)
.append(BroadcastUtils.BROADCAST_DIV)
.append(text(getReason(), NamedTextColor.RED))
.build();

return builder.build();
}

private Component formatTimeComponent(Duration duration) {
Duration length = this.getDuration();
String time = TextTranslations.translateLegacy(duration(length));

// TODO: Clean up (There's most likely an easier way to do this)
String[] timeParts = time.split(" ");
boolean seconds = timeParts.length == 2 && timeParts[1].toLowerCase().startsWith("s");
if (!seconds && time.contains("s")) {
time = time.substring(0, time.lastIndexOf('s'));
} else if (time.lastIndexOf("s") == time.length() - 1) {
time = time.substring(0, time.length() - 1);
}
return getType().getPunishmentPrefix(text(time, NamedTextColor.GOLD));
}

public Component getExpireDateMessage() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ public class PunishmentFormats {

// Broadcast
public static CompletableFuture<Component> formatBroadcast(
Punishment punishment, String server, UsersFeature users) {
Punishment punishment, String server, String format, UsersFeature users) {
CompletableFuture<Component> broadcast = new CompletableFuture<>();
CompletableFuture<Component> issuer =
users.renderUsername(punishment.getIssuerId(), NameStyle.FANCY);
Expand All @@ -35,7 +35,7 @@ public static CompletableFuture<Component> formatBroadcast(
CompletableFuture.allOf(issuer, target)
.thenAcceptAsync(
x -> {
Component msg = punishment.formatBroadcast(issuer.join(), target.join());
Component msg = punishment.formatBroadcast(issuer.join(), target.join(), format);
broadcast.complete(msg);
});
return broadcast;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,26 +1,29 @@
package dev.pgm.community.moderation.punishments;

import static net.kyori.adventure.text.Component.empty;
import static net.kyori.adventure.text.Component.text;
import static net.kyori.adventure.text.Component.translatable;

import net.kyori.adventure.text.Component;
import net.kyori.adventure.text.format.NamedTextColor;

/** Types of Punishments* */
public enum PunishmentType {
MUTE(false, true, false),
WARN(false, false, false),
KICK(true, false, false),
BAN(true, true, true),
TEMP_BAN(true, true, true),
NAME_BAN(true, true, true);
MUTE(false, true, false, true, "Muted"),
WARN(false, false, false, false, "Warned"),
KICK(true, false, false, false, "Kicked"),
BAN(true, true, true, false, "Permanent Ban"),
TEMP_BAN(true, true, true, true, "Temporary Ban"),
NAME_BAN(true, true, true, false, "Username Ban");

private String PREFIX_TRANSLATE_KEY = "moderation.type.";
private String SCREEN_TRANSLATE_KEY = "moderation.screen.";

private final boolean screen;
private final boolean canRescind;
private final boolean preventLogin;
private final boolean durationBased;
private final String fallbackActionName;

/**
* A Punishment Type
Expand All @@ -29,10 +32,17 @@ public enum PunishmentType {
* @param rescind Whether punishment can be revoked
* @param preventLogin Whether punishment will prevent login to the server
*/
PunishmentType(boolean screen, boolean rescind, boolean preventLogin) {
PunishmentType(
boolean screen,
boolean rescind,
boolean preventLogin,
boolean durationBased,
String fallbackActionName) {
this.screen = screen;
this.canRescind = rescind;
this.preventLogin = preventLogin;
this.durationBased = durationBased;
this.fallbackActionName = fallbackActionName;
}

/**
Expand All @@ -53,7 +63,20 @@ public boolean isLoginPrevented() {
return preventLogin;
}

public boolean isDurationBased() {
return durationBased;
}

public String getFallbackActionName() {
return fallbackActionName;
}

public Component getPunishmentPrefix() {
// TODO: TEMP SOLUTION - fix when we add full translation support
if (isDurationBased()) {
return text(getFallbackActionName(), NamedTextColor.GOLD);
}

return translatable(PREFIX_TRANSLATE_KEY + name().toLowerCase(), NamedTextColor.GOLD);
}

Expand Down
Loading

0 comments on commit 85c193f

Please sign in to comment.