Compare commits

..
16 Commits
Author SHA1 Message Date
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
56 changed files with 378 additions and 383 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:
+1 -1
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 -
+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;
}
}
@@ -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");
}
@@ -20,7 +20,7 @@ package com.viaversion.viaversion.bukkit.providers;
import com.viaversion.viaversion.ViaVersionPlugin;
import com.viaversion.viaversion.api.connection.UserConnection;
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;
@@ -45,4 +45,4 @@ public final class BukkitAckSequenceProvider extends AckSequenceProvider {
}
}
}
}
}
@@ -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 +
'}';
}
@@ -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();
@@ -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());
}
}
}
+1 -1
View File
@@ -1,5 +1,5 @@
# 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.3
# 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
+1 -3
View File
@@ -10,8 +10,7 @@ mcstructs = "5-2.5.0-SNAPSHOT"
# 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" }
-2
View File
@@ -24,8 +24,6 @@ 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")
@@ -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> {