diff --git a/SpigotCore_Main/build.gradle b/SpigotCore_Main/build.gradle index fe306ca..4122646 100644 --- a/SpigotCore_Main/build.gradle +++ b/SpigotCore_Main/build.gradle @@ -47,6 +47,7 @@ dependencies { compileOnly 'io.netty:netty-all:4.1.68.Final' compileOnly 'com.mojang:authlib:1.5.25' compileOnly 'mysql:mysql-connector-java:5.1.49' + compileOnly 'com.viaversion:viaversion-api:4.3.1' compileOnly files("${project.rootDir}/lib/WorldEdit-1.12.jar") implementation 'net.wesjd:anvilgui:1.5.3-SNAPSHOT' diff --git a/SpigotCore_Main/src/com/comphenix/tinyprotocol/TinyProtocol.java b/SpigotCore_Main/src/com/comphenix/tinyprotocol/TinyProtocol.java index 6951a9a..82a4afb 100644 --- a/SpigotCore_Main/src/com/comphenix/tinyprotocol/TinyProtocol.java +++ b/SpigotCore_Main/src/com/comphenix/tinyprotocol/TinyProtocol.java @@ -20,6 +20,7 @@ import org.bukkit.scheduler.BukkitRunnable; import java.util.*; import java.util.concurrent.atomic.AtomicInteger; +import java.util.function.BiFunction; import java.util.logging.Level; /** @@ -71,7 +72,12 @@ public class TinyProtocol { private volatile boolean closed; private final Plugin plugin; + private final Map, List>> packetFilters = new HashMap<>(); + + @Deprecated private PacketFilter inFilter = (player, channel, packet) -> packet; + + @Deprecated private PacketFilter outFilter = (player, channel, packet) -> packet; public static final TinyProtocol instance = new TinyProtocol(Core.getInstance()); @@ -245,18 +251,41 @@ public class TinyProtocol { } } + public void addFilter(Class packetType, BiFunction filter) { + packetFilters.computeIfAbsent(packetType, c -> new ArrayList<>(1)).add(filter); + } + + public void removeFilter(Class packetType, BiFunction filter) { + packetFilters.getOrDefault(packetType, Collections.emptyList()).remove(filter); + } + public Object onPacketOutAsync(Player receiver, Channel channel, Object packet) { - return outFilter.onPacket(receiver, channel, packet); + return filterPacket(outFilter, receiver, channel, packet); } public Object onPacketInAsync(Player sender, Channel channel, Object packet) { - return inFilter.onPacket(sender, channel, packet); + return filterPacket(inFilter, sender, channel, packet); } + private Object filterPacket(PacketFilter handler, Player player, Channel channel, Object packet) { + List> filters = packetFilters.getOrDefault(packet.getClass(), Collections.emptyList()); + + for(BiFunction filter : filters) { + packet = filter.apply(player, packet); + + if(packet == null) + return packet; + } + + return handler.onPacket(player, channel, packet); + } + + @Deprecated public void setInFilter(PacketFilter filter) { inFilter = filter; } + @Deprecated public void setOutFilter(PacketFilter filter) { outFilter = filter; } @@ -363,6 +392,7 @@ public class TinyProtocol { } } + @Deprecated public interface PacketFilter { Object onPacket(Player player, Channel channel, Object packet); } diff --git a/SpigotCore_Main/src/de/steamwar/core/Core.java b/SpigotCore_Main/src/de/steamwar/core/Core.java index d759b3d..ab7da7a 100644 --- a/SpigotCore_Main/src/de/steamwar/core/Core.java +++ b/SpigotCore_Main/src/de/steamwar/core/Core.java @@ -26,6 +26,7 @@ import de.steamwar.command.TabCompletionCache; import de.steamwar.command.TypeMapper; import de.steamwar.core.authlib.AuthlibInjector; import de.steamwar.core.events.ChattingEvent; +import de.steamwar.core.events.PartialChunkFixer; import de.steamwar.core.events.PlayerJoinedEvent; import de.steamwar.core.events.WorldLoadEvent; import de.steamwar.message.Message; @@ -127,6 +128,10 @@ public class Core extends JavaPlugin{ if(Core.getVersion() < 19) AuthlibInjector.inject(); TinyProtocol.init(); + + if(Core.getVersion() < 17 && Bukkit.getPluginManager().getPlugin("ViaVersion") != null) + new PartialChunkFixer(); + try { getLogger().log(Level.INFO, "Running on: " + new BufferedReader(new InputStreamReader(Runtime.getRuntime().exec("hostname").getInputStream())).readLine()); } catch (IOException e) { diff --git a/SpigotCore_Main/src/de/steamwar/core/events/ChunkListener.java b/SpigotCore_Main/src/de/steamwar/core/events/ChunkListener.java deleted file mode 100644 index 9e51366..0000000 --- a/SpigotCore_Main/src/de/steamwar/core/events/ChunkListener.java +++ /dev/null @@ -1,33 +0,0 @@ -/* - This file is a part of the SteamWar software. - - Copyright (C) 2020 SteamWar.de-Serverteam - - 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 de.steamwar.core.events; - -import de.steamwar.core.CraftbukkitWrapper; -import org.bukkit.entity.Player; - -@Deprecated -public class ChunkListener { - private ChunkListener(){} - - @Deprecated - public static void sendChunk(Player p, int chunkX, int chunkZ) { - CraftbukkitWrapper.impl.sendChunk(p, chunkX, chunkZ); - } -} diff --git a/SpigotCore_Main/src/de/steamwar/core/events/PartialChunkFixer.java b/SpigotCore_Main/src/de/steamwar/core/events/PartialChunkFixer.java new file mode 100644 index 0000000..07a879d --- /dev/null +++ b/SpigotCore_Main/src/de/steamwar/core/events/PartialChunkFixer.java @@ -0,0 +1,56 @@ +/* + * This file is a part of the SteamWar software. + * + * Copyright (C) 2022 SteamWar.de-Serverteam + * + * 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 de.steamwar.core.events; + +import com.comphenix.tinyprotocol.Reflection; +import com.comphenix.tinyprotocol.TinyProtocol; +import com.viaversion.viaversion.api.Via; +import com.viaversion.viaversion.api.ViaAPI; +import de.steamwar.core.CraftbukkitWrapper; +import org.bukkit.entity.Player; + +/** + * TinyProtocol can't translate BlockEntities during 1.16 to 1.17 conversions du to removed partial chunk update support. This class cancels PartialChunkUpdates for this players and sends them a complete chunk instead. + * This class can only be loaded on 1.9 to 1.15 with active ViaVersion. + **/ +public class PartialChunkFixer { + + private static final int PROTOCOL1_17 = 755; + private static final Class mapChunk = Reflection.getClass("{nms}.PacketPlayOutMapChunk"); + private static final Reflection.FieldAccessor fullChunkFlag = Reflection.getField(mapChunk, boolean.class, 0); + private static final Reflection.FieldAccessor chunkX = Reflection.getField(mapChunk, int.class, 0); + private static final Reflection.FieldAccessor chunkZ = Reflection.getField(mapChunk, int.class, 1); + + private final ViaAPI via = Via.getAPI(); + + public PartialChunkFixer() { + TinyProtocol.instance.addFilter(mapChunk, this::chunkFilter); + } + + private Object chunkFilter(Player player, Object packet) { + if(via.getPlayerVersion(player) >= PROTOCOL1_17 && !fullChunkFlag.get(packet)) { + // partial chunk update + System.out.println("Partial chunk at " + chunkX.get(packet) + " " + chunkZ.get(packet)); + CraftbukkitWrapper.impl.sendChunk(player, chunkX.get(packet), chunkZ.get(packet)); + return null; + } + return packet; + } +} diff --git a/SpigotCore_Main/src/plugin.yml b/SpigotCore_Main/src/plugin.yml index a29249d..7565266 100644 --- a/SpigotCore_Main/src/plugin.yml +++ b/SpigotCore_Main/src/plugin.yml @@ -4,6 +4,7 @@ author: Lixfel api-version: "1.13" load: STARTUP softdepend: + - ViaVersion - WorldEdit main: de.steamwar.core.Core diff --git a/build.gradle b/build.gradle index 11b9180..fba0534 100644 --- a/build.gradle +++ b/build.gradle @@ -81,6 +81,10 @@ allprojects { maven { url = uri('https://libraries.minecraft.net') } + + maven { + url = uri('https://repo.viaversion.com') + } } }