Compare commits

...
Author SHA1 Message Date
RaphiMC dea6dee7f9 Properly handle block change acknowledgements in 1.18.2 -> 1.19 2024-08-13 23:54:23 +02:00
Nassim Jahnke bda4ea9fd0 [ci skip] Move template protocol into common module
Had to move the rewriter classes into the flattened package to make them package private, but this is nicer than having a separate module just for those
2024-08-13 10:24:20 +02:00
FlorianMichael cbd26ce9d9 [ci skip] Link to our new website instead 2024-08-13 10:14:22 +02:00
Nassim Jahnke 8d53f4aa5a Update mcstructs 2024-08-13 09:59:59 +02:00
EnZaXD 1438f1f68d [ci skip] Update README.md (#4088) 2024-08-11 11:33:12 +02:00
RK_01 61fcf6f895 Update 1.21 version range (#4082) 2024-08-08 17:27:38 +02:00
Nassim Jahnke 736834441d [ci skip] Update shadow 2024-08-08 10:55:56 +02:00
Nassim Jahnke 3f5417be97 5.0.3 Release 2024-08-07 17:56:01 +02:00
Nassim Jahnke cc1c88001f Hotfix item id changes in item hover events 2024-08-07 17:36:42 +02:00
Nassim Jahnke 274f98c24e Fix double remapping of area effect cloud particle in 1.20.2->.3
Fixes #4042
2024-08-07 15:37:14 +02:00
Kichura f39b466ac0 Update Ubuntu, Change wrapper-validation in publish. (#4081) 2024-08-07 15:27:03 +02:00
EnZaXD aa22ca1d56 Handle pitch/yaw->data item frame rotation change in 1.16.4->1.17 (#4064)
See https://github.com/ViaVersion/ViaBackwards/pull/848
2024-08-07 13:02:51 +02:00
Nassim Jahnke 802e868b2e Track sent armor trim registries in 1.20.3->1.20.5 2024-08-07 12:36:51 +02:00
Nassim Jahnke 02442a9775 Only resend attribute modifiers when necessary
Fixes #3973
2024-08-07 11:59:13 +02:00
EnZaXD 5349de91c5 Rename CI workflow and update gradle wrapper validation (#4079) 2024-08-07 11:32:16 +02:00
Nassim Jahnke a8ef3c890a Only add dummy enchantment once 2024-08-06 15:21:18 +02:00
EnZaXD b556e6528a Rename remaining packages in bukkit modules to new format (#4074) 2024-08-05 09:48:01 +02:00
EnZaXD 434b32cad8 Fix typo in ViaManagerImpl#destroy log message (#4073) 2024-08-05 09:30:48 +02:00
EnZaXD 60b3ba6bb7 Include snakeyaml into final jar, delete compat layers (#4070)
Snakeyaml is an untypical library which most Via platforms don't have and also broke in the past with V2, having it directly in the jar like Gson cleans up the build scripts massively, reduces the build time and also doesn't break in the future if they release V3 or any other breaking changes.
2024-08-05 09:30:34 +02:00
EnZaXD 864beef341 Regenerate toString() functions and remove them from protocol internals (#4072) 2024-08-05 09:09:34 +02:00
EnZaXD 7b21df2c12 Use GH repository description in platforms (#4071) 2024-08-05 09:09:09 +02:00
Nassim Jahnke 462a10363c Only print reload info when needed, add additional log message after shutdown
Thanks to its name and dependency order, ViaVersion will generally be the last plugin to be disabled and has occasionally been blamed for other plugins stalling server shutdown
2024-08-03 20:35:22 +02:00
EnZaXD 040f85659d Fix enchantment emulation in 1.20.5->1.21 on non Paper servers (#4060) 2024-08-02 11:05:17 +02:00
67 changed files with 598 additions and 496 deletions

No files matched your search

@@ -7,13 +7,13 @@ jobs:
# Only run on PRs if the source branch is on a different repo. We do not need to run everything twice.
if: ${{ github.event_name != 'pull_request' || github.repository != github.event.pull_request.head.repo.full_name }}
runs-on: ubuntu-22.04
runs-on: ubuntu-24.04
steps:
- name: Checkout Repository
uses: actions/checkout@v4
- name: Validate Gradle Wrapper
uses: gradle/actions/wrapper-validation@v3
uses: gradle/actions/wrapper-validation@v4
- name: Set up JDK 17
uses: actions/setup-java@v4
with:
+2 -2
View File
@@ -8,12 +8,12 @@ on:
jobs:
publish:
if: github.repository_owner == 'ViaVersion'
runs-on: ubuntu-22.04
runs-on: ubuntu-24.04
steps:
- name: Checkout Repository
uses: actions/checkout@v4
- name: Validate Gradle Wrapper
uses: gradle/actions/wrapper-validation@v3
uses: gradle/actions/wrapper-validation@v4
- name: Set up JDK 17
uses: actions/setup-java@v4
with:
+5 -5
View File
@@ -1,7 +1,7 @@
# ViaVersion
[![Latest Release](https://img.shields.io/github/v/release/ViaVersion/ViaVersion)](https://viaversion.com)
[![Build Status](https://github.com/ViaVersion/ViaVersion/actions/workflows/gradle.yml/badge.svg?branch=master)](https://github.com/ViaVersion/ViaVersion/actions)
[![Build Status](https://github.com/ViaVersion/ViaVersion/actions/workflows/build.yml/badge.svg?branch=master)](https://github.com/ViaVersion/ViaVersion/actions)
[![Discord](https://img.shields.io/badge/chat-on%20discord-blue.svg)](https://viaversion.com/discord)
**Allows the connection of higher client versions to lower server versions -
@@ -9,9 +9,9 @@ it works on any platform you can think of.**
The base ViaVersion jar runs on Paper and Velocity. We also have projects integrating ViaVersion to run
on Fabric, Forge, Bungee, Sponge, or as a standalone proxy to join from basically any client version on
any server version from the past decade. **See [HERE](https://github.com/ViaVersion) for an overview of the different Via\* projects.**
any server version from the past decade. **See [HERE](https://viaversion.com) for an overview of the different Via\* projects.**
Note that ViaVersion will be able to **run best on either Paper servers or Fabric clients** due to having
Note that ViaVersion will be able to **run best on either Paper servers or through [ViaFabricPlus](https://github.com/ViaVersion/ViaFabricPlus?tab=readme-ov-file#viafabricplus)** due to having
direct access to client/server state and more extensive API.
Supported Versions:
@@ -83,7 +83,7 @@ You need JDK 17 or newer to build ViaVersion.
Mapping Files
--------------
Mapping files are generated and managed in our [Mappings repository](https://github.com/ViaVersion/Mappings).
Mapping files are generated and managed in our [Mappings repository](https://github.com/ViaVersion/Mappings). The generated mapping output is stored [here](./common/src/main/resources/assets/viaversion).
Resources
@@ -96,7 +96,7 @@ Resources
License
--------
The entirety of the [API directory](api) (including the legacy API directory) is licensed under the MIT License;
The entirety of the [API directory](api) is licensed under the MIT License;
see [licenses/MIT.md](licenses/MIT.md) for
details.
+1 -1
View File
@@ -24,8 +24,8 @@ dependencies {
exclude("com.google.code.gson", "gson")
exclude("com.viaversion", "nbt")
}
api(libs.snakeYaml)
compileOnlyApi(libs.snakeYaml)
compileOnlyApi(libs.netty)
compileOnlyApi(libs.guava)
compileOnlyApi(libs.checkerQual)
@@ -212,6 +212,8 @@ public final class StructuredDataContainer {
public String toString() {
return "StructuredDataContainer{" +
"data=" + data +
", lookup=" + lookup +
", mappedNames=" + mappedNames +
'}';
}
}
@@ -67,7 +67,7 @@ public interface EntityDataType {
@Override
public String toString() {
return "EntityDataType{" +
return "EntityDataTypeImpl{" +
"typeId=" + typeId +
", type=" + type +
'}';
@@ -124,11 +124,11 @@ public class DataItem implements Item {
@Override
public String toString() {
return "Item{" +
return "DataItem{" +
"identifier=" + identifier +
", amount=" + amount +
", data=" + data +
", tag=" + tag +
'}';
}
}
}
@@ -215,4 +215,13 @@ public interface ViaPlatform<T> {
* @return whether the platform has a plugin/mod with the given name
*/
boolean hasPlugin(String name);
/**
* Returns whether the platform might be reloading.
*
* @return whether the platform might be reloading
*/
default boolean couldBeReloading() {
return true;
}
}
@@ -30,4 +30,9 @@ public interface ViaServerProxyPlatform<T> extends ViaPlatform<T> {
* @return protocol detector service
*/
ProtocolDetectorService protocolDetectorService();
@Override
default boolean couldBeReloading() {
return false;
}
}
@@ -84,7 +84,7 @@ public class ProtocolVersion implements Comparable<ProtocolVersion> {
public static final ProtocolVersion v1_20_2 = register(764, "1.20.2");
public static final ProtocolVersion v1_20_3 = register(765, "1.20.3-1.20.4", new SubVersionRange("1.20", 3, 4));
public static final ProtocolVersion v1_20_5 = register(766, "1.20.5-1.20.6", new SubVersionRange("1.20", 5, 6));
public static final ProtocolVersion v1_21 = register(767, "1.21");
public static final ProtocolVersion v1_21 = register(767, "1.21-1.21.1", new SubVersionRange("1.21", 0, 1));
public static final ProtocolVersion unknown = new ProtocolVersion(VersionType.SPECIAL, -1, -1, "UNKNOWN", null);
public static ProtocolVersion register(int version, String name) {
+1 -1
View File
@@ -8,5 +8,5 @@ repositories {
dependencies {
// version must be manually kept in sync with the one in root project settings.gradle.kts
implementation("com.github.johnrengelman", "shadow", "8.1.1")
implementation("com.gradleup.shadow", "shadow-gradle-plugin", "8.3.0")
}
@@ -4,7 +4,7 @@ import org.gradle.jvm.tasks.Jar
plugins {
id("via.base-conventions")
id("maven-publish")
id("com.github.johnrengelman.shadow")
id("com.gradleup.shadow")
}
tasks {
@@ -45,6 +45,7 @@ fun ShadowJar.configureRelocations() {
relocate("com.google.gson", "com.viaversion.viaversion.libs.gson")
relocate("it.unimi.dsi.fastutil", "com.viaversion.viaversion.libs.fastutil")
relocate("net.lenni0451.mcstructs", "com.viaversion.viaversion.libs.mcstructs")
relocate("org.yaml.snakeyaml", "com.viaversion.viaversion.libs.snakeyaml")
}
fun ShadowJar.configureExcludes() {
+1 -1
View File
@@ -6,7 +6,7 @@ plugins {
allprojects {
group = "com.viaversion"
version = property("projectVersion") as String // from gradle.properties
description = "Allow newer clients to join older server versions."
description = "Allows the connection of newer clients to older server versions for Minecraft servers."
}
val main = setOf(
@@ -15,7 +15,7 @@
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.viaversion.viaversion.bukkit.listeners.protocol1_9to1_8;
package com.viaversion.viaversion.bukkit.listeners.v1_8to1_9;
import com.viaversion.viaversion.api.Via;
import com.viaversion.viaversion.api.protocol.packet.PacketWrapper;
@@ -117,4 +117,4 @@ public class ArmorListener extends ViaBukkitListener {
if (!isOnPipe(player)) return; // Don't start a task if the player is not on the pipe
Via.getPlatform().runSync(() -> sendArmorUpdate(player));
}
}
}
@@ -15,7 +15,7 @@
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.viaversion.viaversion.bukkit.listeners.protocol1_9to1_8;
package com.viaversion.viaversion.bukkit.listeners.v1_8to1_9;
import com.viaversion.viaversion.api.minecraft.BlockPosition;
import com.viaversion.viaversion.bukkit.listeners.ViaBukkitListener;
@@ -15,7 +15,7 @@
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.viaversion.viaversion.bukkit.listeners.protocol1_9to1_8;
package com.viaversion.viaversion.bukkit.listeners.v1_8to1_9;
import com.viaversion.viaversion.api.Via;
import com.viaversion.viaversion.api.connection.UserConnection;
@@ -15,7 +15,7 @@
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.viaversion.viaversion.bukkit.listeners.protocol1_9to1_8;
package com.viaversion.viaversion.bukkit.listeners.v1_8to1_9;
import com.viaversion.viaversion.api.minecraft.item.DataItem;
import com.viaversion.viaversion.api.minecraft.item.Item;
@@ -15,7 +15,7 @@
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.viaversion.viaversion.bukkit.listeners.protocol1_9to1_8;
package com.viaversion.viaversion.bukkit.listeners.v1_8to1_9;
import com.viaversion.viaversion.bukkit.listeners.ViaBukkitListener;
import com.viaversion.viaversion.bukkit.util.CollisionChecker;
@@ -268,6 +268,11 @@ public class ViaVersionPlugin extends JavaPlugin implements ViaPlatform<Player>
return getServer().getPluginManager().getPlugin(name) != null;
}
@Override
public boolean couldBeReloading() {
return !(PaperViaInjector.PAPER_IS_STOPPING_METHOD && Bukkit.isStopping());
}
public boolean isLateBind() {
return lateBind;
}
@@ -0,0 +1,51 @@
/*
* This file is part of ViaVersion - https://github.com/ViaVersion/ViaVersion
* Copyright (C) 2016-2024 ViaVersion and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.viaversion.viaversion.bukkit.listeners.v1_20_5to1_21;
import com.viaversion.viaversion.ViaVersionPlugin;
import io.papermc.paper.event.player.PlayerInventorySlotChangeEvent;
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
import org.bukkit.event.EventPriority;
import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.PlayerInventory;
public final class PaperPlayerChangeItemListener extends PlayerChangeItemListener {
public PaperPlayerChangeItemListener(final ViaVersionPlugin plugin) {
super(plugin);
}
@EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true)
public void onPlayerInventorySlotChangedEvent(final PlayerInventorySlotChangeEvent event) {
final Player player = event.getPlayer();
final ItemStack item = event.getNewItemStack();
final PlayerInventory inventory = player.getInventory();
final int slot = event.getSlot();
if (slot == inventory.getHeldItemSlot()) {
sendAttributeUpdate(player, item, Slot.HAND);
} else if (slot == 36) {
sendAttributeUpdate(player, item, Slot.BOOTS);
} else if (slot == 37) {
sendAttributeUpdate(player, item, Slot.LEGGINGS);
} else if (slot == 39) {
sendAttributeUpdate(player, item, Slot.HELMET);
}
}
}
@@ -23,50 +23,31 @@ import com.viaversion.viaversion.api.connection.UserConnection;
import com.viaversion.viaversion.bukkit.listeners.ViaBukkitListener;
import com.viaversion.viaversion.protocols.v1_20_5to1_21.Protocol1_20_5To1_21;
import com.viaversion.viaversion.protocols.v1_20_5to1_21.storage.EfficiencyAttributeStorage;
import io.papermc.paper.event.player.PlayerInventorySlotChangeEvent;
import org.bukkit.NamespacedKey;
import org.bukkit.enchantments.Enchantment;
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
import org.bukkit.event.EventPriority;
import org.bukkit.event.player.PlayerItemHeldEvent;
import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.PlayerInventory;
import org.checkerframework.checker.nullness.qual.Nullable;
/**
* For some reason, mining efficiency is not calculated by the client anymore, but by the server,
* then sending the current value to the client every time the item changes. This roughly emulates that behavior.
*/
public final class PlayerChangeItemListener extends ViaBukkitListener {
public class PlayerChangeItemListener extends ViaBukkitListener {
private final Enchantment efficiency = Enchantment.getByKey(NamespacedKey.minecraft("efficiency"));
private final Enchantment aquaAffinity = Enchantment.getByKey(NamespacedKey.minecraft("aqua_affinity"));
private final Enchantment depthStrider = Enchantment.getByKey(NamespacedKey.minecraft("depth_strider"));
private final Enchantment soulSpeed = Enchantment.getByKey(NamespacedKey.minecraft("soul_speed"));
private final Enchantment swiftSneak = Enchantment.getByKey(NamespacedKey.minecraft("swift_sneak"));
// Use legacy function and names here to support all versions
private final Enchantment efficiency = getByName("efficiency", "DIG_SPEED");
private final Enchantment aquaAffinity = getByName("aqua_affinity", "WATER_WORKER");
private final Enchantment depthStrider = getByName("depth_strider", "DEPTH_STRIDER");
private final Enchantment soulSpeed = getByName("soul_speed", "SOUL_SPEED");
private final Enchantment swiftSneak = getByName("swift_sneak", "SWIFT_SNEAK");
public PlayerChangeItemListener(final ViaVersionPlugin plugin) {
super(plugin, Protocol1_20_5To1_21.class);
}
@EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true)
public void onPlayerInventorySlotChangedEvent(final PlayerInventorySlotChangeEvent event) {
final Player player = event.getPlayer();
final ItemStack item = event.getNewItemStack();
final PlayerInventory inventory = player.getInventory();
final int slot = event.getSlot();
if (slot == inventory.getHeldItemSlot()) {
sendAttributeUpdate(player, item, Slot.HAND);
} else if (slot == 36) {
sendAttributeUpdate(player, item, Slot.BOOTS);
} else if (slot == 37) {
sendAttributeUpdate(player, item, Slot.LEGGINGS);
} else if (slot == 39) {
sendAttributeUpdate(player, item, Slot.HELMET);
}
}
@EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true)
public void onPlayerItemHeld(final PlayerItemHeldEvent event) {
final Player player = event.getPlayer();
@@ -74,7 +55,7 @@ public final class PlayerChangeItemListener extends ViaBukkitListener {
sendAttributeUpdate(player, item, Slot.HAND);
}
private void sendAttributeUpdate(final Player player, @Nullable final ItemStack item, final Slot slot) {
void sendAttributeUpdate(final Player player, @Nullable final ItemStack item, final Slot slot) {
final UserConnection connection = Via.getAPI().getConnection(player.getUniqueId());
if (connection == null || !isOnPipe(player)) {
return;
@@ -105,7 +86,15 @@ public final class PlayerChangeItemListener extends ViaBukkitListener {
storage.setEnchants(player.getEntityId(), connection, efficiencyLevel, soulSpeedLevel, swiftSneakLevel, aquaAffinityLevel, depthStriderLevel);
}
private enum Slot {
enum Slot {
HAND, BOOTS, LEGGINGS, HELMET
}
private Enchantment getByName(final String newName, final String oldName) {
final Enchantment enchantment = Enchantment.getByName(newName);
if (enchantment == null) {
return Enchantment.getByName(oldName);
}
return enchantment;
}
}
@@ -28,11 +28,12 @@ import com.viaversion.viaversion.bukkit.listeners.multiversion.PlayerSneakListen
import com.viaversion.viaversion.bukkit.listeners.v1_14_4to1_15.EntityToggleGlideListener;
import com.viaversion.viaversion.bukkit.listeners.v1_19_3to1_19_4.ArmorToggleListener;
import com.viaversion.viaversion.bukkit.listeners.v1_18_2to1_19.BlockBreakListener;
import com.viaversion.viaversion.bukkit.listeners.protocol1_9to1_8.ArmorListener;
import com.viaversion.viaversion.bukkit.listeners.protocol1_9to1_8.BlockListener;
import com.viaversion.viaversion.bukkit.listeners.protocol1_9to1_8.DeathListener;
import com.viaversion.viaversion.bukkit.listeners.protocol1_9to1_8.HandItemCache;
import com.viaversion.viaversion.bukkit.listeners.protocol1_9to1_8.PaperPatch;
import com.viaversion.viaversion.bukkit.listeners.v1_8to1_9.ArmorListener;
import com.viaversion.viaversion.bukkit.listeners.v1_8to1_9.BlockListener;
import com.viaversion.viaversion.bukkit.listeners.v1_8to1_9.DeathListener;
import com.viaversion.viaversion.bukkit.listeners.v1_8to1_9.HandItemCache;
import com.viaversion.viaversion.bukkit.listeners.v1_8to1_9.PaperPatch;
import com.viaversion.viaversion.bukkit.listeners.v1_20_5to1_21.PaperPlayerChangeItemListener;
import com.viaversion.viaversion.bukkit.listeners.v1_20_5to1_21.PlayerChangeItemListener;
import com.viaversion.viaversion.bukkit.providers.BukkitAckSequenceProvider;
import com.viaversion.viaversion.bukkit.providers.BukkitBlockConnectionProvider;
@@ -179,8 +180,12 @@ public class BukkitViaLoader implements ViaPlatformLoader {
Via.getManager().getProviders().use(AckSequenceProvider.class, new BukkitAckSequenceProvider(plugin));
new BlockBreakListener(plugin).register();
}
if (serverProtocolVersion.olderThan(ProtocolVersion.v1_21) && PaperViaInjector.hasClass("io.papermc.paper.event.player.PlayerInventorySlotChangeEvent")) {
new PlayerChangeItemListener(plugin).register();
if (serverProtocolVersion.olderThan(ProtocolVersion.v1_21)) {
if (PaperViaInjector.hasClass("io.papermc.paper.event.player.PlayerInventorySlotChangeEvent")) {
new PaperPlayerChangeItemListener(plugin).register();
} else {
new PlayerChangeItemListener(plugin).register();
}
}
}
@@ -28,6 +28,7 @@ public final class PaperViaInjector {
public static final boolean PAPER_INJECTION_METHOD = hasPaperInjectionMethod();
public static final boolean PAPER_PROTOCOL_METHOD = hasServerProtocolMethod();
public static final boolean PAPER_PACKET_LIMITER = hasPacketLimiter();
public static final boolean PAPER_IS_STOPPING_METHOD = hasIsStoppingMethod();
private PaperViaInjector() {
}
@@ -76,6 +77,15 @@ public final class PaperViaInjector {
return hasClass("io.papermc.paper.network.ChannelInitializeListener");
}
private static boolean hasIsStoppingMethod() {
try {
Bukkit.class.getDeclaredMethod("isStopping");
return true;
} catch (final NoSuchMethodException e) {
return false;
}
}
private static boolean hasPacketLimiter() {
return hasClass("com.destroystokyo.paper.PaperConfig$PacketLimit") || hasClass("io.papermc.paper.configuration.GlobalConfiguration$PacketLimiter");
}
@@ -19,8 +19,9 @@ package com.viaversion.viaversion.bukkit.providers;
import com.viaversion.viaversion.ViaVersionPlugin;
import com.viaversion.viaversion.api.connection.UserConnection;
import com.viaversion.viaversion.api.minecraft.BlockPosition;
import com.viaversion.viaversion.api.protocol.version.ProtocolVersion;
import com.viaversion.viaversion.bukkit.tasks.protocol1_19to1_18_2.AckSequenceTask;
import com.viaversion.viaversion.bukkit.tasks.v1_18_2to1_19.AckSequenceTask;
import com.viaversion.viaversion.protocols.v1_18_2to1_19.provider.AckSequenceProvider;
import com.viaversion.viaversion.protocols.v1_18_2to1_19.storage.SequenceStorage;
@@ -33,7 +34,9 @@ public final class BukkitAckSequenceProvider extends AckSequenceProvider {
}
@Override
public void handleSequence(final UserConnection connection, final int sequence) {
public void handleSequence(final UserConnection connection, final BlockPosition position, final int sequence) {
if (sequence <= 0) return; // Does not need to be acked
final SequenceStorage sequenceStorage = connection.get(SequenceStorage.class);
final int previousSequence = sequenceStorage.setSequenceId(sequence);
if (previousSequence == -1) {
@@ -45,4 +48,10 @@ public final class BukkitAckSequenceProvider extends AckSequenceProvider {
}
}
}
}
@Override
public void handleBlockChange(final UserConnection connection, final BlockPosition position) {
// no op on bukkit
}
}
@@ -21,7 +21,7 @@ import com.viaversion.viaversion.api.Via;
import com.viaversion.viaversion.api.connection.ProtocolInfo;
import com.viaversion.viaversion.api.connection.UserConnection;
import com.viaversion.viaversion.api.protocol.version.ProtocolVersion;
import com.viaversion.viaversion.bukkit.tasks.protocol1_12to1_11_1.BukkitInventoryUpdateTask;
import com.viaversion.viaversion.bukkit.tasks.v1_11_1to1_12.BukkitInventoryUpdateTask;
import com.viaversion.viaversion.bukkit.util.NMSUtil;
import com.viaversion.viaversion.protocols.v1_11_1to1_12.provider.InventoryQuickMoveProvider;
import com.viaversion.viaversion.protocols.v1_11_1to1_12.storage.ItemTransactionStorage;
@@ -201,4 +201,4 @@ public class BukkitInventoryQuickMoveProvider extends InventoryQuickMoveProvider
final ProtocolVersion protocol = Via.getAPI().getServerVersion().lowestSupportedProtocolVersion();
return protocol.newerThanOrEqualTo(ProtocolVersion.v1_8) && protocol.olderThanOrEqualTo(ProtocolVersion.v1_11_1);
}
}
}
@@ -15,7 +15,7 @@
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.viaversion.viaversion.bukkit.tasks.protocol1_12to1_11_1;
package com.viaversion.viaversion.bukkit.tasks.v1_11_1to1_12;
import com.viaversion.viaversion.bukkit.providers.BukkitInventoryQuickMoveProvider;
import com.viaversion.viaversion.protocols.v1_11_1to1_12.storage.ItemTransactionStorage;
@@ -65,4 +65,4 @@ public class BukkitInventoryUpdateTask implements Runnable {
provider.onTaskExecuted(uuid);
}
}
}
}
@@ -15,7 +15,7 @@
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.viaversion.viaversion.bukkit.tasks.protocol1_19to1_18_2;
package com.viaversion.viaversion.bukkit.tasks.v1_18_2to1_19;
import com.viaversion.viaversion.api.Via;
import com.viaversion.viaversion.api.connection.UserConnection;
+1 -3
View File
@@ -3,13 +3,11 @@ dependencies {
api(rootProject.libs.text) {
exclude("com.google.code.gson", "gson")
}
implementation(projects.compat.snakeyaml2Compat)
implementation(projects.compat.snakeyaml1Compat)
// Note: If manually starting tests doesn't work for you in IJ, change 'Gradle -> Run Tests Using' to 'IntelliJ IDEA'
testImplementation(rootProject.libs.netty)
testImplementation(rootProject.libs.guava)
testImplementation(rootProject.libs.snakeYaml2)
testImplementation(rootProject.libs.snakeYaml)
testImplementation(rootProject.libs.bundles.junit)
}
@@ -210,8 +210,10 @@ public class ViaManagerImpl implements ViaManager {
}
public void destroy() {
// Uninject
platform.getLogger().info("ViaVersion is disabling, if this is a reload and you experience issues consider rebooting.");
if (platform.couldBeReloading()) {
platform.getLogger().info("ViaVersion is disabling. If this is a reload and you experience issues, please reboot instead.");
}
try {
injector.uninject();
} catch (Exception e) {
@@ -220,6 +222,8 @@ public class ViaManagerImpl implements ViaManager {
loader.unload();
scheduler.shutdown();
platform.getLogger().info("ViaVersion has been disabled; uninjected the platform and shut down the scheduler.");
}
private void checkJavaVersion() { // Stolen from Paper
@@ -73,8 +73,9 @@ public final class DimensionDataImpl implements DimensionData {
@Override
public String toString() {
return "DimensionData{" +
"minY=" + minY +
return "DimensionDataImpl{" +
"id=" + id +
", minY=" + minY +
", height=" + height +
'}';
}
@@ -15,23 +15,22 @@
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.viaversion.viaversion.template.protocols.rewriter;
package com.viaversion.viaversion.protocols.template;
import com.viaversion.viaversion.api.type.types.chunk.ChunkType1_20_2;
import com.viaversion.viaversion.api.type.types.version.Types1_20_5;
import com.viaversion.viaversion.protocols.v1_20_2to1_20_3.rewriter.RecipeRewriter1_20_3;
import com.viaversion.viaversion.protocols.v1_20_3to1_20_5.packet.ClientboundPacket1_20_5;
import com.viaversion.viaversion.protocols.v1_20_3to1_20_5.packet.ClientboundPackets1_20_5;
import com.viaversion.viaversion.protocols.v1_20_3to1_20_5.packet.ServerboundPacket1_20_5;
import com.viaversion.viaversion.protocols.v1_20_3to1_20_5.packet.ServerboundPackets1_20_5;
import com.viaversion.viaversion.protocols.v1_20_5to1_21.packet.ClientboundPacket1_21;
import com.viaversion.viaversion.protocols.v1_20_5to1_21.packet.ClientboundPackets1_21;
import com.viaversion.viaversion.rewriter.BlockRewriter;
import com.viaversion.viaversion.rewriter.StructuredItemRewriter;
import com.viaversion.viaversion.template.protocols.Protocol1_99To_98;
// To replace if needed:
// ChunkType1_20_2
// RecipeRewriter1_20_3
public final class BlockItemPacketRewriter1_99 extends StructuredItemRewriter<ClientboundPacket1_20_5, ServerboundPacket1_20_5, Protocol1_99To_98> {
final class BlockItemPacketRewriter1_99 extends StructuredItemRewriter<ClientboundPacket1_21, ServerboundPacket1_20_5, Protocol1_99To_98> {
public BlockItemPacketRewriter1_99(final Protocol1_99To_98 protocol) {
super(protocol, /*TypesOLD.ITEM, TypesOLD.ITEM_ARRAY, */Types1_20_5.ITEM, Types1_20_5.ITEM_ARRAY);
@@ -42,31 +41,31 @@ public final class BlockItemPacketRewriter1_99 extends StructuredItemRewriter<Cl
// Register block and block state id changes
// Other places using block state id mappings: Spawn particle, entity data, entity spawn (falling blocks)
// Tags and statistics use block (!) ids
final BlockRewriter<ClientboundPacket1_20_5> blockRewriter = BlockRewriter.for1_20_2(protocol);
blockRewriter.registerBlockEvent(ClientboundPackets1_20_5.BLOCK_EVENT);
blockRewriter.registerBlockUpdate(ClientboundPackets1_20_5.BLOCK_UPDATE);
blockRewriter.registerSectionBlocksUpdate1_20(ClientboundPackets1_20_5.SECTION_BLOCKS_UPDATE);
blockRewriter.registerLevelEvent1_21(ClientboundPackets1_20_5.LEVEL_EVENT, 2001);
blockRewriter.registerLevelChunk1_19(ClientboundPackets1_20_5.LEVEL_CHUNK_WITH_LIGHT, ChunkType1_20_2::new);
blockRewriter.registerBlockEntityData(ClientboundPackets1_20_5.BLOCK_ENTITY_DATA);
final BlockRewriter<ClientboundPacket1_21> blockRewriter = BlockRewriter.for1_20_2(protocol);
blockRewriter.registerBlockEvent(ClientboundPackets1_21.BLOCK_EVENT);
blockRewriter.registerBlockUpdate(ClientboundPackets1_21.BLOCK_UPDATE);
blockRewriter.registerSectionBlocksUpdate1_20(ClientboundPackets1_21.SECTION_BLOCKS_UPDATE);
blockRewriter.registerLevelEvent1_21(ClientboundPackets1_21.LEVEL_EVENT, 2001);
blockRewriter.registerLevelChunk1_19(ClientboundPackets1_21.LEVEL_CHUNK_WITH_LIGHT, ChunkType1_20_2::new);
blockRewriter.registerBlockEntityData(ClientboundPackets1_21.BLOCK_ENTITY_DATA);
// Registers item id changes
// Other places using item ids are: Entity data, tags, statistics, effect
// registerOpenWindow(ClientboundPackets1_20_5.OPEN_WINDOW); - If a new container type was added
registerCooldown(ClientboundPackets1_20_5.COOLDOWN);
registerSetContent1_17_1(ClientboundPackets1_20_5.CONTAINER_SET_CONTENT);
registerSetSlot1_17_1(ClientboundPackets1_20_5.CONTAINER_SET_SLOT);
registerAdvancements1_20_3(ClientboundPackets1_20_5.UPDATE_ADVANCEMENTS);
registerSetEquipment(ClientboundPackets1_20_5.SET_EQUIPMENT);
// registerOpenWindow(ClientboundPackets1_21.OPEN_WINDOW); - If a new container type was added
registerCooldown(ClientboundPackets1_21.COOLDOWN);
registerSetContent1_17_1(ClientboundPackets1_21.CONTAINER_SET_CONTENT);
registerSetSlot1_17_1(ClientboundPackets1_21.CONTAINER_SET_SLOT);
registerAdvancements1_20_3(ClientboundPackets1_21.UPDATE_ADVANCEMENTS);
registerSetEquipment(ClientboundPackets1_21.SET_EQUIPMENT);
registerContainerClick1_17_1(ServerboundPackets1_20_5.CONTAINER_CLICK);
registerMerchantOffers1_20_5(ClientboundPackets1_20_5.MERCHANT_OFFERS, Types1_20_5.ITEM_COST, Types1_20_5.ITEM_COST, Types1_20_5.OPTIONAL_ITEM_COST, Types1_20_5.OPTIONAL_ITEM_COST);
registerMerchantOffers1_20_5(ClientboundPackets1_21.MERCHANT_OFFERS, Types1_20_5.ITEM_COST, Types1_20_5.ITEM_COST, Types1_20_5.OPTIONAL_ITEM_COST, Types1_20_5.OPTIONAL_ITEM_COST);
registerSetCreativeModeSlot(ServerboundPackets1_20_5.SET_CREATIVE_MODE_SLOT);
registerLevelParticles1_20_5(ClientboundPackets1_20_5.LEVEL_PARTICLES, Types1_20_5.PARTICLE, Types1_20_5.PARTICLE);
registerExplosion(ClientboundPackets1_20_5.EXPLODE, Types1_20_5.PARTICLE, Types1_20_5.PARTICLE); // Rewrites the included sound and particles
registerLevelParticles1_20_5(ClientboundPackets1_21.LEVEL_PARTICLES, Types1_20_5.PARTICLE, Types1_20_5.PARTICLE);
registerExplosion(ClientboundPackets1_21.EXPLODE, Types1_20_5.PARTICLE, Types1_20_5.PARTICLE); // Rewrites the included sound and particles
new RecipeRewriter1_20_3<>(protocol).register1_20_5(ClientboundPackets1_20_5.UPDATE_RECIPES);
new RecipeRewriter1_20_3<>(protocol).register1_20_5(ClientboundPackets1_21.UPDATE_RECIPES);
// OR do this if serialization of recipes changed and override the relevant method
// Add new serializers to RecipeRewriter, or extend the last one for changes
// new RecipeRewriter1_20_3<ClientboundPackets1_20_5>(this) {}.register1_20_5(ClientboundPackets1_20_5.DECLARE_RECIPES);
// new RecipeRewriter1_20_3<ClientboundPacket1_21>(this) {}.register1_20_5(ClientboundPackets1_21.DECLARE_RECIPES);
}
}
}
@@ -15,25 +15,24 @@
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.viaversion.viaversion.template.protocols.rewriter;
package com.viaversion.viaversion.protocols.template;
import com.viaversion.viaversion.api.minecraft.RegistryEntry;
import com.viaversion.viaversion.api.minecraft.entities.EntityType;
import com.viaversion.viaversion.api.minecraft.entities.EntityTypes1_20_5;
import com.viaversion.viaversion.api.protocol.remapper.PacketHandlers;
import com.viaversion.viaversion.api.type.Types;
import com.viaversion.viaversion.api.type.types.version.Types1_20_5;
import com.viaversion.viaversion.protocols.v1_20_3to1_20_5.packet.ClientboundConfigurationPackets1_20_5;
import com.viaversion.viaversion.protocols.v1_20_3to1_20_5.packet.ClientboundPacket1_20_5;
import com.viaversion.viaversion.protocols.v1_20_3to1_20_5.packet.ClientboundPackets1_20_5;
import com.viaversion.viaversion.api.type.types.version.Types1_21;
import com.viaversion.viaversion.protocols.v1_20_5to1_21.packet.ClientboundConfigurationPackets1_21;
import com.viaversion.viaversion.protocols.v1_20_5to1_21.packet.ClientboundPacket1_21;
import com.viaversion.viaversion.protocols.v1_20_5to1_21.packet.ClientboundPackets1_21;
import com.viaversion.viaversion.rewriter.EntityRewriter;
import com.viaversion.viaversion.template.protocols.Protocol1_99To_98;
import com.viaversion.viaversion.util.Key;
// Replace if needed
// Types1_OLD
// Types1_20_5
public final class EntityPacketRewriter1_99 extends EntityRewriter<ClientboundPacket1_20_5, Protocol1_99To_98> {
// Types1_21
final class EntityPacketRewriter1_99 extends EntityRewriter<ClientboundPacket1_21, Protocol1_99To_98> {
public EntityPacketRewriter1_99(final Protocol1_99To_98 protocol) {
super(protocol);
@@ -42,17 +41,17 @@ public final class EntityPacketRewriter1_99 extends EntityRewriter<ClientboundPa
@Override
public void registerPackets() {
// Tracks entities, applies entity data rewrites registered below, untracks entities
registerTrackerWithData1_19(ClientboundPackets1_20_5.ADD_ENTITY, EntityTypes1_20_5.FALLING_BLOCK);
registerSetEntityData(ClientboundPackets1_20_5.SET_ENTITY_DATA, /*Types1_OLD_ENTITY_DATA_LIST, */Types1_20_5.ENTITY_DATA_LIST); // Specify old and new entity data list if changed
registerRemoveEntities(ClientboundPackets1_20_5.REMOVE_ENTITIES);
registerTrackerWithData1_19(ClientboundPackets1_21.ADD_ENTITY, EntityTypes1_20_5.FALLING_BLOCK);
registerSetEntityData(ClientboundPackets1_21.SET_ENTITY_DATA, /*Types1_OLD_ENTITY_DATA_LIST, */Types1_21.ENTITY_DATA_LIST); // Specify old and new entity data list if changed
registerRemoveEntities(ClientboundPackets1_21.REMOVE_ENTITIES);
protocol.registerClientbound(ClientboundConfigurationPackets1_20_5.REGISTRY_DATA, wrapper -> {
protocol.registerClientbound(ClientboundConfigurationPackets1_21.REGISTRY_DATA, wrapper -> {
final String registryKey = Key.stripMinecraftNamespace(wrapper.passthrough(Types.STRING));
final RegistryEntry[] entries = wrapper.passthrough(Types.REGISTRY_ENTRY_ARRAY);
handleRegistryData1_20_5(wrapper.user(), registryKey, entries); // Caches dimensions to access data like height later and tracks the amount of biomes sent for chunk data
});
protocol.registerClientbound(ClientboundPackets1_20_5.LOGIN, new PacketHandlers() {
protocol.registerClientbound(ClientboundPackets1_21.LOGIN, new PacketHandlers() {
@Override
public void register() {
map(Types.INT); // Entity id
@@ -71,7 +70,7 @@ public final class EntityPacketRewriter1_99 extends EntityRewriter<ClientboundPa
}
});
protocol.registerClientbound(ClientboundPackets1_20_5.RESPAWN, wrapper -> {
protocol.registerClientbound(ClientboundPackets1_21.RESPAWN, wrapper -> {
final int dimensionId = wrapper.passthrough(Types.VAR_INT);
final String world = wrapper.passthrough(Types.STRING);
trackWorldDataByKey1_20_5(wrapper.user(), dimensionId, world); // Tracks world height and name for chunk data and entity (un)tracking
@@ -82,24 +81,23 @@ public final class EntityPacketRewriter1_99 extends EntityRewriter<ClientboundPa
protected void registerRewrites() {
/* Uncomment if entity data classes changed
filter().mapDataType(typeId -> {
final int id = typeId;
int id = typeId;
if (id >= SomeAddedIndex) {
id++;
}
return Types1_20_5.ENTITY_DATA_TYPES.byId(id);
return Types1_21.ENTITY_DATA_TYPES.byId(id);
});*/
// Registers registry type id changes
registerEntityDataTypeHandler(
Types1_20_5.ENTITY_DATA_TYPES.itemType,
Types1_20_5.ENTITY_DATA_TYPES.blockStateType,
Types1_20_5.ENTITY_DATA_TYPES.optionalBlockStateType,
Types1_20_5.ENTITY_DATA_TYPES.particleType,
Types1_20_5.ENTITY_DATA_TYPES.particlesType,
Types1_20_5.ENTITY_DATA_TYPES.componentType,
Types1_20_5.ENTITY_DATA_TYPES.optionalComponentType
Types1_21.ENTITY_DATA_TYPES.itemType,
Types1_21.ENTITY_DATA_TYPES.blockStateType,
Types1_21.ENTITY_DATA_TYPES.optionalBlockStateType,
Types1_21.ENTITY_DATA_TYPES.particleType,
Types1_21.ENTITY_DATA_TYPES.particlesType,
Types1_21.ENTITY_DATA_TYPES.componentType,
Types1_21.ENTITY_DATA_TYPES.optionalComponentType
);
// Minecarts are special
registerBlockStateHandler(EntityTypes1_20_5.ABSTRACT_MINECART, 11);
}
@@ -113,4 +111,4 @@ public final class EntityPacketRewriter1_99 extends EntityRewriter<ClientboundPa
public EntityType typeFromId(final int type) {
return EntityTypes1_20_5.getTypeFromId(type);
}
}
}
@@ -15,7 +15,7 @@
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.viaversion.viaversion.template.protocols;
package com.viaversion.viaversion.protocols.template;
import com.viaversion.viaversion.api.connection.UserConnection;
import com.viaversion.viaversion.api.data.MappingData;
@@ -25,65 +25,63 @@ import com.viaversion.viaversion.api.protocol.AbstractProtocol;
import com.viaversion.viaversion.api.protocol.packet.provider.PacketTypesProvider;
import com.viaversion.viaversion.api.protocol.packet.provider.SimplePacketTypesProvider;
import com.viaversion.viaversion.data.entity.EntityTrackerBase;
import com.viaversion.viaversion.protocols.v1_20_3to1_20_5.packet.ClientboundConfigurationPackets1_20_5;
import com.viaversion.viaversion.protocols.v1_20_3to1_20_5.packet.ClientboundPacket1_20_5;
import com.viaversion.viaversion.protocols.v1_20_3to1_20_5.packet.ClientboundPackets1_20_5;
import com.viaversion.viaversion.protocols.v1_20_3to1_20_5.packet.ServerboundConfigurationPackets1_20_5;
import com.viaversion.viaversion.protocols.v1_20_3to1_20_5.packet.ServerboundPacket1_20_5;
import com.viaversion.viaversion.protocols.v1_20_3to1_20_5.packet.ServerboundPackets1_20_5;
import com.viaversion.viaversion.protocols.v1_20_5to1_21.packet.ClientboundConfigurationPackets1_21;
import com.viaversion.viaversion.protocols.v1_20_5to1_21.packet.ClientboundPacket1_21;
import com.viaversion.viaversion.protocols.v1_20_5to1_21.packet.ClientboundPackets1_21;
import com.viaversion.viaversion.rewriter.AttributeRewriter;
import com.viaversion.viaversion.rewriter.SoundRewriter;
import com.viaversion.viaversion.rewriter.StatisticsRewriter;
import com.viaversion.viaversion.rewriter.TagRewriter;
import com.viaversion.viaversion.template.protocols.rewriter.BlockItemPacketRewriter1_99;
import com.viaversion.viaversion.template.protocols.rewriter.EntityPacketRewriter1_99;
import static com.viaversion.viaversion.util.ProtocolUtil.packetTypeMap;
// Placeholders to replace (in the entire package):
// Protocol1_99To_98, EntityPacketRewriter1_99, BlockItemPacketRewriter1_99
// ClientboundPacket1_20_5
// Protocol1_99To_98, EntityPacketRewriter1_99, BlockItemPacketRewriter1_99 - move the latter two to a rewriter package
// ClientboundPacket1_21
// ServerboundPacket1_20_5
// EntityTypes1_20_5 (MAPPED type)
// 1.99, 1.98
public final class Protocol1_99To_98 extends AbstractProtocol<ClientboundPacket1_20_5, ClientboundPacket1_20_5, ServerboundPacket1_20_5, ServerboundPacket1_20_5> {
final class Protocol1_99To_98 extends AbstractProtocol<ClientboundPacket1_21, ClientboundPacket1_21, ServerboundPacket1_20_5, ServerboundPacket1_20_5> {
public static final MappingData MAPPINGS = new MappingDataBase("1.98", "1.99");
private final EntityPacketRewriter1_99 entityRewriter = new EntityPacketRewriter1_99(this);
private final BlockItemPacketRewriter1_99 itemRewriter = new BlockItemPacketRewriter1_99(this);
private final TagRewriter<ClientboundPacket1_20_5> tagRewriter = new TagRewriter<>(this);
private final TagRewriter<ClientboundPacket1_21> tagRewriter = new TagRewriter<>(this);
public Protocol1_99To_98() {
// Passing the class types into the super constructor is needed for automatic packet type id remapping, but can otherwise be omitted
super(ClientboundPacket1_20_5.class, ClientboundPacket1_20_5.class, ServerboundPacket1_20_5.class, ServerboundPacket1_20_5.class);
super(ClientboundPacket1_21.class, ClientboundPacket1_21.class, ServerboundPacket1_20_5.class, ServerboundPacket1_20_5.class);
}
@Override
protected void registerPackets() {
super.registerPackets();
tagRewriter.registerGeneric(ClientboundPackets1_20_5.UPDATE_TAGS);
tagRewriter.registerGeneric(ClientboundConfigurationPackets1_20_5.UPDATE_TAGS);
tagRewriter.registerGeneric(ClientboundPackets1_21.UPDATE_TAGS);
tagRewriter.registerGeneric(ClientboundConfigurationPackets1_21.UPDATE_TAGS);
final SoundRewriter<ClientboundPacket1_20_5> soundRewriter = new SoundRewriter<>(this);
soundRewriter.registerSound1_19_3(ClientboundPackets1_20_5.SOUND);
soundRewriter.registerSound1_19_3(ClientboundPackets1_20_5.SOUND_ENTITY);
final SoundRewriter<ClientboundPacket1_21> soundRewriter = new SoundRewriter<>(this);
soundRewriter.registerSound1_19_3(ClientboundPackets1_21.SOUND);
soundRewriter.registerSound1_19_3(ClientboundPackets1_21.SOUND_ENTITY);
new StatisticsRewriter<>(this).register(ClientboundPackets1_20_5.AWARD_STATS);
new AttributeRewriter<>(this).register1_21(ClientboundPackets1_20_5.UPDATE_ATTRIBUTES);
new StatisticsRewriter<>(this).register(ClientboundPackets1_21.AWARD_STATS);
new AttributeRewriter<>(this).register1_21(ClientboundPackets1_21.UPDATE_ATTRIBUTES);
// Uncomment if an existing type changed serialization format. Mappings for argument type keys can also be defined in mapping files
/*final CommandRewriter1_19_4<ClientboundPackets1_20_5> commandRewriter = new CommandRewriter1_19_4<ClientboundPackets1_20_5>(this) {
/*new CommandRewriter1_19_4<>(this) {
@Override
public void handleArgument(final PacketWrapper wrapper, final String argumentType) throws Exception {
public void handleArgument(final PacketWrapper wrapper, final String argumentType) {
if (argumentType.equals("minecraft:abc")) {
// New argument
wrapper.write(Type.INT, 0);
wrapper.write(Types.INT, 0);
} else {
super.handleArgument(wrapper, argumentType);
}
}
}.registerDeclareCommands1_19(ClientboundPackets1_20_5.DECLARE_COMMANDS);*/
}.registerDeclareCommands1_19(ClientboundPackets1_21.COMMANDS);*/
}
@Override
@@ -130,17 +128,17 @@ public final class Protocol1_99To_98 extends AbstractProtocol<ClientboundPacket1
}
@Override
public TagRewriter<ClientboundPacket1_20_5> getTagRewriter() {
public TagRewriter<ClientboundPacket1_21> getTagRewriter() {
return tagRewriter;
}
@Override
protected PacketTypesProvider<ClientboundPacket1_20_5, ClientboundPacket1_20_5, ServerboundPacket1_20_5, ServerboundPacket1_20_5> createPacketTypesProvider() {
protected PacketTypesProvider<ClientboundPacket1_21, ClientboundPacket1_21, ServerboundPacket1_20_5, ServerboundPacket1_20_5> createPacketTypesProvider() {
return new SimplePacketTypesProvider<>(
packetTypeMap(unmappedClientboundPacketType, ClientboundPackets1_20_5.class, ClientboundConfigurationPackets1_20_5.class),
packetTypeMap(mappedClientboundPacketType, ClientboundPackets1_20_5.class, ClientboundConfigurationPackets1_20_5.class),
packetTypeMap(unmappedClientboundPacketType, ClientboundPackets1_21.class, ClientboundConfigurationPackets1_21.class),
packetTypeMap(mappedClientboundPacketType, ClientboundPackets1_21.class, ClientboundConfigurationPackets1_21.class),
packetTypeMap(mappedServerboundPacketType, ServerboundPackets1_20_5.class, ServerboundConfigurationPackets1_20_5.class),
packetTypeMap(unmappedServerboundPacketType, ServerboundPackets1_20_5.class, ServerboundConfigurationPackets1_20_5.class)
);
}
}
}
@@ -48,6 +48,30 @@ public final class EntityPacketRewriter1_17 extends EntityRewriter<ClientboundPa
registerTracker(ClientboundPackets1_16_2.ADD_PLAYER, EntityTypes1_17.PLAYER);
registerSetEntityData(ClientboundPackets1_16_2.SET_ENTITY_DATA, Types1_16.ENTITY_DATA_LIST, Types1_17.ENTITY_DATA_LIST);
protocol.appendClientbound(ClientboundPackets1_16_2.ADD_ENTITY, wrapper -> {
final int entityType = wrapper.get(Types.VAR_INT, 1);
if (entityType != EntityTypes1_17.ITEM_FRAME.getId()) {
return;
}
// Older clients will ignore the data field and the server sets the item frame rotation by the yaw/pitch field inside the packet,
// newer clients do the opposite and ignore yaw/pitch and use the data field from the packet.
final int entityId = wrapper.get(Types.VAR_INT, 0);
final byte pitch = wrapper.get(Types.BYTE, 0);
final byte yaw = wrapper.get(Types.BYTE, 1);
final PacketWrapper setDirection = PacketWrapper.create(ClientboundPackets1_17.MOVE_ENTITY_ROT, wrapper.user());
setDirection.write(Types.VAR_INT, entityId);
setDirection.write(Types.BYTE, yaw);
setDirection.write(Types.BYTE, pitch);
setDirection.write(Types.BOOLEAN, false); // On Ground
wrapper.send(Protocol1_16_4To1_17.class);
wrapper.cancel();
setDirection.send(Protocol1_16_4To1_17.class);
});
protocol.registerClientbound(ClientboundPackets1_16_2.REMOVE_ENTITIES, null, wrapper -> {
int[] entityIds = wrapper.read(Types.VAR_INT_ARRAY_PRIMITIVE);
wrapper.cancel();
@@ -18,18 +18,37 @@
package com.viaversion.viaversion.protocols.v1_18_2to1_19.provider;
import com.viaversion.viaversion.api.connection.UserConnection;
import com.viaversion.viaversion.api.minecraft.BlockPosition;
import com.viaversion.viaversion.api.platform.providers.Provider;
import com.viaversion.viaversion.api.protocol.packet.PacketWrapper;
import com.viaversion.viaversion.api.type.Types;
import com.viaversion.viaversion.protocols.v1_18_2to1_19.Protocol1_18_2To1_19;
import com.viaversion.viaversion.protocols.v1_18_2to1_19.packet.ClientboundPackets1_19;
import com.viaversion.viaversion.protocols.v1_18_2to1_19.storage.SequenceStorage;
public class AckSequenceProvider implements Provider {
public void handleSequence(final UserConnection connection, final int sequence) {
final PacketWrapper ackPacket = PacketWrapper.create(ClientboundPackets1_19.BLOCK_CHANGED_ACK, connection);
ackPacket.write(Types.VAR_INT, sequence);
ackPacket.send(Protocol1_18_2To1_19.class);
public void handleSequence(final UserConnection connection, final BlockPosition position, final int sequence) {
if (sequence <= 0) return; // Does not need to be acked
if (position == null) {
// Acknowledge immediately if the position isn't known
final PacketWrapper ackPacket = PacketWrapper.create(ClientboundPackets1_19.BLOCK_CHANGED_ACK, connection);
ackPacket.write(Types.VAR_INT, sequence);
ackPacket.send(Protocol1_18_2To1_19.class);
} else {
// Store sequence to be acknowledged when the block change is received
connection.get(SequenceStorage.class).addPendingBlockChange(position, sequence);
}
}
public void handleBlockChange(final UserConnection connection, final BlockPosition position) {
final int sequence = connection.get(SequenceStorage.class).removePendingBlockChange(position);
if (sequence > 0) { // Acknowledge if pending sequence was found
final PacketWrapper ackPacket = PacketWrapper.create(ClientboundPackets1_19.BLOCK_CHANGED_ACK, connection);
ackPacket.write(Types.VAR_INT, sequence);
ackPacket.scheduleSend(Protocol1_18_2To1_19.class);
}
}
}
@@ -26,6 +26,7 @@ import com.viaversion.nbt.tag.NumberTag;
import com.viaversion.viaversion.api.Via;
import com.viaversion.viaversion.api.data.ParticleMappings;
import com.viaversion.viaversion.api.data.entity.DimensionData;
import com.viaversion.viaversion.api.data.entity.EntityTracker;
import com.viaversion.viaversion.api.minecraft.BlockPosition;
import com.viaversion.viaversion.api.minecraft.Particle;
import com.viaversion.viaversion.api.minecraft.entities.EntityType;
@@ -41,6 +42,7 @@ import com.viaversion.viaversion.protocols.v1_17_1to1_18.packet.ClientboundPacke
import com.viaversion.viaversion.protocols.v1_18_2to1_19.Protocol1_18_2To1_19;
import com.viaversion.viaversion.protocols.v1_18_2to1_19.packet.ClientboundPackets1_19;
import com.viaversion.viaversion.protocols.v1_18_2to1_19.storage.DimensionRegistryStorage;
import com.viaversion.viaversion.protocols.v1_18_2to1_19.storage.SequenceStorage;
import com.viaversion.viaversion.rewriter.EntityRewriter;
import com.viaversion.viaversion.util.Key;
import com.viaversion.viaversion.util.Pair;
@@ -229,6 +231,13 @@ public final class EntityPacketRewriter1_19 extends EntityRewriter<ClientboundPa
map(Types.BOOLEAN); // Flat
map(Types.BOOLEAN); // Keep player attributes
create(Types.OPTIONAL_GLOBAL_POSITION, null); // Last death location
handler(wrapper -> {
final String world = wrapper.get(Types.STRING, 1);
final EntityTracker tracker = tracker(wrapper.user());
if (tracker.currentWorld() != null && !tracker.currentWorld().equals(world)) {
wrapper.user().get(SequenceStorage.class).clearPendingBlockChanges();
}
});
handler(worldDataTrackerHandlerByKey());
}
});
@@ -349,4 +358,4 @@ public final class EntityPacketRewriter1_19 extends EntityRewriter<ClientboundPa
public EntityType typeFromId(final int type) {
return EntityTypes1_19.getTypeFromId(type);
}
}
}
@@ -19,7 +19,8 @@ package com.viaversion.viaversion.protocols.v1_18_2to1_19.rewriter;
import com.viaversion.viaversion.api.Via;
import com.viaversion.viaversion.api.data.ParticleMappings;
import com.viaversion.viaversion.api.protocol.remapper.PacketHandler;
import com.viaversion.viaversion.api.minecraft.BlockFace;
import com.viaversion.viaversion.api.minecraft.BlockPosition;
import com.viaversion.viaversion.api.protocol.remapper.PacketHandlers;
import com.viaversion.viaversion.api.type.Types;
import com.viaversion.viaversion.protocols.v1_17_1to1_18.packet.ClientboundPackets1_18;
@@ -113,7 +114,14 @@ public final class ItemPacketRewriter1_19 extends ItemRewriter<ClientboundPacket
map(Types.VAR_INT); // Action
map(Types.BLOCK_POSITION1_14); // Block position
map(Types.UNSIGNED_BYTE); // Direction
handler(sequenceHandler());
handler(wrapper -> {
final AckSequenceProvider ackSequenceProvider = Via.getManager().getProviders().get(AckSequenceProvider.class);
final BlockPosition position = wrapper.get(Types.BLOCK_POSITION1_14, 0);
final BlockPosition relativePosition = position.getRelative(getBlockFace(wrapper.get(Types.UNSIGNED_BYTE, 0)));
final int sequence = wrapper.read(Types.VAR_INT);
ackSequenceProvider.handleSequence(wrapper.user(), position, sequence);
ackSequenceProvider.handleSequence(wrapper.user(), relativePosition, sequence);
});
}
});
protocol.registerServerbound(ServerboundPackets1_19.USE_ITEM_ON, new PacketHandlers() {
@@ -126,25 +134,42 @@ public final class ItemPacketRewriter1_19 extends ItemRewriter<ClientboundPacket
map(Types.FLOAT); // Y
map(Types.FLOAT); // Z
map(Types.BOOLEAN); // Inside
handler(sequenceHandler());
handler(wrapper -> {
final AckSequenceProvider ackSequenceProvider = Via.getManager().getProviders().get(AckSequenceProvider.class);
final BlockPosition position = wrapper.get(Types.BLOCK_POSITION1_14, 0);
final BlockPosition relativePosition = position.getRelative(getBlockFace(wrapper.get(Types.VAR_INT, 1)));
final int sequence = wrapper.read(Types.VAR_INT);
ackSequenceProvider.handleSequence(wrapper.user(), position, sequence);
ackSequenceProvider.handleSequence(wrapper.user(), relativePosition, sequence);
});
}
});
protocol.registerServerbound(ServerboundPackets1_19.USE_ITEM, new PacketHandlers() {
@Override
public void register() {
map(Types.VAR_INT); // Hand
handler(sequenceHandler());
handler(wrapper -> {
final AckSequenceProvider ackSequenceProvider = Via.getManager().getProviders().get(AckSequenceProvider.class);
final int sequence = wrapper.read(Types.VAR_INT);
ackSequenceProvider.handleSequence(wrapper.user(), null, sequence);
});
}
});
new RecipeRewriter<>(protocol).register(ClientboundPackets1_18.UPDATE_RECIPES);
}
private PacketHandler sequenceHandler() {
return wrapper -> {
final int sequence = wrapper.read(Types.VAR_INT);
final AckSequenceProvider provider = Via.getManager().getProviders().get(AckSequenceProvider.class);
provider.handleSequence(wrapper.user(), sequence);
private BlockFace getBlockFace(int direction) {
direction = Math.abs(direction % 6);
return switch (direction) {
case 0 -> BlockFace.BOTTOM;
case 1 -> BlockFace.TOP;
case 2 -> BlockFace.NORTH;
case 3 -> BlockFace.SOUTH;
case 4 -> BlockFace.WEST;
case 5 -> BlockFace.EAST;
default -> throw new IllegalStateException("Unexpected value: " + direction);
};
}
}
@@ -17,11 +17,16 @@
*/
package com.viaversion.viaversion.protocols.v1_18_2to1_19.rewriter;
import com.viaversion.viaversion.api.Via;
import com.viaversion.viaversion.api.minecraft.BlockChangeRecord;
import com.viaversion.viaversion.api.minecraft.BlockPosition;
import com.viaversion.viaversion.api.protocol.remapper.PacketHandlers;
import com.viaversion.viaversion.api.type.Types;
import com.viaversion.viaversion.api.type.types.chunk.ChunkType1_18;
import com.viaversion.viaversion.protocols.v1_17_1to1_18.packet.ClientboundPackets1_18;
import com.viaversion.viaversion.protocols.v1_18_2to1_19.Protocol1_18_2To1_19;
import com.viaversion.viaversion.protocols.v1_18_2to1_19.packet.ServerboundPackets1_19;
import com.viaversion.viaversion.protocols.v1_18_2to1_19.provider.AckSequenceProvider;
import com.viaversion.viaversion.rewriter.BlockRewriter;
public final class WorldPacketRewriter1_19 {
@@ -29,11 +34,35 @@ public final class WorldPacketRewriter1_19 {
public static void register(final Protocol1_18_2To1_19 protocol) {
final BlockRewriter<ClientboundPackets1_18> blockRewriter = BlockRewriter.for1_14(protocol);
blockRewriter.registerBlockEvent(ClientboundPackets1_18.BLOCK_EVENT);
blockRewriter.registerBlockUpdate(ClientboundPackets1_18.BLOCK_UPDATE);
blockRewriter.registerSectionBlocksUpdate(ClientboundPackets1_18.SECTION_BLOCKS_UPDATE);
blockRewriter.registerLevelEvent(ClientboundPackets1_18.LEVEL_EVENT, 1010, 2001);
blockRewriter.registerLevelChunk1_19(ClientboundPackets1_18.LEVEL_CHUNK_WITH_LIGHT, ChunkType1_18::new);
protocol.registerClientbound(ClientboundPackets1_18.BLOCK_UPDATE, wrapper -> {
final BlockPosition position = wrapper.passthrough(Types.BLOCK_POSITION1_14);
wrapper.write(Types.VAR_INT, protocol.getMappingData().getNewBlockStateId(wrapper.read(Types.VAR_INT)));
Via.getManager().getProviders().get(AckSequenceProvider.class).handleBlockChange(wrapper.user(), position);
});
protocol.registerClientbound(ClientboundPackets1_18.SECTION_BLOCKS_UPDATE, new PacketHandlers() {
@Override
public void register() {
map(Types.LONG); // Chunk position
map(Types.BOOLEAN); // Suppress light updates
handler(wrapper -> {
final AckSequenceProvider ackSequenceProvider = Via.getManager().getProviders().get(AckSequenceProvider.class);
final long chunkPosition = wrapper.get(Types.LONG, 0);
final int x = (int) ((chunkPosition >> 42) & 0x3FFFFFL) << 4;
final int z = (int) ((chunkPosition >> 20) & 0x3FFFFFL) << 4;
final int y = (int) (chunkPosition & 0xFFFL) << 4;
for (BlockChangeRecord record : wrapper.passthrough(Types.VAR_LONG_BLOCK_CHANGE_ARRAY)) {
record.setBlockId(protocol.getMappingData().getNewBlockStateId(record.getBlockId()));
final BlockPosition position = new BlockPosition(x + record.getSectionX(), y + record.getSectionY(), z + record.getSectionZ());
ackSequenceProvider.handleBlockChange(wrapper.user(), position);
}
});
}
});
protocol.cancelClientbound(ClientboundPackets1_18.BLOCK_BREAK_ACK);
protocol.registerServerbound(ServerboundPackets1_19.SET_BEACON, wrapper -> {
@@ -18,17 +18,18 @@
package com.viaversion.viaversion.protocols.v1_18_2to1_19.storage;
import com.viaversion.viaversion.api.connection.StorableObject;
import com.viaversion.viaversion.api.minecraft.BlockPosition;
import it.unimi.dsi.fastutil.objects.Object2IntLinkedOpenHashMap;
import it.unimi.dsi.fastutil.objects.Object2IntSortedMap;
public final class SequenceStorage implements StorableObject {
// Bukkit fix
private final Object lock = new Object();
private int sequenceId = -1;
public int sequenceId() {
synchronized (lock) {
return sequenceId;
}
}
// Protocol level fix
private final Object2IntSortedMap<BlockPosition> pendingBlockChanges = new Object2IntLinkedOpenHashMap<>();
public int setSequenceId(final int sequenceId) {
synchronized (lock) {
@@ -37,4 +38,28 @@ public final class SequenceStorage implements StorableObject {
return previousSequence;
}
}
public void addPendingBlockChange(final BlockPosition position, final int id) {
final int lastSequence = this.pendingBlockChanges.isEmpty() ? 0 : this.pendingBlockChanges.getInt(this.pendingBlockChanges.lastKey());
if (id > 0 && id >= lastSequence && !this.pendingBlockChanges.containsKey(position)) {
// Store the last 200 pending block changes. Some may never get acked, so we need to limit the size.
while (this.pendingBlockChanges.size() > 200) {
this.pendingBlockChanges.removeInt(this.pendingBlockChanges.firstKey());
}
this.pendingBlockChanges.put(position, id);
}
}
public int removePendingBlockChange(final BlockPosition position) {
final int ackedSequence = this.pendingBlockChanges.getInt(position); // 0 if not found
if (ackedSequence > 0) {
this.pendingBlockChanges.values().removeIf(sequence -> sequence <= ackedSequence); // Remove all previous pending changes
}
return ackedSequence;
}
public void clearPendingBlockChanges() {
this.pendingBlockChanges.clear();
}
}
@@ -125,8 +125,6 @@ public final class EntityPacketRewriter1_20_3 extends EntityRewriter<Clientbound
particle.add(0, Types.VAR_INT, 1);
}
}
rewriteParticle(event.user(), particle);
});
registerEntityDataTypeHandler(
@@ -134,7 +132,8 @@ public final class EntityPacketRewriter1_20_3 extends EntityRewriter<Clientbound
Types1_20_3.ENTITY_DATA_TYPES.blockStateType,
Types1_20_3.ENTITY_DATA_TYPES.optionalBlockStateType,
Types1_20_3.ENTITY_DATA_TYPES.particleType,
null);
null
);
registerBlockStateHandler(EntityTypes1_20_3.ABSTRACT_MINECART, 11);
}
@@ -147,4 +146,4 @@ public final class EntityPacketRewriter1_20_3 extends EntityRewriter<Clientbound
public EntityType typeFromId(final int type) {
return EntityTypes1_20_3.getTypeFromId(type);
}
}
}
@@ -50,6 +50,7 @@ import com.viaversion.viaversion.protocols.v1_20_3to1_20_5.rewriter.BlockItemPac
import com.viaversion.viaversion.protocols.v1_20_3to1_20_5.rewriter.ComponentRewriter1_20_5;
import com.viaversion.viaversion.protocols.v1_20_3to1_20_5.rewriter.EntityPacketRewriter1_20_5;
import com.viaversion.viaversion.protocols.v1_20_3to1_20_5.storage.AcknowledgedMessagesStorage;
import com.viaversion.viaversion.protocols.v1_20_3to1_20_5.storage.ArmorTrimStorage;
import com.viaversion.viaversion.protocols.v1_20to1_20_2.packet.ServerboundConfigurationPackets1_20_2;
import com.viaversion.viaversion.rewriter.ComponentRewriter;
import com.viaversion.viaversion.rewriter.SoundRewriter;
@@ -292,6 +293,7 @@ public final class Protocol1_20_3To1_20_5 extends AbstractProtocol<ClientboundPa
public void init(final UserConnection connection) {
addEntityTracker(connection, new EntityTrackerBase(connection, EntityTypes1_20_5.PLAYER));
connection.put(new AcknowledgedMessagesStorage());
connection.put(new ArmorTrimStorage());
}
@Override
@@ -332,4 +334,4 @@ public final class Protocol1_20_3To1_20_5 extends AbstractProtocol<ClientboundPa
packetTypeMap(unmappedServerboundPacketType, ServerboundPackets1_20_5.class, ServerboundConfigurationPackets1_20_5.class)
);
}
}
}
@@ -1,45 +0,0 @@
/*
* This file is part of ViaVersion - https://github.com/ViaVersion/ViaVersion
* Copyright (C) 2016-2024 ViaVersion and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.viaversion.viaversion.protocols.v1_20_3to1_20_5.data;
import com.viaversion.viaversion.util.KeyMappings;
import org.checkerframework.checker.nullness.qual.Nullable;
public final class TrimMaterials1_20_3 {
private static final KeyMappings MATERIALS = new KeyMappings(
"amethyst",
"copper",
"diamond",
"emerald",
"gold",
"iron",
"lapis",
"netherite",
"quartz",
"redstone"
);
public static @Nullable String idToKey(final int id) {
return MATERIALS.idToKey(id);
}
public static int keyToId(final String material) {
return MATERIALS.keyToId(material);
}
}
@@ -93,10 +93,9 @@ import com.viaversion.viaversion.protocols.v1_20_3to1_20_5.data.MapDecorations1_
import com.viaversion.viaversion.protocols.v1_20_3to1_20_5.data.MaxStackSize1_20_3;
import com.viaversion.viaversion.protocols.v1_20_3to1_20_5.data.PotionEffects1_20_5;
import com.viaversion.viaversion.protocols.v1_20_3to1_20_5.data.Potions1_20_5;
import com.viaversion.viaversion.protocols.v1_20_3to1_20_5.data.TrimMaterials1_20_3;
import com.viaversion.viaversion.protocols.v1_20_3to1_20_5.data.TrimPatterns1_20_3;
import com.viaversion.viaversion.protocols.v1_20_3to1_20_5.packet.ServerboundPacket1_20_5;
import com.viaversion.viaversion.protocols.v1_20_3to1_20_5.packet.ServerboundPackets1_20_5;
import com.viaversion.viaversion.protocols.v1_20_3to1_20_5.storage.ArmorTrimStorage;
import com.viaversion.viaversion.protocols.v1_20_3to1_20_5.storage.BannerPatternStorage;
import com.viaversion.viaversion.rewriter.BlockRewriter;
import com.viaversion.viaversion.rewriter.ItemRewriter;
@@ -499,7 +498,7 @@ public final class BlockItemPacketRewriter1_20_5 extends ItemRewriter<Clientboun
final CompoundTag trimTag = tag.getCompoundTag("Trim");
if (trimTag != null) {
updateArmorTrim(data, trimTag, (hideFlagsValue & StructuredDataConverter.HIDE_ARMOR_TRIM) == 0);
updateArmorTrim(connection, data, trimTag, (hideFlagsValue & StructuredDataConverter.HIDE_ARMOR_TRIM) == 0);
}
final CompoundTag explosionTag = tag.getCompoundTag("Explosion");
@@ -967,12 +966,12 @@ public final class BlockItemPacketRewriter1_20_5 extends ItemRewriter<Clientboun
}
}
private void updateArmorTrim(final StructuredDataContainer data, final CompoundTag trimTag, final boolean showInTooltip) {
private void updateArmorTrim(final UserConnection connection, final StructuredDataContainer data, final CompoundTag trimTag, final boolean showInTooltip) {
final Tag materialTag = trimTag.get("material");
final Holder<ArmorTrimMaterial> materialHolder;
final ArmorTrimStorage trimStorage = connection.get(ArmorTrimStorage.class);
if (materialTag instanceof StringTag materialStringTag) {
// Would technically have to be stored and retrieved from registry data, but that'd mean a lot of work
final int id = TrimMaterials1_20_3.keyToId(materialStringTag.getValue());
final int id = trimStorage.trimMaterials().keyToId(materialStringTag.getValue());
if (id == -1) {
return;
}
@@ -1020,11 +1019,11 @@ public final class BlockItemPacketRewriter1_20_5 extends ItemRewriter<Clientboun
final Tag patternTag = trimTag.get("pattern");
final Holder<ArmorTrimPattern> patternHolder;
if (patternTag instanceof StringTag patternStringTag) {
// Would technically have to be stored and retrieved from registry data, but that'd mean a lot of work
final int id = TrimPatterns1_20_3.keyToId(patternStringTag.getValue());
final int id = trimStorage.trimPatterns().keyToId(patternStringTag.getValue());
if (id == -1) {
return;
}
patternHolder = Holder.of(id);
} else if (patternTag instanceof CompoundTag patternCompoundTag) {
final String assetId = patternCompoundTag.getString("assetId");
@@ -17,6 +17,7 @@
*/
package com.viaversion.viaversion.protocols.v1_20_3to1_20_5.rewriter;
import com.google.common.base.Preconditions;
import com.viaversion.nbt.tag.ByteTag;
import com.viaversion.nbt.tag.CompoundTag;
import com.viaversion.nbt.tag.FloatTag;
@@ -25,7 +26,6 @@ import com.viaversion.nbt.tag.IntTag;
import com.viaversion.nbt.tag.ListTag;
import com.viaversion.nbt.tag.StringTag;
import com.viaversion.nbt.tag.Tag;
import com.google.common.base.Preconditions;
import com.viaversion.viaversion.api.Via;
import com.viaversion.viaversion.api.connection.UserConnection;
import com.viaversion.viaversion.api.minecraft.GameProfile;
@@ -83,8 +83,7 @@ import com.viaversion.viaversion.protocols.v1_20_3to1_20_5.data.EquipmentSlots1_
import com.viaversion.viaversion.protocols.v1_20_3to1_20_5.data.Instruments1_20_3;
import com.viaversion.viaversion.protocols.v1_20_3to1_20_5.data.PotionEffects1_20_5;
import com.viaversion.viaversion.protocols.v1_20_3to1_20_5.data.Potions1_20_5;
import com.viaversion.viaversion.protocols.v1_20_3to1_20_5.data.TrimMaterials1_20_3;
import com.viaversion.viaversion.protocols.v1_20_3to1_20_5.data.TrimPatterns1_20_3;
import com.viaversion.viaversion.protocols.v1_20_3to1_20_5.storage.ArmorTrimStorage;
import com.viaversion.viaversion.rewriter.ComponentRewriter;
import com.viaversion.viaversion.util.ComponentUtil;
import com.viaversion.viaversion.util.Either;
@@ -132,7 +131,7 @@ public class ComponentRewriter1_20_5<C extends ClientboundPacketType> extends Co
register(StructuredDataKey.HIDE_TOOLTIP, this::convertHideTooltip);
register(StructuredDataKey.REPAIR_COST, this::convertRepairCost);
register(StructuredDataKey.ENCHANTMENT_GLINT_OVERRIDE, this::convertEnchantmentGlintOverride);
register(StructuredDataKey.CREATIVE_SLOT_LOCK, null);
registerEmpty(StructuredDataKey.CREATIVE_SLOT_LOCK);
register(StructuredDataKey.INTANGIBLE_PROJECTILE, this::convertIntangibleProjectile);
register(StructuredDataKey.FOOD1_20_5, this::convertFood);
register(StructuredDataKey.FIRE_RESISTANT, this::convertFireResistant);
@@ -142,7 +141,7 @@ public class ComponentRewriter1_20_5<C extends ClientboundPacketType> extends Co
register(StructuredDataKey.MAP_COLOR, this::convertMapColor);
register(StructuredDataKey.MAP_ID, this::convertMapId);
register(StructuredDataKey.MAP_DECORATIONS, this::convertMapDecorations);
register(StructuredDataKey.MAP_POST_PROCESSING, null);
registerEmpty(StructuredDataKey.MAP_POST_PROCESSING);
register(StructuredDataKey.CHARGED_PROJECTILES1_20_5, this::convertChargedProjectiles);
register(StructuredDataKey.BUNDLE_CONTENTS1_20_5, this::convertBundleContents);
register(StructuredDataKey.POTION_CONTENTS, this::convertPotionContents);
@@ -247,7 +246,7 @@ public class ComponentRewriter1_20_5<C extends ClientboundPacketType> extends Co
if (!data.isEmpty()) {
final CompoundTag components;
try {
components = toTag(data, false);
components = toTag(connection, data, false);
} catch (final Exception e) {
if (!Via.getConfig().isSuppressConversionWarnings()) {
protocol.getLogger().log(Level.WARNING, "Error writing components in show_item!", e);
@@ -278,7 +277,7 @@ public class ComponentRewriter1_20_5<C extends ClientboundPacketType> extends Co
}
}
public CompoundTag toTag(final Map<StructuredDataKey<?>, StructuredData<?>> data, final boolean empty) {
public CompoundTag toTag(final UserConnection connection, final Map<StructuredDataKey<?>, StructuredData<?>> data, final boolean empty) {
final CompoundTag tag = new CompoundTag();
for (final Map.Entry<StructuredDataKey<?>, StructuredData<?>> entry : data.entrySet()) {
final StructuredDataKey<?> key = entry.getKey();
@@ -302,7 +301,7 @@ public class ComponentRewriter1_20_5<C extends ClientboundPacketType> extends Co
}
//noinspection unchecked
final Tag valueTag = converter.dataConverter.convert(value.value());
final Tag valueTag = converter.dataConverter.convert(connection, value.value());
if (valueTag == null) {
continue;
}
@@ -578,12 +577,12 @@ public class ComponentRewriter1_20_5<C extends ClientboundPacketType> extends Co
return value; // String<->id conversion is already done by the item rewriter
}
protected ListTag<CompoundTag> convertChargedProjectiles(final Item[] value) {
return convertItemArray(value);
protected ListTag<CompoundTag> convertChargedProjectiles(final UserConnection connection, final Item[] value) {
return convertItemArray(connection, value);
}
protected ListTag<CompoundTag> convertBundleContents(final Item[] value) {
return convertItemArray(value);
protected ListTag<CompoundTag> convertBundleContents(final UserConnection connection, final Item[] value) {
return convertItemArray(connection, value);
}
protected CompoundTag convertPotionContents(final PotionContents value) {
@@ -668,11 +667,12 @@ public class ComponentRewriter1_20_5<C extends ClientboundPacketType> extends Co
return tag;
}
protected CompoundTag convertTrim(final ArmorTrim value) {
protected CompoundTag convertTrim(final UserConnection connection, final ArmorTrim value) {
final CompoundTag tag = new CompoundTag();
final Holder<ArmorTrimMaterial> material = value.material();
final ArmorTrimStorage trimStorage = connection.get(ArmorTrimStorage.class);
if (material.hasId()) {
final String trimMaterial = TrimMaterials1_20_3.idToKey(material.id());
final String trimMaterial = trimStorage.trimMaterials().idToKey(material.id());
tag.putString("material", trimMaterial);
} else {
final ArmorTrimMaterial armorTrimMaterial = material.value();
@@ -700,7 +700,7 @@ public class ComponentRewriter1_20_5<C extends ClientboundPacketType> extends Co
final Holder<ArmorTrimPattern> pattern = value.pattern();
if (pattern.hasId()) {
tag.putString("pattern", TrimPatterns1_20_3.idToKey(pattern.id()));
tag.putString("pattern", trimStorage.trimPatterns().idToKey(pattern.id()));
} else {
final ArmorTrimPattern armorTrimPattern = pattern.value();
final CompoundTag patternTag = new CompoundTag();
@@ -862,9 +862,9 @@ public class ComponentRewriter1_20_5<C extends ClientboundPacketType> extends Co
return tag;
}
protected ListTag<CompoundTag> convertContainer(final Item[] value) {
protected ListTag<CompoundTag> convertContainer(final UserConnection connection, final Item[] value) {
final ListTag<CompoundTag> tag = new ListTag<>(CompoundTag.class);
final ListTag<CompoundTag> items = convertItemArray(value);
final ListTag<CompoundTag> items = convertItemArray(connection, value);
for (int i = 0; i < items.size(); i++) {
final CompoundTag itemTag = new CompoundTag();
itemTag.putInt("slot", i);
@@ -950,17 +950,17 @@ public class ComponentRewriter1_20_5<C extends ClientboundPacketType> extends Co
}
}
protected ListTag<CompoundTag> convertItemArray(final Item[] value) {
protected ListTag<CompoundTag> convertItemArray(final UserConnection connection, final Item[] value) {
final ListTag<CompoundTag> tag = new ListTag<>(CompoundTag.class);
for (final Item item : value) {
final CompoundTag itemTag = new CompoundTag();
convertItem(itemTag, item);
convertItem(connection, itemTag, item);
tag.add(itemTag);
}
return tag;
}
protected void convertItem(final CompoundTag tag, final Item item) {
protected void convertItem(final UserConnection connection, final CompoundTag tag, final Item item) {
final String identifier = mappedIdentifier(item.identifier());
if (identifier == null) {
throw new IllegalArgumentException("Unknown item: " + item.identifier());
@@ -972,7 +972,7 @@ public class ComponentRewriter1_20_5<C extends ClientboundPacketType> extends Co
tag.putInt("count", 1);
}
final Map<StructuredDataKey<?>, StructuredData<?>> components = item.dataContainer().data();
tag.put("components", toTag(components, true));
tag.put("components", toTag(connection, components, true));
}
protected void convertFilterableString(final CompoundTag tag, final FilterableString string, final int max) {
@@ -1126,10 +1126,19 @@ public class ComponentRewriter1_20_5<C extends ClientboundPacketType> extends Co
// ---------------------------------------------------------------------------------------
protected <T> void registerEmpty(final StructuredDataKey<T> key) {
converters.put(key, new ConverterPair<>(null, null));
}
protected <T> void register(final StructuredDataKey<T> key, final DataConverter<T> dataConverter) { // TODO Remove this method
converters.put(key, new ConverterPair<>(dataConverter, null));
}
protected <T> void register(final StructuredDataKey<T> key, final SimpleDataConverter<T> dataConverter) {
final DataConverter<T> converter = ($, value) -> dataConverter.convert(value);
converters.put(key, new ConverterPair<>(converter, null));
}
protected <T> void register(final StructuredDataKey<T> key, final DataConverter<T> dataConverter, final TagConverter<T> tagConverter) {
converters.put(key, new ConverterPair<>(dataConverter, tagConverter));
}
@@ -1151,11 +1160,17 @@ public class ComponentRewriter1_20_5<C extends ClientboundPacketType> extends Co
}
@FunctionalInterface
protected interface DataConverter<T> {
protected interface SimpleDataConverter<T> {
Tag convert(T value);
}
@FunctionalInterface
protected interface DataConverter<T> {
Tag convert(UserConnection connection, T value);
}
@FunctionalInterface
protected interface TagConverter<T> {
@@ -1164,4 +1179,4 @@ public class ComponentRewriter1_20_5<C extends ClientboundPacketType> extends Co
private record ConverterPair<T>(DataConverter<T> dataConverter, TagConverter<T> tagConverter) {
}
}
}
@@ -46,8 +46,10 @@ import com.viaversion.viaversion.protocols.v1_20_3to1_20_5.data.BannerPatterns1_
import com.viaversion.viaversion.protocols.v1_20_3to1_20_5.packet.ClientboundConfigurationPackets1_20_5;
import com.viaversion.viaversion.protocols.v1_20_3to1_20_5.packet.ClientboundPackets1_20_5;
import com.viaversion.viaversion.protocols.v1_20_3to1_20_5.storage.AcknowledgedMessagesStorage;
import com.viaversion.viaversion.protocols.v1_20_3to1_20_5.storage.ArmorTrimStorage;
import com.viaversion.viaversion.rewriter.EntityRewriter;
import com.viaversion.viaversion.util.Key;
import com.viaversion.viaversion.util.KeyMappings;
import com.viaversion.viaversion.util.TagUtil;
import it.unimi.dsi.fastutil.ints.IntArraySet;
import it.unimi.dsi.fastutil.ints.IntSet;
@@ -156,7 +158,8 @@ public final class EntityPacketRewriter1_20_5 extends EntityRewriter<Clientbound
registryEntries[id] = new RegistryEntry(name, tag.get("element"));
}
if (Key.stripMinecraftNamespace(type).equals("damage_type")) {
final String strippedKey = Key.stripMinecraftNamespace(type);
if (strippedKey.equals("damage_type")) {
// Add spit damage type
highestId++;
registryEntries = Arrays.copyOf(registryEntries, highestId + 1);
@@ -188,6 +191,13 @@ public final class EntityPacketRewriter1_20_5 extends EntityRewriter<Clientbound
replaceNullValues(registryEntries);
}
// Track custom armor trims
if (strippedKey.equals("trim_pattern")) {
wrapper.user().get(ArmorTrimStorage.class).setTrimPatterns(toMappings(registryEntries));
} else if (strippedKey.equals("trim_material")) {
wrapper.user().get(ArmorTrimStorage.class).setTrimMaterials(toMappings(registryEntries));
}
final PacketWrapper registryPacket = wrapper.create(ClientboundConfigurationPackets1_20_5.REGISTRY_DATA);
registryPacket.write(Types.STRING, type);
registryPacket.write(Types.REGISTRY_ENTRY_ARRAY, registryEntries);
@@ -328,6 +338,14 @@ public final class EntityPacketRewriter1_20_5 extends EntityRewriter<Clientbound
});
}
private KeyMappings toMappings(final RegistryEntry[] entries) {
final String[] keys = new String[entries.length];
for (int i = 0; i < entries.length; i++) {
keys[i] = Key.stripMinecraftNamespace(entries[i].key());
}
return new KeyMappings(keys);
}
private void updateParticleFormat(final CompoundTag options, final String particleType) {
if ("block".equals(particleType) || "block_marker".equals(particleType) || "falling_dust".equals(particleType) || "dust_pillar".equals(particleType)) {
moveTag(options, "value", "block_state");
@@ -486,10 +504,6 @@ public final class EntityPacketRewriter1_20_5 extends EntityRewriter<Clientbound
return;
}
if (dataIndex > 9) {
event.setIndex(dataIndex - 1);
}
if (dataIndex == 11) {
// If the particle is found first
final EntityData colorData = event.dataAtIndex(9);
@@ -497,6 +511,10 @@ public final class EntityPacketRewriter1_20_5 extends EntityRewriter<Clientbound
addColor(data, colorData.value());
}
}
if (dataIndex > 9) {
event.setIndex(dataIndex - 1);
}
});
filter().type(EntityTypes1_20_5.ARROW).index(10).handler((event, data) -> {
@@ -18,7 +18,6 @@
package com.viaversion.viaversion.protocols.v1_20_3to1_20_5.rewriter;
import com.google.common.base.Preconditions;
import com.viaversion.nbt.tag.ByteTag;
import com.viaversion.nbt.tag.CompoundTag;
import com.viaversion.nbt.tag.FloatTag;
import com.viaversion.nbt.tag.IntArrayTag;
@@ -61,8 +60,7 @@ import com.viaversion.viaversion.protocols.v1_20_3to1_20_5.data.Instruments1_20_
import com.viaversion.viaversion.protocols.v1_20_3to1_20_5.data.MapDecorations1_20_5;
import com.viaversion.viaversion.protocols.v1_20_3to1_20_5.data.PotionEffects1_20_5;
import com.viaversion.viaversion.protocols.v1_20_3to1_20_5.data.Potions1_20_5;
import com.viaversion.viaversion.protocols.v1_20_3to1_20_5.data.TrimMaterials1_20_3;
import com.viaversion.viaversion.protocols.v1_20_3to1_20_5.data.TrimPatterns1_20_3;
import com.viaversion.viaversion.protocols.v1_20_3to1_20_5.storage.ArmorTrimStorage;
import com.viaversion.viaversion.protocols.v1_20_3to1_20_5.storage.BannerPatternStorage;
import com.viaversion.viaversion.util.ComponentUtil;
import com.viaversion.viaversion.util.UUIDUtil;
@@ -390,6 +388,9 @@ public final class StructuredDataConverter {
if (enchantmentsTag == null) {
enchantmentsTag = new ListTag<>(CompoundTag.class);
tag.put("Enchantments", enchantmentsTag);
} else if (!enchantmentsTag.isEmpty()) {
// If there already are enchantments, we don't need to add an invalid one
return;
}
final CompoundTag invalidEnchantment = new CompoundTag();
@@ -513,8 +514,9 @@ public final class StructuredDataConverter {
tag.putInt("map_scale_direction", 1);
}
});
register(StructuredDataKey.TRIM, (data, tag) -> {
register(StructuredDataKey.TRIM, (connection, data, tag) -> {
final CompoundTag trimTag = new CompoundTag();
final ArmorTrimStorage trimStorage = connection.get(ArmorTrimStorage.class);
if (data.material().isDirect()) {
final CompoundTag materialTag = new CompoundTag();
final ArmorTrimMaterial material = data.material().value();
@@ -537,7 +539,7 @@ public final class StructuredDataConverter {
materialTag.put("description", material.description());
trimTag.put("material", materialTag);
} else {
final String oldKey = TrimMaterials1_20_3.idToKey(data.material().id());
final String oldKey = trimStorage.trimMaterials().idToKey(data.material().id());
if (oldKey != null) {
trimTag.putString("material", oldKey);
}
@@ -556,7 +558,7 @@ public final class StructuredDataConverter {
patternTag.putBoolean("decal", pattern.decal());
trimTag.put("pattern", patternTag);
} else {
final String oldKey = TrimPatterns1_20_3.idToKey(data.pattern().id());
final String oldKey = trimStorage.trimPatterns().idToKey(data.pattern().id());
if (oldKey != null) {
trimTag.putString("pattern", oldKey);
}
@@ -15,13 +15,26 @@
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.viaversion.viaversion.protocols.v1_20_3to1_20_5.data;
package com.viaversion.viaversion.protocols.v1_20_3to1_20_5.storage;
import com.viaversion.viaversion.api.connection.StorableObject;
import com.viaversion.viaversion.util.KeyMappings;
import org.checkerframework.checker.nullness.qual.Nullable;
public final class TrimPatterns1_20_3 {
public final class ArmorTrimStorage implements StorableObject {
// Default 1.20.3 registries
private static final KeyMappings MATERIALS = new KeyMappings(
"amethyst",
"copper",
"diamond",
"emerald",
"gold",
"iron",
"lapis",
"netherite",
"quartz",
"redstone"
);
private static final KeyMappings PATTERNS = new KeyMappings(
"coast",
"dune",
@@ -41,11 +54,22 @@ public final class TrimPatterns1_20_3 {
"wild"
);
public static @Nullable String idToKey(final int id) {
return PATTERNS.idToKey(id);
private KeyMappings trimPatterns = PATTERNS;
private KeyMappings trimMaterials = MATERIALS;
public KeyMappings trimPatterns() {
return trimPatterns;
}
public static int keyToId(final String pattern) {
return PATTERNS.keyToId(pattern);
public KeyMappings trimMaterials() {
return trimMaterials;
}
public void setTrimPatterns(final KeyMappings trimPatterns) {
this.trimPatterns = trimPatterns;
}
public void setTrimMaterials(final KeyMappings trimMaterials) {
this.trimMaterials = trimMaterials;
}
}
@@ -48,26 +48,12 @@ public final class ComponentRewriter1_21 extends ComponentRewriter<ClientboundPa
}
}
private void handleContainerComponent(final CompoundTag tag) {
final ListTag<CompoundTag> container = TagUtil.getNamespacedCompoundTagList(tag, "minecraft:container");
if (container == null) {
return;
}
for (final CompoundTag entryTag : container) {
final CompoundTag itemTag = entryTag.getCompoundTag("item");
final CompoundTag componentsTag = itemTag.getCompoundTag("components");
if (componentsTag != null) {
convertAttributeModifiersComponent(componentsTag);
handleContainerComponent(componentsTag);
}
}
}
@Override
protected void handleShowItem(final UserConnection connection, final CompoundTag componentsTag) {
convertAttributeModifiersComponent(componentsTag);
handleContainerComponent(componentsTag);
protected void handleShowItem(final UserConnection connection, final CompoundTag itemTag, final CompoundTag componentsTag) {
super.handleShowItem(connection, itemTag, componentsTag);
if (componentsTag != null) {
convertAttributeModifiersComponent(componentsTag);
}
}
@Override
@@ -124,6 +124,9 @@ public final class EntityPacketRewriter1_21 extends EntityRewriter<ClientboundPa
final int dimensionId = wrapper.passthrough(Types.VAR_INT);
final String world = wrapper.passthrough(Types.STRING);
trackWorldDataByKey1_20_5(wrapper.user(), dimensionId, world); // Tracks world height and name for chunk data and entity (un)tracking
// Resend attribute modifiers from items
wrapper.user().get(EfficiencyAttributeStorage.class).onRespawn(wrapper.user());
});
}
@@ -157,4 +160,4 @@ public final class EntityPacketRewriter1_21 extends EntityRewriter<ClientboundPa
public EntityType typeFromId(final int type) {
return EntityTypes1_20_5.getTypeFromId(type);
}
}
}
@@ -24,6 +24,7 @@ import com.viaversion.viaversion.api.type.Types;
import com.viaversion.viaversion.protocols.v1_20_5to1_21.Protocol1_20_5To1_21;
import com.viaversion.viaversion.protocols.v1_20_5to1_21.packet.ClientboundPackets1_21;
import java.util.List;
import java.util.stream.Stream;
public final class EfficiencyAttributeStorage implements StorableObject {
@@ -33,11 +34,11 @@ public final class EfficiencyAttributeStorage implements StorableObject {
private static final EnchantAttributeModifier AQUA_AFFINITY = new EnchantAttributeModifier("minecraft:enchantment.aqua_affinity", 28, 0.2, level -> level * 4, (byte) 2);
private static final EnchantAttributeModifier DEPTH_STRIDER = new EnchantAttributeModifier("minecraft:enchantment.depth_strider", 30, 0, level -> level / 3D);
private static final ActiveEnchants DEFAULT = new ActiveEnchants(-1,
new ActiveEnchant(EFFICIENCY, 0),
new ActiveEnchant(SOUL_SPEED, 0),
new ActiveEnchant(SWIFT_SNEAK, 0),
new ActiveEnchant(AQUA_AFFINITY, 0),
new ActiveEnchant(DEPTH_STRIDER, 0)
new ActiveEnchant(EFFICIENCY, 0, 0),
new ActiveEnchant(SOUL_SPEED, 0, 0),
new ActiveEnchant(SWIFT_SNEAK, 0, 0),
new ActiveEnchant(AQUA_AFFINITY, 0, 0),
new ActiveEnchant(DEPTH_STRIDER, 0, 0)
);
private final Object lock = new Object();
private volatile boolean attributesSent = true;
@@ -57,15 +58,15 @@ public final class EfficiencyAttributeStorage implements StorableObject {
synchronized (lock) {
this.activeEnchants = new ActiveEnchants(entityId,
new ActiveEnchant(EFFICIENCY, efficiency),
new ActiveEnchant(SOUL_SPEED, soulSpeed),
new ActiveEnchant(SWIFT_SNEAK, swiftSneak),
new ActiveEnchant(AQUA_AFFINITY, aquaAffinity),
new ActiveEnchant(DEPTH_STRIDER, depthStrider)
new ActiveEnchant(activeEnchants.efficiency, efficiency),
new ActiveEnchant(activeEnchants.soulSpeed, soulSpeed),
new ActiveEnchant(activeEnchants.swiftSneak, swiftSneak),
new ActiveEnchant(activeEnchants.aquaAffinity, aquaAffinity),
new ActiveEnchant(activeEnchants.depthStrider, depthStrider)
);
this.attributesSent = false;
}
sendAttributesPacket(connection);
sendAttributesPacket(connection, false);
}
public ActiveEnchants activeEnchants() {
@@ -75,14 +76,18 @@ public final class EfficiencyAttributeStorage implements StorableObject {
public void onLoginSent(final UserConnection connection) {
// Always called from the netty thread
this.loginSent = true;
sendAttributesPacket(connection);
sendAttributesPacket(connection, false);
}
private void sendAttributesPacket(final UserConnection connection) {
public void onRespawn(final UserConnection connection) {
sendAttributesPacket(connection, true);
}
private void sendAttributesPacket(final UserConnection connection, final boolean forceSendAll) {
final ActiveEnchants enchants;
synchronized (lock) {
// Older servers (and often Bungee) will send world state packets before sending the login packet
if (!loginSent || attributesSent) {
if (!forceSendAll && (!loginSent || attributesSent)) {
return;
}
@@ -93,13 +98,15 @@ public final class EfficiencyAttributeStorage implements StorableObject {
final PacketWrapper attributesPacket = PacketWrapper.create(ClientboundPackets1_21.UPDATE_ATTRIBUTES, connection);
attributesPacket.write(Types.VAR_INT, enchants.entityId());
final List<ActiveEnchant> list = List.of(
// Make sure to update this list with new enchantments
// Only send the attribute if it actually changed
final List<ActiveEnchant> list = Stream.of(
enchants.efficiency(),
enchants.soulSpeed(),
enchants.swiftSneak(),
enchants.aquaAffinity(),
enchants.depthStrider()
);
).filter(enchant -> forceSendAll || enchant.previousLevel != enchant.level).toList();
attributesPacket.write(Types.VAR_INT, list.size());
for (final ActiveEnchant enchant : list) {
final EnchantAttributeModifier modifier = enchant.modifier;
@@ -123,7 +130,11 @@ public final class EfficiencyAttributeStorage implements StorableObject {
ActiveEnchant swiftSneak, ActiveEnchant aquaAffinity, ActiveEnchant depthStrider) {
}
public record ActiveEnchant(EnchantAttributeModifier modifier, int level) {
public record ActiveEnchant(EnchantAttributeModifier modifier, int previousLevel, int level) {
public ActiveEnchant(final ActiveEnchant from, final int level) {
this(from.modifier, from.level, level);
}
}
public record EnchantAttributeModifier(String key, int attributeId, double baseValue, LevelToModifier modifierFunction, byte operation) {
@@ -209,17 +209,6 @@ public class ConfigurationState implements StorableObject {
public boolean skipCurrentPipeline() {
return skipCurrentPipeline;
}
@Override
public String toString() {
return "QueuedPacket{" +
"buf=" + buf +
", clientbound=" + clientbound +
", packetType=" + packetType +
", packetId=" + packetId +
", skipCurrentPipeline=" + skipCurrentPipeline +
'}';
}
}
public static final class ClientInformation {
@@ -29,11 +29,4 @@ public class ResourcePackTracker implements StorableObject {
public void setLastHash(String lastHash) {
this.lastHash = lastHash;
}
@Override
public String toString() {
return "ResourcePackTracker{" +
"lastHash='" + lastHash + '\'' +
'}';
}
}
@@ -38,6 +38,7 @@ import com.viaversion.viaversion.api.type.Types;
import com.viaversion.viaversion.protocols.base.ClientboundLoginPackets;
import com.viaversion.viaversion.util.ComponentUtil;
import com.viaversion.viaversion.util.SerializerVersion;
import com.viaversion.viaversion.util.TagUtil;
import org.checkerframework.checker.nullness.qual.Nullable;
/**
@@ -316,15 +317,46 @@ public class ComponentRewriter<C extends ClientboundPacketType> implements com.v
return;
}
// Until they're properly parsed
final CompoundTag componentsTag = contentsTag.getCompoundTag("components");
handleShowItem(connection, contentsTag, componentsTag);
if (componentsTag != null) {
handleShowItem(connection, componentsTag);
handleContainerContents(connection, componentsTag);
handleItemArrayContents(connection, componentsTag, "bundle_contents");
handleItemArrayContents(connection, componentsTag, "charged_projectiles");
}
}
}
protected void handleShowItem(final UserConnection connection, final CompoundTag componentsTag) {
// To override if needed
protected void handleShowItem(final UserConnection connection, final CompoundTag itemTag, @Nullable final CompoundTag componentsTag) {
final StringTag idTag = itemTag.getStringTag("id");
final String mappedId = protocol.getMappingData().getFullItemMappings().mappedIdentifier(idTag.getValue());
if (mappedId != null) {
idTag.setValue(mappedId);
}
}
protected void handleContainerContents(final UserConnection connection, final CompoundTag tag) {
final ListTag<CompoundTag> container = TagUtil.getNamespacedCompoundTagList(tag, "minecraft:container");
if (container == null) {
return;
}
for (final CompoundTag entryTag : container) {
final CompoundTag itemTag = entryTag.getCompoundTag("item");
handleShowItem(connection, itemTag, itemTag.getCompoundTag("components"));
}
}
protected void handleItemArrayContents(final UserConnection connection, final CompoundTag tag, final String key) {
final ListTag<CompoundTag> container = TagUtil.getNamespacedCompoundTagList(tag, key);
if (container == null) {
return;
}
for (final CompoundTag itemTag : container) {
handleShowItem(connection, itemTag, itemTag.getCompoundTag("components"));
}
}
protected SerializerVersion inputSerializerVersion() {
@@ -18,9 +18,6 @@
package com.viaversion.viaversion.util;
import com.google.gson.JsonElement;
import com.viaversion.viaversion.compatibility.YamlCompat;
import com.viaversion.viaversion.compatibility.unsafe.Yaml1Compat;
import com.viaversion.viaversion.compatibility.unsafe.Yaml2Compat;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
@@ -34,19 +31,32 @@ import java.util.concurrent.ConcurrentSkipListMap;
import java.util.logging.Logger;
import org.checkerframework.checker.nullness.qual.Nullable;
import org.yaml.snakeyaml.DumperOptions;
import org.yaml.snakeyaml.LoaderOptions;
import org.yaml.snakeyaml.Yaml;
import org.yaml.snakeyaml.constructor.SafeConstructor;
import org.yaml.snakeyaml.nodes.NodeId;
import org.yaml.snakeyaml.nodes.Tag;
import org.yaml.snakeyaml.representer.Representer;
@SuppressWarnings("VulnerableCodeUsages")
public abstract class Config {
private static final YamlCompat YAMP_COMPAT = YamlCompat.isVersion1() ? new Yaml1Compat() : new Yaml2Compat();
private static final ThreadLocal<Yaml> YAML = ThreadLocal.withInitial(() -> {
DumperOptions options = new DumperOptions();
options.setDefaultFlowStyle(DumperOptions.FlowStyle.BLOCK);
options.setPrettyFlow(false);
options.setIndent(2);
return new Yaml(YAMP_COMPAT.createSafeConstructor(), YAMP_COMPAT.createRepresenter(options), options);
return new Yaml(new CustomSafeConstructor(), new Representer(options), options);
});
private static final class CustomSafeConstructor extends SafeConstructor {
public CustomSafeConstructor() {
super(new LoaderOptions());
yamlClassConstructors.put(NodeId.mapping, new ConstructYamlMap());
yamlConstructors.put(Tag.OMAP, new ConstructYamlOmap());
}
}
private final CommentStore commentStore = new CommentStore('.', 2);
private final File configFile;
protected final Logger logger;
@@ -254,4 +264,4 @@ public abstract class Config {
return null;
}
}
}
}
@@ -136,4 +136,9 @@ public final class TestPlatform implements ViaPlatform {
public boolean hasPlugin(final String name) {
return false;
}
@Override
public boolean couldBeReloading() {
return false;
}
}
-5
View File
@@ -1,5 +0,0 @@
dependencies {
api(projects.compat.snakeyamlCompatCommon)
api(projects.compat.snakeyaml2Compat)
api(projects.compat.snakeyaml1Compat)
}
@@ -1,3 +0,0 @@
dependencies {
compileOnly(rootProject.libs.snakeYaml2)
}
@@ -1,38 +0,0 @@
/*
* This file is part of ViaVersion - https://github.com/ViaVersion/ViaVersion
* Copyright (C) 2016-2024 ViaVersion and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.viaversion.viaversion.compatibility;
import org.yaml.snakeyaml.DumperOptions;
import org.yaml.snakeyaml.constructor.SafeConstructor;
import org.yaml.snakeyaml.representer.Representer;
public interface YamlCompat {
Representer createRepresenter(DumperOptions dumperOptions);
SafeConstructor createSafeConstructor();
static boolean isVersion1() {
try {
SafeConstructor.class.getDeclaredConstructor();
return true;
} catch (NoSuchMethodException e) {
return false;
}
}
}
@@ -1,4 +0,0 @@
dependencies {
api(projects.compat.snakeyamlCompatCommon)
compileOnly(rootProject.libs.snakeYaml)
}
@@ -1,46 +0,0 @@
/*
* This file is part of ViaVersion - https://github.com/ViaVersion/ViaVersion
* Copyright (C) 2016-2024 ViaVersion and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.viaversion.viaversion.compatibility.unsafe;
import com.viaversion.viaversion.compatibility.YamlCompat;
import org.yaml.snakeyaml.DumperOptions;
import org.yaml.snakeyaml.constructor.SafeConstructor;
import org.yaml.snakeyaml.nodes.NodeId;
import org.yaml.snakeyaml.nodes.Tag;
import org.yaml.snakeyaml.representer.Representer;
public final class Yaml1Compat implements YamlCompat {
@Override
public Representer createRepresenter(DumperOptions dumperOptions) {
return new Representer();
}
@Override
public SafeConstructor createSafeConstructor() {
return new CustomSafeConstructor();
}
private static final class CustomSafeConstructor extends SafeConstructor {
public CustomSafeConstructor() {
yamlClassConstructors.put(NodeId.mapping, new ConstructYamlMap());
yamlConstructors.put(Tag.OMAP, new ConstructYamlOmap());
}
}
}
@@ -1,4 +0,0 @@
dependencies {
api(projects.compat.snakeyamlCompatCommon)
compileOnly(rootProject.libs.snakeYaml2)
}
@@ -1,48 +0,0 @@
/*
* This file is part of ViaVersion - https://github.com/ViaVersion/ViaVersion
* Copyright (C) 2016-2024 ViaVersion and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.viaversion.viaversion.compatibility.unsafe;
import com.viaversion.viaversion.compatibility.YamlCompat;
import org.yaml.snakeyaml.DumperOptions;
import org.yaml.snakeyaml.LoaderOptions;
import org.yaml.snakeyaml.constructor.SafeConstructor;
import org.yaml.snakeyaml.nodes.NodeId;
import org.yaml.snakeyaml.nodes.Tag;
import org.yaml.snakeyaml.representer.Representer;
public final class Yaml2Compat implements YamlCompat {
@Override
public Representer createRepresenter(DumperOptions dumperOptions) {
return new Representer(dumperOptions);
}
@Override
public SafeConstructor createSafeConstructor() {
return new CustomSafeConstructor();
}
private static final class CustomSafeConstructor extends SafeConstructor {
public CustomSafeConstructor() {
super(new LoaderOptions());
yamlClassConstructors.put(NodeId.mapping, new ConstructYamlMap());
yamlConstructors.put(Tag.OMAP, new ConstructYamlOmap());
}
}
}
+3 -3
View File
@@ -1,9 +1,9 @@
# Project properties - we put these here so they can be modified without causing a recompile of the build scripts
projectVersion=5.0.2
projectVersion=5.0.4-SNAPSHOT
# Smile emoji
mcVersions=1.21,1.20.6,1.20.5,1.20.4, 1.20.3, 1.20.2, 1.20.1, 1.20, 1.19.4, 1.19.3, 1.19.2, 1.19.1, 1.19, 1.18.2, 1.18.1, 1.18, 1.17.1, 1.17, 1.16.5, 1.16.4, 1.16.3, 1.16.2, 1.16.1, 1.16, 1.15.2, 1.15.1, 1.15, 1.14.4, 1.14.3, 1.14.2, 1.14.1, 1.14, 1.13.2, 1.13.1, 1.13, 1.12.2, 1.12.1, 1.12, 1.11.2, 1.11.1, 1.11, 1.10.2, 1.10.1, 1.10, 1.9.4, 1.9.3, 1.9.2, 1.9.1, 1.9, 1.8.9
mcVersionRange=1.8-1.21
mcVersions=1.21.1,1.21,1.20.6,1.20.5,1.20.4, 1.20.3, 1.20.2, 1.20.1, 1.20, 1.19.4, 1.19.3, 1.19.2, 1.19.1, 1.19, 1.18.2, 1.18.1, 1.18, 1.17.1, 1.17, 1.16.5, 1.16.4, 1.16.3, 1.16.2, 1.16.1, 1.16, 1.15.2, 1.15.1, 1.15, 1.14.4, 1.14.3, 1.14.2, 1.14.1, 1.14, 1.13.2, 1.13.1, 1.13, 1.12.2, 1.12.1, 1.12, 1.11.2, 1.11.1, 1.11, 1.10.2, 1.10.1, 1.10, 1.9.4, 1.9.3, 1.9.2, 1.9.1, 1.9, 1.8.9
mcVersionRange=1.8-1.21.1
velocityVersion=3.3
# Gradle properties
+2 -4
View File
@@ -5,13 +5,12 @@ metadata.format.version = "1.1"
gson = "2.10.1"
fastutil = "8.5.12"
vianbt = "5.0.0"
mcstructs = "5-2.5.0-SNAPSHOT"
mcstructs = "5-2.5.1"
# Common provided
netty = "4.0.20.Final"
guava = "17.0"
snakeYaml = "1.18"
snakeYaml2 = "2.0"
snakeYaml = "2.2"
junit = "5.10.2"
checkerQual = "3.43.0"
@@ -33,7 +32,6 @@ text = { group = "com.viaversion.mcstructs", name = "text", version.ref = "mcstr
netty = { group = "io.netty", name = "netty-all", version.ref = "netty" }
guava = { group = "com.google.guava", name = "guava", version.ref = "guava" }
snakeYaml = { group = "org.yaml", name = "snakeyaml", version.ref = "snakeYaml" }
snakeYaml2 = { group = "org.yaml", name = "snakeyaml", version.ref = "snakeYaml2" }
jupiterApi = { group = "org.junit.jupiter", name = "junit-jupiter-api", version.ref = "junit" }
jupiterEngine = { group = "org.junit.jupiter", name = "junit-jupiter-engine", version.ref = "junit" }
+1 -4
View File
@@ -16,7 +16,7 @@ pluginManagement {
plugins {
id("net.kyori.blossom") version "2.1.0"
id("org.jetbrains.gradle.plugin.idea-ext") version "1.1.7"
id("com.github.johnrengelman.shadow") version "8.1.1"
id("com.gradleup.shadow") version "8.3.0"
}
}
@@ -24,15 +24,12 @@ rootProject.name = "viaversion-parent"
includeBuild("build-logic")
include("compat", "compat:snakeyaml-compat-common", "compat:snakeyaml2-compat", "compat:snakeyaml1-compat")
setupViaSubproject("api")
setupViaSubproject("common")
setupViaSubproject("bukkit")
setupViaSubproject("bukkit-legacy")
setupViaSubproject("velocity")
setupViaSubproject("fabric")
setupViaSubproject("template")
setupSubproject("viaversion") {
projectDir = file("universal")
-3
View File
@@ -1,3 +0,0 @@
dependencies {
compileOnly(projects.viaversionCommon)
}
@@ -58,7 +58,7 @@ import org.slf4j.Logger;
name = "ViaVersion",
version = VersionInfo.VERSION,
authors = {"_MylesC", "creeper123123321", "Gerrygames", "kennytv", "Matsv", "EnZaXD", "RK_01"},
description = "Allow newer Minecraft versions to connect to an older server version.",
description = "Allows the connection of newer clients to older server versions for Minecraft servers.",
url = "https://viaversion.com"
)
public class VelocityPlugin implements ViaServerProxyPlatform<Player> {