Skip to content

Commit f9fa09d

Browse files
committed
feat: add commands
jp-on, jp-off, role, toggleinvites, hide-guild, hideall, format, info
1 parent c7a381f commit f9fa09d

34 files changed

Lines changed: 1419 additions & 342 deletions

File tree

blueberry-1.20/src/main/java/net/azisaba/interchatmod/blueberry/Mod.java

Lines changed: 22 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -2,12 +2,11 @@
22

33
import com.google.gson.Gson;
44
import com.google.gson.JsonArray;
5-
import com.google.gson.JsonElement;
6-
import com.google.gson.JsonObject;
75
import net.azisaba.interchatmod.blueberry.commands.GuildChatCommand;
86
import net.azisaba.interchatmod.blueberry.commands.GuildCommand;
97
import net.azisaba.interchatmod.blueberry.commands.GuildFocusCommand;
10-
import net.azisaba.interchatmod.blueberry.model.Guild;
8+
import net.azisaba.interchatmod.common.model.Guild;
9+
import net.azisaba.interchatmod.common.model.GuildMember;
1110
import net.blueberrymc.client.commands.ClientCommandManager;
1211
import net.blueberrymc.client.event.player.ClientLocalPlayerChatEvent;
1312
import net.blueberrymc.client.event.render.gui.ScreenChangedEvent;
@@ -20,6 +19,7 @@
2019
import net.minecraft.client.server.IntegratedServer;
2120
import net.minecraft.network.chat.Component;
2221
import org.java_websocket.exceptions.WebsocketNotConnectedException;
22+
import org.jetbrains.annotations.Contract;
2323
import org.jetbrains.annotations.NotNull;
2424

2525
import javax.net.ssl.SSLContext;
@@ -29,13 +29,13 @@
2929
import java.net.URI;
3030
import java.net.URL;
3131
import java.nio.charset.StandardCharsets;
32-
import java.util.Collections;
33-
import java.util.HashSet;
34-
import java.util.Set;
32+
import java.util.*;
33+
import java.util.concurrent.ConcurrentHashMap;
3534

