Skip to content

Commit 95414c8

Browse files
Merge branch 'WiIIiam278:master' into master
2 parents 330df87 + e87666c commit 95414c8

18 files changed

Lines changed: 440 additions & 252 deletions

build.gradle

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -38,23 +38,23 @@ dependencies {
3838
compileOnly "com.velocitypowered:velocity-proxy:${velocity_api_version}-SNAPSHOT"
3939
compileOnly "net.william278:papiproxybridge:${papi_proxy_bridge_minimum_version}"
4040

41-
compileOnly 'io.netty:netty-codec-http:4.1.119.Final'
42-
compileOnly 'org.projectlombok:lombok:1.18.36'
43-
compileOnly 'net.luckperms:api:5.4'
41+
compileOnly 'io.netty:netty-codec-http:4.2.2.Final'
42+
compileOnly 'org.projectlombok:lombok:1.18.38'
43+
compileOnly 'net.luckperms:api:5.5'
4444
compileOnly 'io.github.miniplaceholders:miniplaceholders-api:2.2.3'
4545
compileOnly 'it.unimi.dsi:fastutil:8.5.15'
46-
compileOnly 'net.kyori:adventure-nbt:4.19.0'
46+
compileOnly 'net.kyori:adventure-nbt:4.21.0'
4747

48-
implementation 'org.apache.commons:commons-text:1.13.0'
48+
implementation 'org.apache.commons:commons-text:1.13.1'
4949
implementation 'net.william278:desertwell:2.0.4'
5050
implementation 'net.william278:minedown:1.8.2'
5151
implementation 'org.bstats:bstats-velocity:3.1.0'
52-
implementation 'de.exlll:configlib-yaml:4.5.0'
52+
implementation 'de.exlll:configlib-yaml:4.6.1'
5353
implementation 'org.mvel:mvel2:2.5.2.Final'
5454
implementation 'net.jodah:expiringmap:0.5.11'
5555
implementation 'net.william278.toilet:toilet-velocity:1.0.12'
5656

57-
annotationProcessor 'org.projectlombok:lombok:1.18.36'
57+
annotationProcessor 'org.projectlombok:lombok:1.18.38'
5858
}
5959

