mirror of
https://github.com/NEZNAMY/TAB.git
synced 2026-11-13 12:42:06 -05:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
f6359d2f77 | ||
|
|
727c500b17 | ||
|
|
bebf2988fb | ||
|
|
e3cde1968b | ||
|
|
ef6b668c70 | ||
|
|
fef62e796b | ||
|
|
0d4b1dbce2 | ||
|
|
43d210dbf8 | ||
|
|
e0d2209e97 | ||
|
|
720cae3e94 | ||
|
|
f2ea34a717 | ||
|
|
2c33747e1b | ||
|
|
5f9d72eb90 | ||
|
|
3abcc1d96f | ||
|
|
7d458422c7 | ||
|
|
0feee14bfb | ||
|
|
0023cfcafb |
No files matched your search
@@ -1 +1 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="92" height="20" role="img" aria-label="Release: 6.1.2"><title>Release: 6.1.2</title><filter id="blur"><feGaussianBlur stdDeviation="16"/></filter><linearGradient id="s" x2="0" y2="100%"><stop offset="0" stop-color="#bbb" stop-opacity=".1"/><stop offset="1" stop-opacity=".1"/></linearGradient><clipPath id="r"><rect width="92" height="20" rx="3"/></clipPath><g clip-path="url(#r)"><rect width="53" height="20" fill="#555"/><rect x="53" width="39" height="20" fill="#007ec6"/><rect width="92" height="20" fill="url(#s)"/></g><g fill="#fff" text-anchor="middle" font-family="Verdana,Geneva,DejaVu Sans,sans-serif" text-rendering="geometricPrecision" font-size="110"><g transform="scale(.1)"><g aria-hidden="true" fill="#010101"><text x="275" y="150" fill-opacity=".8" filter="url(#blur)" textLength="430">Release</text><text x="275" y="150" fill-opacity=".3" textLength="430">Release</text></g><text x="275" y="140" textLength="430">Release</text></g><g transform="scale(.1)"><g aria-hidden="true" fill="#010101"><text x="715" y="150" fill-opacity=".8" filter="url(#blur)" textLength="290">6.1.2</text><text x="715" y="150" fill-opacity=".3" textLength="290">6.1.2</text></g><text x="715" y="140" textLength="290">6.1.2</text></g></g></svg>
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="92" height="20" role="img" aria-label="Release: 6.1.3"><title>Release: 6.1.3</title><filter id="blur"><feGaussianBlur stdDeviation="16"/></filter><linearGradient id="s" x2="0" y2="100%"><stop offset="0" stop-color="#bbb" stop-opacity=".1"/><stop offset="1" stop-opacity=".1"/></linearGradient><clipPath id="r"><rect width="92" height="20" rx="3"/></clipPath><g clip-path="url(#r)"><rect width="53" height="20" fill="#555"/><rect x="53" width="39" height="20" fill="#007ec6"/><rect width="92" height="20" fill="url(#s)"/></g><g fill="#fff" text-anchor="middle" font-family="Verdana,Geneva,DejaVu Sans,sans-serif" text-rendering="geometricPrecision" font-size="110"><g transform="scale(.1)"><g aria-hidden="true" fill="#010101"><text x="275" y="150" fill-opacity=".8" filter="url(#blur)" textLength="430">Release</text><text x="275" y="150" fill-opacity=".3" textLength="430">Release</text></g><text x="275" y="140" textLength="430">Release</text></g><g transform="scale(.1)"><g aria-hidden="true" fill="#010101"><text x="715" y="150" fill-opacity=".8" filter="url(#blur)" textLength="290">6.1.3</text><text x="715" y="150" fill-opacity=".3" textLength="290">6.1.3</text></g><text x="715" y="140" textLength="290">6.1.3</text></g></g></svg>
|
||||
|
Before Width: | Height: | Size: 1.3 KiB After Width: | Height: | Size: 1.3 KiB |
@@ -274,7 +274,7 @@ if __name__ == "__main__":
|
||||
]
|
||||
)
|
||||
|
||||
release = "6.1.2"
|
||||
release = "6.1.3"
|
||||
download_image(f"https://img.shields.io/badge/Release-{release}-blue.svg", "Badge_Release.svg")
|
||||
|
||||
java = "8+"
|
||||
|
||||
@@ -48,14 +48,12 @@ public interface LayoutManager {
|
||||
Layout getLayout(@NonNull String name);
|
||||
|
||||
/**
|
||||
* Sends layout to player. Set to {@code null} to make player not see
|
||||
* any layout, but default TabList instead.
|
||||
* Sends layout to player. Set to {@code null} to reset layout back to original one based on configuration.
|
||||
*
|
||||
* @param player
|
||||
* Player to send layout to
|
||||
* @param layout
|
||||
* Layout to send
|
||||
* @see #resetLayout(TabPlayer)
|
||||
*/
|
||||
void sendLayout(@NonNull TabPlayer player, @Nullable Layout layout);
|
||||
|
||||
@@ -65,6 +63,8 @@ public interface LayoutManager {
|
||||
* @param player
|
||||
* Player to reset layout for
|
||||
* @see #sendLayout(TabPlayer, Layout)
|
||||
* @deprecated Use {@link #sendLayout(TabPlayer, Layout)} with {@code null} instead
|
||||
*/
|
||||
@Deprecated
|
||||
void resetLayout(@NonNull TabPlayer player);
|
||||
}
|
||||
+1
-3
@@ -4,7 +4,7 @@ plugins {
|
||||
|
||||
allprojects {
|
||||
group = "me.neznamy"
|
||||
version = "6.1.3"
|
||||
version = "6.2.0"
|
||||
description = "An all-in-one solution that works"
|
||||
|
||||
ext.set("id", "tab")
|
||||
@@ -27,8 +27,6 @@ val platformPaths = setOf(
|
||||
":bukkit:v1_16_R3",
|
||||
":bukkit:v1_17_R1",
|
||||
":bukkit:v1_18_R2",
|
||||
":bukkit:v1_19_R1",
|
||||
":bukkit:v1_19_R2",
|
||||
":bukkit:v1_19_R3",
|
||||
":bukkit:v1_20_R1",
|
||||
":bukkit:v1_20_R2",
|
||||
|
||||
@@ -28,7 +28,7 @@ public class BukkitTAB extends JavaPlugin {
|
||||
Bukkit.getConsoleSender().sendMessage("§c[TAB] Use the other jar in the release instead.");
|
||||
} else {
|
||||
Bukkit.getConsoleSender().sendMessage("§c[TAB] Your server version (" + Bukkit.getBukkitVersion() + ") is not supported.");
|
||||
Bukkit.getConsoleSender().sendMessage("§c[TAB] This jar only supports 1.7.10, 1.8.8, 1.12.2, 1.16.5, 1.17.1 and 1.18.2 - 26.2");
|
||||
Bukkit.getConsoleSender().sendMessage("§c[TAB] This jar only supports 1.7.10, 1.8.8, 1.12.2, 1.16.5, 1.17.1, 1.18.2 and 1.19.4 - 26.3");
|
||||
Bukkit.getConsoleSender().sendMessage("§c[TAB] If you just updated to a new Minecraft version, check for TAB updates.");
|
||||
Bukkit.getConsoleSender().sendMessage("§c[TAB] If you are using an unsupported 1.x version, use an older version of TAB (latest TAB 5.x supports all MC 1.x versions).");
|
||||
Bukkit.getConsoleSender().sendMessage("§c[TAB] Thrown error message: " + e.getMessage());
|
||||
|
||||
@@ -96,6 +96,7 @@ public class ServerVersionInfo {
|
||||
spigotVersions.put(ProtocolVersion.V26_1_1, "v26_1");
|
||||
spigotVersions.put(ProtocolVersion.V26_1_2, "v26_1");
|
||||
spigotVersions.put(ProtocolVersion.V26_2, "v26_2");
|
||||
spigotVersions.put(ProtocolVersion.V26_3, "v26_2");
|
||||
|
||||
Map<ProtocolVersion, String> paperVersions = new LinkedHashMap<>();
|
||||
paperVersions.put(ProtocolVersion.V1_20_5, "paper_1_20_5");
|
||||
@@ -116,6 +117,7 @@ public class ServerVersionInfo {
|
||||
paperVersions.put(ProtocolVersion.V26_1_1, "paper_1_21_11"); // v26_1 works too
|
||||
paperVersions.put(ProtocolVersion.V26_1_2, "paper_1_21_11"); // v26_1 works too
|
||||
paperVersions.put(ProtocolVersion.V26_2, "paper_26_2"); // v26_2 works too
|
||||
paperVersions.put(ProtocolVersion.V26_3, "paper_26_2");
|
||||
|
||||
if (serverVersion == ProtocolVersion.UNKNOWN) {
|
||||
throw new IllegalStateException(String.format(
|
||||
|
||||
@@ -238,9 +238,9 @@ public class BukkitPlatform implements BackendPlatform {
|
||||
Metrics metrics = new Metrics(plugin, TabConstants.BSTATS_PLUGIN_ID_BUKKIT);
|
||||
metrics.addCustomChart(new SimplePie(TabConstants.MetricsChart.PERMISSION_SYSTEM,
|
||||
() -> TAB.getInstance().getGroupManager().getPermissionPlugin()));
|
||||
metrics.addCustomChart(new SimplePie("tab_6_1_0_servers",
|
||||
metrics.addCustomChart(new SimplePie("tab_6_2_x_servers",
|
||||
() -> serverVersionInfo.getServerName() + " " + serverVersionInfo.getServerVersion().getFriendlyName()));
|
||||
metrics.addCustomChart(new SimplePie("tab_6_1_0_package", serverVersionInfo::getImplementationPackage));
|
||||
metrics.addCustomChart(new SimplePie("tab_6_2_x_package", serverVersionInfo::getImplementationPackage));
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -1,10 +0,0 @@
|
||||
dependencies {
|
||||
implementation(projects.bukkit)
|
||||
compileOnly("org.spigotmc:spigot:1.19.2-R0.1-SNAPSHOT") {
|
||||
// Broken dependencies
|
||||
exclude("com.mojang", "authlib")
|
||||
exclude("com.mojang", "logging")
|
||||
exclude("com.mojang", "datafixerupper")
|
||||
}
|
||||
compileOnly("com.mojang:authlib:1.5.25")
|
||||
}
|
||||
-64
@@ -1,64 +0,0 @@
|
||||
package me.neznamy.tab.platforms.bukkit.v1_19_R1;
|
||||
|
||||
import me.neznamy.tab.shared.chat.TabStyle;
|
||||
import me.neznamy.tab.shared.chat.component.object.TabAtlasSprite;
|
||||
import me.neznamy.tab.shared.chat.component.object.TabObjectComponent;
|
||||
import me.neznamy.tab.platforms.bukkit.provider.ComponentConverter;
|
||||
import me.neznamy.tab.shared.chat.component.object.TabPlayerSprite;
|
||||
import net.minecraft.network.chat.*;
|
||||
import net.minecraft.resources.MinecraftKey;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
/**
|
||||
* Component converter using direct NMS code.
|
||||
*/
|
||||
public class NMSComponentConverter extends ComponentConverter<IChatBaseComponent> {
|
||||
|
||||
@Override
|
||||
@NotNull
|
||||
public IChatBaseComponent newTextComponent(@NotNull String text) {
|
||||
return IChatBaseComponent.b(text);
|
||||
}
|
||||
|
||||
@Override
|
||||
@NotNull
|
||||
public IChatBaseComponent newTranslatableComponent(@NotNull String key) {
|
||||
return IChatBaseComponent.c(key);
|
||||
}
|
||||
|
||||
@Override
|
||||
@NotNull
|
||||
public IChatBaseComponent newKeybindComponent(@NotNull String keybind) {
|
||||
return IChatBaseComponent.d(keybind);
|
||||
}
|
||||
|
||||
@Override
|
||||
@NotNull
|
||||
public IChatBaseComponent newObjectComponent(@NotNull TabAtlasSprite sprite) {
|
||||
return IChatBaseComponent.b(TabObjectComponent.ERROR_MESSAGE);
|
||||
}
|
||||
|
||||
@Override
|
||||
@NotNull
|
||||
public IChatBaseComponent newObjectComponent(@NotNull TabPlayerSprite sprite) {
|
||||
return IChatBaseComponent.b(TabObjectComponent.ERROR_MESSAGE);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void applyStyle(@NotNull IChatBaseComponent nmsComponent, @NotNull TabStyle modifier) {
|
||||
((IChatMutableComponent)nmsComponent).c(ChatModifier.a
|
||||
.a(modifier.getColor() == null ? null : ChatHexColor.a(modifier.getColor().getRgb()))
|
||||
.a(modifier.getBold())
|
||||
.b(modifier.getItalic())
|
||||
.c(modifier.getUnderlined())
|
||||
.d(modifier.getStrikethrough())
|
||||
.e(modifier.getObfuscated())
|
||||
.a(modifier.getFont() == null ? null : MinecraftKey.a(modifier.getFont()))
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addSibling(@NotNull IChatBaseComponent parent, @NotNull IChatBaseComponent child) {
|
||||
((IChatMutableComponent)parent).b(child);
|
||||
}
|
||||
}
|
||||
-52
@@ -1,52 +0,0 @@
|
||||
package me.neznamy.tab.platforms.bukkit.v1_19_R1;
|
||||
|
||||
import io.netty.channel.Channel;
|
||||
import lombok.Getter;
|
||||
import me.neznamy.tab.platforms.bukkit.BukkitTabPlayer;
|
||||
import me.neznamy.tab.platforms.bukkit.provider.ComponentConverter;
|
||||
import me.neznamy.tab.platforms.bukkit.provider.ImplementationProvider;
|
||||
import me.neznamy.tab.shared.platform.Scoreboard;
|
||||
import me.neznamy.tab.shared.platform.TabList;
|
||||
import me.neznamy.tab.shared.platform.TabListEntryTracker;
|
||||
import org.bukkit.craftbukkit.v1_19_R1.entity.CraftPlayer;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
/**
|
||||
* Implementation provider using direct NMS code for 1.19.1 - 1.19.2.
|
||||
*/
|
||||
@Getter
|
||||
public class NMSImplementationProvider implements ImplementationProvider {
|
||||
|
||||
@NotNull
|
||||
private final ComponentConverter<?> componentConverter = new NMSComponentConverter();
|
||||
|
||||
@Override
|
||||
@NotNull
|
||||
public Scoreboard newScoreboard(@NotNull BukkitTabPlayer player) {
|
||||
return new NMSPacketScoreboard(player);
|
||||
}
|
||||
|
||||
@Override
|
||||
@NotNull
|
||||
public TabList newTabList(@NotNull BukkitTabPlayer player) {
|
||||
return new NMSPacketTabList(player);
|
||||
}
|
||||
|
||||
@Override
|
||||
@NotNull
|
||||
public Channel getChannel(@NotNull Player player) {
|
||||
return ((CraftPlayer)player).getHandle().b.b.m;
|
||||
}
|
||||
|
||||
@Override
|
||||
@NotNull
|
||||
public TabListEntryTracker newTabListEntryTracker(@NotNull Player player) {
|
||||
return new NMSTabListEntryTracker(getChannel(player));
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getPing(@NotNull BukkitTabPlayer player) {
|
||||
return player.getPlayer().getPing();
|
||||
}
|
||||
}
|
||||
-207
@@ -1,207 +0,0 @@
|
||||
package me.neznamy.tab.platforms.bukkit.v1_19_R1;
|
||||
|
||||
import lombok.NonNull;
|
||||
import lombok.SneakyThrows;
|
||||
import me.neznamy.tab.platforms.bukkit.BukkitTabPlayer;
|
||||
import me.neznamy.tab.shared.TAB;
|
||||
import me.neznamy.tab.shared.platform.decorators.SafeScoreboard;
|
||||
import net.minecraft.EnumChatFormat;
|
||||
import net.minecraft.network.chat.IChatBaseComponent;
|
||||
import net.minecraft.network.protocol.Packet;
|
||||
import net.minecraft.network.protocol.game.PacketPlayOutScoreboardDisplayObjective;
|
||||
import net.minecraft.network.protocol.game.PacketPlayOutScoreboardObjective;
|
||||
import net.minecraft.network.protocol.game.PacketPlayOutScoreboardScore;
|
||||
import net.minecraft.network.protocol.game.PacketPlayOutScoreboardTeam;
|
||||
import net.minecraft.server.ScoreboardServer;
|
||||
import net.minecraft.world.scores.Scoreboard;
|
||||
import net.minecraft.world.scores.ScoreboardObjective;
|
||||
import net.minecraft.world.scores.ScoreboardTeam;
|
||||
import net.minecraft.world.scores.ScoreboardTeamBase;
|
||||
import net.minecraft.world.scores.criteria.IScoreboardCriteria;
|
||||
import org.bukkit.craftbukkit.v1_19_R1.entity.CraftPlayer;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.lang.reflect.Constructor;
|
||||
import java.util.Collection;
|
||||
import java.util.Optional;
|
||||
|
||||
/**
|
||||
* Scoreboard implementation using direct NMS code.
|
||||
*/
|
||||
public class NMSPacketScoreboard extends SafeScoreboard<BukkitTabPlayer> {
|
||||
|
||||
private static final ScoreboardTeamBase.EnumNameTagVisibility[] visibilities = ScoreboardTeamBase.EnumNameTagVisibility.values();
|
||||
private static final ScoreboardTeamBase.EnumTeamPush[] collisions = ScoreboardTeamBase.EnumTeamPush.values();
|
||||
private static final Scoreboard dummyScoreboard = new Scoreboard();
|
||||
|
||||
private static final Constructor<PacketPlayOutScoreboardTeam> teamConstructor;
|
||||
|
||||
static {
|
||||
try {
|
||||
teamConstructor = PacketPlayOutScoreboardTeam.class.getDeclaredConstructor(String.class, int.class, Optional.class, Collection.class);
|
||||
teamConstructor.setAccessible(true);
|
||||
} catch (NoSuchMethodException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs new instance with given player.
|
||||
*
|
||||
* @param player
|
||||
* Player this scoreboard will belong to
|
||||
*/
|
||||
public NMSPacketScoreboard(@NotNull BukkitTabPlayer player) {
|
||||
super(player);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void registerObjective(@NonNull Objective objective) {
|
||||
ScoreboardObjective obj = new ScoreboardObjective(
|
||||
dummyScoreboard,
|
||||
objective.getName(),
|
||||
IScoreboardCriteria.a,
|
||||
objective.getTitle().convert(),
|
||||
IScoreboardCriteria.EnumScoreboardHealthDisplay.values()[objective.getHealthDisplay().ordinal()]
|
||||
);
|
||||
objective.setPlatformObjective(obj);
|
||||
sendPacket(new PacketPlayOutScoreboardObjective(obj, ObjectiveAction.REGISTER));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setDisplaySlot(@NonNull Objective objective) {
|
||||
sendPacket(new PacketPlayOutScoreboardDisplayObjective(
|
||||
objective.getDisplaySlot().ordinal(),
|
||||
(ScoreboardObjective) objective.getPlatformObjective()
|
||||
));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void unregisterObjective(@NonNull Objective objective) {
|
||||
sendPacket(new PacketPlayOutScoreboardObjective((ScoreboardObjective) objective.getPlatformObjective(), ObjectiveAction.UNREGISTER));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateObjective(@NonNull Objective objective) {
|
||||
ScoreboardObjective obj = (ScoreboardObjective) objective.getPlatformObjective();
|
||||
obj.a((IChatBaseComponent) objective.getTitle().convert());
|
||||
obj.a(IScoreboardCriteria.EnumScoreboardHealthDisplay.valueOf(objective.getHealthDisplay().name()));
|
||||
sendPacket(new PacketPlayOutScoreboardObjective(obj, ObjectiveAction.UPDATE));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setScore(@NonNull Score score) {
|
||||
sendPacket(new PacketPlayOutScoreboardScore(
|
||||
ScoreboardServer.Action.a,
|
||||
score.getObjective().getName(),
|
||||
score.getHolder(),
|
||||
score.getValue()
|
||||
));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removeScore(@NonNull Score score) {
|
||||
sendPacket(new PacketPlayOutScoreboardScore(
|
||||
ScoreboardServer.Action.b,
|
||||
score.getObjective().getName(),
|
||||
score.getHolder(),
|
||||
score.getValue()
|
||||
));
|
||||
}
|
||||
|
||||
@Override
|
||||
@NotNull
|
||||
public Object createTeam(@NonNull String name) {
|
||||
return new ScoreboardTeam(dummyScoreboard, name);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void registerTeam(@NonNull Team team) {
|
||||
updateTeamProperties(team);
|
||||
ScoreboardTeam t = (ScoreboardTeam) team.getPlatformTeam();
|
||||
t.g().addAll(team.getPlayers());
|
||||
sendPacket(PacketPlayOutScoreboardTeam.a(t, true));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void unregisterTeam(@NonNull Team team) {
|
||||
sendPacket(PacketPlayOutScoreboardTeam.a((ScoreboardTeam) team.getPlatformTeam()));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateTeam(@NonNull Team team) {
|
||||
updateTeamProperties(team);
|
||||
sendPacket(PacketPlayOutScoreboardTeam.a((ScoreboardTeam) team.getPlatformTeam(), false));
|
||||
}
|
||||
|
||||
private void updateTeamProperties(@NonNull Team team) {
|
||||
ScoreboardTeam t = (ScoreboardTeam) team.getPlatformTeam();
|
||||
t.a((team.getOptions() & 0x01) != 0);
|
||||
t.b((team.getOptions() & 0x02) != 0);
|
||||
t.a(visibilities[team.getVisibility().ordinal()]);
|
||||
t.a(collisions[team.getCollision().ordinal()]);
|
||||
t.b((IChatBaseComponent) team.getPrefix().convert());
|
||||
t.c(team.getSuffix().convert());
|
||||
t.a(EnumChatFormat.valueOf(team.getColor().name()));
|
||||
}
|
||||
|
||||
@Override
|
||||
@SneakyThrows
|
||||
@NotNull
|
||||
public Object onPacketSend(@NonNull Object packet) {
|
||||
if (packet instanceof PacketPlayOutScoreboardDisplayObjective) {
|
||||
TAB.getInstance().getFeatureManager().onDisplayObjective(
|
||||
player,
|
||||
((PacketPlayOutScoreboardDisplayObjective)packet).b(),
|
||||
((PacketPlayOutScoreboardDisplayObjective)packet).c()
|
||||
);
|
||||
}
|
||||
if (packet instanceof PacketPlayOutScoreboardObjective) {
|
||||
TAB.getInstance().getFeatureManager().onObjective(
|
||||
player,
|
||||
((PacketPlayOutScoreboardObjective)packet).d(),
|
||||
((PacketPlayOutScoreboardObjective)packet).b()
|
||||
);
|
||||
}
|
||||
if (packet instanceof PacketPlayOutScoreboardTeam) {
|
||||
int action = getMethod((PacketPlayOutScoreboardTeam) packet);
|
||||
if (action != TeamAction.UPDATE) {
|
||||
Collection<String> players = ((PacketPlayOutScoreboardTeam) packet).e();
|
||||
if (players != null) {
|
||||
String name = ((PacketPlayOutScoreboardTeam) packet).d();
|
||||
return teamConstructor.newInstance(
|
||||
name,
|
||||
action,
|
||||
((PacketPlayOutScoreboardTeam) packet).f(),
|
||||
onTeamPacket(action, name, players)
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
return packet;
|
||||
}
|
||||
|
||||
private int getMethod(@NonNull PacketPlayOutScoreboardTeam team) {
|
||||
if (team.c() == PacketPlayOutScoreboardTeam.a.a) {
|
||||
return 0;
|
||||
} else if (team.c() == PacketPlayOutScoreboardTeam.a.b) {
|
||||
return 1;
|
||||
} else if (team.b() == PacketPlayOutScoreboardTeam.a.a) {
|
||||
return 3;
|
||||
} else if (team.b() == PacketPlayOutScoreboardTeam.a.b) {
|
||||
return 4;
|
||||
} else {
|
||||
return 2;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Sends the packet to the player.
|
||||
*
|
||||
* @param packet
|
||||
* Packet to send
|
||||
*/
|
||||
private void sendPacket(@NotNull Packet<?> packet) {
|
||||
((CraftPlayer)player.getPlayer()).getHandle().b.a(packet);
|
||||
}
|
||||
}
|
||||
-210
@@ -1,210 +0,0 @@
|
||||
package me.neznamy.tab.platforms.bukkit.v1_19_R1;
|
||||
|
||||
import com.mojang.authlib.GameProfile;
|
||||
import com.mojang.authlib.properties.Property;
|
||||
import lombok.NonNull;
|
||||
import lombok.SneakyThrows;
|
||||
import me.neznamy.tab.platforms.bukkit.BukkitTabPlayer;
|
||||
import me.neznamy.tab.shared.TAB;
|
||||
import me.neznamy.tab.shared.chat.component.TabComponent;
|
||||
import me.neznamy.tab.shared.platform.TabList;
|
||||
import me.neznamy.tab.shared.platform.decorators.TrackedTabList;
|
||||
import net.minecraft.network.chat.IChatBaseComponent;
|
||||
import net.minecraft.network.protocol.Packet;
|
||||
import net.minecraft.network.protocol.game.PacketPlayOutPlayerInfo;
|
||||
import net.minecraft.network.protocol.game.PacketPlayOutPlayerInfo.EnumPlayerInfoAction;
|
||||
import net.minecraft.network.protocol.game.PacketPlayOutPlayerInfo.PlayerInfoData;
|
||||
import net.minecraft.network.protocol.game.PacketPlayOutPlayerListHeaderFooter;
|
||||
import net.minecraft.world.entity.player.ProfilePublicKey;
|
||||
import net.minecraft.world.level.EnumGamemode;
|
||||
import org.bukkit.craftbukkit.v1_19_R1.entity.CraftPlayer;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
* TabList implementation using direct NMS code.
|
||||
*/
|
||||
public class NMSPacketTabList extends TrackedTabList<BukkitTabPlayer> {
|
||||
|
||||
private static final EnumPlayerInfoAction ADD_PLAYER = EnumPlayerInfoAction.a;
|
||||
private static final EnumPlayerInfoAction UPDATE_GAME_MODE = EnumPlayerInfoAction.b;
|
||||
private static final EnumPlayerInfoAction UPDATE_LATENCY = EnumPlayerInfoAction.c;
|
||||
private static final EnumPlayerInfoAction UPDATE_DISPLAY_NAME = EnumPlayerInfoAction.d;
|
||||
private static final EnumPlayerInfoAction REMOVE_PLAYER = EnumPlayerInfoAction.e;
|
||||
|
||||
/**
|
||||
* Constructs new instance.
|
||||
*
|
||||
* @param player
|
||||
* Player this tablist will belong to
|
||||
*/
|
||||
public NMSPacketTabList(@NotNull BukkitTabPlayer player) {
|
||||
super(player);
|
||||
}
|
||||
|
||||
@Override
|
||||
@SneakyThrows
|
||||
public void removeEntry(@NonNull UUID entry) {
|
||||
sendPacket(EnumPlayerInfoAction.e, entry, "", null, 0, 0, null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateDisplayName0(@NonNull UUID entry, @Nullable TabComponent displayName) {
|
||||
sendPacket(EnumPlayerInfoAction.d, entry, "", null, 0, 0, displayName);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateLatency(@NonNull UUID entry, int latency) {
|
||||
sendPacket(EnumPlayerInfoAction.c, entry, "", null, latency, 0, null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateGameMode(@NonNull UUID entry, int gameMode) {
|
||||
sendPacket(EnumPlayerInfoAction.b, entry, "", null, 0, gameMode, null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateListed(@NonNull UUID entry, boolean listed) {
|
||||
// Added in 1.19.3
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateListOrder(@NonNull UUID entry, int listOrder) {
|
||||
// Added in 1.21.2
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateHat(@NonNull UUID entry, boolean showHat) {
|
||||
// Added in 1.21.4
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addEntry0(@NonNull Entry entry) {
|
||||
sendPacket(EnumPlayerInfoAction.a, entry.getUniqueId(), entry.getName(), entry.getSkin(), entry.getLatency(),
|
||||
entry.getGameMode(), entry.getDisplayName());
|
||||
}
|
||||
|
||||
@Override
|
||||
@SneakyThrows
|
||||
public void setPlayerListHeaderFooter0(@NonNull TabComponent header, @NonNull TabComponent footer) {
|
||||
sendPacket(new PacketPlayOutPlayerListHeaderFooter(header.convert(), footer.convert()));
|
||||
}
|
||||
|
||||
@Override
|
||||
@Nullable
|
||||
public Skin getSkin() {
|
||||
Collection<Property> properties = ((CraftPlayer)player.getPlayer()).getProfile().getProperties().get(TEXTURES_PROPERTY);
|
||||
if (properties.isEmpty()) return null; // Offline mode
|
||||
Property property = properties.iterator().next();
|
||||
return new Skin(property.getValue(), property.getSignature());
|
||||
}
|
||||
|
||||
@Override
|
||||
@SneakyThrows
|
||||
@NotNull
|
||||
public Object onPacketSend(@NonNull Object packet) {
|
||||
if (packet instanceof PacketPlayOutPlayerListHeaderFooter) {
|
||||
PacketPlayOutPlayerListHeaderFooter tablist = (PacketPlayOutPlayerListHeaderFooter) packet;
|
||||
if (header == null || footer == null) return packet;
|
||||
if (tablist.a != header.convert() || tablist.b != footer.convert()) {
|
||||
return new PacketPlayOutPlayerListHeaderFooter(header.convert(), footer.convert());
|
||||
}
|
||||
}
|
||||
if (!(packet instanceof PacketPlayOutPlayerInfo)) return packet;
|
||||
PacketPlayOutPlayerInfo info = (PacketPlayOutPlayerInfo) packet;
|
||||
EnumPlayerInfoAction action = info.c();
|
||||
List<PlayerInfoData> updatedList = new ArrayList<>();
|
||||
boolean rewritePacket = false;
|
||||
for (PlayerInfoData nmsData : info.b()) {
|
||||
boolean rewriteEntry = false;
|
||||
GameProfile profile = nmsData.a();
|
||||
UUID id = profile.getId();
|
||||
IChatBaseComponent displayName = nmsData.d();
|
||||
int latency = nmsData.b();
|
||||
int gameMode = nmsData.c().a();
|
||||
ProfilePublicKey.a publicKey = nmsData.e();
|
||||
if (action == UPDATE_DISPLAY_NAME || action == ADD_PLAYER) {
|
||||
TabComponent forcedDisplayName = getForcedDisplayNames().get(id);
|
||||
if (forcedDisplayName != null && forcedDisplayName.convert() != displayName) {
|
||||
displayName = forcedDisplayName.convert();
|
||||
rewriteEntry = rewritePacket = true;
|
||||
}
|
||||
}
|
||||
if (action == UPDATE_GAME_MODE || action == ADD_PLAYER) {
|
||||
if (getBlockedSpectators().contains(id) && gameMode == 3) {
|
||||
gameMode = 0;
|
||||
rewriteEntry = rewritePacket = true;
|
||||
}
|
||||
}
|
||||
if (action == UPDATE_LATENCY || action == ADD_PLAYER) {
|
||||
if (getForcedLatency() != null) {
|
||||
latency = getForcedLatency();
|
||||
rewriteEntry = rewritePacket = true;
|
||||
}
|
||||
}
|
||||
if (action == ADD_PLAYER) {
|
||||
TAB.getInstance().getFeatureManager().onEntryAdd(player, id, profile.getName());
|
||||
}
|
||||
updatedList.add(rewriteEntry ? new PlayerInfoData(
|
||||
profile,
|
||||
latency,
|
||||
EnumGamemode.a(gameMode),
|
||||
displayName,
|
||||
publicKey
|
||||
) : nmsData);
|
||||
}
|
||||
if (rewritePacket) {
|
||||
PacketPlayOutPlayerInfo newPacket = new PacketPlayOutPlayerInfo(action, Collections.emptyList());
|
||||
newPacket.b().clear();
|
||||
newPacket.b().addAll(updatedList);
|
||||
return newPacket;
|
||||
}
|
||||
return packet;
|
||||
}
|
||||
|
||||
private void sendPacket(@NonNull EnumPlayerInfoAction action, @NonNull UUID id, @NonNull String name,
|
||||
@Nullable Skin skin, int latency, int gameMode, @Nullable TabComponent displayName) {
|
||||
PacketPlayOutPlayerInfo packet = new PacketPlayOutPlayerInfo(action);
|
||||
packet.b().add(new PlayerInfoData(
|
||||
createProfile(id, name, skin),
|
||||
latency,
|
||||
EnumGamemode.a(gameMode),
|
||||
displayName == null ? null : displayName.convert(),
|
||||
null
|
||||
));
|
||||
sendPacket(packet);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates GameProfile from given parameters.
|
||||
*
|
||||
* @param id
|
||||
* Profile ID
|
||||
* @param name
|
||||
* Profile name
|
||||
* @param skin
|
||||
* Player skin
|
||||
* @return GameProfile from given parameters
|
||||
*/
|
||||
@NotNull
|
||||
private GameProfile createProfile(@NonNull UUID id, @NonNull String name, @Nullable Skin skin) {
|
||||
GameProfile profile = new GameProfile(id, name);
|
||||
if (skin != null) {
|
||||
profile.getProperties().put(TabList.TEXTURES_PROPERTY,
|
||||
new Property(TabList.TEXTURES_PROPERTY, skin.getValue(), skin.getSignature()));
|
||||
}
|
||||
return profile;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sends the packet to the player.
|
||||
*
|
||||
* @param packet
|
||||
* Packet to send
|
||||
*/
|
||||
private void sendPacket(@NotNull Packet<?> packet) {
|
||||
((CraftPlayer)player.getPlayer()).getHandle().b.a(packet);
|
||||
}
|
||||
}
|
||||
-35
@@ -1,35 +0,0 @@
|
||||
package me.neznamy.tab.platforms.bukkit.v1_19_R1;
|
||||
|
||||
import io.netty.channel.Channel;
|
||||
import me.neznamy.tab.shared.platform.NettyTabListEntryTracker;
|
||||
import net.minecraft.network.protocol.game.PacketPlayOutPlayerInfo;
|
||||
import net.minecraft.network.protocol.game.PacketPlayOutPlayerInfo.EnumPlayerInfoAction;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
/**
|
||||
* Implementation of TabListEntryTracker.
|
||||
*/
|
||||
public class NMSTabListEntryTracker extends NettyTabListEntryTracker {
|
||||
|
||||
private static final EnumPlayerInfoAction ADD_PLAYER = EnumPlayerInfoAction.valueOf("ADD_PLAYER");
|
||||
private static final EnumPlayerInfoAction REMOVE_PLAYER = EnumPlayerInfoAction.valueOf("REMOVE_PLAYER");
|
||||
|
||||
public NMSTabListEntryTracker(@NotNull Channel channel) {
|
||||
super(channel);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPacketSend(@NotNull Object packet) {
|
||||
if (packet instanceof PacketPlayOutPlayerInfo) {
|
||||
PacketPlayOutPlayerInfo info = (PacketPlayOutPlayerInfo) packet;
|
||||
for (PacketPlayOutPlayerInfo.PlayerInfoData nmsData : info.b()) {
|
||||
if (info.c() == ADD_PLAYER) {
|
||||
tablistEntries.add(nmsData.a().getId());
|
||||
}
|
||||
if (info.c() == REMOVE_PLAYER) {
|
||||
tablistEntries.remove(nmsData.a().getId());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,14 +0,0 @@
|
||||
dependencies {
|
||||
implementation(projects.bukkit)
|
||||
compileOnly("org.spigotmc:spigot:1.19.3-R0.1-SNAPSHOT") {
|
||||
// Broken dependencies
|
||||
exclude("com.mojang", "authlib")
|
||||
exclude("com.mojang", "logging")
|
||||
exclude("com.mojang", "datafixerupper")
|
||||
}
|
||||
compileOnly("com.mojang:authlib:1.5.25")
|
||||
}
|
||||
|
||||
tasks.compileJava {
|
||||
options.release.set(14) // Records
|
||||
}
|
||||
-64
@@ -1,64 +0,0 @@
|
||||
package me.neznamy.tab.platforms.bukkit.v1_19_R2;
|
||||
|
||||
import me.neznamy.tab.shared.chat.TabStyle;
|
||||
import me.neznamy.tab.shared.chat.component.object.TabAtlasSprite;
|
||||
import me.neznamy.tab.shared.chat.component.object.TabObjectComponent;
|
||||
import me.neznamy.tab.platforms.bukkit.provider.ComponentConverter;
|
||||
import me.neznamy.tab.shared.chat.component.object.TabPlayerSprite;
|
||||
import net.minecraft.network.chat.*;
|
||||
import net.minecraft.resources.MinecraftKey;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
/**
|
||||
* Component converter using direct NMS code.
|
||||
*/
|
||||
public class NMSComponentConverter extends ComponentConverter<IChatBaseComponent> {
|
||||
|
||||
@Override
|
||||
@NotNull
|
||||
public IChatBaseComponent newTextComponent(@NotNull String text) {
|
||||
return IChatBaseComponent.b(text);
|
||||
}
|
||||
|
||||
@Override
|
||||
@NotNull
|
||||
public IChatBaseComponent newTranslatableComponent(@NotNull String key) {
|
||||
return IChatBaseComponent.c(key);
|
||||
}
|
||||
|
||||
@Override
|
||||
@NotNull
|
||||
public IChatBaseComponent newKeybindComponent(@NotNull String keybind) {
|
||||
return IChatBaseComponent.d(keybind);
|
||||
}
|
||||
|
||||
@Override
|
||||
@NotNull
|
||||
public IChatBaseComponent newObjectComponent(@NotNull TabAtlasSprite sprite) {
|
||||
return IChatBaseComponent.b(TabObjectComponent.ERROR_MESSAGE);
|
||||
}
|
||||
|
||||
@Override
|
||||
@NotNull
|
||||
public IChatBaseComponent newObjectComponent(@NotNull TabPlayerSprite sprite) {
|
||||
return IChatBaseComponent.b(TabObjectComponent.ERROR_MESSAGE);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void applyStyle(@NotNull IChatBaseComponent nmsComponent, @NotNull TabStyle modifier) {
|
||||
((IChatMutableComponent)nmsComponent).c(ChatModifier.a
|
||||
.a(modifier.getColor() == null ? null : ChatHexColor.a(modifier.getColor().getRgb()))
|
||||
.a(modifier.getBold())
|
||||
.b(modifier.getItalic())
|
||||
.c(modifier.getUnderlined())
|
||||
.d(modifier.getStrikethrough())
|
||||
.e(modifier.getObfuscated())
|
||||
.a(modifier.getFont() == null ? null : MinecraftKey.a(modifier.getFont()))
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addSibling(@NotNull IChatBaseComponent parent, @NotNull IChatBaseComponent child) {
|
||||
((IChatMutableComponent)parent).b(child);
|
||||
}
|
||||
}
|
||||
-52
@@ -1,52 +0,0 @@
|
||||
package me.neznamy.tab.platforms.bukkit.v1_19_R2;
|
||||
|
||||
import io.netty.channel.Channel;
|
||||
import lombok.Getter;
|
||||
import me.neznamy.tab.platforms.bukkit.BukkitTabPlayer;
|
||||
import me.neznamy.tab.platforms.bukkit.provider.ComponentConverter;
|
||||
import me.neznamy.tab.platforms.bukkit.provider.ImplementationProvider;
|
||||
import me.neznamy.tab.shared.platform.Scoreboard;
|
||||
import me.neznamy.tab.shared.platform.TabList;
|
||||
import me.neznamy.tab.shared.platform.TabListEntryTracker;
|
||||
import org.bukkit.craftbukkit.v1_19_R2.entity.CraftPlayer;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
/**
|
||||
* Implementation provider using direct NMS code for 1.19.3.
|
||||
*/
|
||||
@Getter
|
||||
public class NMSImplementationProvider implements ImplementationProvider {
|
||||
|
||||
@NotNull
|
||||
private final ComponentConverter<?> componentConverter = new NMSComponentConverter();
|
||||
|
||||
@Override
|
||||
@NotNull
|
||||
public Scoreboard newScoreboard(@NotNull BukkitTabPlayer player) {
|
||||
return new NMSPacketScoreboard(player);
|
||||
}
|
||||
|
||||
@Override
|
||||
@NotNull
|
||||
public TabList newTabList(@NotNull BukkitTabPlayer player) {
|
||||
return new NMSPacketTabList(player);
|
||||
}
|
||||
|
||||
@Override
|
||||
@NotNull
|
||||
public Channel getChannel(@NotNull Player player) {
|
||||
return ((CraftPlayer)player).getHandle().b.b.m;
|
||||
}
|
||||
|
||||
@Override
|
||||
@NotNull
|
||||
public TabListEntryTracker newTabListEntryTracker(@NotNull Player player) {
|
||||
return new NMSTabListEntryTracker(getChannel(player));
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getPing(@NotNull BukkitTabPlayer player) {
|
||||
return player.getPlayer().getPing();
|
||||
}
|
||||
}
|
||||
-206
@@ -1,206 +0,0 @@
|
||||
package me.neznamy.tab.platforms.bukkit.v1_19_R2;
|
||||
|
||||
import lombok.NonNull;
|
||||
import lombok.SneakyThrows;
|
||||
import me.neznamy.tab.platforms.bukkit.BukkitTabPlayer;
|
||||
import me.neznamy.tab.shared.TAB;
|
||||
import me.neznamy.tab.shared.platform.decorators.SafeScoreboard;
|
||||
import net.minecraft.EnumChatFormat;
|
||||
import net.minecraft.network.chat.IChatBaseComponent;
|
||||
import net.minecraft.network.protocol.Packet;
|
||||
import net.minecraft.network.protocol.game.PacketPlayOutScoreboardDisplayObjective;
|
||||
import net.minecraft.network.protocol.game.PacketPlayOutScoreboardObjective;
|
||||
import net.minecraft.network.protocol.game.PacketPlayOutScoreboardScore;
|
||||
import net.minecraft.network.protocol.game.PacketPlayOutScoreboardTeam;
|
||||
import net.minecraft.server.ScoreboardServer;
|
||||
import net.minecraft.world.scores.Scoreboard;
|
||||
import net.minecraft.world.scores.ScoreboardObjective;
|
||||
import net.minecraft.world.scores.ScoreboardTeam;
|
||||
import net.minecraft.world.scores.ScoreboardTeamBase;
|
||||
import net.minecraft.world.scores.criteria.IScoreboardCriteria;
|
||||
import org.bukkit.craftbukkit.v1_19_R2.entity.CraftPlayer;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.lang.reflect.Constructor;
|
||||
import java.util.Collection;
|
||||
import java.util.Optional;
|
||||
|
||||
/**
|
||||
* Scoreboard implementation using direct NMS code.
|
||||
*/
|
||||
public class NMSPacketScoreboard extends SafeScoreboard<BukkitTabPlayer> {
|
||||
|
||||
private static final ScoreboardTeamBase.EnumNameTagVisibility[] visibilities = ScoreboardTeamBase.EnumNameTagVisibility.values();
|
||||
private static final ScoreboardTeamBase.EnumTeamPush[] collisions = ScoreboardTeamBase.EnumTeamPush.values();
|
||||
private static final Scoreboard dummyScoreboard = new Scoreboard();
|
||||
|
||||
private static final Constructor<PacketPlayOutScoreboardTeam> teamConstructor;
|
||||
|
||||
static {
|
||||
try {
|
||||
teamConstructor = PacketPlayOutScoreboardTeam.class.getDeclaredConstructor(String.class, int.class, Optional.class, Collection.class);
|
||||
teamConstructor.setAccessible(true);
|
||||
} catch (NoSuchMethodException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Constructs new instance with given player.
|
||||
*
|
||||
* @param player
|
||||
* Player this scoreboard will belong to
|
||||
*/
|
||||
public NMSPacketScoreboard(@NotNull BukkitTabPlayer player) {
|
||||
super(player);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void registerObjective(@NonNull Objective objective) {
|
||||
ScoreboardObjective obj = new ScoreboardObjective(
|
||||
dummyScoreboard,
|
||||
objective.getName(),
|
||||
IScoreboardCriteria.a,
|
||||
objective.getTitle().convert(),
|
||||
IScoreboardCriteria.EnumScoreboardHealthDisplay.values()[objective.getHealthDisplay().ordinal()]
|
||||
);
|
||||
objective.setPlatformObjective(obj);
|
||||
sendPacket(new PacketPlayOutScoreboardObjective(obj, ObjectiveAction.REGISTER));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setDisplaySlot(@NonNull Objective objective) {
|
||||
sendPacket(new PacketPlayOutScoreboardDisplayObjective(
|
||||
objective.getDisplaySlot().ordinal(),
|
||||
(ScoreboardObjective) objective.getPlatformObjective()
|
||||
));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void unregisterObjective(@NonNull Objective objective) {
|
||||
sendPacket(new PacketPlayOutScoreboardObjective((ScoreboardObjective) objective.getPlatformObjective(), ObjectiveAction.UNREGISTER));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateObjective(@NonNull Objective objective) {
|
||||
ScoreboardObjective obj = (ScoreboardObjective) objective.getPlatformObjective();
|
||||
obj.a((IChatBaseComponent) objective.getTitle().convert());
|
||||
obj.a(IScoreboardCriteria.EnumScoreboardHealthDisplay.valueOf(objective.getHealthDisplay().name()));
|
||||
sendPacket(new PacketPlayOutScoreboardObjective(obj, ObjectiveAction.UPDATE));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setScore(@NonNull Score score) {
|
||||
sendPacket(new PacketPlayOutScoreboardScore(
|
||||
ScoreboardServer.Action.a,
|
||||
score.getObjective().getName(),
|
||||
score.getHolder(),
|
||||
score.getValue()
|
||||
));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removeScore(@NonNull Score score) {
|
||||
sendPacket(new PacketPlayOutScoreboardScore(
|
||||
ScoreboardServer.Action.b,
|
||||
score.getObjective().getName(),
|
||||
score.getHolder(),
|
||||
score.getValue()
|
||||
));
|
||||
}
|
||||
|
||||
@Override
|
||||
@NotNull
|
||||
public Object createTeam(@NonNull String name) {
|
||||
return new ScoreboardTeam(dummyScoreboard, name);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void registerTeam(@NonNull Team team) {
|
||||
updateTeamProperties(team);
|
||||
ScoreboardTeam t = (ScoreboardTeam) team.getPlatformTeam();
|
||||
t.g().addAll(team.getPlayers());
|
||||
sendPacket(PacketPlayOutScoreboardTeam.a(t, true));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void unregisterTeam(@NonNull Team team) {
|
||||
sendPacket(PacketPlayOutScoreboardTeam.a((ScoreboardTeam) team.getPlatformTeam()));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateTeam(@NonNull Team team) {
|
||||
updateTeamProperties(team);
|
||||
sendPacket(PacketPlayOutScoreboardTeam.a((ScoreboardTeam) team.getPlatformTeam(), false));
|
||||
}
|
||||
|
||||
private void updateTeamProperties(@NonNull Team team) {
|
||||
ScoreboardTeam t = (ScoreboardTeam) team.getPlatformTeam();
|
||||
t.a((team.getOptions() & 0x01) != 0);
|
||||
t.b((team.getOptions() & 0x02) != 0);
|
||||
t.a(visibilities[team.getVisibility().ordinal()]);
|
||||
t.a(collisions[team.getCollision().ordinal()]);
|
||||
t.b((IChatBaseComponent) team.getPrefix().convert());
|
||||
t.c(team.getSuffix().convert());
|
||||
t.a(EnumChatFormat.valueOf(team.getColor().name()));
|
||||
}
|
||||
|
||||
@Override
|
||||
@SneakyThrows
|
||||
@NotNull
|
||||
public Object onPacketSend(@NonNull Object packet) {
|
||||
if (packet instanceof PacketPlayOutScoreboardDisplayObjective) {
|
||||
TAB.getInstance().getFeatureManager().onDisplayObjective(
|
||||
player,
|
||||
((PacketPlayOutScoreboardDisplayObjective)packet).b(),
|
||||
((PacketPlayOutScoreboardDisplayObjective)packet).c()
|
||||
);
|
||||
}
|
||||
if (packet instanceof PacketPlayOutScoreboardObjective) {
|
||||
TAB.getInstance().getFeatureManager().onObjective(
|
||||
player,
|
||||
((PacketPlayOutScoreboardObjective)packet).d(),
|
||||
((PacketPlayOutScoreboardObjective)packet).b()
|
||||
);
|
||||
}
|
||||
if (packet instanceof PacketPlayOutScoreboardTeam) {
|
||||
int action = getMethod((PacketPlayOutScoreboardTeam) packet);
|
||||
if (action != TeamAction.UPDATE) {
|
||||
Collection<String> players = ((PacketPlayOutScoreboardTeam) packet).e();
|
||||
if (players != null) {
|
||||
String name = ((PacketPlayOutScoreboardTeam) packet).d();
|
||||
return teamConstructor.newInstance(
|
||||
name,
|
||||
action,
|
||||
((PacketPlayOutScoreboardTeam) packet).f(),
|
||||
onTeamPacket(action, name, players)
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
return packet;
|
||||
}
|
||||
|
||||
private int getMethod(@NonNull PacketPlayOutScoreboardTeam team) {
|
||||
if (team.c() == PacketPlayOutScoreboardTeam.a.a) {
|
||||
return 0;
|
||||
} else if (team.c() == PacketPlayOutScoreboardTeam.a.b) {
|
||||
return 1;
|
||||
} else if (team.b() == PacketPlayOutScoreboardTeam.a.a) {
|
||||
return 3;
|
||||
} else if (team.b() == PacketPlayOutScoreboardTeam.a.b) {
|
||||
return 4;
|
||||
} else {
|
||||
return 2;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Sends the packet to the player.
|
||||
*
|
||||
* @param packet
|
||||
* Packet to send
|
||||
*/
|
||||
private void sendPacket(@NotNull Packet<?> packet) {
|
||||
((CraftPlayer)player.getPlayer()).getHandle().b.a(packet);
|
||||
}
|
||||
}
|
||||
-223
@@ -1,223 +0,0 @@
|
||||
package me.neznamy.tab.platforms.bukkit.v1_19_R2;
|
||||
|
||||
import com.mojang.authlib.GameProfile;
|
||||
import com.mojang.authlib.properties.Property;
|
||||
import lombok.NonNull;
|
||||
import lombok.SneakyThrows;
|
||||
import me.neznamy.tab.platforms.bukkit.BukkitTabPlayer;
|
||||
import me.neznamy.tab.shared.TAB;
|
||||
import me.neznamy.tab.shared.chat.component.TabComponent;
|
||||
import me.neznamy.tab.shared.features.layout.LayoutManagerImpl;
|
||||
import me.neznamy.tab.shared.platform.TabList;
|
||||
import me.neznamy.tab.shared.platform.decorators.TrackedTabList;
|
||||
import me.neznamy.tab.shared.util.ReflectionUtils;
|
||||
import net.minecraft.network.chat.IChatBaseComponent;
|
||||
import net.minecraft.network.protocol.Packet;
|
||||
import net.minecraft.network.protocol.game.ClientboundPlayerInfoRemovePacket;
|
||||
import net.minecraft.network.protocol.game.ClientboundPlayerInfoUpdatePacket;
|
||||
import net.minecraft.network.protocol.game.PacketPlayOutPlayerListHeaderFooter;
|
||||
import net.minecraft.world.level.EnumGamemode;
|
||||
import org.bukkit.craftbukkit.v1_19_R2.entity.CraftPlayer;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
* TabList implementation using direct NMS code.
|
||||
*/
|
||||
public class NMSPacketTabList extends TrackedTabList<BukkitTabPlayer> {
|
||||
|
||||
private static final Field PLAYERS = ReflectionUtils.getOnlyField(ClientboundPlayerInfoUpdatePacket.class, List.class);
|
||||
|
||||
private static final ClientboundPlayerInfoUpdatePacket.a ADD_PLAYER = ClientboundPlayerInfoUpdatePacket.a.valueOf("ADD_PLAYER");
|
||||
private static final ClientboundPlayerInfoUpdatePacket.a UPDATE_GAME_MODE = ClientboundPlayerInfoUpdatePacket.a.valueOf("UPDATE_GAME_MODE");
|
||||
private static final ClientboundPlayerInfoUpdatePacket.a UPDATE_LATENCY = ClientboundPlayerInfoUpdatePacket.a.valueOf("UPDATE_LATENCY");
|
||||
private static final ClientboundPlayerInfoUpdatePacket.a UPDATE_DISPLAY_NAME = ClientboundPlayerInfoUpdatePacket.a.valueOf("UPDATE_DISPLAY_NAME");
|
||||
private static final ClientboundPlayerInfoUpdatePacket.a UPDATE_LISTED = ClientboundPlayerInfoUpdatePacket.a.valueOf("UPDATE_LISTED");
|
||||
|
||||
private static final EnumSet<ClientboundPlayerInfoUpdatePacket.a> ADD_PLAYER_SET = EnumSet.allOf(ClientboundPlayerInfoUpdatePacket.a.class);
|
||||
private static final EnumSet<ClientboundPlayerInfoUpdatePacket.a> UPDATE_GAME_MODE_SET = EnumSet.of(UPDATE_GAME_MODE);
|
||||
private static final EnumSet<ClientboundPlayerInfoUpdatePacket.a> UPDATE_DISPLAY_NAME_SET = EnumSet.of(UPDATE_DISPLAY_NAME);
|
||||
private static final EnumSet<ClientboundPlayerInfoUpdatePacket.a> UPDATE_LATENCY_SET = EnumSet.of(UPDATE_LATENCY);
|
||||
private static final EnumSet<ClientboundPlayerInfoUpdatePacket.a> UPDATE_LISTED_SET = EnumSet.of(UPDATE_LISTED);
|
||||
|
||||
/**
|
||||
* Constructs new instance.
|
||||
*
|
||||
* @param player
|
||||
* Player this tablist will belong to
|
||||
*/
|
||||
public NMSPacketTabList(@NotNull BukkitTabPlayer player) {
|
||||
super(player);
|
||||
}
|
||||
|
||||
@Override
|
||||
@SneakyThrows
|
||||
public void removeEntry(@NonNull UUID entry) {
|
||||
sendPacket(new ClientboundPlayerInfoRemovePacket(Collections.singletonList(entry)));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateDisplayName0(@NonNull UUID entry, @Nullable TabComponent displayName) {
|
||||
sendPacket(UPDATE_DISPLAY_NAME_SET, entry, "", null, false, 0, 0, displayName);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateLatency(@NonNull UUID entry, int latency) {
|
||||
sendPacket(UPDATE_LATENCY_SET, entry, "", null, false, latency, 0, null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateGameMode(@NonNull UUID entry, int gameMode) {
|
||||
sendPacket(UPDATE_GAME_MODE_SET, entry, "", null, false, 0, gameMode, null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateListed(@NonNull UUID entry, boolean listed) {
|
||||
sendPacket(UPDATE_LISTED_SET, entry, "", null, listed, 0, 0, null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateListOrder(@NonNull UUID entry, int listOrder) {
|
||||
// Added in 1.21.2
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateHat(@NonNull UUID entry, boolean showHat) {
|
||||
// Added in 1.21.4
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addEntry0(@NonNull Entry entry) {
|
||||
sendPacket(ADD_PLAYER_SET, entry.getUniqueId(), entry.getName(), entry.getSkin(), entry.isListed(), entry.getLatency(),
|
||||
entry.getGameMode(), entry.getDisplayName());
|
||||
}
|
||||
|
||||
@Override
|
||||
@SneakyThrows
|
||||
public void setPlayerListHeaderFooter0(@NonNull TabComponent header, @NonNull TabComponent footer) {
|
||||
sendPacket(new PacketPlayOutPlayerListHeaderFooter(header.convert(), footer.convert()));
|
||||
}
|
||||
|
||||
@Override
|
||||
@Nullable
|
||||
public Skin getSkin() {
|
||||
Collection<Property> properties = ((CraftPlayer)player.getPlayer()).getProfile().getProperties().get(TEXTURES_PROPERTY);
|
||||
if (properties.isEmpty()) return null; // Offline mode
|
||||
Property property = properties.iterator().next();
|
||||
return new Skin(property.getValue(), property.getSignature());
|
||||
}
|
||||
|
||||
@SneakyThrows
|
||||
@Override
|
||||
@NotNull
|
||||
public Object onPacketSend(@NonNull Object packet) {
|
||||
if (packet instanceof PacketPlayOutPlayerListHeaderFooter) {
|
||||
PacketPlayOutPlayerListHeaderFooter tablist = (PacketPlayOutPlayerListHeaderFooter) packet;
|
||||
if (header == null || footer == null) return packet;
|
||||
if (tablist.a != header.convert() || tablist.b != footer.convert()) {
|
||||
return new PacketPlayOutPlayerListHeaderFooter(header.convert(), footer.convert());
|
||||
}
|
||||
}
|
||||
if (!(packet instanceof ClientboundPlayerInfoUpdatePacket)) return packet;
|
||||
ClientboundPlayerInfoUpdatePacket info = (ClientboundPlayerInfoUpdatePacket) packet;
|
||||
EnumSet<ClientboundPlayerInfoUpdatePacket.a> actions = info.b();
|
||||
List<ClientboundPlayerInfoUpdatePacket.b> updatedList = new ArrayList<>();
|
||||
boolean rewritePacket = false;
|
||||
for (ClientboundPlayerInfoUpdatePacket.b nmsData : info.c()) {
|
||||
UUID profileId = nmsData.a();
|
||||
boolean rewriteEntry = false;
|
||||
IChatBaseComponent displayName = nmsData.f();
|
||||
int latency = nmsData.d();
|
||||
int gameMode = nmsData.e().a();
|
||||
boolean listed = nmsData.c();
|
||||
if (actions.contains(UPDATE_DISPLAY_NAME)) {
|
||||
TabComponent forcedDisplayName = getForcedDisplayNames().get(profileId);
|
||||
if (forcedDisplayName != null && forcedDisplayName.convert() != displayName) {
|
||||
displayName = forcedDisplayName.convert();
|
||||
rewriteEntry = rewritePacket = true;
|
||||
}
|
||||
}
|
||||
if (actions.contains(UPDATE_GAME_MODE)) {
|
||||
if (getBlockedSpectators().contains(profileId) && gameMode == 3) {
|
||||
gameMode = 0;
|
||||
rewriteEntry = rewritePacket = true;
|
||||
}
|
||||
}
|
||||
if (actions.contains(UPDATE_LATENCY)) {
|
||||
if (getForcedLatency() != null) {
|
||||
latency = getForcedLatency();
|
||||
rewriteEntry = rewritePacket = true;
|
||||
}
|
||||
}
|
||||
if (actions.contains(UPDATE_LISTED)) {
|
||||
if (allPlayersHidden && !LayoutManagerImpl.UUIDS_SET.contains(nmsData.a())) { // Filter out layout entries
|
||||
listed = false;
|
||||
rewriteEntry = rewritePacket = true;
|
||||
}
|
||||
}
|
||||
if (actions.contains(ADD_PLAYER)) {
|
||||
TAB.getInstance().getFeatureManager().onEntryAdd(player, profileId, nmsData.b().getName());
|
||||
}
|
||||
updatedList.add(rewriteEntry ? new ClientboundPlayerInfoUpdatePacket.b(
|
||||
profileId, nmsData.b(), listed, latency, EnumGamemode.a(gameMode), displayName,
|
||||
nmsData.g()
|
||||
) : nmsData);
|
||||
}
|
||||
if (rewritePacket) {
|
||||
ClientboundPlayerInfoUpdatePacket newPacket = new ClientboundPlayerInfoUpdatePacket(actions, Collections.emptyList());
|
||||
PLAYERS.set(newPacket, updatedList);
|
||||
return newPacket;
|
||||
}
|
||||
return packet;
|
||||
}
|
||||
|
||||
@SneakyThrows
|
||||
private void sendPacket(@NonNull EnumSet<ClientboundPlayerInfoUpdatePacket.a> action, @NonNull UUID id, @NonNull String name,
|
||||
@Nullable Skin skin, boolean listed, int latency, int gameMode, @Nullable TabComponent displayName) {
|
||||
ClientboundPlayerInfoUpdatePacket packet = new ClientboundPlayerInfoUpdatePacket(action, Collections.emptyList());
|
||||
PLAYERS.set(packet, Collections.singletonList(new ClientboundPlayerInfoUpdatePacket.b(
|
||||
id,
|
||||
createProfile(id, name, skin),
|
||||
listed,
|
||||
latency,
|
||||
EnumGamemode.a(gameMode),
|
||||
displayName == null ? null : displayName.convert(),
|
||||
null
|
||||
)));
|
||||
sendPacket(packet);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates GameProfile from given parameters.
|
||||
*
|
||||
* @param id
|
||||
* Profile ID
|
||||
* @param name
|
||||
* Profile name
|
||||
* @param skin
|
||||
* Player skin
|
||||
* @return GameProfile from given parameters
|
||||
*/
|
||||
@NotNull
|
||||
private GameProfile createProfile(@NonNull UUID id, @NonNull String name, @Nullable Skin skin) {
|
||||
GameProfile profile = new GameProfile(id, name);
|
||||
if (skin != null) {
|
||||
profile.getProperties().put(TabList.TEXTURES_PROPERTY,
|
||||
new Property(TabList.TEXTURES_PROPERTY, skin.getValue(), skin.getSignature()));
|
||||
}
|
||||
return profile;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sends the packet to the player.
|
||||
*
|
||||
* @param packet
|
||||
* Packet to send
|
||||
*/
|
||||
private void sendPacket(@NotNull Packet<?> packet) {
|
||||
((CraftPlayer)player.getPlayer()).getHandle().b.a(packet);
|
||||
}
|
||||
}
|
||||
-40
@@ -1,40 +0,0 @@
|
||||
package me.neznamy.tab.platforms.bukkit.v1_19_R2;
|
||||
|
||||
import io.netty.channel.Channel;
|
||||
import me.neznamy.tab.shared.platform.NettyTabListEntryTracker;
|
||||
import net.minecraft.network.protocol.game.ClientboundPlayerInfoRemovePacket;
|
||||
import net.minecraft.network.protocol.game.ClientboundPlayerInfoUpdatePacket;
|
||||
import net.minecraft.network.protocol.game.ClientboundPlayerInfoUpdatePacket.a;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
* Implementation of TabListEntryTracker.
|
||||
*/
|
||||
public class NMSTabListEntryTracker extends NettyTabListEntryTracker {
|
||||
|
||||
private static final a ADD_PLAYER = a.valueOf("ADD_PLAYER");
|
||||
|
||||
public NMSTabListEntryTracker(@NotNull Channel channel) {
|
||||
super(channel);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPacketSend(@NotNull Object packet) {
|
||||
if (packet instanceof ClientboundPlayerInfoRemovePacket) {
|
||||
ClientboundPlayerInfoRemovePacket remove = (ClientboundPlayerInfoRemovePacket) packet;
|
||||
for (UUID id : remove.b()) {
|
||||
tablistEntries.remove(id);
|
||||
}
|
||||
}
|
||||
if (packet instanceof ClientboundPlayerInfoUpdatePacket) {
|
||||
ClientboundPlayerInfoUpdatePacket update = (ClientboundPlayerInfoUpdatePacket) packet;
|
||||
if (update.b().contains(ADD_PLAYER)) {
|
||||
for (ClientboundPlayerInfoUpdatePacket.b nmsData : update.c()) {
|
||||
tablistEntries.add(nmsData.a());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -14,11 +14,12 @@ repositories {
|
||||
maven("https://repo.papermc.io/repository/maven-public/") // Adventure
|
||||
}
|
||||
|
||||
val minecraftVersion = "26.2"
|
||||
val minecraftVersion = "26.3"
|
||||
|
||||
// Fabric API versions for each Minecraft version for easier backporting
|
||||
// Official website (for updating in the future): https://fabricmc.net/develop/
|
||||
val fabricApiVersions = mapOf(
|
||||
"26.3" to "0.160.5+26.3",
|
||||
"26.2" to "0.150.3+26.2",
|
||||
"26.1.2" to "0.150.0+26.1.2"
|
||||
)
|
||||
|
||||
@@ -133,7 +133,12 @@ public class FabricScoreboard extends SafeScoreboard<FabricTabPlayer> {
|
||||
if (packet instanceof ClientboundSetPlayerTeamPacket team) {
|
||||
int method = getMethod(team);
|
||||
if (method != TeamAction.UPDATE) {
|
||||
team.players = onTeamPacket(method, team.getName(), team.getPlayers());
|
||||
return new ClientboundSetPlayerTeamPacket(
|
||||
team.getName(),
|
||||
method,
|
||||
team.getParameters(),
|
||||
onTeamPacket(method, team.getName(), team.getPlayers())
|
||||
);
|
||||
}
|
||||
}
|
||||
return packet;
|
||||
|
||||
@@ -14,7 +14,8 @@
|
||||
"fabric-api-base": "*",
|
||||
"java": ">=25",
|
||||
"minecraft": [
|
||||
"26.2"
|
||||
"26.2",
|
||||
"26.3"
|
||||
]
|
||||
},
|
||||
"recommends": {
|
||||
|
||||
@@ -5,8 +5,7 @@ accessible field net/minecraft/server/network/ServerCommonPacketListenerImpl con
|
||||
accessible field net/minecraft/network/Connection channel Lio/netty/channel/Channel;
|
||||
|
||||
# Scoreboard team
|
||||
accessible field net/minecraft/network/protocol/game/ClientboundSetPlayerTeamPacket players Ljava/util/Collection;
|
||||
mutable field net/minecraft/network/protocol/game/ClientboundSetPlayerTeamPacket players Ljava/util/Collection;
|
||||
accessible method net/minecraft/network/protocol/game/ClientboundSetPlayerTeamPacket <init> (Ljava/lang/String;ILjava/util/Optional;Ljava/util/Collection;)V
|
||||
|
||||
# Player info
|
||||
accessible field net/minecraft/network/protocol/game/ClientboundPlayerInfoUpdatePacket entries Ljava/util/List;
|
||||
|
||||
@@ -27,8 +27,6 @@ val platformPaths = setOf(
|
||||
":bukkit:v1_16_R3",
|
||||
":bukkit:v1_17_R1",
|
||||
":bukkit:v1_18_R2",
|
||||
":bukkit:v1_19_R1",
|
||||
":bukkit:v1_19_R2",
|
||||
":bukkit:v1_19_R3",
|
||||
":bukkit:v1_20_R1",
|
||||
":bukkit:v1_20_R2",
|
||||
|
||||
@@ -15,13 +15,14 @@ repositories {
|
||||
maven("https://repo.papermc.io/repository/maven-public/") // Adventure
|
||||
}
|
||||
|
||||
val minecraftVersion = "26.2"
|
||||
val minecraftVersion = "26.3"
|
||||
|
||||
// NeoForge API versions for each Minecraft version for easier backporting
|
||||
// Official website (for updating in the future): https://projects.neoforged.net/neoforged/neoforge
|
||||
val neoforgeApiVersions = mapOf(
|
||||
"26.2" to "26.2.0.1-beta",
|
||||
"26.1.2" to "26.1.2.17-beta"
|
||||
"26.3" to "26.3.0.1-beta",
|
||||
"26.2" to "26.2.0.88",
|
||||
"26.1.2" to "26.1.2.109"
|
||||
)
|
||||
|
||||
dependencies {
|
||||
|
||||
@@ -133,7 +133,12 @@ public class NeoForgeScoreboard extends SafeScoreboard<NeoForgeTabPlayer> {
|
||||
if (packet instanceof ClientboundSetPlayerTeamPacket team) {
|
||||
int method = getMethod(team);
|
||||
if (method != TeamAction.UPDATE) {
|
||||
team.players = onTeamPacket(method, team.getName(), team.getPlayers());
|
||||
return new ClientboundSetPlayerTeamPacket(
|
||||
team.getName(),
|
||||
method,
|
||||
team.getParameters(),
|
||||
onTeamPacket(method, team.getName(), team.getPlayers())
|
||||
);
|
||||
}
|
||||
}
|
||||
return packet;
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
# Scoreboard team
|
||||
public-f net.minecraft.network.protocol.game.ClientboundSetPlayerTeamPacket players
|
||||
public net.minecraft.network.protocol.game.ClientboundSetPlayerTeamPacket <init>(Ljava/lang/String;ILjava/util/Optional;Ljava/util/Collection;)V
|
||||
|
||||
# Player info
|
||||
public-f net.minecraft.network.protocol.game.ClientboundPlayerInfoUpdatePacket entries
|
||||
@@ -15,6 +15,6 @@ description = '''@description@'''
|
||||
[[dependencies.tab]]
|
||||
modId = "minecraft"
|
||||
type = "required"
|
||||
versionRange = "[26.2]"
|
||||
versionRange = "[26.2],[26.3]"
|
||||
ordering = "NONE"
|
||||
side = "SERVER"
|
||||
@@ -52,8 +52,6 @@ include(":bukkit:v1_12_R1")
|
||||
include(":bukkit:v1_16_R3")
|
||||
include(":bukkit:v1_17_R1")
|
||||
include(":bukkit:v1_18_R2")
|
||||
include(":bukkit:v1_19_R1")
|
||||
include(":bukkit:v1_19_R2")
|
||||
include(":bukkit:v1_19_R3")
|
||||
include(":bukkit:v1_20_R1")
|
||||
include(":bukkit:v1_20_R2")
|
||||
|
||||
@@ -596,8 +596,12 @@ public class FeatureManager {
|
||||
if (config.getScoreboard() != null) {
|
||||
registerFeature(TabConstants.Feature.SCOREBOARD, new ScoreboardManagerImpl(config.getScoreboard()));
|
||||
}
|
||||
registerFeature(TabConstants.Feature.YELLOW_NUMBER, new YellowNumber(config.getPlayerlistObjective()));
|
||||
registerFeature(TabConstants.Feature.BELOW_NAME, new BelowName(config.getBelowname()));
|
||||
if (config.getPlayerlistObjective() != null) {
|
||||
registerFeature(TabConstants.Feature.YELLOW_NUMBER, new YellowNumber(config.getPlayerlistObjective()));
|
||||
}
|
||||
if (config.getBelowname() != null) {
|
||||
registerFeature(TabConstants.Feature.BELOW_NAME, new BelowName(config.getBelowname()));
|
||||
}
|
||||
if (config.getSorting() != null) {
|
||||
registerFeature(TabConstants.Feature.SORTING, new Sorting(config.getSorting()));
|
||||
}
|
||||
|
||||
@@ -11,6 +11,7 @@ import org.jetbrains.annotations.NotNull;
|
||||
public enum ProtocolVersion {
|
||||
|
||||
UNKNOWN,
|
||||
V26_3 (777),
|
||||
V26_2 (776),
|
||||
V26_1_2 (775),
|
||||
V26_1_1 (775),
|
||||
|
||||
@@ -40,7 +40,7 @@ public class Config {
|
||||
@NotNull private final ConfigurationFile config = new YamlConfigurationFile(getClass().getClassLoader().getResourceAsStream("config/config.yml"),
|
||||
new File(TAB.getInstance().getDataFolder(), "config.yml"));
|
||||
|
||||
@NotNull private final BelowNameConfiguration belowname;
|
||||
@Nullable private BelowNameConfiguration belowname;
|
||||
@Nullable private BossBarConfiguration bossbar;
|
||||
@NotNull private final ConditionsSection conditions;
|
||||
@Nullable private GlobalPlayerListConfiguration globalPlayerList;
|
||||
@@ -52,7 +52,7 @@ public class Config {
|
||||
@NotNull private final PlaceholderRefreshConfiguration refresh;
|
||||
@NotNull private final PlaceholderReplacementsConfiguration replacements;
|
||||
@NotNull private final PlaceholdersConfiguration placeholders;
|
||||
@NotNull private final PlayerListObjectiveConfiguration playerlistObjective;
|
||||
@Nullable private PlayerListObjectiveConfiguration playerlistObjective;
|
||||
@Nullable private ScoreboardConfiguration scoreboard;
|
||||
@Nullable private SortingConfiguration sorting;
|
||||
@Nullable private TablistFormattingConfiguration tablistFormatting;
|
||||
@@ -95,10 +95,10 @@ public class Config {
|
||||
replacements = PlaceholderReplacementsConfiguration.fromSection(config.getConfigurationSection("placeholder-output-replacements"));
|
||||
placeholders = PlaceholdersConfiguration.fromSection(config.getConfigurationSection("placeholders"));
|
||||
components = ComponentConfiguration.fromSection(config.getConfigurationSection("components"));
|
||||
belowname = BelowNameConfiguration.fromSection(config.getConfigurationSection("belowname-objective"));
|
||||
playerlistObjective = PlayerListObjectiveConfiguration.fromSection(config.getConfigurationSection("playerlist-objective"));
|
||||
|
||||
if (config.getBoolean("bossbar.enabled", false)) bossbar = BossBarConfiguration.fromSection(config.getConfigurationSection("bossbar"));
|
||||
if (config.getBoolean("belowname-objective.enabled", false)) belowname = BelowNameConfiguration.fromSection(config.getConfigurationSection("belowname-objective"));
|
||||
if (config.getBoolean("playerlist-objective.enabled", true)) playerlistObjective = PlayerListObjectiveConfiguration.fromSection(config.getConfigurationSection("playerlist-objective"));
|
||||
if (config.getBoolean("global-playerlist.enabled", false)) globalPlayerList = GlobalPlayerListConfiguration.fromSection(config.getConfigurationSection("global-playerlist"));
|
||||
if (config.getBoolean("header-footer.enabled", true)) headerFooter = HeaderFooterConfiguration.fromSection(config.getConfigurationSection("header-footer"));
|
||||
if (config.getBoolean("layout.enabled", false)) layout = LayoutConfiguration.fromSection(config.getConfigurationSection("layout"));
|
||||
@@ -118,7 +118,7 @@ public class Config {
|
||||
" fake players, making per world playerlist completely useless as real players are pushed out of the playerlist. " +
|
||||
"Disable per world playerlist for the same result, but with better performance.");
|
||||
}
|
||||
if (playerlistObjective.isEnabled()) {
|
||||
if (playerlistObjective != null) {
|
||||
TAB.getInstance().getConfigHelper().startup().startupWarn(config.getFile(), "Layout feature breaks playerlist-objective feature, because it replaces real player with fake slots " +
|
||||
"with different usernames for more reliable functionality. Disable playerlist-objective feature, as it will only look bad " +
|
||||
"and consume resources.");
|
||||
|
||||
@@ -150,15 +150,11 @@ public class BelowName extends RefreshableFeature implements JoinListener, QuitL
|
||||
p.belowNameData.disabled.set(!forced);
|
||||
return;
|
||||
}
|
||||
if (!configuration.isEnabled()) {
|
||||
p.belowNameData.disabled.set(true);
|
||||
return;
|
||||
}
|
||||
updateVisibility(p, disabledNow);
|
||||
}
|
||||
|
||||
private boolean configuredDisabled(@NotNull TabPlayer p) {
|
||||
return !configuration.isEnabled() || disableChecker.isDisableConditionMet(p);
|
||||
return disableChecker.isDisableConditionMet(p);
|
||||
}
|
||||
|
||||
private void applyDisabledState(@NotNull TabPlayer p, boolean disabled) {
|
||||
|
||||
-2
@@ -17,7 +17,6 @@ import java.util.Arrays;
|
||||
public class BelowNameConfiguration {
|
||||
|
||||
@NotNull private final ConfigurationSection section;
|
||||
private final boolean enabled;
|
||||
@NotNull private final String value;
|
||||
@NotNull private final String title;
|
||||
@NotNull private final String fancyValue;
|
||||
@@ -71,7 +70,6 @@ public class BelowNameConfiguration {
|
||||
|
||||
return new BelowNameConfiguration(
|
||||
section,
|
||||
section.getBoolean("enabled", false),
|
||||
value,
|
||||
title,
|
||||
section.getString("fancy-value", "&c" + TabConstants.Placeholder.HEALTH),
|
||||
|
||||
@@ -210,11 +210,7 @@ public class LayoutManagerImpl extends RefreshableFeature implements LayoutManag
|
||||
|
||||
@Override
|
||||
public void resetLayout(@NonNull me.neznamy.tab.api.TabPlayer player) {
|
||||
ensureActive();
|
||||
TabPlayer p = (TabPlayer) player;
|
||||
p.ensureLoaded();
|
||||
p.layoutData.forcedLayout = null;
|
||||
refresh(p, false);
|
||||
sendLayout(player, null);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
|
||||
-2
@@ -18,7 +18,6 @@ import java.util.Arrays;
|
||||
public class PlayerListObjectiveConfiguration {
|
||||
|
||||
@NotNull private final ConfigurationSection section;
|
||||
private final boolean enabled;
|
||||
@NotNull private final String value;
|
||||
@NotNull private final String fancyValue;
|
||||
@NotNull private final String title;
|
||||
@@ -72,7 +71,6 @@ public class PlayerListObjectiveConfiguration {
|
||||
|
||||
return new PlayerListObjectiveConfiguration(
|
||||
section,
|
||||
section.getBoolean("enabled", true),
|
||||
value,
|
||||
section.getString("fancy-value", "&7Ping: " + Placeholder.PING),
|
||||
section.getString("title", "TAB"),
|
||||
|
||||
+1
-5
@@ -138,15 +138,11 @@ public class YellowNumber extends RefreshableFeature implements JoinListener, Qu
|
||||
p.playerlistObjectiveData.disabled.set(!forced);
|
||||
return;
|
||||
}
|
||||
if (!configuration.isEnabled()) {
|
||||
p.playerlistObjectiveData.disabled.set(true);
|
||||
return;
|
||||
}
|
||||
updateVisibility(p, disabledNow);
|
||||
}
|
||||
|
||||
private boolean configuredDisabled(@NotNull TabPlayer p) {
|
||||
return !configuration.isEnabled() || disableChecker.isDisableConditionMet(p);
|
||||
return disableChecker.isDisableConditionMet(p);
|
||||
}
|
||||
|
||||
private void applyDisabledState(@NotNull TabPlayer p, boolean disabled) {
|
||||
|
||||
@@ -78,6 +78,7 @@ public class Condition {
|
||||
|
||||
List<PlaceholderReference> placeholdersInConditions = new ArrayList<>();
|
||||
PlaceholderManagerImpl manager = TAB.getInstance().getPlaceholderManager();
|
||||
if (manager == null) return; // Header / footer config conversion, the placeholder manager is not initialized yet
|
||||
placeholdersInConditions.addAll(manager.detectPlaceholders(yes).stream().map(manager::getPlaceholderReference).collect(Collectors.toList()));
|
||||
placeholdersInConditions.addAll(manager.detectPlaceholders(no).stream().map(manager::getPlaceholderReference).collect(Collectors.toList()));
|
||||
for (ConditionalExpression expression : expressions) {
|
||||
|
||||
+1
-1
@@ -138,7 +138,7 @@ public class PlayerPlaceholderImpl extends TabPlaceholder implements PlayerPlace
|
||||
|
||||
@Override
|
||||
@NotNull
|
||||
public String getLastReturnedValue(@Nullable TabPlayer player) {
|
||||
public synchronized String getLastReturnedValue(@Nullable TabPlayer player) {
|
||||
if (player == null) return identifier;
|
||||
String value = player.lastPlaceholderReturnedValues.get(this);
|
||||
if (value != null) return value;
|
||||
|
||||
@@ -324,11 +324,11 @@ public abstract class SafeScoreboard<T extends TabPlayer> implements Scoreboard
|
||||
* Team name in the packet
|
||||
* @param players
|
||||
* Players in the packet
|
||||
* @return Modified collection of players
|
||||
* @return Modified list of players
|
||||
*/
|
||||
@NotNull
|
||||
public Collection<String> onTeamPacket(int action, @NonNull String teamName, @NonNull Collection<String> players) {
|
||||
Collection<String> newList = new ArrayList<>();
|
||||
public List<String> onTeamPacket(int action, @NonNull String teamName, @NonNull Collection<String> players) {
|
||||
List<String> newList = new ArrayList<>();
|
||||
if (action == TeamAction.CREATE || action == TeamAction.ADD_PLAYER) {
|
||||
for (String entry : players) {
|
||||
Team expectedTeam = getExpectedTeam(entry);
|
||||
|
||||
Reference in new issue
Block a user