Skip to content

Commit 7997309

Browse files
Better Avatars
1 parent 6e6e224 commit 7997309

3 files changed

Lines changed: 59 additions & 38 deletions

File tree

src/main/java/net/aerh/discordbridge/DiscordBridgePlugin.java

Lines changed: 33 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@
3030
import java.util.Properties;
3131
import java.util.concurrent.ConcurrentHashMap;
3232
import java.util.function.BiConsumer;
33+
import java.util.function.BiFunction;
3334
import java.util.function.Consumer;
3435
import java.util.regex.Matcher;
3536
import java.util.regex.Pattern;
@@ -48,8 +49,9 @@ public final class DiscordBridgePlugin extends JavaPlugin {
4849
private DiscordBotConnection botConnection;
4950
private boolean serverStartMessageSent;
5051
private boolean serverStopMessageSent;
51-
private final Map<String, String> discordUserToAvatarUrl = new ConcurrentHashMap<>();
52+
private final Map<String, String> hytaleUsernameToAvatarUrl = new ConcurrentHashMap<>();
5253
private final Map<String, String> hytaleUsernameToDiscordUserId = new ConcurrentHashMap<>();
54+
private volatile boolean isShuttingDown = false;
5355

5456
public DiscordBridgePlugin(@NotNull JavaPluginInit init) {
5557
super(init);
@@ -88,26 +90,35 @@ protected void setup() {
8890
return;
8991
}
9092

91-
BiConsumer<String, String> avatarSetter = (userId, url) -> {
92-
discordUserToAvatarUrl.put(userId, url);
93-
saveMappings();
94-
};
95-
BiConsumer<String, String> linkSetter = (username, userId) -> {
96-
hytaleUsernameToDiscordUserId.put(username, userId);
97-
saveMappings();
98-
};
99-
Consumer<String> unlinkUser = userId -> {
100-
hytaleUsernameToDiscordUserId.entrySet().removeIf(entry -> entry.getValue().equals(userId));
101-
saveMappings();
102-
};
103-
this.botConnection = new DiscordBotConnection(cfg, getLogger(), this::relayDiscordMessage, avatarSetter, linkSetter, unlinkUser);
93+
BiConsumer<String, String> avatarSetter = (username, url) -> {
94+
hytaleUsernameToAvatarUrl.put(username, url);
95+
saveMappings();
96+
};
97+
BiFunction<String, String, Boolean> linkSetter = (username, userId) -> {
98+
if (hytaleUsernameToDiscordUserId.containsKey(username) && !hytaleUsernameToDiscordUserId.get(username).equals(userId)) {
99+
return false;
100+
}
101+
hytaleUsernameToDiscordUserId.put(username, userId);
102+
saveMappings();
103+
return true;
104+
};
105+
Consumer<String> unlinkUser = userId -> {
106+
hytaleUsernameToDiscordUserId.entrySet().removeIf(entry -> entry.getValue().equals(userId));
107+
saveMappings();
108+
};
109+
BiFunction<String, String, Boolean> isLinked = (username, userId) -> {
110+
String linkedUserId = hytaleUsernameToDiscordUserId.get(username);
111+
return linkedUserId != null && linkedUserId.equals(userId);
112+
};
113+
this.botConnection = new DiscordBotConnection(cfg, getLogger(), this::relayDiscordMessage, avatarSetter, linkSetter, unlinkUser, isLinked);
104114
getLogger().at(Level.INFO).log("Discord bot connection initialized");
105115
}
106116

107117
@Override
108118
protected void start() {
109119
this.serverStartMessageSent = false;
110120
this.serverStopMessageSent = false;
121+
this.isShuttingDown = false;
111122

112123
if (botConnection == null) {
113124
getLogger().at(Level.INFO).log("Skipping Discord bot start - not configured");
@@ -132,6 +143,7 @@ protected void start() {
132143
@Override
133144
protected void shutdown() {
134145
getLogger().at(Level.INFO).log("Shutting down Discord bridge...");
146+
this.isShuttingDown = true;
135147
sendServerStopMessage();
136148
if (botConnection != null) {
137149
botConnection.shutdown();
@@ -161,7 +173,7 @@ private void onPlayerChat(@NotNull PlayerChatEvent event) {
161173
}
162174
String username = event.getSender().getUsername();
163175
String discordUserId = hytaleUsernameToDiscordUserId.get(username);
164-
String avatarUrl = discordUserId != null ? discordUserToAvatarUrl.get(discordUserId) : null;
176+
String avatarUrl = discordUserId != null ? hytaleUsernameToAvatarUrl.get(username) : null;
165177
botConnection.sendWebhookMessage(webhookUrl, event.getSender().getUsername(), cleaned, avatarUrl);
166178
}
167179

@@ -173,6 +185,9 @@ private void onPlayerConnect(@NotNull PlayerConnectEvent event) {
173185
}
174186

175187
private void onPlayerDisconnect(@NotNull PlayerDisconnectEvent event) {
188+
if (isShuttingDown) {
189+
return;
190+
}
176191
DiscordBridgeConfig cfg = config.get();
177192
EventsConfig events = cfg.getEventsConfig();
178193
MessagesConfig messages = cfg.getMessagesConfig();
@@ -399,8 +414,8 @@ private void loadMappings() {
399414
for (String key : props.stringPropertyNames()) {
400415
String value = props.getProperty(key);
401416
if (key.startsWith("avatar.")) {
402-
String userId = key.substring(7);
403-
discordUserToAvatarUrl.put(userId, value);
417+
String username = key.substring(7);
418+
hytaleUsernameToAvatarUrl.put(username, value);
404419
} else if (key.startsWith("link.")) {
405420
String username = key.substring(5);
406421
hytaleUsernameToDiscordUserId.put(username, value);
@@ -414,7 +429,7 @@ private void loadMappings() {
414429
private void saveMappings() {
415430
Path mappingsFile = getDataDirectory().resolve("mappings.properties");
416431
Properties props = new Properties();
417-
for (Map.Entry<String, String> entry : discordUserToAvatarUrl.entrySet()) {
432+
for (Map.Entry<String, String> entry : hytaleUsernameToAvatarUrl.entrySet()) {
418433
props.setProperty("avatar." + entry.getKey(), entry.getValue());
419434
}
420435
for (Map.Entry<String, String> entry : hytaleUsernameToDiscordUserId.entrySet()) {

src/main/java/net/aerh/discordbridge/discord/BridgeListener.java

Lines changed: 18 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323
import java.util.List;
2424
import java.util.concurrent.CompletableFuture;
2525
import java.util.function.BiConsumer;
26+
import java.util.function.BiFunction;
2627
import java.util.function.Consumer;
2728
import java.util.logging.Level;
2829

@@ -34,8 +35,9 @@ final class BridgeListener extends ListenerAdapter {
3435
private final Consumer<DiscordMessage> relayToGameChat;
3536
private final Consumer<TextChannel> discordChannelUpdater;
3637
private final BiConsumer<String, String> avatarSetter;
37-
private final BiConsumer<String, String> linkSetter;
38+
private final BiFunction<String, String, Boolean> linkSetter;
3839
private final Consumer<String> unlinkUser;
40+
private final BiFunction<String, String, Boolean> isLinked;
3941

4042
BridgeListener(
4143
@NotNull DiscordBridgeConfig config,
@@ -44,8 +46,9 @@ final class BridgeListener extends ListenerAdapter {
4446
@NotNull Consumer<DiscordMessage> relayToGameChat,
4547
@NotNull Consumer<TextChannel> discordChannelUpdater,
4648
@NotNull BiConsumer<String, String> avatarSetter,
47-
@NotNull BiConsumer<String, String> linkSetter,
48-
@NotNull Consumer<String> unlinkUser
49+
@NotNull BiFunction<String, String, Boolean> linkSetter,
50+
@NotNull Consumer<String> unlinkUser,
51+
@NotNull BiFunction<String, String, Boolean> isLinked
4952
) {
5053
this.config = config;
5154
this.logger = logger;
@@ -55,6 +58,7 @@ final class BridgeListener extends ListenerAdapter {
5558
this.avatarSetter = avatarSetter;
5659
this.linkSetter = linkSetter;
5760
this.unlinkUser = unlinkUser;
61+
this.isLinked = isLinked;
5862
}
5963

6064
@Override
@@ -72,11 +76,9 @@ public void onReady(@NotNull ReadyEvent event) {
7276
discordChannelUpdater.accept(channel);
7377
logger.at(Level.INFO).log("Discord bot connected as %s", event.getJDA().getSelfUser().getAsTag());
7478
event.getJDA().updateCommands().addCommands(
75-
Commands.slash("avatar", "Set your avatar")
76-
.addOption(OptionType.ATTACHMENT, "image", "The image file", true),
77-
Commands.slash("link", "Link your Discord account to a Hytale username")
78-
.addOption(OptionType.STRING, "username", "The Hytale username", true),
79-
Commands.slash("unlink", "Unlink your Discord account from Hytale UUID")
79+
Commands.slash("avatar", "Set your avatar for a Hytale account")
80+
.addOption(OptionType.ATTACHMENT, "image", "The image file", true)
81+
.addOption(OptionType.STRING, "username", "The Hytale username", true)
8082
).queue();
8183
readyFuture.complete(null);
8284
}
@@ -133,15 +135,15 @@ public void onSlashCommandInteraction(@NotNull SlashCommandInteractionEvent even
133135
if (event.getName().equals("avatar")) {
134136
Message.Attachment attachment = event.getOption("image").getAsAttachment();
135137
String imageUrl = attachment.getUrl();
136-
avatarSetter.accept(userId, imageUrl);
137-
event.reply("Avatar set.").setEphemeral(true).queue();
138-
} else if (event.getName().equals("link")) {
139138
String username = event.getOption("username").getAsString();
140-
linkSetter.accept(username, userId);
141-
event.reply("Linked to username " + username).setEphemeral(true).queue();
142-
} else if (event.getName().equals("unlink")) {
143-
unlinkUser.accept(userId);
144-
event.reply("Unlinked.").setEphemeral(true).queue();
139+
if (!isLinked.apply(username, userId)) {
140+
if (!linkSetter.apply(username, userId)) {
141+
event.reply("This username is already linked to another Discord user.").setEphemeral(true).queue();
142+
return;
143+
}
144+
}
145+
avatarSetter.accept(username, imageUrl);
146+
event.reply("Avatar set for " + username).setEphemeral(true).queue();
145147
}
146148
}
147149
}

src/main/java/net/aerh/discordbridge/discord/DiscordBotConnection.java

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
import java.util.concurrent.CompletableFuture;
1717
import java.util.concurrent.atomic.AtomicBoolean;
1818
import java.util.function.BiConsumer;
19+
import java.util.function.BiFunction;
1920
import java.util.function.Consumer;
2021
import java.util.logging.Level;
2122

@@ -25,8 +26,9 @@ public final class DiscordBotConnection implements AutoCloseable {
2526
private final HytaleLogger logger;
2627
private final Consumer<DiscordMessage> relayToGameChat;
2728
private final BiConsumer<String, String> avatarSetter;
28-
private final BiConsumer<String, String> linkSetter;
29+
private final BiFunction<String, String, Boolean> linkSetter;
2930
private final Consumer<String> unlinkUser;
31+
private final BiFunction<String, String, Boolean> isLinked;
3032
private final CompletableFuture<Void> readyFuture = new CompletableFuture<>();
3133
private final AtomicBoolean shuttingDown = new AtomicBoolean(false);
3234

@@ -38,22 +40,24 @@ public DiscordBotConnection(
3840
@NotNull HytaleLogger logger,
3941
@NotNull Consumer<DiscordMessage> relayToGameChat,
4042
@NotNull BiConsumer<String, String> avatarSetter,
41-
@NotNull BiConsumer<String, String> linkSetter,
42-
@NotNull Consumer<String> unlinkUser
43+
@NotNull BiFunction<String, String, Boolean> linkSetter,
44+
@NotNull Consumer<String> unlinkUser,
45+
@NotNull BiFunction<String, String, Boolean> isLinked
4346
) {
4447
this.config = config;
4548
this.logger = logger;
4649
this.relayToGameChat = relayToGameChat;
4750
this.avatarSetter = avatarSetter;
4851
this.linkSetter = linkSetter;
4952
this.unlinkUser = unlinkUser;
53+
this.isLinked = isLinked;
5054
}
5155

5256
@NotNull
5357
public CompletableFuture<Void> start() {
5458
try {
5559
DiscordConfig discordConfig = config.getDiscordConfig();
56-
BridgeListener listener = new BridgeListener(config, logger, readyFuture, relayToGameChat, this::onChannelReady, avatarSetter, linkSetter, unlinkUser);
60+
BridgeListener listener = new BridgeListener(config, logger, readyFuture, relayToGameChat, this::onChannelReady, avatarSetter, linkSetter, unlinkUser, isLinked);
5761
JDABuilder builder = JDABuilder.createDefault(discordConfig.getBotToken())
5862
.setMemberCachePolicy(MemberCachePolicy.NONE)
5963
.enableIntents(GatewayIntent.GUILD_MESSAGES, GatewayIntent.MESSAGE_CONTENT)

0 commit comments

Comments
 (0)