6060
processResources {

gradle.properties

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ javaVersion=17
33
org.gradle.jvmargs='-Dfile.encoding=UTF-8'
44
org.gradle.daemon=true
55

6-
plugin_version=1.7.5
6+
plugin_version=1.7.7
77
plugin_archive=velocitab
88
plugin_description=A beautiful and versatile TAB list plugin for Velocity proxies
99

src/main/java/net/william278/velocitab/Velocitab.java

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,10 @@
3737
import net.william278.velocitab.api.PluginMessageAPI;
3838
import net.william278.velocitab.api.VelocitabAPI;
3939
import net.william278.velocitab.commands.VelocitabCommand;
40-
import net.william278.velocitab.config.*;
40+
import net.william278.velocitab.config.ConfigProvider;
41+
import net.william278.velocitab.config.Formatter;
42+
import net.william278.velocitab.config.Settings;
43+
import net.william278.velocitab.config.TabGroupsManager;
4144
import net.william278.velocitab.hook.Hook;
4245
import net.william278.velocitab.hook.LuckPermsHook;
4346
import net.william278.velocitab.packet.PacketEventManager;

src/main/java/net/william278/velocitab/commands/VelocitabCommand.java

Lines changed: 138 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -28,14 +28,18 @@
2828
import com.velocitypowered.api.proxy.Player;
2929
import net.kyori.adventure.text.Component;
3030
import net.kyori.adventure.text.format.TextColor;
31+
import net.kyori.adventure.text.minimessage.MiniMessage;
3132
import net.kyori.adventure.text.serializer.plain.PlainTextComponentSerializer;
3233
import net.william278.desertwell.about.AboutMenu;
3334
import net.william278.velocitab.Velocitab;
35+
import net.william278.velocitab.config.Group;
36+
import net.william278.velocitab.config.Settings;
37+
import net.william278.velocitab.config.TabGroups;
3438
import net.william278.velocitab.player.TabPlayer;
3539
import org.jetbrains.annotations.NotNull;
40+
import org.slf4j.event.Level;
3641

37-
import java.util.Optional;
38-
import java.util.UUID;
42+
import java.util.*;
3943

4044
public final class VelocitabCommand {
4145

@@ -146,24 +150,126 @@ public BrigadierCommand command() {
146150
.then(LiteralArgumentBuilder.<CommandSource>literal("reload")
147151
.requires(src -> hasPermission(src, "reload"))
148152
.executes(ctx -> {
149-
plugin.loadConfigs();
153+
final Settings settings = plugin.getSettings();
154+
try {
155+
plugin.loadSettings();
156+
} catch (Throwable e) {
157+
plugin.setSettings(settings);
158+
ctx.getSource().sendRichMessage("<red>An error occurred while reloading the settings file");
159+
plugin.log(Level.ERROR, "An error occurred while reloading the settings file", e);
160+
return Command.SINGLE_SUCCESS;
161+
}
162+
163+
final Map<String, Group> groups = Map.copyOf(plugin.getTabGroupsManager().getGroupsMap());
164+
final Map<TabGroups, String> groupsFiles = Map.copyOf(plugin.getTabGroupsManager().getGroupsFilesMap());
165+
166+
try {
167+
plugin.getTabGroupsManager().loadGroups();
168+
} catch (Throwable e) {
169+
plugin.getTabGroupsManager().loadGroupsBackup(groups, groupsFiles);
170+
ctx.getSource().sendRichMessage("<red>An error occurred while reloading the tab groups file");
171+
plugin.log(Level.ERROR, "An error occurred while reloading the tab groups file", e);
172+
return Command.SINGLE_SUCCESS;
173+
}
174+
150175
plugin.getTabList().reloadUpdate();
151176
ctx.getSource().sendRichMessage(systemReloaded);
152177
return Command.SINGLE_SUCCESS;
153178
})
154179
)
155180
.then(LiteralArgumentBuilder.<CommandSource>literal("debug")
156181
.requires(src -> hasPermission(src, "debug"))
182+
.then(LiteralArgumentBuilder.<CommandSource>literal("tabgroups")
183+
.then(RequiredArgumentBuilder.<CommandSource, String>argument("group", StringArgumentType.string())
184+
.suggests((ctx, builder1) -> {
185+
final String input = builder1.getRemainingLowerCase();
186+
plugin.getTabGroupsManager().getGroups().stream()
187+
.map(Group::name)
188+
.filter(s -> input.isEmpty() || s.toLowerCase().contains(input))
189+
.forEach(builder1::suggest);
190+
return builder1.buildFuture();
191+
})
192+
// players - headers - footers
193+
.then(LiteralArgumentBuilder.<CommandSource>literal("players")
194+
.executes(ctx -> {
195+
final String input = ctx.getArgument("group", String.class);
196+
final Optional<Group> optionalGroup = plugin.getTabGroupsManager().getGroup(input);
197+
if (optionalGroup.isEmpty()) {
198+
ctx.getSource().sendRichMessage(errorTabNameChangeUntracked);
199+
return Command.SINGLE_SUCCESS;
200+
}
201+
202+
//send group info: players count(hover with player list sorted by their team name)
203+
204+
final List<TabPlayer> players = optionalGroup.get().getTabPlayers(plugin)
205+
.stream()
206+
.sorted(Comparator.comparing(t -> -plugin.getScoreboardManager().getPosition(t.getTeamName())))
207+
.toList();
208+
209+
Component playersCount = MiniMessage.miniMessage().deserialize("<yellow>Players:</yellow> <gray>%s".formatted(players.size()));
210+
final String join = joinPlayersName(players);
211+
Component playersCountHover = MiniMessage.miniMessage().deserialize("<yellow>Players:</yellow> <gray>%s".formatted(join));
212+
playersCount = playersCount.hoverEvent(playersCountHover);
213+
214+
ctx.getSource().sendMessage(playersCount);
215+
return Command.SINGLE_SUCCESS;
216+
})
217+
)
218+
.then(LiteralArgumentBuilder.<CommandSource>literal("header")
219+
.executes(ctx -> {
220+
final String input = ctx.getArgument("group", String.class);
221+
final Optional<Group> optionalGroup = plugin.getTabGroupsManager().getGroup(input);
222+
if (optionalGroup.isEmpty()) {
223+
ctx.getSource().sendRichMessage(errorTabNameChangeUntracked);
224+
return Command.SINGLE_SUCCESS;
225+
}
226+
227+
final Group group = optionalGroup.get();
228+
229+
for (int i = 0; i < group.headers().size(); i++) {
230+
final String header = group.getHeader(i);
231+
232+
Component headerComponent = MiniMessage.miniMessage().deserialize("<yellow>Header:</yellow> <gray>%s".formatted((i + 1)));
233+
Component headerHover = plugin.getFormatter().deserialize(header);
234+
headerComponent = headerComponent.hoverEvent(headerHover);
235+
ctx.getSource().sendMessage(headerComponent);
236+
}
237+
238+
return Command.SINGLE_SUCCESS;
239+
})
240+
)
241+
.then(LiteralArgumentBuilder.<CommandSource>literal("footer")
242+
.executes(ctx -> {
243+
final String input = ctx.getArgument("group", String.class);
244+
final Optional<Group> optionalGroup = plugin.getTabGroupsManager().getGroup(input);
245+
if (optionalGroup.isEmpty()) {
246+
ctx.getSource().sendRichMessage(errorTabNameChangeUntracked);
247+
return Command.SINGLE_SUCCESS;
248+
}
249+
250+
final Group group = optionalGroup.get();
251+
252+
for (int i = 0; i < group.footers().size(); i++) {
253+
final String footer = group.getFooter(i);
254+
255+
Component footerComponent = MiniMessage.miniMessage().deserialize("<yellow>Footer:</yellow> <gray>%s".formatted((i + 1)));
256+
Component footerHover = plugin.getFormatter().deserialize(footer);
257+
footerComponent = footerComponent.hoverEvent(footerHover);
258+
ctx.getSource().sendMessage(footerComponent);
259+
}
260+
261+
return Command.SINGLE_SUCCESS;
262+
})
263+
)
264+
)
265+
)
157266
.then(LiteralArgumentBuilder.<CommandSource>literal("tablist")
158267
.then(RequiredArgumentBuilder.<CommandSource, String>argument("player", StringArgumentType.string())
159268
.suggests((ctx, builder1) -> {
160-
final String input = ctx.getInput();
161-
if (input.isEmpty()) {
162-
return builder1.buildFuture();
163-
}
269+
final String input = builder1.getRemainingLowerCase();
164270
plugin.getServer().getAllPlayers().stream()
165271
.map(Player::getUsername)
166-
.filter(s -> s.toLowerCase().startsWith(input.toLowerCase()))
272+
.filter(s -> input.isEmpty() || s.toLowerCase().contains(input))
167273
.forEach(builder1::suggest);
168274
return builder1.buildFuture();
169275
})
@@ -183,9 +289,14 @@ public BrigadierCommand command() {
183289
.map(c -> PlainTextComponentSerializer.plainText().serialize(c))
184290
.orElse("empty");
185291

186-
ctx.getSource().sendMessage(Component.text(
187-
"Name: %s, UUID: %s, Unformatted display name: %s"
188-
.formatted(name, uuid, unformattedDisplayName)));
292+
final Component hover = MiniMessage.miniMessage().deserialize("<yellow>UUID:</yellow> <gray>%s<gray>".formatted(uuid))
293+
.appendNewline()
294+
.append(MiniMessage.miniMessage().deserialize("<yellow>Format</yellow>: ").append(entry.getDisplayNameComponent().orElse(Component.empty())));
295+
296+
final Component component = MiniMessage.miniMessage().deserialize("<gray>%s<gray> <yellow>-</yellow> <gray>%s"
297+
.formatted(name, unformattedDisplayName))
298+
.hoverEvent(hover);
299+
ctx.getSource().sendMessage(component);
189300
});
190301

191302
return Command.SINGLE_SUCCESS;
@@ -228,6 +339,22 @@ public BrigadierCommand command() {
228339
return new BrigadierCommand(builder);
229340
}
230341

342+
@NotNull
343+
private static String joinPlayersName(@NotNull List<TabPlayer> players) {
344+
final StringBuilder join = new StringBuilder();
345+
for(int i = 0; i < players.size(); i++) {
346+
join.append("<yellow>%s</yellow>".formatted(players.get(i).getPlayer().getUsername()));
347+
if (i != players.size() - 1) {
348+
join.append("<gray>,</gray> ");
349+
}
350+
if (i % 4 == 0) {
351+
join.append("<br>");
352+
}
353+
}
354+
355+
return join.toString();
356+
}
357+
231358
private boolean hasPermission(@NotNull CommandSource source, @NotNull String command) {
232359
return source.hasPermission(String.join(".", "velocitab", "command", command));
233360
}

0 commit comments

Comments
 (0)