3635
public class Mod extends BlueberryMod {
3736
public WebSocketChatClient client;
3837
public Set<Guild> guilds = Collections.synchronizedSet(new HashSet<>());
38+
public Map<Long, Set<GuildMember>> guildMembers = new ConcurrentHashMap<>();
3939

4040
@Override
4141
public void onLoad() {
@@ -109,42 +109,32 @@ public void reconnect() {
109109
public void onPostInit() {
110110
reconnect();
111111

112-
Blueberry.getUtil().getClientScheduler().runTaskTimerAsynchronously(this, 1000 * 30, 1000 * 30, () -> {
112+
Blueberry.getUtil().getClientScheduler().runTaskTimerAsynchronously(this, 1000 * 5, 1000 * 30, () -> {
113113
try {
114-
String url = "https://api-ktor.azisaba.net/interchat/guilds/list";
115-
if (ICConfig.apiHostOverride != null && !ICConfig.apiHostOverride.isBlank()) {
116-
url = ICConfig.apiHostOverride + "/interchat/guilds/list";
117-
}
118-
HttpURLConnection connection = (HttpURLConnection) new URL(url).openConnection();
119-
connection.addRequestProperty("Authorization", "Bearer " + ICConfig.apiKey);
120-
String response = new String(connection.getInputStream().readAllBytes(), StandardCharsets.UTF_8);
121-
JsonArray arr = new Gson().fromJson(response, JsonArray.class);
122-
Set<Guild> localGuilds = getGuildsFromArray(arr);
114+
Gson gson = new Gson();
115+
JsonArray arr = gson.fromJson(makeRequest("interchat/guilds/list"), JsonArray.class);
116+
Set<Guild> localGuilds = Guild.getGuildsFromArray(arr);
123117
guilds.clear();
124118
guilds.addAll(localGuilds);
119+
for (Guild guild : localGuilds) {
120+
JsonArray membersArray = gson.fromJson(makeRequest("interchat/guilds/" + guild.id() + "/members"), JsonArray.class);
121+
guildMembers.put(guild.id(), GuildMember.getGuildMembersFromArray(membersArray));
122+
}
125123
} catch (Exception e) {
126124
getLogger().warn("Failed to fetch guild list", e);
127125
}
128126
});
129127
}
130128

131-
@NotNull
132-
private static Set<Guild> getGuildsFromArray(JsonArray arr) {
133-
Set<Guild> localGuilds = new HashSet<>();
134-
for (JsonElement element : arr) {
135-
JsonObject obj = element.getAsJsonObject();
136-
localGuilds.add(
137-
new Guild(
138-
obj.get("id").getAsLong(),
139-
obj.get("name").getAsString(),
140-
obj.get("format").getAsString(),
141-
obj.get("capacity").getAsInt(),
142-
obj.get("open").getAsBoolean(),
143-
obj.get("deleted").getAsBoolean()
144-
)
145-
);
129+
@Contract("_ -> new")
130+
private static @NotNull String makeRequest(String path) throws IOException {
131+
String url = "https://api-ktor.azisaba.net/" + path;
132+
if (ICConfig.apiHostOverride != null && !ICConfig.apiHostOverride.isBlank()) {
133+
url = ICConfig.apiHostOverride + "/" + path;
146134
}
147-
return localGuilds;
135+
HttpURLConnection connection = (HttpURLConnection) new URL(url).openConnection();
136+
connection.addRequestProperty("Authorization", "Bearer " + ICConfig.apiKey);
137+
return new String(connection.getInputStream().readAllBytes(), StandardCharsets.UTF_8);
148138
}
149139

150140
@EventHandler

blueberry-1.20/src/main/java/net/azisaba/interchatmod/blueberry/WebSocketChatClient.java

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,17 @@ protected void trySwitch() {
4949

5050
@Override
5151
protected void scheduleReconnect() {
52-
Blueberry.getUtil().getClientScheduler().runTaskLaterAsynchronously(mod, 1000 * 15, mod::reconnect);
52+
Blueberry.getUtil().getClientScheduler().runTaskLaterAsynchronously(mod, 1000 * 5, mod::reconnect);
53+
Blueberry.getUtil().getClientScheduler().runTaskLaterAsynchronously(mod, 1000 * 15, () -> {
54+
if (!mod.client.isOpen()) {
55+
mod.reconnect();
56+
}
57+
});
58+
Blueberry.getUtil().getClientScheduler().runTaskLaterAsynchronously(mod, 1000 * 30, () -> {
59+
if (!mod.client.isOpen()) {
60+
mod.reconnect();
61+
}
62+
});
5363
}
5464

5565
@Override

blueberry-1.20/src/main/java/net/azisaba/interchatmod/blueberry/commands/GuildCommand.java

Lines changed: 137 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -3,11 +3,27 @@
33
import com.mojang.brigadier.CommandDispatcher;
44
import com.mojang.brigadier.arguments.StringArgumentType;
55
import net.azisaba.interchatmod.blueberry.Mod;
6+
import net.azisaba.interchatmod.common.model.GuildMember;
7+
import net.azisaba.interchatmod.common.util.Constants;
68
import net.blueberrymc.client.commands.ClientCommandHandler;
9+
import net.minecraft.ChatFormatting;
710
import net.minecraft.commands.CommandSourceStack;
8-
import net.minecraft.commands.Commands;
11+
import net.minecraft.commands.SharedSuggestionProvider;
12+
import net.minecraft.network.chat.ClickEvent;
13+
import net.minecraft.network.chat.Component;
14+
import net.minecraft.network.chat.HoverEvent;
915
import org.jetbrains.annotations.NotNull;
1016

17+
import java.util.Collections;
18+
import java.util.Locale;
19+
import java.util.function.Consumer;
20+
import java.util.stream.Collectors;
21+
import java.util.stream.Stream;
22+
23+
import static net.minecraft.commands.Commands.argument;
24+
import static net.minecraft.commands.Commands.literal;
25+
26+
@SuppressWarnings("SameReturnValue")
1127
public class GuildCommand implements ClientCommandHandler {
1228
private final Mod mod;
1329

@@ -18,29 +34,140 @@ public GuildCommand(Mod mod) {
1834
@Override
1935
public void register(@NotNull CommandDispatcher<CommandSourceStack> commandDispatcher) {
2036
commandDispatcher.register(
21-
Commands.literal("cguild")
22-
.then(Commands.literal("invite")
23-
.then(Commands.argument("player", StringArgumentType.word())
37+
literal("cguild")
38+
.then(literal("invite")
39+
.then(argument("player", StringArgumentType.word())
2440
.executes(ctx -> executeInvite(StringArgumentType.getString(ctx, "player")))
2541
)
2642
)
27-
.then(Commands.literal("accept")
28-
.then(Commands.argument("guild", StringArgumentType.word())
43+
.then(literal("accept")
44+
.then(argument("guild", StringArgumentType.word())
2945
.executes(ctx -> executeRespondInvite(StringArgumentType.getString(ctx, "guild"), true))
3046
)
3147
)
32-
.then(Commands.literal("reject")
33-
.then(Commands.argument("guild", StringArgumentType.word())
48+
.then(literal("reject")
49+
.then(argument("guild", StringArgumentType.word())
3450
.executes(ctx -> executeRespondInvite(StringArgumentType.getString(ctx, "guild"), false))
3551
)
3652
)
37-
.then(Commands.literal("nick")
53+
.then(literal("nick")
3854
.executes(ctx -> executeNick(null))
39-
.then(Commands.argument("nickname", StringArgumentType.greedyString())
55+
.then(argument("nickname", StringArgumentType.greedyString())
4056
.executes(ctx -> executeNick(StringArgumentType.getString(ctx, "nickname")))
4157
)
4258
)
59+
.then(literal("jp-on")
60+
.executes(ctx -> {
61+
mod.client.toggleTranslate(true);
62+
return 0;
63+
})
64+
)
65+
.then(literal("jp-off")
66+
.executes(ctx -> {
67+
mod.client.toggleTranslate(false);
68+
return 0;
69+
})
70+
)
71+
.then(literal("role")
72+
.then(argument("member", StringArgumentType.word())
73+
.suggests((ctx, builder) -> {
74+
var set = mod.guildMembers.getOrDefault(mod.client.getSelectedGuild(), Collections.emptySet());
75+
return SharedSuggestionProvider.suggest(set.stream().map(GuildMember::name), builder);
76+
})
77+
.then(argument("role", StringArgumentType.word())
78+
.suggests((ctx, builder) -> SharedSuggestionProvider.suggest(Stream.of("owner", "moderator", "member"), builder))
79+
.executes(ctx -> {
80+
mod.client.role(StringArgumentType.getString(ctx, "member"), StringArgumentType.getString(ctx, "role"));
81+
return 0;
82+
})
83+
)
84+
)
85+
)
86+
.then(literal("toggleinvites")
87+
.executes(ctx -> {
88+
mod.client.toggleInvites();
89+
return 0;
90+
})
91+
)
92+
.then(literal("hide-guild")
93+
.executes(ctx -> {
94+
mod.client.hideGuild();
95+
return 0;
96+
})
97+
)
98+
.then(literal("hideall")
99+
.executes(ctx -> {
100+
mod.client.hideAll("");
101+
return 0;
102+
})
103+
.then(argument("duration", StringArgumentType.greedyString())
104+
.executes(ctx -> {
105+
mod.client.hideAll(StringArgumentType.getString(ctx, "duration"));
106+
return 0;
107+
})
108+
)
109+
)
110+
.then(literal("format")
111+
.then(argument("format", StringArgumentType.greedyString())
112+
.suggests((ctx, builder) -> SharedSuggestionProvider.suggest(Constants.FORMAT_VARIABLES.stream(), builder))
113+
.executes(ctx -> {
114+
mod.client.format(StringArgumentType.getString(ctx, "format"));
115+
return 0;
116+
})
117+
)
118+
)
119+
.then(literal("info").executes(ctx -> executeInfo(ctx.getSource())))
120+
);
121+
}
122+
123+
private int executeInfo(CommandSourceStack source) {
124+
var guild = mod.guilds.stream().filter(g -> g.id() == mod.client.getSelectedGuild()).findAny().orElse(null);
125+
if (guild == null) {
126+
source.sendFailure(Component.literal("無効なギルドが指定されています。/cgs (ギルド)で選択してください。"));
127+
return 0;
128+
}
129+
var members = mod.guildMembers.getOrDefault(guild.id(), Collections.emptySet());
130+
source.sendSystemMessage(
131+
Component.literal("--- ギルド").withStyle(ChatFormatting.GOLD)
132+
.append(Component.literal(guild.name()).withStyle(ChatFormatting.AQUA))
133+
.append(Component.literal("の情報 ---").withStyle(ChatFormatting.GOLD))
134+
);
135+
source.sendSystemMessage(
136+
Component.literal("メンバー数: ").withStyle(ChatFormatting.GOLD)
137+
.append(Component.literal(String.valueOf(members.size())).withStyle(ChatFormatting.RED))
138+
.append(Component.literal("/").withStyle(ChatFormatting.GOLD))
139+
.append(Component.literal(String.valueOf(guild.capacity())).withStyle(ChatFormatting.RED))
140+
);
141+
Consumer<String> sendRole = (role) -> {
142+
String players =
143+
members.stream()
144+
.filter(m -> m.role().equals(role.toUpperCase(Locale.ROOT)))
145+
.map(GuildMember::name)
146+
.collect(Collectors.joining(", "));
147+
source.sendSystemMessage(
148+
Component.literal(role + ": ").withStyle(ChatFormatting.GOLD)
149+
.append(Component.literal(players).withStyle(ChatFormatting.WHITE))
150+
);
151+
};
152+
sendRole.accept("Owner");
153+
sendRole.accept("Moderator");
154+
sendRole.accept("Member");
155+
source.sendSystemMessage(Component.empty());
156+
source.sendSystemMessage(
157+
Component.literal("公開: ").withStyle(ChatFormatting.GOLD)
158+
.append(Component.literal(String.valueOf(guild.open())).withStyle(guild.open() ? ChatFormatting.GREEN : ChatFormatting.RED))
159+
);
160+
source.sendSystemMessage(
161+
Component.literal("チャット形式: ").withStyle(ChatFormatting.GOLD)
162+
.append(Component.literal(guild.format())
163+
.withStyle(ChatFormatting.WHITE)
164+
.withStyle(style ->
165+
style.withHoverEvent(new HoverEvent(HoverEvent.Action.SHOW_TEXT, Component.literal("クリックでコピー")))
166+
.withClickEvent(new ClickEvent(ClickEvent.Action.COPY_TO_CLIPBOARD, guild.format()))
167+
)
168+
)
43169
);
170+
return 0;
44171
}
45172

46173
private int executeInvite(String player) {

blueberry-1.20/src/main/java/net/azisaba/interchatmod/blueberry/commands/GuildFocusCommand.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
import com.mojang.brigadier.CommandDispatcher;
44
import com.mojang.brigadier.arguments.StringArgumentType;
55
import net.azisaba.interchatmod.blueberry.Mod;
6-
import net.azisaba.interchatmod.blueberry.model.Guild;
6+
import net.azisaba.interchatmod.common.model.Guild;
77
import net.blueberrymc.client.commands.ClientCommandHandler;
88
import net.minecraft.commands.CommandSourceStack;
99
import net.minecraft.commands.Commands;

blueberry-1.20/src/main/java/net/azisaba/interchatmod/blueberry/model/Guild.java

Lines changed: 0 additions & 4 deletions
This file was deleted.

build.gradle.kts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ allprojects {
1212
}
1313

1414
group = "net.azisaba.interchatmod"
15-
version = "0.2.0"
15+
version = "0.4.0"
1616

1717
repositories {
1818
// mavenLocal()

0 commit comments

Comments
 (0)