diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index f869d20..b1bca69 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -13,16 +13,16 @@ jobs: runs-on: ubuntu-latest steps: - name: Checkout - uses: actions/checkout@v3.0.0 + uses: actions/checkout@v4.2.2 - name: Set up JDK - uses: actions/setup-java@v3.0.0 + uses: actions/setup-java@v4.7.0 with: - distribution: adopt - java-version: 17 + distribution: temurin + java-version: 25 - name: Build LimboFilter run: ./gradlew build - name: Upload LimboFilter - uses: actions/upload-artifact@v3.0.0 + uses: actions/upload-artifact@v4.6.2 with: name: LimboFilter path: "build/libs/limbofilter*.jar" diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 0676a79..c6e9830 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -9,16 +9,16 @@ jobs: runs-on: ubuntu-latest steps: - name: Checkout - uses: actions/checkout@v3.0.0 + uses: actions/checkout@v4.2.2 - name: Set up JDK - uses: actions/setup-java@v3.0.0 + uses: actions/setup-java@v4.7.0 with: - distribution: adopt - java-version: 17 + distribution: temurin + java-version: 25 - name: Build LimboFilter run: ./gradlew build - name: Upload LimboFilter - uses: actions/upload-artifact@v3.0.0 + uses: actions/upload-artifact@v4.6.2 with: name: LimboFilter path: "build/libs/limbofilter*.jar" diff --git a/HEADER.txt b/HEADER.txt index 1fde5b4..99a4f73 100644 --- a/HEADER.txt +++ b/HEADER.txt @@ -1,4 +1,4 @@ -Copyright (C) 2021 - 2023 Elytrium +Copyright (C) 2021 - 2025 Elytrium This program is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by diff --git a/VERSION b/VERSION index e9bc149..852ed67 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -1.1.14 +1.1.18 diff --git a/build.gradle b/build.gradle index e0430cc..7d0930b 100644 --- a/build.gradle +++ b/build.gradle @@ -3,21 +3,21 @@ plugins { id("java") id("checkstyle") - id("com.github.spotbugs").version("5.0.6") - id("org.cadixdev.licenser").version("0.6.1") - id("com.github.johnrengelman.shadow").version("7.1.2") + id("com.github.spotbugs").version("6.4.8") + id("net.minecraftforge.licenser").version("1.2.0") + id("com.gradleup.shadow").version("9.4.0") } setGroup("net.elytrium") -setVersion("1.1.14") +setVersion("1.1.19") compileJava { getOptions().setEncoding("UTF-8") } java { - setSourceCompatibility(JavaVersion.VERSION_17) - setTargetCompatibility(JavaVersion.VERSION_17) + setSourceCompatibility(JavaVersion.VERSION_21) + setTargetCompatibility(JavaVersion.VERSION_21) } repositories { @@ -29,11 +29,7 @@ repositories { } maven { setName("papermc-repo") - setUrl("https://papermc.io/repo/repository/maven-public/") - } - maven() { - setName("sonatype-snapshots-repo") - setUrl("https://s01.oss.sonatype.org/content/repositories/snapshots/") + setUrl("https://repo.papermc.io/repository/maven-public/") } } @@ -70,7 +66,6 @@ license { } checkstyle { - setToolVersion("10.1") setConfigFile(file("${this.getRootDir()}/config/checkstyle/checkstyle.xml")) setConfigProperties("configDirectory": "${this.getRootDir()}/config/checkstyle") @@ -107,16 +102,7 @@ sourceSets.main.getJava().srcDir( assemble.dependsOn(shadowJar) String getCurrentShortRevision() { - OutputStream outputStream = new ByteArrayOutputStream() - exec { - if (System.getProperty("os.name").toLowerCase().contains("win")) { - commandLine("cmd", "/c", "git rev-parse --short HEAD") - } else { - commandLine("bash", "-c", "git rev-parse --short HEAD") - } - - setStandardOutput(outputStream) - } - - return outputStream.toString().trim() + return System.getProperty("os.name").toLowerCase().contains("win") + ? ["cmd", "/c", "git rev-parse --short HEAD"].execute().text.trim() + : ["bash", "-c", "git rev-parse --short HEAD"].execute().text.trim() } diff --git a/config/checkstyle/checkstyle.xml b/config/checkstyle/checkstyle.xml index ebdad7f..d46c334 100644 --- a/config/checkstyle/checkstyle.xml +++ b/config/checkstyle/checkstyle.xml @@ -37,7 +37,7 @@ - + diff --git a/config/spotbugs/suppressions.xml b/config/spotbugs/suppressions.xml index eb21bfb..1e4e2e6 100644 --- a/config/spotbugs/suppressions.xml +++ b/config/spotbugs/suppressions.xml @@ -7,4 +7,7 @@ + + + diff --git a/gradle.properties b/gradle.properties index fee5d72..2a8d17d 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,5 +1,5 @@ -limboapiVersion=1.1.14 -velocityVersion=3.3.0-SNAPSHOT +limboapiVersion=1.1.27 +velocityVersion=3.5.0-SNAPSHOT nettyVersion=4.1.86.Final fastutilVersion=8.5.11 log4jVersion=2.19.0 diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index 00e33ed..221c4f9 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,5 +1,5 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-7.4.1-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-9.4.1-bin.zip zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists diff --git a/src/main/java/net/elytrium/limbofilter/LimboFilter.java b/src/main/java/net/elytrium/limbofilter/LimboFilter.java index 651c593..d671110 100644 --- a/src/main/java/net/elytrium/limbofilter/LimboFilter.java +++ b/src/main/java/net/elytrium/limbofilter/LimboFilter.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2021 - 2023 Elytrium + * Copyright (C) 2021 - 2025 Elytrium * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as published by @@ -30,7 +30,6 @@ import com.velocitypowered.api.proxy.ProxyServer; import com.velocitypowered.api.scheduler.ScheduledTask; import com.velocitypowered.proxy.console.VelocityConsole; -import edu.umd.cs.findbugs.annotations.SuppressFBWarnings; import java.io.File; import java.io.FileNotFoundException; import java.io.IOError; @@ -164,7 +163,6 @@ public void onProxyInitialization(ProxyInitializeEvent event) { Configurator.setLevel(consoleLogger.getName(), consoleLogger.getLevel()); } - @SuppressFBWarnings(value = "NP_NULL_ON_SOME_PATH", justification = "LEGACY_AMPERSAND can't be null in velocity.") public void reload() { Settings.IMP.reload(this.configFile, Settings.IMP.PREFIX); @@ -238,6 +236,23 @@ public void reload() { (float) captchaCoords.CAPTCHA_YAW, (float) captchaCoords.CAPTCHA_PITCH ); + // Make LimboAPI preload parent to captcha chunks to ensure that Sodium can properly render captcha. + if (Settings.IMP.MAIN.FRAMED_CAPTCHA.FRAMED_CAPTCHA_ENABLED) { + Settings.MAIN.FRAMED_CAPTCHA settings = Settings.IMP.MAIN.FRAMED_CAPTCHA; + for (int x = 0; x < settings.WIDTH; x++) { + this.filterWorld.getChunkOrNew(settings.COORDS.X + x, settings.COORDS.Z); + } + + for (int x = -1; x <= 1; x++) { + for (int z = -1; z <= 1; z++) { + this.filterWorld.getChunkOrNew( + (int) captchaCoords.CAPTCHA_X + (x * 16), + (int) captchaCoords.CAPTCHA_Z + (z * 16) + ); + } + } + } + if (Settings.IMP.MAIN.LOAD_WORLD) { try { Path path = this.dataDirectory.resolve(Settings.IMP.MAIN.WORLD_FILE_PATH); @@ -279,8 +294,12 @@ public void reload() { new PacketMapping(0x10, ProtocolVersion.MINECRAFT_1_19_4, false), new PacketMapping(0x12, ProtocolVersion.MINECRAFT_1_20_2, false), new PacketMapping(0x13, ProtocolVersion.MINECRAFT_1_20_3, false), + new PacketMapping(0x16, ProtocolVersion.MINECRAFT_1_20_5, false), + new PacketMapping(0x18, ProtocolVersion.MINECRAFT_1_21_2, false), + new PacketMapping(0x19, ProtocolVersion.MINECRAFT_1_21_6, false), + new PacketMapping(0x1A, ProtocolVersion.MINECRAFT_26_1, false), }) - .registerPacket(PacketDirection.CLIENTBOUND, SetEntityMetadata.class, SetEntityMetadata::new, new PacketMapping[]{ + .registerPacket(PacketDirection.CLIENTBOUND, SetEntityMetadata.class, null, new PacketMapping[]{ new PacketMapping(0x1C, ProtocolVersion.MINIMUM_VERSION, true), new PacketMapping(0x39, ProtocolVersion.MINECRAFT_1_9, true), new PacketMapping(0x3B, ProtocolVersion.MINECRAFT_1_12, true), @@ -294,8 +313,13 @@ public void reload() { new PacketMapping(0x52, ProtocolVersion.MINECRAFT_1_19_4, true), new PacketMapping(0x54, ProtocolVersion.MINECRAFT_1_20_2, true), new PacketMapping(0x56, ProtocolVersion.MINECRAFT_1_20_3, true), + new PacketMapping(0x58, ProtocolVersion.MINECRAFT_1_20_5, true), + new PacketMapping(0x5D, ProtocolVersion.MINECRAFT_1_21_2, true), + new PacketMapping(0x5C, ProtocolVersion.MINECRAFT_1_21_5, true), + new PacketMapping(0x61, ProtocolVersion.MINECRAFT_1_21_9, true), + new PacketMapping(0x63, ProtocolVersion.MINECRAFT_26_1, true), }) - .registerPacket(PacketDirection.CLIENTBOUND, SpawnEntity.class, SpawnEntity::new, new PacketMapping[]{ + .registerPacket(PacketDirection.CLIENTBOUND, SpawnEntity.class, null, new PacketMapping[]{ new PacketMapping(0x0E, ProtocolVersion.MINIMUM_VERSION, true), new PacketMapping(0x00, ProtocolVersion.MINECRAFT_1_9, true), new PacketMapping(0x01, ProtocolVersion.MINECRAFT_1_19_4, true), @@ -379,6 +403,10 @@ public boolean shouldCheck(Player player) { return false; } + if (player.getRemoteAddress().getPort() == 0 && !this.checkCpsLimit(Settings.IMP.MAIN.FILTER_AUTO_TOGGLE.GEYSER_BYPASS)) { + return false; + } + return this.shouldCheck(player.getUsername(), player.getRemoteAddress().getAddress()); } diff --git a/src/main/java/net/elytrium/limbofilter/Settings.java b/src/main/java/net/elytrium/limbofilter/Settings.java index 987d1bc..16306ab 100644 --- a/src/main/java/net/elytrium/limbofilter/Settings.java +++ b/src/main/java/net/elytrium/limbofilter/Settings.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2021 - 2023 Elytrium + * Copyright (C) 2021 - 2025 Elytrium * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as published by @@ -56,7 +56,7 @@ public static class MAIN { public boolean CHECK_CLIENT_SETTINGS = true; @Comment("Check if player's Minecraft client has a brand.") public boolean CHECK_CLIENT_BRAND = true; - @Comment("If player's Minecraft client brand (e.g. fabric or forge) is set here, then this player will be kicked.") + @Comment("If a player's Minecraft client brand (e.g., fabric or forge) is set here, then that player will be kicked.") public List BLOCKED_CLIENT_BRANDS = List.of("brand1", "brand2"); @Comment("Time in milliseconds, how frequently will the cache list with verified players be reset. Before that time, verified players can join the server without passing antibot checks.") public long PURGE_CACHE_MILLIS = 3600000; @@ -98,7 +98,7 @@ public static class MAIN { public boolean LOAD_WORLD = false; @Comment({ - "World file type:", + "World file types:", " SCHEMATIC (MCEdit .schematic, 1.12.2 and lower, not recommended)", " STRUCTURE (structure block .nbt, any Minecraft version is supported, but the latest one is recommended).", " WORLDEDIT_SCHEM (WorldEdit .schem, any Minecraft version is supported, but the latest one is recommended)." @@ -118,7 +118,13 @@ public static class MAIN { @Comment("Available: ADVENTURE, CREATIVE, SURVIVAL, SPECTATOR") public GameMode GAME_MODE = GameMode.ADVENTURE; - @Comment("Unit of time in seconds for the Auto Toggles the Statistics.") + @Comment({ + "Should we prevent the player from falling after passing the fall check, or after they join the game when the ONLY_CAPTCHA mode is enabled", + "This might be useful when using a world schema to allow players to walk in that world" + }) + public boolean DISABLE_FALLING_ON_CAPTCHA = true; + + @Comment("Unit of time in seconds for the Auto Toggles and Statistics.") public int UNIT_OF_TIME_CPS = 300; @Comment("Unit of time in seconds for the Auto Toggles and the Statistics.") @@ -170,6 +176,9 @@ public static class FILTER_AUTO_TOGGLE { }) public int ONLINE_MODE_BYPASS = 49; + @Comment("Geyser players will bypass all anti-bot checks.") + public int GEYSER_BYPASS = 0; + @Comment({ "Verify Online Mode connection before AntiBot.", "If connections per unit of time amount is bigger than the limit: online mode players will need to reconnect.", @@ -186,7 +195,7 @@ public static class FILTER_AUTO_TOGGLE { }) public int CHECK_STATE_TOGGLE = 0; - @Comment("The player will need to reconnect after passing AntiBot check.") + @Comment("The player will need to reconnect after passing the AntiBot check.") public int NEED_TO_RECONNECT = 129; @Comment("Picture in the MOTD Server Ping packet will be disabled.") @@ -251,7 +260,7 @@ public static class CAPTCHA_GENERATOR { public boolean NUMBER_SPELLING = false; @Comment({ "Set to true if you want to verify the number spelling configuration.", - "The results will be saved to the number_spelling.txt file." + "Results will be saved to the number_spelling.txt file." }) public boolean SAVE_NUMBER_SPELLING_OUTPUT = false; public boolean EACH_WORD_ON_SEPARATE_LINE = true; @@ -424,11 +433,11 @@ public static class STRINGS { public String CHECKING_SUBTITLE = "&aPlease wait.."; public String CHECKING_CAPTCHA_CHAT = "{PRFX} &aPlease, solve the captcha, you have &6{0} &aattempts."; - public String CHECKING_WRONG_CAPTCHA_CHAT = "{PRFX} &cYou entered the captcha incorrectly, you have &6{0} &cattempts left."; + public String CHECKING_WRONG_CAPTCHA_CHAT = "{PRFX} &cYou have entered the captcha incorrectly, you have &6{0} &cattempts left."; public String CHECKING_CAPTCHA_TITLE = "&aPlease solve the captcha."; public String CHECKING_CAPTCHA_SUBTITLE = "&aYou have &6{0} &aattempts."; - public String SUCCESSFUL_CRACKED = "{PRFX} &aSuccessfully passed Bot-Filter check."; + public String SUCCESSFUL_CRACKED = "{PRFX} &aSuccessfully passed the Bot-Filter check."; public String SUCCESSFUL_PREMIUM_KICK = "{PRFX}{NL}&aSuccessfully passed Bot-Filter check.{NL}&6Please, rejoin the server!"; public String CAPTCHA_FAILED_KICK = "{PRFX}{NL}&cYou've mistaken in captcha check.{NL}&6Please, rejoin the server."; @@ -436,14 +445,14 @@ public static class STRINGS { public String TIMES_UP = "{PRFX}{NL}&cYou have exceeded the maximum Bot-Filter check time.{NL}&6Please, rejoin the server."; public String STATS_FORMAT = "&c&lTotal Blocked: &6&l{0} &c&l| Connections: &6&l{1}s &c&l| Pings: &6&l{2}s &c&l| Total Connections: &6&l{3} &c&l| L7 Ping: &6&l{4} &c&l| L4 Ping: &6&l{5}"; - public String STATS_ENABLED = "{PRFX} &aNow you see statistics in your action bar."; - public String STATS_DISABLED = "{PRFX} &cYou're no longer see statistics in your action bar."; + public String STATS_ENABLED = "{PRFX} &aNow you may see statistics in your action bar."; + public String STATS_DISABLED = "{PRFX} &cYou can no longer see statistics in your action bar."; public String SEND_PLAYER_SUCCESSFUL = "{PRFX} Successfully sent {0} to the filter limbo."; - public String SEND_SERVER_SUCCESSFUL = "{PRFX} Successfully sent {0} players from {1} to the filter limbo."; + public String SEND_SERVER_SUCCESSFUL = "{PRFX} Successfully sent {0} players from {1} to filter limbo."; public String SEND_FAILED = "{PRFX} There is no registered servers or connected players named {0}."; - public String CAPTCHA_NOT_READY_YET = "{PRFX} Captcha is not ready yet. Try again in a few seconds"; + public String CAPTCHA_NOT_READY_YET = "{PRFX} The captcha is not ready yet. Try again in a few seconds."; } } } diff --git a/src/main/java/net/elytrium/limbofilter/cache/CachedPackets.java b/src/main/java/net/elytrium/limbofilter/cache/CachedPackets.java index 3d38ad6..20712b7 100644 --- a/src/main/java/net/elytrium/limbofilter/cache/CachedPackets.java +++ b/src/main/java/net/elytrium/limbofilter/cache/CachedPackets.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2021 - 2023 Elytrium + * Copyright (C) 2021 - 2025 Elytrium * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as published by @@ -21,11 +21,12 @@ import com.velocitypowered.api.network.ProtocolVersion; import com.velocitypowered.proxy.protocol.MinecraftPacket; import com.velocitypowered.proxy.protocol.ProtocolUtils; -import com.velocitypowered.proxy.protocol.packet.Disconnect; +import com.velocitypowered.proxy.protocol.StateRegistry; +import com.velocitypowered.proxy.protocol.packet.DisconnectPacket; import com.velocitypowered.proxy.protocol.packet.chat.ChatType; import com.velocitypowered.proxy.protocol.packet.chat.ComponentHolder; -import com.velocitypowered.proxy.protocol.packet.chat.SystemChat; -import com.velocitypowered.proxy.protocol.packet.chat.legacy.LegacyChat; +import com.velocitypowered.proxy.protocol.packet.chat.SystemChatPacket; +import com.velocitypowered.proxy.protocol.packet.chat.legacy.LegacyChatPacket; import com.velocitypowered.proxy.protocol.packet.title.GenericTitlePacket; import java.text.MessageFormat; import java.util.UUID; @@ -35,6 +36,7 @@ import net.elytrium.limboapi.api.material.Item; import net.elytrium.limboapi.api.material.VirtualItem; import net.elytrium.limboapi.api.protocol.PreparedPacket; +import net.elytrium.limboapi.api.protocol.item.ItemComponentMap; import net.elytrium.limboapi.api.protocol.packets.PacketFactory; import net.elytrium.limbofilter.LimboFilter; import net.elytrium.limbofilter.Settings; @@ -58,6 +60,7 @@ public class CachedPackets { private PreparedPacket kickProxyCheck; private PreparedPacket successfulBotFilterChat; private PreparedPacket successfulBotFilterDisconnect; + private PreparedPacket fallingCheckChunkUnload; private PreparedPacket noAbilities; private PreparedPacket[] experience; private PreparedPacket captchaNotReadyYet; @@ -97,6 +100,7 @@ public void createPackets(LimboFactory limboFactory, PacketFactory packetFactory this.successfulBotFilterDisconnect = this.createDisconnectPacket(limboFactory, strings.SUCCESSFUL_PREMIUM_KICK); + this.fallingCheckChunkUnload = this.createFallingCheckChunkUnloadPacket(limboFactory, packetFactory); this.noAbilities = this.createAbilitiesPacket(limboFactory, packetFactory); this.experience = this.createExpPackets(limboFactory, packetFactory); @@ -169,7 +173,12 @@ private PreparedPacket[] createCaptchaAttemptsPacket(LimboFactory limboFactory, this.createSetSlotPacketModern( packetFactory, limboFactory.getItem(Item.FILLED_MAP), 1, CompoundBinaryTag.builder().put("map", IntBinaryTag.intBinaryTag(0)).build() - ), ProtocolVersion.MINECRAFT_1_17 + ), ProtocolVersion.MINECRAFT_1_17, ProtocolVersion.MINECRAFT_1_20_3 + ).prepare( + this.createSetSlotPacketComponent( + packetFactory, limboFactory.getItem(Item.FILLED_MAP), 1, + limboFactory.createItemComponentMap().add(ProtocolVersion.MINECRAFT_1_20_5, "minecraft:map_id", 0) + ), ProtocolVersion.MINECRAFT_1_20_5 ); } packets[i] = packet.build(); @@ -190,7 +199,12 @@ private PreparedPacket[] createCaptchaAttemptsPacket(LimboFactory limboFactory, this.createSetSlotPacketModern( packetFactory, limboFactory.getItem(Item.FILLED_MAP), 1, CompoundBinaryTag.builder().put("map", IntBinaryTag.intBinaryTag(0)).build() - ), ProtocolVersion.MINECRAFT_1_17 + ), ProtocolVersion.MINECRAFT_1_17, ProtocolVersion.MINECRAFT_1_20_3 + ).prepare( + this.createSetSlotPacketComponent( + packetFactory, limboFactory.getItem(Item.FILLED_MAP), 1, + limboFactory.createItemComponentMap().add(ProtocolVersion.MINECRAFT_1_20_5, "minecraft:map_id", 0) + ), ProtocolVersion.MINECRAFT_1_20_5 ); } packets[Settings.IMP.MAIN.CAPTCHA_ATTEMPTS].build(); @@ -211,6 +225,7 @@ public void dispose() { this.singleDispose(this.kickProxyCheck); this.singleDispose(this.successfulBotFilterChat); this.singleDispose(this.successfulBotFilterDisconnect); + this.singleDispose(this.fallingCheckChunkUnload); this.singleDispose(this.noAbilities); this.singleDispose(this.experience); this.singleDispose(this.captchaNotReadyYet); @@ -294,6 +309,11 @@ private MinecraftPacket createUpdateViewPosition(PacketFactory factory, int x, i return (MinecraftPacket) factory.createUpdateViewPositionPacket(x >> 4, z >> 4); } + private PreparedPacket createFallingCheckChunkUnloadPacket(LimboFactory limboFactory, PacketFactory packetFactory) { + Settings.MAIN.FALLING_COORDS coords = Settings.IMP.MAIN.FALLING_COORDS; + return limboFactory.createPreparedPacket().prepare(packetFactory.createChunkUnloadPacket(coords.X >> 4, coords.Z >> 4), ProtocolVersion.MINECRAFT_1_21_2).build(); + } + private PreparedPacket createAbilitiesPacket(LimboFactory limboFactory, PacketFactory packetFactory) { return limboFactory.createPreparedPacket().prepare(packetFactory.createPlayerAbilitiesPacket((byte) 6, 0f, 0f)).build(); } @@ -301,11 +321,9 @@ private PreparedPacket createAbilitiesPacket(LimboFactory limboFactory, PacketFa private PreparedPacket[] createExpPackets(LimboFactory limboFactory, PacketFactory packetFactory) { int ticks = Settings.IMP.MAIN.FALLING_CHECK_TICKS; PreparedPacket[] packets = new PreparedPacket[ticks]; - float expInterval = 0.01F; + final int ticksM1 = ticks - 1; for (int i = 0; i < ticks; ++i) { - int percentage = i * 100 / ticks; - packets[i] = - limboFactory.createPreparedPacket().prepare(packetFactory.createSetExperiencePacket(percentage * expInterval, percentage, 0)).build(); + packets[i] = limboFactory.createPreparedPacket().prepare(packetFactory.createSetExperiencePacket((float) i / ticksM1, (i * 100) / ticksM1, 0)).build(); } return packets; @@ -319,25 +337,30 @@ private MinecraftPacket createSetSlotPacketModern(PacketFactory packetFactory, V return (MinecraftPacket) packetFactory.createSetSlotPacket(0, Settings.IMP.MAIN.CAPTCHA_LEFT_HAND ? 45 : 36, item, count, 0, nbt); } + private MinecraftPacket createSetSlotPacketComponent(PacketFactory packetFactory, VirtualItem item, int count, ItemComponentMap map) { + return (MinecraftPacket) packetFactory.createSetSlotPacket(0, Settings.IMP.MAIN.CAPTCHA_LEFT_HAND ? 45 : 36, item, count, 0, map); + } + public void createChatPacket(PreparedPacket packet, String text) { packet - .prepare(new LegacyChat( + .prepare(new LegacyChatPacket( ProtocolUtils.getJsonChatSerializer(ProtocolVersion.MINIMUM_VERSION).serialize( LimboFilter.getSerializer().deserialize(text) - ), LegacyChat.CHAT_TYPE, null + ), LegacyChatPacket.CHAT_TYPE, null ), ProtocolVersion.MINIMUM_VERSION, ProtocolVersion.MINECRAFT_1_15_2) - .prepare(new LegacyChat( + .prepare(new LegacyChatPacket( ProtocolUtils.getJsonChatSerializer(ProtocolVersion.MINECRAFT_1_16).serialize( LimboFilter.getSerializer().deserialize(text) - ), LegacyChat.CHAT_TYPE, null + ), LegacyChatPacket.CHAT_TYPE, null ), ProtocolVersion.MINECRAFT_1_16, ProtocolVersion.MINECRAFT_1_18_2) - .prepare(version -> new SystemChat( + .prepare(version -> new SystemChatPacket( new ComponentHolder(version, LimboFilter.getSerializer().deserialize(text)), ChatType.SYSTEM ), ProtocolVersion.MINECRAFT_1_19); } private PreparedPacket createDisconnectPacket(LimboFactory factory, String message) { - return factory.createPreparedPacket().prepare(version -> Disconnect.create(LimboFilter.getSerializer().deserialize(message), version, false)).build(); + return factory.createPreparedPacket().prepare(version -> + DisconnectPacket.create(LimboFilter.getSerializer().deserialize(message), version, StateRegistry.PLAY)).build(); } public void createTitlePacket(PreparedPacket preparedPacket, String title, String subtitle) { @@ -402,6 +425,10 @@ public PreparedPacket getSuccessfulBotFilterDisconnect() { return this.successfulBotFilterDisconnect; } + public PreparedPacket getFallingCheckChunkUnload() { + return this.fallingCheckChunkUnload; + } + public PreparedPacket getNoAbilities() { return this.noAbilities; } diff --git a/src/main/java/net/elytrium/limbofilter/cache/captcha/CachedCaptcha.java b/src/main/java/net/elytrium/limbofilter/cache/captcha/CachedCaptcha.java index 7b48f40..59663d6 100644 --- a/src/main/java/net/elytrium/limbofilter/cache/captcha/CachedCaptcha.java +++ b/src/main/java/net/elytrium/limbofilter/cache/captcha/CachedCaptcha.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2021 - 2023 Elytrium + * Copyright (C) 2021 - 2025 Elytrium * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as published by diff --git a/src/main/java/net/elytrium/limbofilter/captcha/CaptchaGenerator.java b/src/main/java/net/elytrium/limbofilter/captcha/CaptchaGenerator.java index bfbdfd8..21d1edc 100644 --- a/src/main/java/net/elytrium/limbofilter/captcha/CaptchaGenerator.java +++ b/src/main/java/net/elytrium/limbofilter/captcha/CaptchaGenerator.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2021 - 2023 Elytrium + * Copyright (C) 2021 - 2025 Elytrium * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as published by diff --git a/src/main/java/net/elytrium/limbofilter/captcha/CaptchaHolder.java b/src/main/java/net/elytrium/limbofilter/captcha/CaptchaHolder.java index 8ce143d..645f26c 100644 --- a/src/main/java/net/elytrium/limbofilter/captcha/CaptchaHolder.java +++ b/src/main/java/net/elytrium/limbofilter/captcha/CaptchaHolder.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2021 - 2023 Elytrium + * Copyright (C) 2021 - 2025 Elytrium * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as published by diff --git a/src/main/java/net/elytrium/limbofilter/captcha/map/CraftMapCanvas.java b/src/main/java/net/elytrium/limbofilter/captcha/map/CraftMapCanvas.java index 6a4201e..71921d4 100644 --- a/src/main/java/net/elytrium/limbofilter/captcha/map/CraftMapCanvas.java +++ b/src/main/java/net/elytrium/limbofilter/captcha/map/CraftMapCanvas.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2021 - 2023 Elytrium + * Copyright (C) 2021 - 2025 Elytrium * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as published by diff --git a/src/main/java/net/elytrium/limbofilter/captcha/painter/CaptchaEffect.java b/src/main/java/net/elytrium/limbofilter/captcha/painter/CaptchaEffect.java index 900e4bc..cd06985 100644 --- a/src/main/java/net/elytrium/limbofilter/captcha/painter/CaptchaEffect.java +++ b/src/main/java/net/elytrium/limbofilter/captcha/painter/CaptchaEffect.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2021 - 2023 Elytrium + * Copyright (C) 2021 - 2025 Elytrium * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as published by diff --git a/src/main/java/net/elytrium/limbofilter/captcha/painter/CaptchaPainter.java b/src/main/java/net/elytrium/limbofilter/captcha/painter/CaptchaPainter.java index f2175ca..7608950 100644 --- a/src/main/java/net/elytrium/limbofilter/captcha/painter/CaptchaPainter.java +++ b/src/main/java/net/elytrium/limbofilter/captcha/painter/CaptchaPainter.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2021 - 2023 Elytrium + * Copyright (C) 2021 - 2025 Elytrium * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as published by diff --git a/src/main/java/net/elytrium/limbofilter/captcha/painter/OutlineEffect.java b/src/main/java/net/elytrium/limbofilter/captcha/painter/OutlineEffect.java index 631de97..e151e5d 100644 --- a/src/main/java/net/elytrium/limbofilter/captcha/painter/OutlineEffect.java +++ b/src/main/java/net/elytrium/limbofilter/captcha/painter/OutlineEffect.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2021 - 2023 Elytrium + * Copyright (C) 2021 - 2025 Elytrium * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as published by diff --git a/src/main/java/net/elytrium/limbofilter/captcha/painter/RenderedFont.java b/src/main/java/net/elytrium/limbofilter/captcha/painter/RenderedFont.java index 8c600d1..523e561 100644 --- a/src/main/java/net/elytrium/limbofilter/captcha/painter/RenderedFont.java +++ b/src/main/java/net/elytrium/limbofilter/captcha/painter/RenderedFont.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2021 - 2023 Elytrium + * Copyright (C) 2021 - 2025 Elytrium * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as published by diff --git a/src/main/java/net/elytrium/limbofilter/captcha/painter/RippleEffect.java b/src/main/java/net/elytrium/limbofilter/captcha/painter/RippleEffect.java index 9f8b736..bf8fe4c 100644 --- a/src/main/java/net/elytrium/limbofilter/captcha/painter/RippleEffect.java +++ b/src/main/java/net/elytrium/limbofilter/captcha/painter/RippleEffect.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2021 - 2023 Elytrium + * Copyright (C) 2021 - 2025 Elytrium * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as published by diff --git a/src/main/java/net/elytrium/limbofilter/commands/CommandPermissionState.java b/src/main/java/net/elytrium/limbofilter/commands/CommandPermissionState.java index fe777c4..338c7ed 100644 --- a/src/main/java/net/elytrium/limbofilter/commands/CommandPermissionState.java +++ b/src/main/java/net/elytrium/limbofilter/commands/CommandPermissionState.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2021 - 2023 Elytrium + * Copyright (C) 2021 - 2025 Elytrium * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as published by diff --git a/src/main/java/net/elytrium/limbofilter/commands/LimboFilterCommand.java b/src/main/java/net/elytrium/limbofilter/commands/LimboFilterCommand.java index f77258c..1c693a5 100644 --- a/src/main/java/net/elytrium/limbofilter/commands/LimboFilterCommand.java +++ b/src/main/java/net/elytrium/limbofilter/commands/LimboFilterCommand.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2021 - 2023 Elytrium + * Copyright (C) 2021 - 2025 Elytrium * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as published by diff --git a/src/main/java/net/elytrium/limbofilter/commands/SendFilterCommand.java b/src/main/java/net/elytrium/limbofilter/commands/SendFilterCommand.java index 4fa4e17..c1ad304 100644 --- a/src/main/java/net/elytrium/limbofilter/commands/SendFilterCommand.java +++ b/src/main/java/net/elytrium/limbofilter/commands/SendFilterCommand.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2021 - 2023 Elytrium + * Copyright (C) 2021 - 2025 Elytrium * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as published by diff --git a/src/main/java/net/elytrium/limbofilter/handler/BotFilterSessionHandler.java b/src/main/java/net/elytrium/limbofilter/handler/BotFilterSessionHandler.java index 627c450..917af52 100644 --- a/src/main/java/net/elytrium/limbofilter/handler/BotFilterSessionHandler.java +++ b/src/main/java/net/elytrium/limbofilter/handler/BotFilterSessionHandler.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2021 - 2023 Elytrium + * Copyright (C) 2021 - 2025 Elytrium * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as published by @@ -19,8 +19,8 @@ import com.velocitypowered.api.network.ProtocolVersion; import com.velocitypowered.api.proxy.Player; -import com.velocitypowered.proxy.protocol.packet.ClientSettings; -import com.velocitypowered.proxy.protocol.packet.PluginMessage; +import com.velocitypowered.proxy.protocol.packet.ClientSettingsPacket; +import com.velocitypowered.proxy.protocol.packet.PluginMessagePacket; import com.velocitypowered.proxy.protocol.util.PluginMessageUtil; import java.util.HashMap; import java.util.Map; @@ -191,9 +191,9 @@ public void onMove(double x, double y, double z) { this.fallingCheckFailed("Non-valid X, Z or Velocity"); return; } - PreparedPacket expBuf = this.plugin.getPackets().getExperience(this.ticks); - if (expBuf != null) { - this.player.writePacketAndFlush(expBuf); + PreparedPacket experience = this.plugin.getPackets().getExperience(this.ticks); + if (experience != null) { + this.player.writePacketAndFlush(experience); } ++this.ticks; @@ -272,8 +272,8 @@ private boolean equalsCaptchaAnswer(String message) { @Override public void onGeneric(Object packet) { - if (packet instanceof PluginMessage) { - PluginMessage pluginMessage = (PluginMessage) packet; + if (packet instanceof PluginMessagePacket) { + PluginMessagePacket pluginMessage = (PluginMessagePacket) packet; if (PluginMessageUtil.isMcBrand(pluginMessage) && !this.checkedByBrand) { String brand = PluginMessageUtil.readBrandMessage(pluginMessage.content()); LimboFilter.getLogger().info("{} has client brand {}", this.proxyPlayer, brand); @@ -281,7 +281,7 @@ public void onGeneric(Object packet) { this.checkedByBrand = true; } } - } else if (packet instanceof ClientSettings) { + } else if (packet instanceof ClientSettingsPacket) { if (Settings.IMP.MAIN.CHECK_CLIENT_SETTINGS && !this.checkedBySettings) { this.checkedBySettings = true; } @@ -366,9 +366,15 @@ private boolean checkPing() { } private void changeStateToCaptcha() { + if (this.state != CheckState.ONLY_CAPTCHA && this.version.noLessThan(ProtocolVersion.MINECRAFT_1_21_2)) { + this.player.writePacket(this.plugin.getPackets().getFallingCheckChunkUnload()); + } + this.state = CheckState.ONLY_CAPTCHA; this.server.respawnPlayer(this.proxyPlayer); - this.player.writePacketAndFlush(this.plugin.getPackets().getNoAbilities()); + if (Settings.IMP.MAIN.DISABLE_FALLING_ON_CAPTCHA) { + this.player.writePacketAndFlush(this.plugin.getPackets().getNoAbilities()); + } this.waitingTeleportId = this.validTeleportId; if (this.captchaAnswer == null) { diff --git a/src/main/java/net/elytrium/limbofilter/listener/FilterListener.java b/src/main/java/net/elytrium/limbofilter/listener/FilterListener.java index 8296e73..bc63279 100644 --- a/src/main/java/net/elytrium/limbofilter/listener/FilterListener.java +++ b/src/main/java/net/elytrium/limbofilter/listener/FilterListener.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2021 - 2023 Elytrium + * Copyright (C) 2021 - 2025 Elytrium * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as published by diff --git a/src/main/java/net/elytrium/limbofilter/listener/TcpListener.java b/src/main/java/net/elytrium/limbofilter/listener/TcpListener.java index cd0c832..dedc715 100644 --- a/src/main/java/net/elytrium/limbofilter/listener/TcpListener.java +++ b/src/main/java/net/elytrium/limbofilter/listener/TcpListener.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2021 - 2023 Elytrium + * Copyright (C) 2021 - 2025 Elytrium * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as published by diff --git a/src/main/java/net/elytrium/limbofilter/protocol/data/EntityMetadata.java b/src/main/java/net/elytrium/limbofilter/protocol/data/EntityMetadata.java index 16b24f6..66fead2 100644 --- a/src/main/java/net/elytrium/limbofilter/protocol/data/EntityMetadata.java +++ b/src/main/java/net/elytrium/limbofilter/protocol/data/EntityMetadata.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2021 - 2023 Elytrium + * Copyright (C) 2021 - 2025 Elytrium * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as published by @@ -22,6 +22,7 @@ import io.netty.buffer.ByteBuf; import java.util.Map; import net.elytrium.limboapi.api.material.VirtualItem; +import net.elytrium.limboapi.api.protocol.item.ItemComponentMap; import net.kyori.adventure.nbt.CompoundBinaryTag; public class EntityMetadata { @@ -40,25 +41,52 @@ public static class SlotEntry implements Entry { private final int count; private final int data; private final CompoundBinaryTag nbt; + private final ItemComponentMap map; - public SlotEntry(boolean present, VirtualItem item, int count, int data, CompoundBinaryTag nbt) { + public SlotEntry(boolean present, VirtualItem item, int count, int data, CompoundBinaryTag nbt, ItemComponentMap map) { this.present = present; this.item = item; this.count = count; this.data = data; this.nbt = nbt; + this.map = map; } - public SlotEntry(VirtualItem item, int count, int data, CompoundBinaryTag nbt) { - this(true, item, count, data, nbt); + public SlotEntry(VirtualItem item, int count, int data, CompoundBinaryTag nbt, ItemComponentMap map) { + this(true, item, count, data, nbt, map); } public SlotEntry() { - this(false, null, 0, 0, null); + this(false, null, 0, 0, null, null); } @Override public void encode(ByteBuf buf, ProtocolVersion protocolVersion) { + if (protocolVersion.compareTo(ProtocolVersion.MINECRAFT_1_20_5) >= 0) { + this.encodeModern(buf, protocolVersion); + } else { + this.encodeLegacy(buf, protocolVersion); + } + } + + public void encodeModern(ByteBuf buf, ProtocolVersion protocolVersion) { + int id = this.item.getID(protocolVersion); + if (id == 0) { + ProtocolUtils.writeVarInt(buf, 0); + } else { + ProtocolUtils.writeVarInt(buf, this.count); + ProtocolUtils.writeVarInt(buf, id); + + if (this.map != null) { + this.map.write(protocolVersion, buf); + } else { + ProtocolUtils.writeVarInt(buf, 0); + ProtocolUtils.writeVarInt(buf, 0); + } + } + } + + public void encodeLegacy(ByteBuf buf, ProtocolVersion protocolVersion) { if (protocolVersion.compareTo(ProtocolVersion.MINECRAFT_1_13_2) >= 0) { buf.writeBoolean(this.present); } diff --git a/src/main/java/net/elytrium/limbofilter/protocol/data/ItemFrame.java b/src/main/java/net/elytrium/limbofilter/protocol/data/ItemFrame.java index 1bfc4c9..9cd0fb8 100644 --- a/src/main/java/net/elytrium/limbofilter/protocol/data/ItemFrame.java +++ b/src/main/java/net/elytrium/limbofilter/protocol/data/ItemFrame.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2021 - 2023 Elytrium + * Copyright (C) 2021 - 2025 Elytrium * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as published by @@ -43,8 +43,20 @@ public static int getID(ProtocolVersion protocolVersion) { return 46; } else if (protocolVersion.compareTo(ProtocolVersion.MINECRAFT_1_20_2) <= 0) { return 56; - } else { + } else if (protocolVersion.compareTo(ProtocolVersion.MINECRAFT_1_20_3) <= 0) { return 57; + } else if (protocolVersion.compareTo(ProtocolVersion.MINECRAFT_1_21) <= 0) { + return 60; + } else if (protocolVersion.compareTo(ProtocolVersion.MINECRAFT_1_21_2) <= 0) { + return 71; + } else if (protocolVersion.compareTo(ProtocolVersion.MINECRAFT_1_21_5) <= 0) { + return 70; + } else if (protocolVersion.compareTo(ProtocolVersion.MINECRAFT_1_21_7) <= 0) { + return 71; + } else if (protocolVersion.compareTo(ProtocolVersion.MINECRAFT_1_21_9) <= 0) { + return 72; + } else { + return 73; } } @@ -59,20 +71,23 @@ public static byte getMetadataIndex(ProtocolVersion protocolVersion) { return 6; } else if (protocolVersion.compareTo(ProtocolVersion.MINECRAFT_1_16_4) <= 0) { return 7; - } else { + } else if (protocolVersion.compareTo(ProtocolVersion.MINECRAFT_1_21_5) <= 0) { return 8; + } else { + return 9; } } public static EntityMetadata createMapMetadata(LimboFactory limboFactory, ProtocolVersion protocolVersion, int mapId) { if (protocolVersion.compareTo(ProtocolVersion.MINECRAFT_1_12_2) <= 0) { return new EntityMetadata(Map.of( - getMetadataIndex(protocolVersion), new EntityMetadata.SlotEntry(limboFactory.getItem(Item.FILLED_MAP), 1, mapId, null) + getMetadataIndex(protocolVersion), new EntityMetadata.SlotEntry(limboFactory.getItem(Item.FILLED_MAP), 1, mapId, null, null) )); } else { return new EntityMetadata(Map.of( getMetadataIndex(protocolVersion), new EntityMetadata.SlotEntry(limboFactory.getItem(Item.FILLED_MAP), 1, 0, - CompoundBinaryTag.builder().put("map", IntBinaryTag.intBinaryTag(mapId)).build()) + CompoundBinaryTag.builder().put("map", IntBinaryTag.intBinaryTag(mapId)).build(), + limboFactory.createItemComponentMap().add(ProtocolVersion.MINECRAFT_1_20_5, "minecraft:map_id", mapId)) )); } } diff --git a/src/main/java/net/elytrium/limbofilter/protocol/data/PackedVector.java b/src/main/java/net/elytrium/limbofilter/protocol/data/PackedVector.java new file mode 100644 index 0000000..c44029c --- /dev/null +++ b/src/main/java/net/elytrium/limbofilter/protocol/data/PackedVector.java @@ -0,0 +1,85 @@ +/* + * Copyright (C) 2021 - 2025 Elytrium + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +package net.elytrium.limbofilter.protocol.data; + +import com.velocitypowered.proxy.protocol.ProtocolUtils; +import io.netty.buffer.ByteBuf; + +public record PackedVector(double x, double y, double z) { + + public static PackedVector read(ByteBuf buffer) { + int first = buffer.readUnsignedByte(); + if (first == 0) { + return new PackedVector(0, 0, 0); + } else { + int second = buffer.readUnsignedByte(); + long third = buffer.readUnsignedInt(); + long result = third << 16 | (long) (second << 8) | (long) first; + long multiplier = first & 3; + if ((first & 4) == 4) { + multiplier |= ((long) ProtocolUtils.readVarInt(buffer) & 4094967295L) << 2L; + } + + return new PackedVector(unpack(result >> 3) * (double) multiplier, + unpack(result >> 18) * (double) multiplier, + unpack(result >> 33) * (double) multiplier); + } + } + + public static void write(ByteBuf buffer, double x, double y, double z) { + double sx = sanitize(x); + double sy = sanitize(y); + double sz = sanitize(z); + double maxValue = Math.max(Math.abs(sx), Math.max(Math.abs(sy), Math.abs(sz))); + if (maxValue < 3.051944088384301E-5) { + buffer.writeByte(0); + return; + } + + long result = (long) maxValue; + long max = maxValue > (double) result ? result + 1L : result; + + boolean continuation = (max & 3) != max; + long px = pack(sx / (double) max) << 3; + long py = pack(sy / (double) max) << 18; + long pz = pack(sz / (double) max) << 33; + long packed = (continuation ? max & 3 | 4 : max) | px | py | pz; + buffer.writeByte((byte) ((int) packed)); + buffer.writeByte((byte) ((int) (packed >> 8))); + buffer.writeInt((int) (packed >> 16)); + if (continuation) { + ProtocolUtils.writeVarInt(buffer, (int) (max >> 2)); + } + } + + private static long pack(double value) { + return Math.round((value * 0.5 + 0.5) * 32766.0); + } + + private static double unpack(long value) { + return Math.min((double) (value & (long) 32767), 32766.0) * 2.0 / 32766.0 - 1.0; + } + + private static double sanitize(double value) { + if (Double.isNaN(value)) { + return 0.0; + } else { + return value < -1.7179869183E10 ? -1.7179869183E10 : Math.min(value, 1.7179869183E10); + } + } +} diff --git a/src/main/java/net/elytrium/limbofilter/protocol/packets/Interact.java b/src/main/java/net/elytrium/limbofilter/protocol/packets/Interact.java index f57e1dd..c29b71d 100644 --- a/src/main/java/net/elytrium/limbofilter/protocol/packets/Interact.java +++ b/src/main/java/net/elytrium/limbofilter/protocol/packets/Interact.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2021 - 2023 Elytrium + * Copyright (C) 2021 - 2025 Elytrium * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as published by @@ -22,6 +22,7 @@ import com.velocitypowered.proxy.protocol.MinecraftPacket; import com.velocitypowered.proxy.protocol.ProtocolUtils; import io.netty.buffer.ByteBuf; +import net.elytrium.limbofilter.protocol.data.PackedVector; public class Interact implements MinecraftPacket { @@ -35,7 +36,15 @@ public class Interact implements MinecraftPacket { @Override public void decode(ByteBuf buf, ProtocolUtils.Direction direction, ProtocolVersion protocolVersion) { - if (protocolVersion.compareTo(ProtocolVersion.MINECRAFT_1_7_6) > 0) { + if (protocolVersion.compareTo(ProtocolVersion.MINECRAFT_26_1) >= 0) { + this.entityId = ProtocolUtils.readVarInt(buf); + this.hand = ProtocolUtils.readVarInt(buf); + PackedVector target = PackedVector.read(buf); + this.targetX = (float) target.x(); + this.targetY = (float) target.y(); + this.targetZ = (float) target.z(); + this.sneaking = buf.readBoolean(); + } else if (protocolVersion.compareTo(ProtocolVersion.MINECRAFT_1_7_6) > 0) { this.entityId = ProtocolUtils.readVarInt(buf); this.type = ProtocolUtils.readVarInt(buf); if (this.type == 2) { diff --git a/src/main/java/net/elytrium/limbofilter/protocol/packets/SetEntityMetadata.java b/src/main/java/net/elytrium/limbofilter/protocol/packets/SetEntityMetadata.java index 6bef892..75fd1bb 100644 --- a/src/main/java/net/elytrium/limbofilter/protocol/packets/SetEntityMetadata.java +++ b/src/main/java/net/elytrium/limbofilter/protocol/packets/SetEntityMetadata.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2021 - 2023 Elytrium + * Copyright (C) 2021 - 2025 Elytrium * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as published by @@ -39,10 +39,6 @@ public SetEntityMetadata(int entityId, EntityMetadata metadata) { this(entityId, protocolVersion -> metadata); } - public SetEntityMetadata() { - throw new IllegalStateException(); - } - @Override public void decode(ByteBuf buf, ProtocolUtils.Direction direction, ProtocolVersion protocolVersion) { throw new IllegalStateException(); diff --git a/src/main/java/net/elytrium/limbofilter/protocol/packets/SpawnEntity.java b/src/main/java/net/elytrium/limbofilter/protocol/packets/SpawnEntity.java index 0f95b77..378bdac 100644 --- a/src/main/java/net/elytrium/limbofilter/protocol/packets/SpawnEntity.java +++ b/src/main/java/net/elytrium/limbofilter/protocol/packets/SpawnEntity.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2021 - 2023 Elytrium + * Copyright (C) 2021 - 2025 Elytrium * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as published by @@ -24,6 +24,7 @@ import io.netty.buffer.ByteBuf; import java.util.UUID; import java.util.function.Function; +import net.elytrium.limbofilter.protocol.data.PackedVector; public class SpawnEntity implements MinecraftPacket { @@ -58,10 +59,6 @@ public SpawnEntity(int id, UUID uuid, Function type, d this.velocityZ = velocityZ; } - public SpawnEntity() { - throw new IllegalStateException(); - } - @Override public void decode(ByteBuf buf, ProtocolUtils.Direction direction, ProtocolVersion protocolVersion) { throw new IllegalStateException(); @@ -80,6 +77,10 @@ public void encode(ByteBuf buf, ProtocolUtils.Direction direction, ProtocolVersi buf.writeDouble(this.positionX); buf.writeDouble(this.positionY); buf.writeDouble(this.positionZ); + + if (protocolVersion.noLessThan(ProtocolVersion.MINECRAFT_1_21_9)) { + PackedVector.write(buf, this.velocityX, this.velocityY, this.velocityZ); + } } else { buf.writeByte(this.type.apply(protocolVersion)); buf.writeInt((int) (this.positionX * 32.0)); @@ -94,9 +95,12 @@ public void encode(ByteBuf buf, ProtocolUtils.Direction direction, ProtocolVersi } else { buf.writeInt(this.data); } - buf.writeShort((int) (this.velocityX * 8000.0F)); - buf.writeShort((int) (this.velocityY * 8000.0F)); - buf.writeShort((int) (this.velocityZ * 8000.0F)); + + if (protocolVersion.lessThan(ProtocolVersion.MINECRAFT_1_21_9)) { + buf.writeShort((int) (this.velocityX * 8000.0F)); + buf.writeShort((int) (this.velocityY * 8000.0F)); + buf.writeShort((int) (this.velocityZ * 8000.0F)); + } } @Override diff --git a/src/main/java/net/elytrium/limbofilter/stats/Statistics.java b/src/main/java/net/elytrium/limbofilter/stats/Statistics.java index 0090368..475012f 100644 --- a/src/main/java/net/elytrium/limbofilter/stats/Statistics.java +++ b/src/main/java/net/elytrium/limbofilter/stats/Statistics.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2021 - 2023 Elytrium + * Copyright (C) 2021 - 2025 Elytrium * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as published by diff --git a/src/main/templates/net/elytrium/limbofilter/BuildConstants.java b/src/main/templates/net/elytrium/limbofilter/BuildConstants.java index f86eaf6..023e80d 100644 --- a/src/main/templates/net/elytrium/limbofilter/BuildConstants.java +++ b/src/main/templates/net/elytrium/limbofilter/BuildConstants.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2021 - 2023 Elytrium + * Copyright (C) 2021 - 2025 Elytrium * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as published by