Compare commits

..
14 Commits
23 changed files with 63 additions and 829 deletions

No files matched your search

+2 -4
View File
@@ -4,7 +4,7 @@ plugins {
allprojects {
group = "me.neznamy"
version = "4.1.0"
version = "4.1.2"
description = "An all-in-one solution that works"
ext.set("id", "tab")
@@ -19,17 +19,15 @@ val platforms = setOf(
projects.sponge7,
projects.sponge8,
projects.fabric,
projects.fabric.v1144,
projects.fabric.v1152,
projects.fabric.v1165,
projects.fabric.v117,
projects.fabric.v1171,
projects.fabric.v1182,
projects.fabric.v1192,
projects.fabric.v1193,
projects.fabric.v1201,
projects.fabric.v1202,
projects.fabric.v1203
projects.fabric.v1204
).map { it.dependencyProject }
val special = setOf(
+2 -4
View File
@@ -1,5 +1,3 @@
val minecraftVersion = "1.20.3"
plugins {
id("fabric-loom")
}
@@ -14,11 +12,11 @@ repositories {
dependencies {
api(projects.shared)
minecraft("com.mojang:minecraft:$minecraftVersion")
minecraft("com.mojang:minecraft:1.20.4")
mappings(loom.officialMojangMappings())
modImplementation("me.lucko:fabric-permissions-api:0.2-SNAPSHOT")
modImplementation("net.fabricmc:fabric-loader:0.14.17")
val version = "0.90.4+1.20.3"
val version = "0.91.1+1.20.4"
modImplementation(fabricApi.module("fabric-api-base", version))
modImplementation(fabricApi.module("fabric-lifecycle-events-v1", version))
modImplementation(fabricApi.module("fabric-networking-api-v1", version))
@@ -13,17 +13,15 @@ public class FabricTAB implements DedicatedServerModInitializer {
@Override
public void onInitializeServer() {
String[] modules = {
"v1_14_4",
"v1_15_2",
"v1_15_2", // 1.14.4, 1.15.2
"v1_16_5",
"v1_17",
"v1_17_1",
"v1_17_1", // 1.17, 1.17.1
"v1_18_2", // 1.18, 1.18.1, 1.18.2
"v1_19_2", // 1.19, 1.19.1, 1.19.2
"v1_19_3",
"v1_20_1", // 1.19.4, 1.20, 1.20.1
"v1_20_2",
"v1_20_3"
"v1_20_4" // 1.20.3, 1.20.4
};
for (String module : modules) {
try {
+1 -1
View File
@@ -18,7 +18,7 @@
"1.17", "1.17.1",
"1.18", "1.18.1", "1.18.2",
"1.19", "1.19.1", "1.19.2", "1.19.3", "1.19.4",
"1.20", "1.20.1", "1.20.2", "1.20.3"
"1.20", "1.20.1", "1.20.2", "1.20.3", "1.20.4"
]
},
"recommends": {
-22
View File
@@ -1,22 +0,0 @@
plugins {
id("fabric-loom")
}
repositories {
// Gradle doesn't support combining settings and project repositories, so we have to re-declare all the settings repos we need
maven("https://jitpack.io") // YamlAssist
maven("https://repo.opencollab.dev/maven-snapshots/")
maven("https://repo.viaversion.com/")
maven("https://oss.sonatype.org/content/repositories/snapshots")
}
dependencies {
implementation(projects.fabric)
minecraft("com.mojang:minecraft:1.14.4")
mappings(loom.officialMojangMappings())
modImplementation("net.fabricmc:fabric-loader:0.14.17")
val fabricApiVersion = "0.28.5+1.14"
modImplementation(fabricApi.module("fabric-api-base", fabricApiVersion))
modImplementation(fabricApi.module("fabric-lifecycle-events-v1", fabricApiVersion))
modImplementation(fabricApi.module("fabric-command-api-v1", fabricApiVersion))
}
@@ -1,149 +0,0 @@
package me.neznamy.tab.platforms.fabric.v1_14_4;
import com.mojang.authlib.GameProfile;
import io.netty.channel.Channel;
import lombok.SneakyThrows;
import me.neznamy.tab.platforms.fabric.FabricTabPlayer;
import me.neznamy.tab.shared.TAB;
import me.neznamy.tab.shared.TabConstants;
import me.neznamy.tab.shared.chat.IChatBaseComponent;
import me.neznamy.tab.shared.features.injection.NettyPipelineInjector;
import me.neznamy.tab.shared.features.nametags.NameTag;
import me.neznamy.tab.shared.features.sorting.Sorting;
import me.neznamy.tab.shared.platform.TabPlayer;
import me.neznamy.tab.shared.util.ReflectionUtils;
import net.minecraft.network.Connection;
import net.minecraft.network.chat.Component;
import net.minecraft.network.protocol.game.ClientboundPlayerInfoPacket;
import net.minecraft.network.protocol.game.ClientboundPlayerInfoPacket.Action;
import net.minecraft.network.protocol.game.ClientboundPlayerInfoPacket.PlayerUpdate;
import net.minecraft.network.protocol.game.ClientboundSetDisplayObjectivePacket;
import net.minecraft.network.protocol.game.ClientboundSetObjectivePacket;
import net.minecraft.network.protocol.game.ClientboundSetPlayerTeamPacket;
import net.minecraft.server.network.ServerGamePacketListenerImpl;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
public class FabricPipelineInjector extends NettyPipelineInjector {
public FabricPipelineInjector() {
super("packet_handler");
}
@Override
@Nullable
@SneakyThrows
protected Channel getChannel(@NotNull TabPlayer player) {
Connection c = (Connection) ReflectionUtils.getFields(ServerGamePacketListenerImpl.class, Connection.class)
.get(0).get(((FabricTabPlayer)player).getPlayer().connection);
return (Channel) ReflectionUtils.getFields(Connection.class, Channel.class).get(0).get(c);
}
@Override
@SneakyThrows
public void onDisplayObjective(@NotNull TabPlayer player, @NotNull Object packet) {
// Getters are client only
int slot = ReflectionUtils.getFields(ClientboundSetDisplayObjectivePacket.class, int.class).get(0).getInt(packet);
String objective = (String) ReflectionUtils.getFields(ClientboundSetDisplayObjectivePacket.class, String.class).get(0).get(packet);
TAB.getInstance().getFeatureManager().onDisplayObjective(player, slot, objective);
}
@Override
@SneakyThrows
public void onObjective(@NotNull TabPlayer player, @NotNull Object packet) {
// Getters are client only
int action = ReflectionUtils.getFields(ClientboundSetObjectivePacket.class, int.class).get(0).getInt(packet);
String objective = (String) ReflectionUtils.getFields(ClientboundSetObjectivePacket.class, String.class).get(0).get(packet);
TAB.getInstance().getFeatureManager().onObjective(player, action, objective);
}
@Override
public boolean isDisplayObjective(@NotNull Object packet) {
return packet instanceof ClientboundSetDisplayObjectivePacket;
}
@Override
public boolean isObjective(@NotNull Object packet) {
return packet instanceof ClientboundSetObjectivePacket;
}
@Override
public boolean isTeam(@NotNull Object packet) {
return packet instanceof ClientboundSetPlayerTeamPacket;
}
@Override
public boolean isPlayerInfo(@NotNull Object packet) {
return packet instanceof ClientboundPlayerInfoPacket;
}
@Override
@SneakyThrows
@SuppressWarnings("unchecked")
public void onPlayerInfo(@NotNull TabPlayer receiver, @NotNull Object packet) {
// Getters are client only
Action action = (Action) ReflectionUtils.getFields(ClientboundPlayerInfoPacket.class, Action.class).get(0).get(packet);
List<PlayerUpdate> players = (List<PlayerUpdate>) ReflectionUtils.getFields(ClientboundPlayerInfoPacket.class, List.class).get(0).get(packet);
for (PlayerUpdate nmsData : players) {
GameProfile profile = nmsData.getProfile();
Field displayNameField = ReflectionUtils.getFields(PlayerUpdate.class, Component.class).get(0);
Field latencyField = ReflectionUtils.getFields(PlayerUpdate.class, int.class).get(0);
if (action == Action.UPDATE_DISPLAY_NAME) {
IChatBaseComponent newDisplayName = TAB.getInstance().getFeatureManager().onDisplayNameChange(receiver, profile.getId());
if (newDisplayName != null) displayNameField.set(nmsData, ((FabricTabPlayer)receiver).getPlatform().toComponent(newDisplayName, receiver.getVersion()));
}
if (action == Action.UPDATE_LATENCY) {
latencyField.set(nmsData, TAB.getInstance().getFeatureManager().onLatencyChange(receiver, profile.getId(), latencyField.getInt(nmsData)));
}
if (action == Action.ADD_PLAYER) {
TAB.getInstance().getFeatureManager().onEntryAdd(receiver, profile.getId(), profile.getName());
}
}
}
@Override
public boolean isLogin(@NotNull Object packet) {
return false;
}
@Override
@SneakyThrows
@SuppressWarnings("unchecked")
public void modifyPlayers(@NotNull Object teamPacket) {
if (TAB.getInstance().getNameTagManager() == null) return;
ClientboundSetPlayerTeamPacket packet = (ClientboundSetPlayerTeamPacket) teamPacket;
int action = ReflectionUtils.getInstanceFields(ClientboundSetPlayerTeamPacket.class, int.class).get(0).getInt(packet);
if (action == 1 || action == 2 || action == 4) return;
Field playersField = ReflectionUtils.getFields(ClientboundSetPlayerTeamPacket.class, Collection.class).get(0);
Collection<String> players = (Collection<String>) playersField.get(packet);
String teamName = String.valueOf(ReflectionUtils.getFields(ClientboundSetPlayerTeamPacket.class, String.class).get(0).get(packet));
if (players == null) return;
//creating a new list to prevent NoSuchFieldException in minecraft packet encoder when a player is removed
Collection<String> newList = new ArrayList<>();
for (String entry : players) {
TabPlayer p = getPlayer(entry);
if (p == null) {
newList.add(entry);
continue;
}
Sorting sorting = TAB.getInstance().getFeatureManager().getFeature(TabConstants.Feature.SORTING);
String expectedTeam = sorting.getShortTeamName(p);
if (expectedTeam == null) {
newList.add(entry);
continue;
}
if (!((NameTag)TAB.getInstance().getNameTagManager()).getDisableChecker().isDisabledPlayer(p) &&
!TAB.getInstance().getNameTagManager().hasTeamHandlingPaused(p) && !teamName.equals(expectedTeam)) {
logTeamOverride(teamName, p.getName(), expectedTeam);
} else {
newList.add(entry);
}
}
playersField.set(packet, newList);
}
}
@@ -1,223 +0,0 @@
package me.neznamy.tab.platforms.fabric.v1_14_4;
import com.mojang.authlib.properties.Property;
import lombok.SneakyThrows;
import me.neznamy.tab.platforms.fabric.*;
import me.neznamy.tab.shared.TAB;
import me.neznamy.tab.shared.backend.EntityData;
import me.neznamy.tab.shared.backend.Location;
import me.neznamy.tab.shared.chat.IChatBaseComponent;
import me.neznamy.tab.shared.features.injection.PipelineInjector;
import me.neznamy.tab.shared.platform.Scoreboard;
import me.neznamy.tab.shared.platform.TabList;
import me.neznamy.tab.shared.platform.TabPlayer;
import me.neznamy.tab.shared.util.ReflectionUtils;
import net.fabricmc.fabric.api.command.v1.CommandRegistrationCallback;
import net.minecraft.SharedConstants;
import net.minecraft.commands.CommandSourceStack;
import net.minecraft.network.chat.Component;
import net.minecraft.network.protocol.Packet;
import net.minecraft.network.protocol.game.*;
import net.minecraft.network.syncher.EntityDataAccessor;
import net.minecraft.network.syncher.EntityDataSerializers;
import net.minecraft.network.syncher.SynchedEntityData;
import net.minecraft.server.ServerScoreboard;
import net.minecraft.server.level.ServerPlayer;
import net.minecraft.world.level.GameType;
import net.minecraft.world.level.Level;
import net.minecraft.world.scores.Objective;
import net.minecraft.world.scores.PlayerTeam;
import net.minecraft.world.scores.criteria.ObjectiveCriteria;
import org.jetbrains.annotations.Nullable;
import java.lang.reflect.Field;
import java.util.Collections;
import java.util.List;
import java.util.Optional;
import java.util.UUID;
public class FabricTAB implements VersionLoader {
@Override
public List<String> getSupportedVersions() {
return Collections.singletonList("1.14.4");
}
@Override
public String getName(Level level) {
return level.getLevelData().getLevelName() + level.dimension.getType().getFileSuffix();
}
@Override
public int getPing(ServerPlayer player) {
return player.latency;
}
@Override
public void sendMessage(ServerPlayer player, Component message) {
player.sendMessage(message);
}
@Override
public TabList.Skin propertyToSkin(Property property) {
return new TabList.Skin(property.getValue(), property.getSignature());
}
@Override
public void sendMessage(CommandSourceStack sender, Component message) {
sender.sendSuccess(message, false);
}
@Override
public String getServerVersion() {
return SharedConstants.getCurrentVersion().getName();
}
@Override
public double getMSPT() {
return ((FabricPlatform)TAB.getInstance().getPlatform()).getServer().getAverageTickTime();
}
@Override
public Component deserialize(String string) {
return Component.Serializer.fromJson(string);
}
@Override
@SneakyThrows
public Packet<?> build(TabList.Action action, FabricTabList.Builder entry) {
ClientboundPlayerInfoPacket packet = new ClientboundPlayerInfoPacket(ClientboundPlayerInfoPacket.Action.valueOf(action.name()), Collections.emptyList());
ReflectionUtils.getFields(ClientboundPlayerInfoPacket.class, List.class).get(0).set(packet,
Collections.singletonList(new ClientboundPlayerInfoPacket().new PlayerUpdate(
entry.createProfile(),
entry.getLatency(),
GameType.byId(entry.getGameMode()),
entry.getDisplayName()
)));
return packet;
}
@Override
public Level getLevel(ServerPlayer player) {
return player.level;
}
@Override
public boolean isSneaking(ServerPlayer player) {
return player.isSneaking();
}
@Override
public EntityData createDataWatcher(TabPlayer viewer, byte flags, String displayName, boolean nameVisible) {
SynchedEntityData data = new SynchedEntityData(null);
data.define(new EntityDataAccessor<>(0, EntityDataSerializers.BYTE), flags);
data.define(new EntityDataAccessor<>(2, EntityDataSerializers.OPTIONAL_COMPONENT),
Optional.of(((FabricTabPlayer)viewer).getPlatform().toComponent(IChatBaseComponent.optimizedComponent(displayName), viewer.getVersion())));
data.define(new EntityDataAccessor<>(3, EntityDataSerializers.BOOLEAN), nameVisible);
data.define(new EntityDataAccessor<>(13, EntityDataSerializers.BYTE), (byte)16);
return () -> data;
}
@Override
public Packet<?> spawnEntity(int entityId, UUID id, Object entityType, Location location) {
dummyEntity.setId(entityId);
dummyEntity.setUUID(id);
dummyEntity.setPos(location.getX(), location.getY(), location.getZ());
return new ClientboundAddMobPacket(dummyEntity);
}
@Override
public Packet<?> newEntityMetadata(int entityId, EntityData data) {
return new ClientboundSetEntityDataPacket(entityId, (SynchedEntityData) data.build(), true);
}
@Override
public boolean isSpawnPlayerPacket(Object packet) {
return packet instanceof ClientboundAddPlayerPacket;
}
@Override
@SneakyThrows
public int getSpawnedPlayer(Object spawnPacket) {
// Getter is client only
return ReflectionUtils.getFields(ClientboundAddPlayerPacket.class, int.class).get(0).getInt(spawnPacket);
}
@Override
@SneakyThrows
public int[] getDestroyedEntities(Object entityDestroyPacket) {
// Getter is client only
return (int[]) ReflectionUtils.getFields(ClientboundRemoveEntitiesPacket.class, int[].class).get(0).get(entityDestroyPacket);
}
@Override
public boolean isBundlePacket(Object packet) {
return false;
}
@Override
public Iterable<Object> getPackets(Object bundlePacket) {
return Collections.emptyList();
}
@Override
public PipelineInjector createPipelineInjector() {
return new FabricPipelineInjector();
}
@Override
public void destroyEntities(FabricTabPlayer player, int... entities) {
player.sendPacket(new ClientboundRemoveEntitiesPacket(entities));
}
@Override
public void registerCommandCallback() {
CommandRegistrationCallback.EVENT.register((dispatcher, $) -> new FabricTabCommand().onRegisterCommands(dispatcher));
}
@Override
@SneakyThrows
public Packet<?> newHeaderFooter(Component header, Component footer) {
ClientboundTabListPacket packet = new ClientboundTabListPacket();
List<Field> fields = ReflectionUtils.getFields(ClientboundTabListPacket.class, Component.class);
fields.get(0).set(packet, header);
fields.get(1).set(packet, footer);
return packet;
}
@Override
public Packet<?> setDisplaySlot(int slot, Objective objective) {
return new ClientboundSetDisplayObjectivePacket(slot, objective);
}
@Override
public Objective newObjective(String name, Component displayName, ObjectiveCriteria.RenderType renderType,
@Nullable Component numberFormat) {
return new Objective(dummyScoreboard, name, ObjectiveCriteria.DUMMY, displayName, renderType);
}
@Override
public Packet<?> registerTeam(PlayerTeam team) {
return new ClientboundSetPlayerTeamPacket(team, Scoreboard.TeamAction.CREATE);
}
@Override
public Packet<?> unregisterTeam(PlayerTeam team) {
return new ClientboundSetPlayerTeamPacket(team, Scoreboard.TeamAction.REMOVE);
}
@Override
public Packet<?> updateTeam(PlayerTeam team) {
return new ClientboundSetPlayerTeamPacket(team, Scoreboard.TeamAction.UPDATE);
}
@Override
public Packet<?> setScore(String objective, String scoreHolder, int score, Component displayName, @Nullable Component numberFormat) {
return new ClientboundSetScorePacket(ServerScoreboard.Method.CHANGE, objective, scoreHolder, score);
}
@Override
public Packet<?> removeScore(String objective, String scoreHolder) {
return new ClientboundSetScorePacket(ServerScoreboard.Method.REMOVE, objective, scoreHolder, 0);
}
}
@@ -37,7 +37,7 @@ public class FabricTAB implements VersionLoader {
@Override
public List<String> getSupportedVersions() {
return Collections.singletonList("1.15.2");
return Arrays.asList("1.14.4", "1.15.2");
}
@Override
@@ -100,7 +100,13 @@ public class FabricTAB implements VersionLoader {
}
@Override
@SneakyThrows
public boolean isSneaking(ServerPlayer player) {
if (getServerVersion().equals("1.14.4")) {
return (boolean) player.getClass().getMethod("method_5715").invoke(player);
}
// 1.15.2
return player.isCrouching();
}
@@ -111,7 +117,8 @@ public class FabricTAB implements VersionLoader {
data.define(new EntityDataAccessor<>(2, EntityDataSerializers.OPTIONAL_COMPONENT),
Optional.of(((FabricTabPlayer)viewer).getPlatform().toComponent(IChatBaseComponent.optimizedComponent(displayName), viewer.getVersion())));
data.define(new EntityDataAccessor<>(3, EntityDataSerializers.BOOLEAN), nameVisible);
data.define(new EntityDataAccessor<>(14, EntityDataSerializers.BYTE), (byte)16);
int markerPosition = viewer.getPlatform().getServerVersion().getMinorVersion() >= 15 ? 14 : 13;
data.define(new EntityDataAccessor<>(markerPosition, EntityDataSerializers.BYTE), (byte)16);
return () -> data;
}
-28
View File
@@ -1,28 +0,0 @@
plugins {
id("fabric-loom")
}
repositories {
// Gradle doesn't support combining settings and project repositories, so we have to re-declare all the settings repos we need
maven("https://jitpack.io") // YamlAssist
maven("https://repo.opencollab.dev/maven-snapshots/")
maven("https://repo.viaversion.com/")
maven("https://oss.sonatype.org/content/repositories/snapshots")
}
dependencies {
implementation(projects.fabric)
minecraft("com.mojang:minecraft:1.17")
mappings(loom.officialMojangMappings())
modImplementation("net.fabricmc:fabric-loader:0.14.17")
val fabricApiVersion = "0.46.1+1.17"
modImplementation(fabricApi.module("fabric-api-base", fabricApiVersion))
modImplementation(fabricApi.module("fabric-lifecycle-events-v1", fabricApiVersion))
modImplementation(fabricApi.module("fabric-command-api-v1", fabricApiVersion))
}
tasks {
compileJava {
options.release.set(17)
}
}
@@ -1,137 +0,0 @@
package me.neznamy.tab.platforms.fabric.v1_17;
import com.mojang.authlib.GameProfile;
import io.netty.channel.Channel;
import lombok.SneakyThrows;
import me.neznamy.tab.platforms.fabric.FabricTabPlayer;
import me.neznamy.tab.shared.TAB;
import me.neznamy.tab.shared.TabConstants;
import me.neznamy.tab.shared.chat.IChatBaseComponent;
import me.neznamy.tab.shared.features.injection.NettyPipelineInjector;
import me.neznamy.tab.shared.features.nametags.NameTag;
import me.neznamy.tab.shared.features.sorting.Sorting;
import me.neznamy.tab.shared.platform.TabPlayer;
import me.neznamy.tab.shared.util.ReflectionUtils;
import net.minecraft.network.Connection;
import net.minecraft.network.chat.Component;
import net.minecraft.network.protocol.game.ClientboundPlayerInfoPacket;
import net.minecraft.network.protocol.game.ClientboundSetDisplayObjectivePacket;
import net.minecraft.network.protocol.game.ClientboundSetObjectivePacket;
import net.minecraft.network.protocol.game.ClientboundSetPlayerTeamPacket;
import net.minecraft.server.network.ServerGamePacketListenerImpl;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.Collection;
public class FabricPipelineInjector extends NettyPipelineInjector {
public FabricPipelineInjector() {
super("packet_handler");
}
@Override
@Nullable
@SneakyThrows
protected Channel getChannel(@NotNull TabPlayer player) {
Connection c = (Connection) ReflectionUtils.getFields(ServerGamePacketListenerImpl.class, Connection.class)
.get(0).get(((FabricTabPlayer)player).getPlayer().connection);
return (Channel) ReflectionUtils.getFields(Connection.class, Channel.class).get(0).get(c);
}
@Override
public void onDisplayObjective(@NotNull TabPlayer player, @NotNull Object packet) {
TAB.getInstance().getFeatureManager().onDisplayObjective(player,
((ClientboundSetDisplayObjectivePacket) packet).getSlot(),
String.valueOf(((ClientboundSetDisplayObjectivePacket)packet).getObjectiveName()));
}
@Override
public void onObjective(@NotNull TabPlayer player, @NotNull Object packet) {
TAB.getInstance().getFeatureManager().onObjective(player,
((ClientboundSetObjectivePacket)packet).getMethod(),
((ClientboundSetObjectivePacket)packet).getObjectiveName());
}
@Override
public boolean isDisplayObjective(@NotNull Object packet) {
return packet instanceof ClientboundSetDisplayObjectivePacket;
}
@Override
public boolean isObjective(@NotNull Object packet) {
return packet instanceof ClientboundSetObjectivePacket;
}
@Override
public boolean isTeam(@NotNull Object packet) {
return packet instanceof ClientboundSetPlayerTeamPacket;
}
@Override
public boolean isPlayerInfo(@NotNull Object packet) {
return packet instanceof ClientboundPlayerInfoPacket;
}
@Override
@SneakyThrows
public void onPlayerInfo(@NotNull TabPlayer receiver, @NotNull Object packet0) {
ClientboundPlayerInfoPacket packet = (ClientboundPlayerInfoPacket) packet0;
for (ClientboundPlayerInfoPacket.PlayerUpdate nmsData : packet.getEntries()) {
GameProfile profile = nmsData.getProfile();
Field displayNameField = ReflectionUtils.getFields(ClientboundPlayerInfoPacket.PlayerUpdate.class, Component.class).get(0);
Field latencyField = ReflectionUtils.getFields(ClientboundPlayerInfoPacket.PlayerUpdate.class, int.class).get(0);
if (packet.getAction() == ClientboundPlayerInfoPacket.Action.UPDATE_DISPLAY_NAME) {
IChatBaseComponent newDisplayName = TAB.getInstance().getFeatureManager().onDisplayNameChange(receiver, profile.getId());
if (newDisplayName != null) displayNameField.set(nmsData, ((FabricTabPlayer)receiver).getPlatform().toComponent(newDisplayName, receiver.getVersion()));
}
if (packet.getAction() == ClientboundPlayerInfoPacket.Action.UPDATE_LATENCY) {
latencyField.set(nmsData, TAB.getInstance().getFeatureManager().onLatencyChange(receiver, profile.getId(), latencyField.getInt(nmsData)));
}
if (packet.getAction() == ClientboundPlayerInfoPacket.Action.ADD_PLAYER) {
TAB.getInstance().getFeatureManager().onEntryAdd(receiver, profile.getId(), profile.getName());
}
}
}
@Override
public boolean isLogin(@NotNull Object packet) {
return false;
}
@Override
@SneakyThrows
public void modifyPlayers(@NotNull Object teamPacket) {
if (TAB.getInstance().getNameTagManager() == null) return;
ClientboundSetPlayerTeamPacket packet = (ClientboundSetPlayerTeamPacket) teamPacket;
int action = ReflectionUtils.getInstanceFields(ClientboundSetPlayerTeamPacket.class, int.class).get(0).getInt(packet);
if (action == 1 || action == 2 || action == 4) return;
Collection<String> players = packet.getPlayers();
String teamName = packet.getName();
if (players == null) return;
//creating a new list to prevent NoSuchFieldException in minecraft packet encoder when a player is removed
Collection<String> newList = new ArrayList<>();
for (String entry : players) {
TabPlayer p = getPlayer(entry);
if (p == null) {
newList.add(entry);
continue;
}
Sorting sorting = TAB.getInstance().getFeatureManager().getFeature(TabConstants.Feature.SORTING);
String expectedTeam = sorting.getShortTeamName(p);
if (expectedTeam == null) {
newList.add(entry);
continue;
}
if (!((NameTag)TAB.getInstance().getNameTagManager()).getDisableChecker().isDisabledPlayer(p) &&
!TAB.getInstance().getNameTagManager().hasTeamHandlingPaused(p) && !teamName.equals(expectedTeam)) {
logTeamOverride(teamName, p.getName(), expectedTeam);
} else {
newList.add(entry);
}
}
ReflectionUtils.getFields(ClientboundSetPlayerTeamPacket.class, Collection.class).get(0).set(packet, newList);
}
}
@@ -1,221 +0,0 @@
package me.neznamy.tab.platforms.fabric.v1_17;
import com.mojang.authlib.properties.Property;
import lombok.SneakyThrows;
import me.neznamy.tab.platforms.fabric.*;
import me.neznamy.tab.shared.TAB;
import me.neznamy.tab.shared.backend.EntityData;
import me.neznamy.tab.shared.backend.Location;
import me.neznamy.tab.shared.chat.IChatBaseComponent;
import me.neznamy.tab.shared.features.injection.PipelineInjector;
import me.neznamy.tab.shared.platform.TabList;
import me.neznamy.tab.shared.platform.TabPlayer;
import me.neznamy.tab.shared.util.ReflectionUtils;
import net.fabricmc.fabric.api.command.v1.CommandRegistrationCallback;
import net.minecraft.SharedConstants;
import net.minecraft.commands.CommandSourceStack;
import net.minecraft.network.chat.Component;
import net.minecraft.network.protocol.Packet;
import net.minecraft.network.protocol.game.*;
import net.minecraft.network.syncher.EntityDataAccessor;
import net.minecraft.network.syncher.EntityDataSerializers;
import net.minecraft.network.syncher.SynchedEntityData;
import net.minecraft.server.ServerScoreboard;
import net.minecraft.server.level.ServerPlayer;
import net.minecraft.world.entity.EntityType;
import net.minecraft.world.level.GameType;
import net.minecraft.world.level.Level;
import net.minecraft.world.level.storage.ServerLevelData;
import net.minecraft.world.phys.Vec3;
import net.minecraft.world.scores.Objective;
import net.minecraft.world.scores.PlayerTeam;
import net.minecraft.world.scores.criteria.ObjectiveCriteria;
import org.jetbrains.annotations.Nullable;
import java.util.Collections;
import java.util.List;
import java.util.Optional;
import java.util.UUID;
public class FabricTAB implements VersionLoader {
@Override
public List<String> getSupportedVersions() {
return List.of("1.17");
}
@Override
public String getName(Level level) {
String path = level.dimension().location().getPath();
String dimensionSuffix = switch (path) {
case "overworld" -> ""; // No suffix for overworld
case "the_nether" -> "_nether";
default -> "_" + path; // End + default behavior for other dimensions created by mods
};
return ((ServerLevelData)level.getLevelData()).getLevelName() + dimensionSuffix;
}
@Override
public int getPing(ServerPlayer player) {
return player.latency;
}
@Override
public void sendMessage(ServerPlayer player, Component message) {
player.sendMessage(message, new UUID(0, 0));
}
@Override
public TabList.Skin propertyToSkin(Property property) {
return new TabList.Skin(property.getValue(), property.getSignature());
}
@Override
public void sendMessage(CommandSourceStack sender, Component message) {
sender.sendSuccess(message, false);
}
@Override
public String getServerVersion() {
return SharedConstants.getCurrentVersion().getName();
}
@Override
public double getMSPT() {
return ((FabricPlatform)TAB.getInstance().getPlatform()).getServer().getAverageTickTime();
}
@Override
public Component deserialize(String string) {
return Component.Serializer.fromJson(string);
}
@Override
@SneakyThrows
public Packet<?> build(TabList.Action action, FabricTabList.Builder entry) {
ClientboundPlayerInfoPacket packet = new ClientboundPlayerInfoPacket(ClientboundPlayerInfoPacket.Action.valueOf(action.name()), Collections.emptyList());
ReflectionUtils.getFields(ClientboundPlayerInfoPacket.class, List.class).get(0).set(packet,
Collections.singletonList(new ClientboundPlayerInfoPacket.PlayerUpdate(
entry.createProfile(),
entry.getLatency(),
GameType.byId(entry.getGameMode()),
entry.getDisplayName()
)));
return packet;
}
@Override
public Level getLevel(ServerPlayer player) {
return player.level;
}
@Override
public boolean isSneaking(ServerPlayer player) {
return player.isCrouching();
}
@Override
public EntityData createDataWatcher(TabPlayer viewer, byte flags, String displayName, boolean nameVisible) {
SynchedEntityData data = new SynchedEntityData(null);
data.define(new EntityDataAccessor<>(0, EntityDataSerializers.BYTE), flags);
data.define(new EntityDataAccessor<>(2, EntityDataSerializers.OPTIONAL_COMPONENT),
Optional.of(((FabricTabPlayer)viewer).getPlatform().toComponent(IChatBaseComponent.optimizedComponent(displayName), viewer.getVersion())));
data.define(new EntityDataAccessor<>(3, EntityDataSerializers.BOOLEAN), nameVisible);
data.define(new EntityDataAccessor<>(15, EntityDataSerializers.BYTE), (byte)16);
return () -> data;
}
@Override
public Packet<?> spawnEntity(int entityId, UUID id, Object entityType, Location location) {
return new ClientboundAddEntityPacket(entityId, id, location.getX(), location.getY(), location.getZ(),
0, 0, (EntityType<?>) entityType, 0, Vec3.ZERO);
}
@Override
public Packet<?> newEntityMetadata(int entityId, EntityData data) {
return new ClientboundSetEntityDataPacket(entityId, (SynchedEntityData) data.build(), true);
}
@Override
public boolean isSpawnPlayerPacket(Object packet) {
return packet instanceof ClientboundAddPlayerPacket;
}
@Override
public int getSpawnedPlayer(Object spawnPacket) {
return ((ClientboundAddPlayerPacket) spawnPacket).getEntityId();
}
@Override
public int[] getDestroyedEntities(Object entityDestroyPacket) {
return new int[]{((ClientboundRemoveEntityPacket) entityDestroyPacket).getEntityId()};
}
@Override
public boolean isBundlePacket(Object packet) {
return false;
}
@Override
public Iterable<Object> getPackets(Object bundlePacket) {
return Collections.emptyList();
}
@Override
public PipelineInjector createPipelineInjector() {
return new FabricPipelineInjector();
}
@Override
public void destroyEntities(FabricTabPlayer player, int... entities) {
for (int entity : entities) {
player.sendPacket(new ClientboundRemoveEntityPacket(entity));
}
}
@Override
public void registerCommandCallback() {
CommandRegistrationCallback.EVENT.register((dispatcher, $) -> new FabricTabCommand().onRegisterCommands(dispatcher));
}
@Override
public Packet<?> newHeaderFooter(Component header, Component footer) {
return new ClientboundTabListPacket(header, footer);
}
@Override
public Packet<?> setDisplaySlot(int slot, Objective objective) {
return new ClientboundSetDisplayObjectivePacket(slot, objective);
}
@Override
public Objective newObjective(String name, Component displayName, ObjectiveCriteria.RenderType renderType,
@Nullable Component numberFormat) {
return new Objective(dummyScoreboard, name, ObjectiveCriteria.DUMMY, displayName, renderType);
}
@Override
public Packet<?> registerTeam(PlayerTeam team) {
return ClientboundSetPlayerTeamPacket.createAddOrModifyPacket(team, true);
}
@Override
public Packet<?> unregisterTeam(PlayerTeam team) {
return ClientboundSetPlayerTeamPacket.createRemovePacket(team);
}
@Override
public Packet<?> updateTeam(PlayerTeam team) {
return ClientboundSetPlayerTeamPacket.createAddOrModifyPacket(team, false);
}
@Override
public Packet<?> setScore(String objective, String scoreHolder, int score, Component displayName, @Nullable Component numberFormat) {
return new ClientboundSetScorePacket(ServerScoreboard.Method.CHANGE, objective, scoreHolder, score);
}
@Override
public Packet<?> removeScore(String objective, String scoreHolder) {
return new ClientboundSetScorePacket(ServerScoreboard.Method.REMOVE, objective, scoreHolder, 0);
}
}
@@ -41,7 +41,7 @@ public class FabricTAB implements VersionLoader {
@Override
public List<String> getSupportedVersions() {
return List.of("1.17.1");
return List.of("1.17", "1.17.1");
}
@Override
@@ -147,8 +147,14 @@ public class FabricTAB implements VersionLoader {
}
@Override
public int[] getDestroyedEntities(Object entityDestroyPacket) {
return ((ClientboundRemoveEntitiesPacket) entityDestroyPacket).getEntityIds().toIntArray();
@SneakyThrows
public int[] getDestroyedEntities(Object packet) {
if (getServerVersion().equals("1.17")) {
return new int[]{(int) ReflectionUtils.getOnlyMethod(packet.getClass(), int.class).invoke(packet)};
}
// 1.17.1
return ((ClientboundRemoveEntitiesPacket) packet).getEntityIds().toIntArray();
}
@Override
@@ -167,7 +173,17 @@ public class FabricTAB implements VersionLoader {
}
@Override
@SneakyThrows
public void destroyEntities(FabricTabPlayer player, int... entities) {
if (getServerVersion().equals("1.17")) {
for (int entity : entities) {
// While the actual packet name is different, fabric-mapped name is the same
player.sendPacket(ClientboundRemoveEntitiesPacket.class.getConstructor(int.class).newInstance(entity));
}
return;
}
// 1.17.1
player.sendPacket(new ClientboundRemoveEntitiesPacket(entities));
}
@@ -12,10 +12,10 @@ repositories {
dependencies {
implementation(projects.fabric)
minecraft("com.mojang:minecraft:1.20.3")
minecraft("com.mojang:minecraft:1.20.4")
mappings(loom.officialMojangMappings())
modImplementation("net.fabricmc:fabric-loader:0.14.17")
val fabricApiVersion = "0.90.4+1.20.3"
val fabricApiVersion = "0.91.1+1.20.4"
modImplementation(fabricApi.module("fabric-api-base", fabricApiVersion))
modImplementation(fabricApi.module("fabric-command-api-v2", fabricApiVersion))
}
@@ -1,4 +1,4 @@
package me.neznamy.tab.platforms.fabric.v1_20_3;
package me.neznamy.tab.platforms.fabric.v1_20_4;
import com.mojang.authlib.GameProfile;
import io.netty.channel.Channel;
@@ -1,4 +1,4 @@
package me.neznamy.tab.platforms.fabric.v1_20_3;
package me.neznamy.tab.platforms.fabric.v1_20_4;
import com.mojang.authlib.properties.Property;
import lombok.SneakyThrows;
@@ -36,7 +36,7 @@ public class FabricTAB implements VersionLoader {
@Override
public List<String> getSupportedVersions() {
return Collections.singletonList("1.20.3");
return Arrays.asList("1.20.3", "1.20.4");
}
@Override
+1 -3
View File
@@ -14,17 +14,15 @@ val platforms = setOf(
val fabrics = setOf(
rootProject.projects.fabric,
rootProject.projects.fabric.v1144,
rootProject.projects.fabric.v1152,
rootProject.projects.fabric.v1165,
rootProject.projects.fabric.v117,
rootProject.projects.fabric.v1171,
rootProject.projects.fabric.v1182,
rootProject.projects.fabric.v1192,
rootProject.projects.fabric.v1193,
rootProject.projects.fabric.v1201,
rootProject.projects.fabric.v1202,
rootProject.projects.fabric.v1203
rootProject.projects.fabric.v1204
).map { it.dependencyProject }
tasks {
+1 -3
View File
@@ -33,15 +33,13 @@ include(":bungeecord")
include(":sponge7")
include(":sponge8")
include(":fabric")
include(":fabric:v1_14_4")
include(":fabric:v1_15_2")
include(":fabric:v1_16_5")
include(":fabric:v1_17")
include(":fabric:v1_17_1")
include(":fabric:v1_18_2")
include(":fabric:v1_19_2")
include(":fabric:v1_19_3")
include(":fabric:v1_20_1")
include(":fabric:v1_20_2")
include(":fabric:v1_20_3")
include(":fabric:v1_20_4")
include(":jar")
@@ -13,6 +13,7 @@ public enum ProtocolVersion {
UNKNOWN_SERVER_VERSION ("Unknown"),
UNKNOWN_CLIENT_VERSION ("Unknown"),
PROXY ("Proxy"),
V1_20_4 (765),
V1_20_3 (765),
V1_20_2 (764),
V1_20_1 (763),
@@ -11,12 +11,15 @@ import org.jetbrains.annotations.NotNull;
public class MiniMessageFormat implements RGBFormatter {
@Override
public @NotNull String reformat(@NotNull String text) {
if (text.contains("<") && !text.contains(EnumChatFormat.COLOR_STRING)) {
try {
return LegacyComponentSerializer.legacySection().serialize(MiniMessage.miniMessage().deserialize(text));
} catch (Throwable ignored) {}
@NotNull
public String reformat(@NotNull String text) {
if (!text.contains("<")) return text; // User did not even attempt to use MiniMessage
String modified = text.replace(EnumChatFormat.WHITE.getFormat(), "<white>"); // Forced &f in scoreboard
if (modified.contains(EnumChatFormat.COLOR_STRING)) return text;
try {
return LegacyComponentSerializer.legacySection().serialize(MiniMessage.miniMessage().deserialize(modified));
} catch (Throwable ignored) {
return text;
}
return text;
}
}
@@ -175,7 +175,7 @@ public class ScoreboardImpl extends TabFeature implements me.neznamy.tab.api.sco
ScoreboardManagerImpl.OBJECTIVE_NAME,
refreshed.getProperty(titleProperty).updateAndGet(),
Scoreboard.HealthDisplay.INTEGER,
new IChatBaseComponent()
new IChatBaseComponent("")
);
}
@@ -211,14 +211,14 @@ public abstract class ScoreboardLine extends TabFeature implements Line {
}
/**
* Splits text using {@code "|"} symbol, where first part is text to display and
* Splits text using {@code "||"} string, where first part is text to display and
* second part is number format (optional)
*
* @param text
* Inputted text to categorize
*/
protected void initializeText(@NotNull String text) {
String[] split = text.split("\\|");
String[] split = text.split("\\|\\|");
this.text = split[0];
this.numberFormat = split.length >= 2 ? split[1] : "";
}
@@ -35,9 +35,7 @@ public class ViaVersionHook {
if (!installed) return TAB.getInstance().getServerVersion().getNetworkId();
int version = Via.getAPI().getPlayerVersion(player);
if (version == -1) {
TAB.getInstance().getPlatform().logWarn(new IChatBaseComponent("ViaVersion returned protocol version -1 for player " + playerName +
". Using server's version (" + TAB.getInstance().getServerVersion().getNetworkId() + " - " +
TAB.getInstance().getServerVersion().getFriendlyName() + ")"));
// Player got instantly disconnected with a packet error
return TAB.getInstance().getServerVersion().getNetworkId();
}
ProtocolVersion protocol = ProtocolVersion.fromNetworkId(version);
+6 -7
View File
@@ -114,16 +114,15 @@ scoreboard:
- "&7%date%"
- "%animation:MyAnimation1%"
- "&6Online:"
- "* &eOnline&7:|%online%"
- "* &eCurrent World&7:|%worldonline%"
- "* &eStaff&7:|%staffonline%"
- "* &eOnline&7:||%online%"
- "* &eCurrent World&7:||%worldonline%"
- "* &eStaff&7:||%staffonline%"
- ""
- "&6Personal Info:"
- "* &bRank&7:|%group%"
- "* &bPing&7:|%ping%&8ms"
- "* &bWorld&7:|%world%"
- "* &bRank&7:||%group%"
- "* &bPing&7:||%ping%&8ms"
- "* &bWorld&7:||%world%"
- "%animation:MyAnimation1%"
scoreboard:
title: "<#E0B11E>MyServer</#FF0000>"
lines: