mirror of
https://github.com/ViaVersion/ViaVersion.git
synced 2026-11-04 17:00:06 -05:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
0c01425641 | ||
|
|
01d26e7ac5 | ||
|
|
99ea6c32ad | ||
|
|
cf231d92b1 | ||
|
|
f555188428 | ||
|
|
93d6fa2e78 | ||
|
|
162fcafb36 | ||
|
|
3d0a0fe590 | ||
|
|
b06556a84e | ||
|
|
ac8bb104b3 | ||
|
|
4b85ca7691 | ||
|
|
ebd8eb79c1 | ||
|
|
09cffbfb33 | ||
|
|
49a1bffc98 | ||
|
|
da022a0b63 | ||
|
|
3beddaf522 | ||
|
|
70139c6838 | ||
|
|
f040077c13 | ||
|
|
1f404820b7 | ||
|
|
742e70fff6 | ||
|
|
dd6a1a7f6e | ||
|
|
08ef7c2f35 | ||
|
|
e128469313 | ||
|
|
cbb753271e | ||
|
|
29f299d882 | ||
|
|
41138aabd1 | ||
|
|
b90f20cfeb | ||
|
|
585028beb7 |
No files matched your search
@@ -26,7 +26,7 @@ jobs:
|
||||
run: ./gradlew build
|
||||
- name: Upload Artifacts to GitHub
|
||||
# Only upload on the preview repository as there is no CI job for it.
|
||||
if: ${{ github.repository == 'ViaVersionDev' && github.ref_name == 'preview' }}
|
||||
if: ${{ github.repository == 'ViaVersion/ViaVersionDev' && github.ref_name == 'preview' }}
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: Artifacts
|
||||
|
||||
@@ -24,6 +24,7 @@ dependencies {
|
||||
}
|
||||
implementation(rootProject.libs.text) {
|
||||
exclude("com.google.code.gson", "gson")
|
||||
exclude("com.google.guava", "guava")
|
||||
exclude("com.viaversion", "nbt")
|
||||
}
|
||||
api(libs.snakeYaml)
|
||||
|
||||
@@ -123,6 +123,20 @@ public interface EntityTracker {
|
||||
*/
|
||||
void setClientEntityId(int clientEntityId);
|
||||
|
||||
/**
|
||||
* Returns whether the client player has the "insta build" ability, usually from creative mode.
|
||||
*
|
||||
* @return whether the client player can insta build
|
||||
*/
|
||||
boolean canInstaBuild();
|
||||
|
||||
/**
|
||||
* Sets whether the client player has the "insta build" ability, usually from creative mode.
|
||||
*
|
||||
* @param instaBuild whether the client player can insta build
|
||||
*/
|
||||
void setInstaBuild(boolean instaBuild);
|
||||
|
||||
/**
|
||||
* Returns the current world section height (block height / 16).
|
||||
* This is always 16 for sub 1.17 worlds.
|
||||
|
||||
+1
-1
@@ -58,7 +58,7 @@ public class BlockChangeRecord1_16_2 implements BlockChangeRecord {
|
||||
|
||||
@Override
|
||||
public short getY(int chunkSectionY) {
|
||||
Preconditions.checkArgument(chunkSectionY >= 0, "Invalid chunkSectionY: " + chunkSectionY);
|
||||
Preconditions.checkArgument(chunkSectionY >= 0, "Invalid chunkSectionY: %s", chunkSectionY);
|
||||
return (short) ((chunkSectionY << 4) + sectionY);
|
||||
}
|
||||
|
||||
|
||||
@@ -24,22 +24,28 @@ package com.viaversion.viaversion.api.minecraft;
|
||||
|
||||
public enum GameMode {
|
||||
|
||||
NOT_SET(""),
|
||||
SURVIVAL("Survival Mode"),
|
||||
CREATIVE("Creative Mode"),
|
||||
ADVENTURE("Adventure Mode"),
|
||||
SPECTATOR("Spectator Mode");
|
||||
NOT_SET("", -1),
|
||||
SURVIVAL("Survival Mode", 0),
|
||||
CREATIVE("Creative Mode", 1),
|
||||
ADVENTURE("Adventure Mode", 2),
|
||||
SPECTATOR("Spectator Mode", 3);
|
||||
|
||||
private final String text;
|
||||
private final int id;
|
||||
|
||||
GameMode(String text) {
|
||||
GameMode(String text, final int id) {
|
||||
this.text = text;
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public String text() {
|
||||
return text;
|
||||
}
|
||||
|
||||
public int id() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public static GameMode getById(int id) {
|
||||
return switch (id) {
|
||||
case -1 -> NOT_SET;
|
||||
|
||||
@@ -36,7 +36,7 @@ public class BitSetType extends Type<BitSet> {
|
||||
public BitSetType(final int length) {
|
||||
super(BitSet.class);
|
||||
this.length = length;
|
||||
this.bytesLength = -Math.floorDiv(-length, 8); // Ceiled quotient
|
||||
this.bytesLength = (int) Math.ceil(length / 8D);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -48,8 +48,8 @@ public class BitSetType extends Type<BitSet> {
|
||||
|
||||
@Override
|
||||
public void write(ByteBuf buffer, BitSet object) {
|
||||
Preconditions.checkArgument(object.length() <= length, "BitSet of length " + object.length() + " larger than max length " + length);
|
||||
Preconditions.checkArgument(object.length() <= length, "BitSet of length %s larger than max length %s", object.length(), length);
|
||||
final byte[] bytes = object.toByteArray();
|
||||
buffer.writeBytes(Arrays.copyOf(bytes, bytesLength));
|
||||
buffer.writeBytes(bytes.length == bytesLength ? bytes : Arrays.copyOf(bytes, bytesLength));
|
||||
}
|
||||
}
|
||||
@@ -49,13 +49,13 @@ public class StringType extends Type<String> {
|
||||
int len = Types.VAR_INT.readPrimitive(buffer);
|
||||
|
||||
Preconditions.checkArgument(len <= maxLength * MAX_CHAR_UTF_8_LENGTH,
|
||||
"Cannot receive string longer than Short.MAX_VALUE * " + MAX_CHAR_UTF_8_LENGTH + " bytes (got %s bytes)", len);
|
||||
"Cannot receive string longer than " + maxLength + " * " + MAX_CHAR_UTF_8_LENGTH + " bytes (got %s bytes)", len);
|
||||
|
||||
String string = buffer.toString(buffer.readerIndex(), len, StandardCharsets.UTF_8);
|
||||
buffer.skipBytes(len);
|
||||
|
||||
Preconditions.checkArgument(string.length() <= maxLength,
|
||||
"Cannot receive string longer than Short.MAX_VALUE characters (got %s bytes)", string.length());
|
||||
"Cannot receive string longer than " + maxLength + " characters (got %s bytes)", string.length());
|
||||
|
||||
return string;
|
||||
}
|
||||
@@ -63,7 +63,7 @@ public class StringType extends Type<String> {
|
||||
@Override
|
||||
public void write(ByteBuf buffer, String object) {
|
||||
if (object.length() > maxLength) {
|
||||
throw new IllegalArgumentException("Cannot send string longer than Short.MAX_VALUE characters (got " + object.length() + " characters)");
|
||||
throw new IllegalArgumentException("Cannot send string longer than " + maxLength + " characters (got " + object.length() + " characters)");
|
||||
}
|
||||
|
||||
byte[] b = object.getBytes(StandardCharsets.UTF_8);
|
||||
|
||||
+66
@@ -0,0 +1,66 @@
|
||||
/*
|
||||
* This file is part of ViaVersion - https://github.com/ViaVersion/ViaVersion
|
||||
* Copyright (C) 2016-2025 ViaVersion and contributors
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
package com.viaversion.viaversion.api.type.types.chunk;
|
||||
|
||||
import com.viaversion.viaversion.api.minecraft.chunks.DataPalette;
|
||||
import com.viaversion.viaversion.api.minecraft.chunks.PaletteType;
|
||||
import com.viaversion.viaversion.api.type.Type;
|
||||
import com.viaversion.viaversion.api.type.Types;
|
||||
import io.netty.buffer.ByteBuf;
|
||||
|
||||
public class ChunkBiomesType1_19_4 extends Type<DataPalette[]> {
|
||||
private final PaletteTypeBase paletteType;
|
||||
private final int ySectionCount;
|
||||
|
||||
public ChunkBiomesType1_19_4(final int ySectionCount, final int globalPaletteBiomeBits) {
|
||||
this(ySectionCount, new PaletteType1_18(PaletteType.BIOMES, globalPaletteBiomeBits));
|
||||
}
|
||||
|
||||
protected ChunkBiomesType1_19_4(final int ySectionCount, final PaletteTypeBase paletteType) {
|
||||
super(DataPalette[].class);
|
||||
this.paletteType = paletteType;
|
||||
this.ySectionCount = ySectionCount;
|
||||
}
|
||||
|
||||
@Override
|
||||
public DataPalette[] read(final ByteBuf buffer) {
|
||||
final ByteBuf data = buffer.readSlice(Types.VAR_INT.readPrimitive(buffer));
|
||||
final DataPalette[] sections = new DataPalette[ySectionCount];
|
||||
for (int i = 0; i < ySectionCount; i++) {
|
||||
sections[i] = paletteType.read(data);
|
||||
}
|
||||
return sections;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void write(final ByteBuf buffer, final DataPalette[] value) {
|
||||
int size = 0;
|
||||
for (final DataPalette biomes : value) {
|
||||
size += paletteType.serializedSize(biomes);
|
||||
}
|
||||
Types.VAR_INT.writePrimitive(buffer, size);
|
||||
for (final DataPalette biomes : value) {
|
||||
paletteType.write(buffer, biomes);
|
||||
}
|
||||
}
|
||||
}
|
||||
+32
@@ -0,0 +1,32 @@
|
||||
/*
|
||||
* This file is part of ViaVersion - https://github.com/ViaVersion/ViaVersion
|
||||
* Copyright (C) 2016-2025 ViaVersion and contributors
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
package com.viaversion.viaversion.api.type.types.chunk;
|
||||
|
||||
import com.viaversion.viaversion.api.minecraft.chunks.PaletteType;
|
||||
|
||||
public class ChunkBiomesType1_21_5 extends ChunkBiomesType1_19_4 {
|
||||
|
||||
public ChunkBiomesType1_21_5(final int ySectionCount, final int globalPaletteBiomeBits) {
|
||||
super(ySectionCount, new PaletteType1_21_5(PaletteType.BIOMES, globalPaletteBiomeBits));
|
||||
}
|
||||
}
|
||||
@@ -30,10 +30,18 @@ public interface Copyable {
|
||||
} else if (object instanceof Copyable copyable) {
|
||||
return (T) copyable.copy();
|
||||
} else if (object.getClass().isArray()) {
|
||||
final Object[] array = (Object[]) object;
|
||||
final Object[] copy = (Object[]) Array.newInstance(array.getClass().getComponentType(), array.length);
|
||||
for (int i = 0; i < array.length; i++) {
|
||||
copy[i] = copy(array[i]);
|
||||
final Class<?> componentType = object.getClass().getComponentType();
|
||||
final int length = Array.getLength(object);
|
||||
final Object copy = Array.newInstance(componentType, length);
|
||||
if (componentType.isPrimitive()) {
|
||||
for (int i = 0; i < length; i++) {
|
||||
Array.set(copy, i, Array.get(object, i));
|
||||
}
|
||||
} else {
|
||||
// See if we need to copy elements, too
|
||||
for (int i = 0; i < length; i++) {
|
||||
Array.set(copy, i, copy(Array.get(object, i)));
|
||||
}
|
||||
}
|
||||
return (T) copy;
|
||||
} else {
|
||||
|
||||
@@ -37,6 +37,16 @@ public final class Key {
|
||||
return identifier.substring(index + 1);
|
||||
}
|
||||
|
||||
public static String namespace(final String identifier) {
|
||||
final int index = identifier.indexOf(':');
|
||||
if (index == -1) {
|
||||
return "minecraft";
|
||||
} else if (index == 0) {
|
||||
return "minecraft";
|
||||
}
|
||||
return identifier.substring(0, index);
|
||||
}
|
||||
|
||||
public static String stripMinecraftNamespace(final String identifier) {
|
||||
if (identifier.startsWith("minecraft:")) {
|
||||
return identifier.substring(MINECRAFT_NAMESPACE_LENGTH);
|
||||
|
||||
+114
@@ -0,0 +1,114 @@
|
||||
/*
|
||||
* This file is part of ViaVersion - https://github.com/ViaVersion/ViaVersion
|
||||
* Copyright (C) 2016-2025 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.util;
|
||||
|
||||
import com.viaversion.viaversion.api.Via;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.block.Block;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
import org.checkerframework.checker.nullness.qual.Nullable;
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.Random;
|
||||
import java.util.logging.Level;
|
||||
|
||||
public class LegacyBlockToItem {
|
||||
private static final LegacyBlockToItem INSTANCE;
|
||||
private static final Random RANDOM = new Random();
|
||||
|
||||
static {
|
||||
LegacyBlockToItem instance = null;
|
||||
try {
|
||||
instance = new LegacyBlockToItem();
|
||||
} catch (ReflectiveOperationException ex) {
|
||||
Via.getPlatform().getLogger().log(
|
||||
Level.WARNING,
|
||||
"Couldn't find reflection methods/fields for pick-block functionality.\n" +
|
||||
"Pick-block won't work on clients 1.21.4 and newer.", ex);
|
||||
}
|
||||
INSTANCE = instance;
|
||||
}
|
||||
|
||||
private final Method GET_WORLD_HANDLE;
|
||||
private final Method GET_BLOCK_TYPE;
|
||||
private final Method GET_BLOCK;
|
||||
private final Method GET_ITEM_FOR_BLOCK;
|
||||
private final Method GET_DROP_TYPE;
|
||||
private final Method TO_BUKKIT_ITEM_STACK;
|
||||
private final Method NEW_BUKKIT_ITEM_STACK;
|
||||
|
||||
private final Method SET_POSITION;
|
||||
private final Object BLOCK_POSITION;
|
||||
|
||||
public LegacyBlockToItem() throws ReflectiveOperationException {
|
||||
Class<?> blockPosition = NMSUtil.nms("BlockPosition");
|
||||
Class<?> mutableBlockPosition = NMSUtil.nms("BlockPosition$MutableBlockPosition");
|
||||
Class<?> world = NMSUtil.nms("World");
|
||||
Class<?> block = NMSUtil.nms("Block");
|
||||
Class<?> iBlockData = NMSUtil.nms("IBlockData");
|
||||
Class<?> nmsItem = NMSUtil.nms("Item");
|
||||
Class<?> nmsItemStack = NMSUtil.nms("ItemStack");
|
||||
Class<?> craftItemStack = NMSUtil.obc("inventory.CraftItemStack");
|
||||
|
||||
GET_WORLD_HANDLE = NMSUtil.obc("CraftWorld").getDeclaredMethod("getHandle");
|
||||
GET_BLOCK_TYPE = world.getDeclaredMethod("getType", blockPosition);
|
||||
GET_BLOCK = iBlockData.getDeclaredMethod("getBlock");
|
||||
GET_ITEM_FOR_BLOCK = block.getDeclaredMethod("i", iBlockData);
|
||||
GET_ITEM_FOR_BLOCK.setAccessible(true);
|
||||
|
||||
GET_DROP_TYPE = block.getDeclaredMethod("getDropType", iBlockData, Random.class, int.class);
|
||||
|
||||
TO_BUKKIT_ITEM_STACK = craftItemStack.getDeclaredMethod("asCraftMirror", nmsItemStack);
|
||||
NEW_BUKKIT_ITEM_STACK = craftItemStack.getDeclaredMethod("asNewCraftStack", nmsItem);
|
||||
|
||||
SET_POSITION = mutableBlockPosition.getDeclaredMethod("c", int.class, int.class, int.class);
|
||||
BLOCK_POSITION = mutableBlockPosition.getConstructor().newInstance();
|
||||
}
|
||||
|
||||
public static LegacyBlockToItem getInstance() {
|
||||
return INSTANCE;
|
||||
}
|
||||
|
||||
public @Nullable ItemStack blockToItem(final Block block) {
|
||||
try {
|
||||
// World nmsWorld = block.getWorld().getHandle();
|
||||
Object nmsWorld = GET_WORLD_HANDLE.invoke(block.getWorld());
|
||||
|
||||
// IBlockData blockData = nmsWorld.get(block.position());
|
||||
SET_POSITION.invoke(BLOCK_POSITION, block.getX(), block.getY(), block.getZ());
|
||||
Object blockData = GET_BLOCK_TYPE.invoke(nmsWorld, BLOCK_POSITION);
|
||||
|
||||
// Block nmsBlock = blockData.getBlock();
|
||||
Object nmsBlock = GET_BLOCK.invoke(blockData);
|
||||
// ItemStack is = nmsBlock.getItemForBlock(blockData);
|
||||
Object nmsItemStack = GET_ITEM_FOR_BLOCK.invoke(nmsBlock, blockData);
|
||||
|
||||
// CraftItemStack.asCraftMirror(nmsItemStack)
|
||||
ItemStack stack = (ItemStack) TO_BUKKIT_ITEM_STACK.invoke(null, nmsItemStack);
|
||||
if (stack.getType() != Material.AIR) return stack;
|
||||
|
||||
// Couldn't find an item for the block (eg: redstone dust, sugarcane, doors, etc.), use the drop instead
|
||||
Object nmsItem = GET_DROP_TYPE.invoke(nmsBlock, blockData, RANDOM, 0);
|
||||
return (ItemStack) NEW_BUKKIT_ITEM_STACK.invoke(null, nmsItem);
|
||||
} catch (ReflectiveOperationException ex) {
|
||||
Via.getPlatform().getLogger().log(
|
||||
Level.WARNING, "Failed when trying to find the right item for pick-block.", ex);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -192,9 +192,7 @@ public class BukkitViaLoader implements ViaPlatformLoader {
|
||||
}
|
||||
}
|
||||
if (serverProtocolVersion.olderThan(ProtocolVersion.v1_21_4)) {
|
||||
if (PaperViaInjector.hasMethod(Material.class, "isItem")) {
|
||||
Via.getManager().getProviders().use(PickItemProvider.class, new BukkitPickItemProvider(plugin));
|
||||
}
|
||||
Via.getManager().getProviders().use(PickItemProvider.class, new BukkitPickItemProvider(plugin));
|
||||
}
|
||||
|
||||
// Needs to be enabled on any version with the updated item desync check
|
||||
|
||||
+65
-22
@@ -21,6 +21,7 @@ import com.viaversion.viaversion.ViaVersionPlugin;
|
||||
import com.viaversion.viaversion.api.connection.UserConnection;
|
||||
import com.viaversion.viaversion.api.minecraft.BlockPosition;
|
||||
import com.viaversion.viaversion.bukkit.platform.PaperViaInjector;
|
||||
import com.viaversion.viaversion.bukkit.util.LegacyBlockToItem;
|
||||
import com.viaversion.viaversion.protocols.v1_21_2to1_21_4.provider.PickItemProvider;
|
||||
import java.util.UUID;
|
||||
import org.bukkit.Bukkit;
|
||||
@@ -31,14 +32,17 @@ import org.bukkit.block.Block;
|
||||
import org.bukkit.entity.Entity;
|
||||
import org.bukkit.entity.EntityType;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.inventory.Inventory;
|
||||
import org.bukkit.inventory.ItemFactory;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
import org.bukkit.inventory.PlayerInventory;
|
||||
import org.bukkit.inventory.meta.BlockStateMeta;
|
||||
import org.checkerframework.checker.nullness.qual.Nullable;
|
||||
|
||||
public final class BukkitPickItemProvider extends PickItemProvider {
|
||||
private static final boolean HAS_PLACEMENT_MATERIAL_METHOD = PaperViaInjector.hasMethod("org.bukkit.block.data.BlockData", "getPlacementMaterial");
|
||||
public class BukkitPickItemProvider extends PickItemProvider {
|
||||
private static final BlockToItem BLOCK_TO_ITEM = BlockToItem.build();
|
||||
private static final GetStorageContents GET_STORAGE_CONTENT = GetStorageContents.build();
|
||||
private static final SetInHand SET_IN_HAND = SetInHand.build();
|
||||
|
||||
private static final boolean HAS_SPAWN_EGG_METHOD = PaperViaInjector.hasMethod(ItemFactory.class, "getSpawnEgg", EntityType.class);
|
||||
private static final double BLOCK_RANGE = 4.5 + 1;
|
||||
private static final double BLOCK_RANGE_SQUARED = BLOCK_RANGE * BLOCK_RANGE;
|
||||
@@ -68,27 +72,13 @@ public final class BukkitPickItemProvider extends PickItemProvider {
|
||||
return;
|
||||
}
|
||||
|
||||
final ItemStack item = blockToItem(block, includeData && player.getGameMode() == GameMode.CREATIVE);
|
||||
if (item != null) {
|
||||
final ItemStack item = BLOCK_TO_ITEM.apply(block, includeData && player.getGameMode() == GameMode.CREATIVE);
|
||||
if (item != null && item.getType() != Material.AIR) {
|
||||
pickItem(player, item);
|
||||
}
|
||||
}, player);
|
||||
}
|
||||
|
||||
private @Nullable ItemStack blockToItem(final Block block, final boolean includeData) {
|
||||
if (HAS_PLACEMENT_MATERIAL_METHOD) {
|
||||
final ItemStack item = new ItemStack(block.getBlockData().getPlacementMaterial(), 1);
|
||||
if (includeData && item.getItemMeta() instanceof final BlockStateMeta blockStateMeta) {
|
||||
blockStateMeta.setBlockState(block.getState());
|
||||
item.setItemMeta(blockStateMeta);
|
||||
}
|
||||
return item;
|
||||
} else if (block.getType().isItem()) {
|
||||
return new ItemStack(block.getType(), 1);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void pickItemFromEntity(final UserConnection connection, final int entityId, final boolean includeData) {
|
||||
if (!HAS_SPAWN_EGG_METHOD) {
|
||||
@@ -120,7 +110,8 @@ public final class BukkitPickItemProvider extends PickItemProvider {
|
||||
private void pickItem(final Player player, final ItemStack item) {
|
||||
// Find matching item
|
||||
final PlayerInventory inventory = player.getInventory();
|
||||
final ItemStack[] contents = inventory.getStorageContents();
|
||||
// Prior to getStorageContents, getContents worked the same (it ignored armor)
|
||||
final ItemStack[] contents = GET_STORAGE_CONTENT.apply(inventory);
|
||||
int sourceSlot = -1;
|
||||
for (int i = 0; i < contents.length; i++) {
|
||||
final ItemStack content = contents[i];
|
||||
@@ -155,7 +146,7 @@ public final class BukkitPickItemProvider extends PickItemProvider {
|
||||
}
|
||||
|
||||
inventory.setItem(emptySlot, heldItem);
|
||||
inventory.setItemInMainHand(item);
|
||||
SET_IN_HAND.apply(inventory, item);
|
||||
}
|
||||
|
||||
private void moveToHotbar(final PlayerInventory inventory, final int sourceSlot, final ItemStack[] contents) {
|
||||
@@ -168,7 +159,7 @@ public final class BukkitPickItemProvider extends PickItemProvider {
|
||||
final int targetSlot = findEmptyHotbarSlot(inventory, heldSlot);
|
||||
inventory.setHeldItemSlot(targetSlot);
|
||||
final ItemStack heldItem = inventory.getItem(targetSlot);
|
||||
inventory.setItemInMainHand(contents[sourceSlot]);
|
||||
SET_IN_HAND.apply(inventory, contents[sourceSlot]);
|
||||
inventory.setItem(sourceSlot, heldItem);
|
||||
}
|
||||
|
||||
@@ -181,4 +172,56 @@ public final class BukkitPickItemProvider extends PickItemProvider {
|
||||
}
|
||||
return heldSlot;
|
||||
}
|
||||
|
||||
@FunctionalInterface
|
||||
private interface BlockToItem {
|
||||
ItemStack apply(final Block block, final boolean includeData);
|
||||
|
||||
static BlockToItem build() {
|
||||
if (PaperViaInjector.hasMethod("org.bukkit.block.data.BlockData", "getPlacementMaterial")) {
|
||||
return (block, includeData) -> {
|
||||
final ItemStack item = new ItemStack(block.getBlockData().getPlacementMaterial(), 1);
|
||||
if (includeData && item.getItemMeta() instanceof final BlockStateMeta blockStateMeta) {
|
||||
blockStateMeta.setBlockState(block.getState());
|
||||
item.setItemMeta(blockStateMeta);
|
||||
}
|
||||
return item;
|
||||
};
|
||||
} else if (PaperViaInjector.hasMethod(Material.class, "isItem")) {
|
||||
return (block, includeData) -> new ItemStack(block.getType(), 1);
|
||||
} else {
|
||||
LegacyBlockToItem legacy = LegacyBlockToItem.getInstance();
|
||||
return legacy != null ? (block, includeData) -> legacy.blockToItem(block) : (b, i) -> null;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@FunctionalInterface
|
||||
private interface GetStorageContents {
|
||||
ItemStack[] apply(final PlayerInventory inv);
|
||||
|
||||
static GetStorageContents build() {
|
||||
if (PaperViaInjector.hasMethod(Inventory.class, "getStorageContents")) {
|
||||
return Inventory::getStorageContents;
|
||||
} else {
|
||||
return Inventory::getContents;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@FunctionalInterface
|
||||
private interface SetInHand {
|
||||
void apply(final PlayerInventory inv, final ItemStack stack);
|
||||
|
||||
@SuppressWarnings("deprecation")
|
||||
static SetInHand build() {
|
||||
if (PaperViaInjector.hasMethod(PlayerInventory.class, "setItemInMainHand")) {
|
||||
return PlayerInventory::setItemInMainHand;
|
||||
} else {
|
||||
return PlayerInventory::setItemInHand;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -2,6 +2,8 @@ dependencies {
|
||||
api(projects.viaversionApi)
|
||||
api(rootProject.libs.text) {
|
||||
exclude("com.google.code.gson", "gson")
|
||||
exclude("com.google.guava", "guava")
|
||||
exclude("com.viaversion", "nbt")
|
||||
}
|
||||
|
||||
// Note: If manually starting tests doesn't work for you in IJ, change 'Gradle -> Run Tests Using' to 'IntelliJ IDEA'
|
||||
|
||||
@@ -148,7 +148,7 @@ public class ViaManagerImpl implements ViaManager {
|
||||
platform.getLogger().warning("ViaVersion only supports newer client versions. Use ViaBackwards to allow older versions (ViaRewind for 1.7/1.8) to join.");
|
||||
platform.getLogger().warning("Get setup help at https://viaversion.com/setup or download ViaBackwards/ViaRewind directly at https://ci.viaversion.com/");
|
||||
platform.getLogger().warning("Need more help? Join our Discord at https://viaversion.com/discord");
|
||||
} else if (protocolVersion.highestSupportedProtocolVersion().olderThan(ProtocolVersion.v1_13)) {
|
||||
} else if (protocolVersion.highestSupportedProtocolVersion().olderThan(ProtocolVersion.v1_16)) {
|
||||
platform.getLogger().warning("This version of Minecraft is extremely outdated and support for it has reached its end of life. "
|
||||
+ "You will still be able to run Via on this Minecraft version, but we will prioritize issues with legacy Minecraft versions less. "
|
||||
+ "Please consider updating to give your players a better experience and to avoid issues that have long been fixed.");
|
||||
|
||||
@@ -19,6 +19,7 @@ package com.viaversion.viaversion.connection;
|
||||
|
||||
import com.google.gson.JsonObject;
|
||||
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.platform.ViaPlatform;
|
||||
import com.viaversion.viaversion.api.protocol.version.ProtocolVersion;
|
||||
@@ -37,7 +38,14 @@ public final class ConnectionDetails {
|
||||
public static final String APP_CHANNEL = "vv:app_details";
|
||||
|
||||
public static void sendConnectionDetails(final UserConnection connection, final String channel) {
|
||||
final ProtocolVersion nativeVersion = connection.getProtocolInfo().protocolVersion();
|
||||
final ProtocolInfo protocolInfo = connection.getProtocolInfo();
|
||||
final ProtocolVersion nativeVersion = protocolInfo.protocolVersion();
|
||||
final ProtocolVersion serverVersion = protocolInfo.serverProtocolVersion();
|
||||
if (serverVersion.equals(nativeVersion)) {
|
||||
// No need to send details if the native version is the same as the server version
|
||||
return;
|
||||
}
|
||||
|
||||
final String platformName = Via.getPlatform().getPlatformName();
|
||||
final String platformVersion = Via.getPlatform().getPlatformVersion();
|
||||
|
||||
|
||||
@@ -43,6 +43,7 @@ public class EntityTrackerBase implements EntityTracker, ClientEntityIdChangeLis
|
||||
private String currentWorld;
|
||||
private int biomesSent = -1;
|
||||
private Map<String, DimensionData> dimensions = Collections.emptyMap();
|
||||
private boolean instaBuild;
|
||||
|
||||
public EntityTrackerBase(UserConnection connection, @Nullable EntityType playerType) {
|
||||
this.connection = connection;
|
||||
@@ -131,6 +132,16 @@ public class EntityTrackerBase implements EntityTracker, ClientEntityIdChangeLis
|
||||
this.clientEntityId = clientEntityId;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canInstaBuild() {
|
||||
return instaBuild;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setInstaBuild(final boolean instaBuild) {
|
||||
this.instaBuild = instaBuild;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int currentWorldSectionHeight() {
|
||||
return currentWorldSectionHeight;
|
||||
|
||||
@@ -263,8 +263,11 @@ public class PacketWrapperImpl implements PacketWrapper {
|
||||
}
|
||||
|
||||
private InformativeException createInformativeException(final Exception cause, final Type<?> type, final int index) {
|
||||
final ProtocolInfo protocolInfo = this.user().getProtocolInfo();
|
||||
return new InformativeException(cause)
|
||||
.set("Packet Type", this.packetType)
|
||||
.set("Client Protocol", protocolInfo.protocolVersion().getName())
|
||||
.set("Server Protocol", protocolInfo.serverProtocolVersion().getName())
|
||||
.set("Index", index)
|
||||
.set("Type", type.getTypeName())
|
||||
.set("Data", this.packetValues)
|
||||
|
||||
+4
-25
@@ -19,7 +19,6 @@ package com.viaversion.viaversion.protocols.template;
|
||||
|
||||
import com.viaversion.viaversion.api.minecraft.entities.EntityType;
|
||||
import com.viaversion.viaversion.api.minecraft.entities.EntityTypes1_21_4;
|
||||
import com.viaversion.viaversion.api.type.Types;
|
||||
import com.viaversion.viaversion.api.type.types.version.Types1_21_4;
|
||||
import com.viaversion.viaversion.protocols.v1_20_5to1_21.packet.ClientboundConfigurationPackets1_21;
|
||||
import com.viaversion.viaversion.protocols.v1_21to1_21_2.packet.ClientboundPacket1_21_2;
|
||||
@@ -42,33 +41,13 @@ final class EntityPacketRewriter1_99 extends EntityRewriter<ClientboundPacket1_2
|
||||
registerTrackerWithData1_19(ClientboundPackets1_21_2.ADD_ENTITY, EntityTypes1_21_4.FALLING_BLOCK);
|
||||
registerSetEntityData(ClientboundPackets1_21_2.SET_ENTITY_DATA, /*Types1_OLD_ENTITY_DATA_LIST, */Types1_21_4.ENTITY_DATA_LIST); // Specify old and new entity data list if changed
|
||||
registerRemoveEntities(ClientboundPackets1_21_2.REMOVE_ENTITIES);
|
||||
registerPlayerAbilities(ClientboundPackets1_21_2.PLAYER_ABILITIES);
|
||||
registerGameEvent(ClientboundPackets1_21_2.GAME_EVENT);
|
||||
registerLogin1_20_5(ClientboundPackets1_21_2.LOGIN);
|
||||
registerRespawn1_20_5(ClientboundPackets1_21_2.RESPAWN);
|
||||
|
||||
final RegistryDataRewriter registryDataRewriter = new RegistryDataRewriter(protocol);
|
||||
protocol.registerClientbound(ClientboundConfigurationPackets1_21.REGISTRY_DATA, registryDataRewriter::handle);
|
||||
|
||||
protocol.registerClientbound(ClientboundPackets1_21_2.LOGIN, wrapper -> {
|
||||
final int entityId = wrapper.passthrough(Types.INT); // Entity id
|
||||
wrapper.passthrough(Types.BOOLEAN); // Hardcore
|
||||
wrapper.passthrough(Types.STRING_ARRAY); // World List
|
||||
wrapper.passthrough(Types.VAR_INT); // Max players
|
||||
wrapper.passthrough(Types.VAR_INT); // View distance
|
||||
wrapper.passthrough(Types.VAR_INT); // Simulation distance
|
||||
wrapper.passthrough(Types.BOOLEAN); // Reduced debug info
|
||||
wrapper.passthrough(Types.BOOLEAN); // Show death screen
|
||||
wrapper.passthrough(Types.BOOLEAN); // Limited crafting
|
||||
|
||||
final int dimensionId = wrapper.passthrough(Types.VAR_INT);
|
||||
final String world = wrapper.passthrough(Types.STRING);
|
||||
trackWorldDataByKey1_20_5(wrapper.user(), dimensionId, world);
|
||||
|
||||
trackPlayer(wrapper.user(), entityId);
|
||||
});
|
||||
|
||||
protocol.registerClientbound(ClientboundPackets1_21_2.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
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
+3
-3
@@ -55,9 +55,9 @@ import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.UUID;
|
||||
import net.lenni0451.mcstructs.core.TextFormatting;
|
||||
import net.lenni0451.mcstructs.text.ATextComponent;
|
||||
import net.lenni0451.mcstructs.text.Style;
|
||||
import net.lenni0451.mcstructs.text.TextComponent;
|
||||
import net.lenni0451.mcstructs.text.TextFormatting;
|
||||
import net.lenni0451.mcstructs.text.components.TranslationComponent;
|
||||
import org.checkerframework.checker.nullness.qual.Nullable;
|
||||
|
||||
@@ -394,7 +394,7 @@ public final class Protocol1_19To1_19_1 extends AbstractProtocol<ClientboundPack
|
||||
|
||||
// Add the replacements
|
||||
final ListTag<StringTag> parameters = tag.getListTag("parameters", StringTag.class);
|
||||
final List<ATextComponent> arguments = new ArrayList<>();
|
||||
final List<TextComponent> arguments = new ArrayList<>();
|
||||
if (parameters != null) {
|
||||
for (final StringTag element : parameters) {
|
||||
JsonElement argument = null;
|
||||
|
||||
+1
-1
@@ -94,7 +94,7 @@ public final class Protocol1_20_3To1_20_5 extends AbstractProtocol<ClientboundPa
|
||||
new StatisticsRewriter<>(this).register(ClientboundPackets1_20_3.AWARD_STATS);
|
||||
|
||||
componentRewriter.registerComponentPacket(ClientboundPackets1_20_3.SYSTEM_CHAT);
|
||||
componentRewriter.registerDisguisedChat(ClientboundPackets1_20_3.DISGUISED_CHAT);
|
||||
componentRewriter.registerComponentPacket(ClientboundPackets1_20_3.DISGUISED_CHAT);
|
||||
componentRewriter.registerPlayerCombatKill1_20(ClientboundPackets1_20_3.PLAYER_COMBAT_KILL);
|
||||
|
||||
// People add item hovers to all sorts of weird places...
|
||||
|
||||
+19
-5
@@ -471,21 +471,35 @@ public final class BlockItemPacketRewriter1_20_5 extends ItemRewriter<Clientboun
|
||||
CompoundTag entityTag = tag.getCompoundTag("EntityTag");
|
||||
if (entityTag != null) {
|
||||
entityTag = entityTag.copy();
|
||||
// Additional tooltips of items don't validate the entity id in 1.20.4, add the entity id for these back so
|
||||
// 1.20.5+ parses it correctly (as otherwise not used on the client).
|
||||
if (entityTag.contains("variant")) {
|
||||
entityTag.putString("id", "minecraft:painting");
|
||||
} else if (entityTag.contains("ShowArms")) {
|
||||
entityTag.putString("id", "minecraft:armor_stand");
|
||||
}
|
||||
data.set(StructuredDataKey.ENTITY_DATA, entityTag);
|
||||
|
||||
if (entityTag.contains("id")) {
|
||||
data.set(StructuredDataKey.ENTITY_DATA, entityTag);
|
||||
}
|
||||
}
|
||||
|
||||
final CompoundTag blockEntityTag = tag.getCompoundTag("BlockEntityTag");
|
||||
if (blockEntityTag != null) {
|
||||
final CompoundTag clonedTag = blockEntityTag.copy();
|
||||
// Same as above
|
||||
updateBlockEntityTag(connection, data, clonedTag);
|
||||
CompoundTag spawnData = clonedTag.getCompoundTag("SpawnData");
|
||||
if (spawnData == null) {
|
||||
spawnData = clonedTag.getCompoundTag("spawn_data");
|
||||
}
|
||||
if (spawnData != null) {
|
||||
final CompoundTag entity = spawnData.getCompoundTag("entity");
|
||||
if (entity != null && entity.getString("id") != null) {
|
||||
addBlockEntityId(clonedTag, clonedTag.contains("SpawnData") ? "mob_spawner" : "trial_spawner");
|
||||
}
|
||||
}
|
||||
|
||||
// Not always needed, e.g. shields that had the base color in a block entity tag before
|
||||
if (blockEntityTag.contains("id")) {
|
||||
if (clonedTag.contains("id")) {
|
||||
item.dataContainer().set(StructuredDataKey.BLOCK_ENTITY_DATA, clonedTag);
|
||||
}
|
||||
}
|
||||
@@ -1518,7 +1532,7 @@ public final class BlockItemPacketRewriter1_20_5 extends ItemRewriter<Clientboun
|
||||
}
|
||||
|
||||
data.set(StructuredDataKey.CONTAINER1_20_5, filteredItems);
|
||||
addBlockEntityId(tag, "shulker_box"); // Won't happen to the others and doesn't actually have to be correct otherwise
|
||||
addBlockEntityId(tag, "shulker_box");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+15
-11
@@ -247,7 +247,7 @@ public class ComponentRewriter1_20_5<C extends ClientboundPacketType> extends Js
|
||||
if (!data.isEmpty()) {
|
||||
final CompoundTag components;
|
||||
try {
|
||||
components = toTag(connection, data, false);
|
||||
components = toTag(connection, data);
|
||||
} catch (final Exception e) {
|
||||
if (!Via.getConfig().isSuppressConversionWarnings()) {
|
||||
protocol.getLogger().log(Level.WARNING, "Error writing components in show_item!", e);
|
||||
@@ -258,7 +258,7 @@ public class ComponentRewriter1_20_5<C extends ClientboundPacketType> extends Js
|
||||
}
|
||||
}
|
||||
|
||||
public CompoundTag toTag(final UserConnection connection, final Map<StructuredDataKey<?>, StructuredData<?>> data, final boolean empty) {
|
||||
public CompoundTag toTag(final UserConnection connection, final Map<StructuredDataKey<?>, StructuredData<?>> data) {
|
||||
final CompoundTag tag = new CompoundTag();
|
||||
for (final Map.Entry<StructuredDataKey<?>, StructuredData<?>> entry : data.entrySet()) {
|
||||
final StructuredDataKey<?> key = entry.getKey();
|
||||
@@ -273,12 +273,8 @@ public class ComponentRewriter1_20_5<C extends ClientboundPacketType> extends Js
|
||||
|
||||
final StructuredData<?> value = entry.getValue();
|
||||
if (value.isEmpty()) {
|
||||
if (empty) {
|
||||
// Theoretically not needed here, but we'll keep it for consistency
|
||||
tag.put("!" + identifier, new CompoundTag());
|
||||
continue;
|
||||
}
|
||||
throw new IllegalArgumentException("Empty structured data: " + identifier);
|
||||
tag.put("!" + identifier, new CompoundTag());
|
||||
continue;
|
||||
}
|
||||
|
||||
//noinspection unchecked
|
||||
@@ -303,11 +299,19 @@ public class ComponentRewriter1_20_5<C extends ClientboundPacketType> extends Js
|
||||
return list;
|
||||
}
|
||||
|
||||
public StructuredData<?> readFromTag(final UserConnection connection, final String identifier, final Tag tag) {
|
||||
private StructuredData<?> readFromTag(final UserConnection connection, String identifier, final Tag tag) {
|
||||
final boolean removed = identifier.startsWith("!");
|
||||
if (removed) {
|
||||
identifier = identifier.substring(1);
|
||||
}
|
||||
final int id = protocol.getMappingData().getDataComponentSerializerMappings().mappedId(identifier);
|
||||
Preconditions.checkArgument(id != -1, "Unknown data component: %s", identifier);
|
||||
final StructuredDataKey<?> key = structuredDataType.key(id);
|
||||
return readFromTag(connection, key, id, tag);
|
||||
if (removed) {
|
||||
return StructuredData.empty(key, id);
|
||||
} else {
|
||||
return readFromTag(connection, key, id, tag);
|
||||
}
|
||||
}
|
||||
|
||||
protected <T> StructuredData<T> readFromTag(final UserConnection connection, final StructuredDataKey<T> key, final int id, final Tag tag) {
|
||||
@@ -1561,7 +1565,7 @@ public class ComponentRewriter1_20_5<C extends ClientboundPacketType> extends Js
|
||||
tag.putInt("count", 1);
|
||||
}
|
||||
final Map<StructuredDataKey<?>, StructuredData<?>> components = item.dataContainer().data();
|
||||
final CompoundTag componentsTag = toTag(connection, components, true);
|
||||
final CompoundTag componentsTag = toTag(connection, components);
|
||||
if (!componentsTag.isEmpty()) {
|
||||
tag.put("components", componentsTag);
|
||||
}
|
||||
|
||||
+5
-5
@@ -24,6 +24,7 @@ import com.viaversion.nbt.tag.Tag;
|
||||
import com.viaversion.viaversion.api.Via;
|
||||
import com.viaversion.viaversion.api.connection.UserConnection;
|
||||
import com.viaversion.viaversion.api.data.entity.DimensionData;
|
||||
import com.viaversion.viaversion.api.minecraft.GameMode;
|
||||
import com.viaversion.viaversion.api.minecraft.Particle;
|
||||
import com.viaversion.viaversion.api.minecraft.RegistryEntry;
|
||||
import com.viaversion.viaversion.api.minecraft.data.StructuredDataContainer;
|
||||
@@ -64,7 +65,6 @@ public final class EntityPacketRewriter1_20_5 extends EntityRewriter<Clientbound
|
||||
|
||||
private static final UUID CREATIVE_BLOCK_INTERACTION_RANGE = UUID.fromString("736565d2-e1a7-403d-a3f8-1aeb3e302542");
|
||||
private static final UUID CREATIVE_ENTITY_INTERACTION_RANGE = UUID.fromString("98491ef6-97b1-4584-ae82-71a8cc85cf73");
|
||||
private static final int CREATIVE_MODE_ID = 1;
|
||||
|
||||
public EntityPacketRewriter1_20_5(final Protocol1_20_3To1_20_5 protocol) {
|
||||
super(protocol);
|
||||
@@ -279,7 +279,7 @@ public final class EntityPacketRewriter1_20_5 extends EntityRewriter<Clientbound
|
||||
|
||||
// Handle creative interaction range
|
||||
final byte gamemode = wrapper.get(Types.BYTE, 0);
|
||||
if (gamemode == CREATIVE_MODE_ID) {
|
||||
if (gamemode == GameMode.CREATIVE.id()) {
|
||||
sendRangeAttributes(wrapper.user(), true);
|
||||
}
|
||||
});
|
||||
@@ -296,7 +296,7 @@ public final class EntityPacketRewriter1_20_5 extends EntityRewriter<Clientbound
|
||||
wrapper.passthrough(Types.LONG); // Seed
|
||||
|
||||
final byte gamemode = wrapper.passthrough(Types.BYTE);
|
||||
sendRangeAttributes(wrapper.user(), gamemode == CREATIVE_MODE_ID);
|
||||
sendRangeAttributes(wrapper.user(), gamemode == GameMode.CREATIVE.id());
|
||||
});
|
||||
|
||||
protocol.registerClientbound(ClientboundPackets1_20_3.UPDATE_MOB_EFFECT, wrapper -> {
|
||||
@@ -338,8 +338,8 @@ public final class EntityPacketRewriter1_20_5 extends EntityRewriter<Clientbound
|
||||
}
|
||||
|
||||
// Resend attributes either with their original list or with the creative range modifier added
|
||||
final float value = wrapper.passthrough(Types.FLOAT);
|
||||
sendRangeAttributes(wrapper.user(), value == CREATIVE_MODE_ID);
|
||||
final int value = (int) Math.floor(wrapper.passthrough(Types.FLOAT) + 0.5F);
|
||||
sendRangeAttributes(wrapper.user(), value == GameMode.CREATIVE.id());
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
+3
-20
@@ -26,7 +26,6 @@ import com.viaversion.viaversion.api.minecraft.entities.EntityType;
|
||||
import com.viaversion.viaversion.api.minecraft.entities.EntityTypes1_20_5;
|
||||
import com.viaversion.viaversion.api.minecraft.entitydata.EntityDataType;
|
||||
import com.viaversion.viaversion.api.protocol.packet.PacketWrapper;
|
||||
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.api.type.types.version.Types1_21;
|
||||
@@ -95,25 +94,9 @@ public final class EntityPacketRewriter1_21 extends EntityRewriter<ClientboundPa
|
||||
jukeboxSongsPacket.send(Protocol1_20_5To1_21.class);
|
||||
});
|
||||
|
||||
protocol.registerClientbound(ClientboundPackets1_20_5.LOGIN, new PacketHandlers() {
|
||||
@Override
|
||||
public void register() {
|
||||
map(Types.INT); // Entity id
|
||||
map(Types.BOOLEAN); // Hardcore
|
||||
map(Types.STRING_ARRAY); // World List
|
||||
map(Types.VAR_INT); // Max players
|
||||
map(Types.VAR_INT); // View distance
|
||||
map(Types.VAR_INT); // Simulation distance
|
||||
map(Types.BOOLEAN); // Reduced debug info
|
||||
map(Types.BOOLEAN); // Show death screen
|
||||
map(Types.BOOLEAN); // Limited crafting
|
||||
map(Types.VAR_INT); // Dimension id
|
||||
map(Types.STRING); // World
|
||||
handler(worldDataTrackerHandlerByKey1_20_5(3));
|
||||
handler(playerTrackerHandler());
|
||||
handler(wrapper -> wrapper.user().get(EfficiencyAttributeStorage.class)
|
||||
.onLoginSent(wrapper.get(Types.INT, 0), wrapper.user()));
|
||||
}
|
||||
registerLogin1_20_5(ClientboundPackets1_20_5.LOGIN);
|
||||
protocol.appendClientbound(ClientboundPackets1_20_5.LOGIN, wrapper -> {
|
||||
wrapper.user().get(EfficiencyAttributeStorage.class).onLoginSent(wrapper.get(Types.INT, 0), wrapper.user());
|
||||
});
|
||||
|
||||
protocol.registerClientbound(ClientboundPackets1_20_5.RESPAWN, wrapper -> {
|
||||
|
||||
+1
-1
@@ -178,7 +178,7 @@ public final class BlockItemPacketRewriter1_21_4 extends StructuredItemRewriter<
|
||||
// and consume time really high, so the eating animation doesn't play
|
||||
item.dataContainer().set(StructuredDataKey.CONSUMABLE1_21_2,
|
||||
new Consumable1_21_2(
|
||||
3600,
|
||||
3600,
|
||||
3,
|
||||
Holder.of(new SoundEvent("minecraft:intentionally_empty", null)),
|
||||
false,
|
||||
|
||||
+2
-23
@@ -77,29 +77,8 @@ public final class EntityPacketRewriter1_21_4 extends EntityRewriter<Clientbound
|
||||
};
|
||||
protocol.registerClientbound(ClientboundConfigurationPackets1_21.REGISTRY_DATA, registryDataRewriter::handle);
|
||||
|
||||
protocol.registerClientbound(ClientboundPackets1_21_2.LOGIN, wrapper -> {
|
||||
final int entityId = wrapper.passthrough(Types.INT); // Entity id
|
||||
wrapper.passthrough(Types.BOOLEAN); // Hardcore
|
||||
wrapper.passthrough(Types.STRING_ARRAY); // World List
|
||||
wrapper.passthrough(Types.VAR_INT); // Max players
|
||||
wrapper.passthrough(Types.VAR_INT); // View distance
|
||||
wrapper.passthrough(Types.VAR_INT); // Simulation distance
|
||||
wrapper.passthrough(Types.BOOLEAN); // Reduced debug info
|
||||
wrapper.passthrough(Types.BOOLEAN); // Show death screen
|
||||
wrapper.passthrough(Types.BOOLEAN); // Limited crafting
|
||||
|
||||
final int dimensionId = wrapper.passthrough(Types.VAR_INT);
|
||||
final String world = wrapper.passthrough(Types.STRING);
|
||||
trackWorldDataByKey1_20_5(wrapper.user(), dimensionId, world);
|
||||
|
||||
trackPlayer(wrapper.user(), entityId);
|
||||
});
|
||||
|
||||
protocol.registerClientbound(ClientboundPackets1_21_2.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
|
||||
});
|
||||
registerLogin1_20_5(ClientboundPackets1_21_2.LOGIN);
|
||||
registerRespawn1_20_5(ClientboundPackets1_21_2.RESPAWN);
|
||||
|
||||
protocol.registerServerbound(ServerboundPackets1_21_4.MOVE_VEHICLE, wrapper -> {
|
||||
wrapper.passthrough(Types.DOUBLE); // X
|
||||
|
||||
+70
-2
@@ -31,6 +31,7 @@ import com.viaversion.viaversion.api.minecraft.Holder;
|
||||
import com.viaversion.viaversion.api.minecraft.blockentity.BlockEntity;
|
||||
import com.viaversion.viaversion.api.minecraft.chunks.Chunk;
|
||||
import com.viaversion.viaversion.api.minecraft.chunks.Chunk1_21_5;
|
||||
import com.viaversion.viaversion.api.minecraft.chunks.DataPalette;
|
||||
import com.viaversion.viaversion.api.minecraft.chunks.Heightmap;
|
||||
import com.viaversion.viaversion.api.minecraft.data.StructuredData;
|
||||
import com.viaversion.viaversion.api.minecraft.data.StructuredDataContainer;
|
||||
@@ -53,8 +54,11 @@ import com.viaversion.viaversion.api.minecraft.item.data.TooltipDisplay;
|
||||
import com.viaversion.viaversion.api.minecraft.item.data.Unbreakable;
|
||||
import com.viaversion.viaversion.api.protocol.packet.PacketWrapper;
|
||||
import com.viaversion.viaversion.api.protocol.version.ProtocolVersion;
|
||||
import com.viaversion.viaversion.api.rewriter.ComponentRewriter;
|
||||
import com.viaversion.viaversion.api.type.Type;
|
||||
import com.viaversion.viaversion.api.type.Types;
|
||||
import com.viaversion.viaversion.api.type.types.chunk.ChunkBiomesType1_19_4;
|
||||
import com.viaversion.viaversion.api.type.types.chunk.ChunkBiomesType1_21_5;
|
||||
import com.viaversion.viaversion.api.type.types.chunk.ChunkType1_20_2;
|
||||
import com.viaversion.viaversion.api.type.types.chunk.ChunkType1_21_5;
|
||||
import com.viaversion.viaversion.api.type.types.version.Types1_21_4;
|
||||
@@ -68,6 +72,7 @@ import com.viaversion.viaversion.protocols.v1_21to1_21_2.packet.ClientboundPacke
|
||||
import com.viaversion.viaversion.rewriter.BlockRewriter;
|
||||
import com.viaversion.viaversion.rewriter.RecipeDisplayRewriter;
|
||||
import com.viaversion.viaversion.rewriter.StructuredItemRewriter;
|
||||
import com.viaversion.viaversion.util.Key;
|
||||
import com.viaversion.viaversion.util.Limit;
|
||||
import com.viaversion.viaversion.util.Unit;
|
||||
import it.unimi.dsi.fastutil.ints.IntLinkedOpenHashSet;
|
||||
@@ -149,6 +154,19 @@ public final class BlockItemPacketRewriter1_21_5 extends StructuredItemRewriter<
|
||||
wrapper.write(newChunkType, mappedChunk);
|
||||
});
|
||||
|
||||
protocol.registerClientbound(ClientboundPackets1_21_2.CHUNKS_BIOMES, wrapper -> {
|
||||
final EntityTracker tracker = protocol.getEntityRewriter().tracker(wrapper.user());
|
||||
final int globalPaletteBiomeBits = ceilLog2(tracker.biomesSent());
|
||||
final Type<DataPalette[]> biomesType = new ChunkBiomesType1_19_4(tracker.currentWorldSectionHeight(), globalPaletteBiomeBits);
|
||||
final Type<DataPalette[]> newBiomesType = new ChunkBiomesType1_21_5(tracker.currentWorldSectionHeight(), globalPaletteBiomeBits);
|
||||
|
||||
final int size = wrapper.passthrough(Types.VAR_INT);
|
||||
for (int i = 0; i < size; i++) {
|
||||
wrapper.passthrough(Types.CHUNK_POSITION);
|
||||
wrapper.passthroughAndMap(biomesType, newBiomesType);
|
||||
}
|
||||
});
|
||||
|
||||
protocol.registerClientbound(ClientboundPackets1_21_2.SET_CURSOR_ITEM, this::passthroughClientboundItem);
|
||||
registerSetPlayerInventory(ClientboundPackets1_21_2.SET_PLAYER_INVENTORY);
|
||||
registerCooldown1_21_2(ClientboundPackets1_21_2.COOLDOWN);
|
||||
@@ -158,6 +176,11 @@ public final class BlockItemPacketRewriter1_21_5 extends StructuredItemRewriter<
|
||||
registerMerchantOffers1_20_5(ClientboundPackets1_21_2.MERCHANT_OFFERS);
|
||||
|
||||
protocol.registerServerbound(ServerboundPackets1_21_5.SET_CREATIVE_MODE_SLOT, wrapper -> {
|
||||
if (!protocol.getEntityRewriter().tracker(wrapper.user()).canInstaBuild()) {
|
||||
wrapper.cancel();
|
||||
return;
|
||||
}
|
||||
|
||||
wrapper.passthrough(Types.SHORT); // Slot
|
||||
|
||||
final Item item = handleItemToServer(wrapper.user(), wrapper.read(Types1_21_5.LENGTH_PREFIXED_ITEM));
|
||||
@@ -185,8 +208,41 @@ public final class BlockItemPacketRewriter1_21_5 extends StructuredItemRewriter<
|
||||
wrapper.write(Types1_21_5.ITEM, handleItemToServer(wrapper.user(), this.convertHashedItemToStructuredItem(wrapper.user(), carriedItem)));
|
||||
});
|
||||
|
||||
registerAdvancements1_20_3(ClientboundPackets1_21_2.UPDATE_ADVANCEMENTS);
|
||||
protocol.appendClientbound(ClientboundPackets1_21_2.UPDATE_ADVANCEMENTS, wrapper -> {
|
||||
protocol.registerClientbound(ClientboundPackets1_21_2.UPDATE_ADVANCEMENTS, wrapper -> {
|
||||
wrapper.passthrough(Types.BOOLEAN); // Reset/clear
|
||||
int size = wrapper.passthrough(Types.VAR_INT); // Mapping size
|
||||
for (int i = 0; i < size; i++) {
|
||||
wrapper.passthrough(Types.STRING); // Identifier
|
||||
wrapper.passthrough(Types.OPTIONAL_STRING); // Parent
|
||||
|
||||
// Display data
|
||||
if (wrapper.passthrough(Types.BOOLEAN)) {
|
||||
final Tag title = wrapper.passthrough(Types.TAG);
|
||||
final Tag description = wrapper.passthrough(Types.TAG);
|
||||
final ComponentRewriter componentRewriter = protocol.getComponentRewriter();
|
||||
if (componentRewriter != null) {
|
||||
componentRewriter.processTag(wrapper.user(), title);
|
||||
componentRewriter.processTag(wrapper.user(), description);
|
||||
}
|
||||
|
||||
passthroughClientboundItem(wrapper); // Icon
|
||||
wrapper.passthrough(Types.VAR_INT); // Frame type
|
||||
int flags = wrapper.passthrough(Types.INT); // Flags
|
||||
if ((flags & 1) != 0) {
|
||||
convertClientAsset(wrapper);
|
||||
}
|
||||
wrapper.passthrough(Types.FLOAT); // X
|
||||
wrapper.passthrough(Types.FLOAT); // Y
|
||||
}
|
||||
|
||||
int requirements = wrapper.passthrough(Types.VAR_INT);
|
||||
for (int array = 0; array < requirements; array++) {
|
||||
wrapper.passthrough(Types.STRING_ARRAY);
|
||||
}
|
||||
|
||||
wrapper.passthrough(Types.BOOLEAN); // Send telemetry
|
||||
}
|
||||
|
||||
wrapper.passthrough(Types.STRING_ARRAY); // Removed
|
||||
final int progressSize = wrapper.passthrough(Types.VAR_INT);
|
||||
for (int i = 0; i < progressSize; i++) {
|
||||
@@ -223,6 +279,18 @@ public final class BlockItemPacketRewriter1_21_5 extends StructuredItemRewriter<
|
||||
recipeRewriter.registerPlaceGhostRecipe(ClientboundPackets1_21_2.PLACE_GHOST_RECIPE);
|
||||
}
|
||||
|
||||
private void convertClientAsset(final PacketWrapper wrapper) {
|
||||
final String background = wrapper.read(Types.STRING);
|
||||
final String namespace = Key.namespace(background);
|
||||
final String path = Key.stripNamespace(background);
|
||||
if (path.startsWith("textures/") && path.endsWith(".png")) {
|
||||
final String stripped = path.substring("textures/".length(), path.length() - ".png".length());
|
||||
wrapper.write(Types.STRING, namespace + ":" + stripped);
|
||||
} else {
|
||||
wrapper.write(Types.STRING, namespace + ":" + path);
|
||||
}
|
||||
}
|
||||
|
||||
private void handleBlockEntity(final UserConnection connection, final BlockEntity blockEntity) {
|
||||
final CompoundTag tag = blockEntity.tag();
|
||||
if (tag != null && (blockEntity.typeId() == SIGN_BOCK_ENTITY_ID || blockEntity.typeId() == HANGING_SIGN_BOCK_ENTITY_ID)) {
|
||||
|
||||
+17
-16
@@ -109,6 +109,19 @@ public final class ComponentRewriter1_21_5 extends JsonNBTComponentRewriter<Clie
|
||||
handleEnchantments(componentsTag, "enchantments");
|
||||
handleEnchantments(componentsTag, "stored_enchantments");
|
||||
|
||||
// Usual item handling
|
||||
final CompoundTag useRemainder = TagUtil.getNamespacedCompoundTag(componentsTag, "use_remainder");
|
||||
if (useRemainder != null) {
|
||||
handleShowItem(connection, useRemainder);
|
||||
}
|
||||
handleContainerContents(connection, componentsTag);
|
||||
handleItemArrayContents(connection, componentsTag, "bundle_contents");
|
||||
handleItemArrayContents(connection, componentsTag, "charged_projectiles");
|
||||
handleWrittenBookContents(connection, componentsTag);
|
||||
|
||||
// NO MORE SNBT IN TEXT COMPONENTS
|
||||
updateUglyJson(componentsTag, connection);
|
||||
|
||||
removeDataComponents(componentsTag, StructuredDataKey.INSTRUMENT1_21_2, StructuredDataKey.JUKEBOX_PLAYABLE1_21);
|
||||
}
|
||||
|
||||
@@ -218,22 +231,9 @@ public final class ComponentRewriter1_21_5 extends JsonNBTComponentRewriter<Clie
|
||||
final CompoundTag componentsTag = compoundContents.getCompoundTag("components");
|
||||
handleShowItem(connection, compoundContents, componentsTag);
|
||||
|
||||
if (componentsTag == null) {
|
||||
return;
|
||||
if (componentsTag != null) {
|
||||
hoverEventTag.put("components", componentsTag);
|
||||
}
|
||||
|
||||
hoverEventTag.put("components", componentsTag);
|
||||
|
||||
final CompoundTag useRemainder = TagUtil.getNamespacedCompoundTag(componentsTag, "use_remainder");
|
||||
if (useRemainder != null) {
|
||||
handleShowItem(connection, useRemainder);
|
||||
}
|
||||
handleContainerContents(connection, componentsTag);
|
||||
handleItemArrayContents(connection, componentsTag, "bundle_contents");
|
||||
handleItemArrayContents(connection, componentsTag, "charged_projectiles");
|
||||
handleWrittenBookContents(connection, componentsTag);
|
||||
|
||||
updateUglyJson(componentsTag, connection);
|
||||
} else if (contentsTag instanceof final StringTag inlinedContents) {
|
||||
hoverEventTag.put("id", inlinedContents);
|
||||
}
|
||||
@@ -267,7 +267,7 @@ public final class ComponentRewriter1_21_5 extends JsonNBTComponentRewriter<Clie
|
||||
final String actualKey = TagUtil.getNamespacedTagKey(componentsTag, key);
|
||||
final String json = componentsTag.getString(actualKey);
|
||||
if (json == null) {
|
||||
return;
|
||||
return;
|
||||
}
|
||||
|
||||
componentsTag.put(actualKey, uglyJsonToTag(connection, json));
|
||||
@@ -299,6 +299,7 @@ public final class ComponentRewriter1_21_5 extends JsonNBTComponentRewriter<Clie
|
||||
}
|
||||
|
||||
public Tag uglyJsonToTag(final UserConnection connection, final String value) {
|
||||
// Use the same version for deserializing and serializing, as we handle the remaining changes ourselves
|
||||
final Tag contents = SerializerVersion.V1_21_4.toTag(SerializerVersion.V1_21_4.toComponent(value));
|
||||
processTag(connection, contents);
|
||||
return contents;
|
||||
|
||||
+5
-23
@@ -56,6 +56,8 @@ public final class EntityPacketRewriter1_21_5 extends EntityRewriter<Clientbound
|
||||
registerTrackerWithData1_19(ClientboundPackets1_21_2.ADD_ENTITY, EntityTypes1_21_5.FALLING_BLOCK);
|
||||
registerSetEntityData(ClientboundPackets1_21_2.SET_ENTITY_DATA, Types1_21_4.ENTITY_DATA_LIST, Types1_21_5.ENTITY_DATA_LIST);
|
||||
registerRemoveEntities(ClientboundPackets1_21_2.REMOVE_ENTITIES);
|
||||
registerPlayerAbilities(ClientboundPackets1_21_2.PLAYER_ABILITIES);
|
||||
registerGameEvent(ClientboundPackets1_21_2.GAME_EVENT);
|
||||
|
||||
// No more special experience orb add packet
|
||||
protocol.registerClientbound(ClientboundPackets1_21_2.ADD_EXPERIENCE_ORB, ClientboundPackets1_21_5.ADD_ENTITY, wrapper -> {
|
||||
@@ -115,30 +117,10 @@ public final class EntityPacketRewriter1_21_5 extends EntityRewriter<Clientbound
|
||||
wolfSoundVariantsPacket.send(Protocol1_21_4To1_21_5.class);
|
||||
});
|
||||
|
||||
protocol.registerClientbound(ClientboundPackets1_21_2.LOGIN, wrapper -> {
|
||||
registerRespawn1_20_5(ClientboundPackets1_21_2.RESPAWN);
|
||||
registerLogin1_20_5(ClientboundPackets1_21_2.LOGIN);
|
||||
protocol.appendClientbound(ClientboundPackets1_21_2.LOGIN, wrapper -> {
|
||||
wrapper.user().get(MessageIndexStorage.class).setIndex(0);
|
||||
|
||||
final int entityId = wrapper.passthrough(Types.INT); // Entity id
|
||||
wrapper.passthrough(Types.BOOLEAN); // Hardcore
|
||||
wrapper.passthrough(Types.STRING_ARRAY); // World List
|
||||
wrapper.passthrough(Types.VAR_INT); // Max players
|
||||
wrapper.passthrough(Types.VAR_INT); // View distance
|
||||
wrapper.passthrough(Types.VAR_INT); // Simulation distance
|
||||
wrapper.passthrough(Types.BOOLEAN); // Reduced debug info
|
||||
wrapper.passthrough(Types.BOOLEAN); // Show death screen
|
||||
wrapper.passthrough(Types.BOOLEAN); // Limited crafting
|
||||
|
||||
final int dimensionId = wrapper.passthrough(Types.VAR_INT);
|
||||
final String world = wrapper.passthrough(Types.STRING);
|
||||
trackWorldDataByKey1_20_5(wrapper.user(), dimensionId, world);
|
||||
|
||||
trackPlayer(wrapper.user(), entityId);
|
||||
});
|
||||
|
||||
protocol.registerClientbound(ClientboundPackets1_21_2.RESPAWN, wrapper -> {
|
||||
final int dimensionId = wrapper.passthrough(Types.VAR_INT);
|
||||
final String world = wrapper.passthrough(Types.STRING);
|
||||
trackWorldDataByKey1_20_5(wrapper.user(), dimensionId, world);
|
||||
});
|
||||
|
||||
protocol.registerClientbound(ClientboundPackets1_21_2.SET_PLAYER_TEAM, wrapper -> {
|
||||
|
||||
+22
-6
@@ -30,6 +30,7 @@ import com.viaversion.viaversion.api.protocol.remapper.PacketHandlers;
|
||||
import com.viaversion.viaversion.api.type.Types;
|
||||
import com.viaversion.viaversion.api.type.types.version.Types1_21;
|
||||
import com.viaversion.viaversion.api.type.types.version.Types1_21_2;
|
||||
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;
|
||||
@@ -265,20 +266,21 @@ public final class EntityPacketRewriter1_21_2 extends EntityRewriter<Clientbound
|
||||
});
|
||||
protocol.registerServerbound(ServerboundPackets1_21_2.PLAYER_INPUT, wrapper -> {
|
||||
// Previously only used while in a vehicle, now always sent
|
||||
// Filter them appropriately
|
||||
if (!wrapper.user().has(ClientVehicleStorage.class)) {
|
||||
wrapper.cancel();
|
||||
// Filter them appropriately and always send them when in a vehicle
|
||||
wrapper.cancel();
|
||||
final ClientVehicleStorage vehicleStorage = wrapper.user().get(ClientVehicleStorage.class);
|
||||
if (vehicleStorage == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
final byte flags = wrapper.read(Types.BYTE);
|
||||
final boolean left = (flags & 1 << 2) != 0;
|
||||
final boolean right = (flags & 1 << 3) != 0;
|
||||
wrapper.write(Types.FLOAT, left ? IMPULSE : (right ? -IMPULSE : 0F));
|
||||
final float sidewaysMovement = left ? IMPULSE : (right ? -IMPULSE : 0F);
|
||||
|
||||
final boolean forward = (flags & 1 << 0) != 0;
|
||||
final boolean backward = (flags & 1 << 1) != 0;
|
||||
wrapper.write(Types.FLOAT, forward ? IMPULSE : (backward ? -IMPULSE : 0F));
|
||||
final float forwardMovement = forward ? IMPULSE : (backward ? -IMPULSE : 0F);
|
||||
|
||||
byte updatedFlags = 0;
|
||||
if ((flags & 1 << 4) != 0) {
|
||||
@@ -287,7 +289,8 @@ public final class EntityPacketRewriter1_21_2 extends EntityRewriter<Clientbound
|
||||
if ((flags & 1 << 5) != 0) {
|
||||
updatedFlags |= 2;
|
||||
}
|
||||
wrapper.write(Types.BYTE, updatedFlags);
|
||||
|
||||
vehicleStorage.storeMovement(sidewaysMovement, forwardMovement, updatedFlags);
|
||||
});
|
||||
|
||||
protocol.registerClientbound(ClientboundPackets1_21.TELEPORT_ENTITY, ClientboundPackets1_21_2.ENTITY_POSITION_SYNC, wrapper -> {
|
||||
@@ -346,6 +349,19 @@ public final class EntityPacketRewriter1_21_2 extends EntityRewriter<Clientbound
|
||||
wrapper.passthrough(Types.FLOAT); // Yaw
|
||||
wrapper.passthrough(Types.FLOAT); // Pitch
|
||||
handleOnGround(wrapper);
|
||||
|
||||
final ClientVehicleStorage vehicleStorage = wrapper.user().get(ClientVehicleStorage.class);
|
||||
if (vehicleStorage == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
wrapper.sendToServer(Protocol1_21To1_21_2.class);
|
||||
wrapper.cancel();
|
||||
final PacketWrapper playerInput = wrapper.create(ServerboundPackets1_20_5.PLAYER_INPUT);
|
||||
playerInput.write(Types.FLOAT, vehicleStorage.sidewaysMovement());
|
||||
playerInput.write(Types.FLOAT, vehicleStorage.forwardMovement());
|
||||
playerInput.write(Types.BYTE, vehicleStorage.flags());
|
||||
playerInput.sendToServer(Protocol1_21To1_21_2.class);
|
||||
});
|
||||
protocol.registerServerbound(ServerboundPackets1_21_2.MOVE_PLAYER_STATUS_ONLY, wrapper -> {
|
||||
final GroundFlagTracker tracker = wrapper.user().get(GroundFlagTracker.class);
|
||||
|
||||
+34
-1
@@ -19,5 +19,38 @@ package com.viaversion.viaversion.protocols.v1_21to1_21_2.storage;
|
||||
|
||||
import com.viaversion.viaversion.api.connection.StorableObject;
|
||||
|
||||
public record ClientVehicleStorage(int vehicleId) implements StorableObject {
|
||||
public final class ClientVehicleStorage implements StorableObject {
|
||||
|
||||
private final int vehicleId;
|
||||
|
||||
private float sidewaysMovement;
|
||||
private float forwardMovement;
|
||||
private byte flags;
|
||||
|
||||
public ClientVehicleStorage(final int vehicleId) {
|
||||
this.vehicleId = vehicleId;
|
||||
}
|
||||
|
||||
public void storeMovement(final float sidewaysMovement, final float forwardMovement, final byte flags) {
|
||||
this.sidewaysMovement = sidewaysMovement;
|
||||
this.forwardMovement = forwardMovement;
|
||||
this.flags = flags;
|
||||
}
|
||||
|
||||
public int vehicleId() {
|
||||
return vehicleId;
|
||||
}
|
||||
|
||||
public float sidewaysMovement() {
|
||||
return sidewaysMovement;
|
||||
}
|
||||
|
||||
public float forwardMovement() {
|
||||
return forwardMovement;
|
||||
}
|
||||
|
||||
public byte flags() {
|
||||
return flags;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -30,6 +30,7 @@ import com.viaversion.viaversion.api.data.Mappings;
|
||||
import com.viaversion.viaversion.api.data.entity.DimensionData;
|
||||
import com.viaversion.viaversion.api.data.entity.EntityTracker;
|
||||
import com.viaversion.viaversion.api.data.entity.TrackedEntity;
|
||||
import com.viaversion.viaversion.api.minecraft.GameMode;
|
||||
import com.viaversion.viaversion.api.minecraft.Particle;
|
||||
import com.viaversion.viaversion.api.minecraft.entities.EntityType;
|
||||
import com.viaversion.viaversion.api.minecraft.entitydata.EntityData;
|
||||
@@ -364,6 +365,60 @@ public abstract class EntityRewriter<C extends ClientboundPacketType, T extends
|
||||
registerSetEntityData(packetType, null, dataType);
|
||||
}
|
||||
|
||||
public void registerLogin1_20_5(C packetType) {
|
||||
protocol.registerClientbound(packetType, wrapper -> {
|
||||
final int entityId = wrapper.passthrough(Types.INT);
|
||||
wrapper.passthrough(Types.BOOLEAN); // Hardcore
|
||||
wrapper.passthrough(Types.STRING_ARRAY); // World List
|
||||
wrapper.passthrough(Types.VAR_INT); // Max players
|
||||
wrapper.passthrough(Types.VAR_INT); // View distance
|
||||
wrapper.passthrough(Types.VAR_INT); // Simulation distance
|
||||
wrapper.passthrough(Types.BOOLEAN); // Reduced debug info
|
||||
wrapper.passthrough(Types.BOOLEAN); // Show death screen
|
||||
wrapper.passthrough(Types.BOOLEAN); // Limited crafting
|
||||
|
||||
final int dimensionId = wrapper.passthrough(Types.VAR_INT);
|
||||
final String world = wrapper.passthrough(Types.STRING);
|
||||
trackWorldDataByKey1_20_5(wrapper.user(), dimensionId, world);
|
||||
|
||||
wrapper.passthrough(Types.LONG); // Seed
|
||||
final byte gamemode = wrapper.passthrough(Types.BYTE);
|
||||
tracker(wrapper.user()).setInstaBuild(gamemode == GameMode.CREATIVE.id());
|
||||
|
||||
trackPlayer(wrapper.user(), entityId);
|
||||
});
|
||||
}
|
||||
|
||||
public void registerRespawn1_20_5(C packetType) {
|
||||
protocol.registerClientbound(packetType, 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
|
||||
|
||||
wrapper.passthrough(Types.LONG); // Seed
|
||||
final byte gamemode = wrapper.passthrough(Types.BYTE);
|
||||
tracker(wrapper.user()).setInstaBuild(gamemode == GameMode.CREATIVE.id());
|
||||
});
|
||||
}
|
||||
|
||||
// Track the insta payer build ability
|
||||
public void registerPlayerAbilities(C packetType) {
|
||||
protocol.registerClientbound(packetType, wrapper -> {
|
||||
final byte flags = wrapper.passthrough(Types.BYTE);
|
||||
tracker(wrapper.user()).setInstaBuild((flags & 1 << 3) != 0);
|
||||
});
|
||||
}
|
||||
|
||||
public void registerGameEvent(C packetType) {
|
||||
protocol.registerClientbound(packetType, wrapper -> {
|
||||
final short event = wrapper.passthrough(Types.UNSIGNED_BYTE);
|
||||
if (event == 3) {
|
||||
final int value = (int) Math.floor(wrapper.passthrough(Types.FLOAT) + 0.5F);
|
||||
tracker(wrapper.user()).setInstaBuild(value == GameMode.CREATIVE.id());
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public void clearEntities(final UserConnection connection) {
|
||||
final EntityTracker tracker = tracker(connection);
|
||||
tracker.clearEntities();
|
||||
|
||||
@@ -198,6 +198,12 @@ public class ItemRewriter<C extends ClientboundPacketType, S extends Serverbound
|
||||
|
||||
public void registerSetCreativeModeSlot1_21_5(S packetType, Type<Item> lengthPrefixedItemType, Type<Item> mappedLengthPrefixedItemType) {
|
||||
protocol.registerServerbound(packetType, wrapper -> {
|
||||
if (!protocol.getEntityRewriter().tracker(wrapper.user()).canInstaBuild()) {
|
||||
// Mimic server/client behavior
|
||||
wrapper.cancel();
|
||||
return;
|
||||
}
|
||||
|
||||
wrapper.passthrough(Types.SHORT); // Slot
|
||||
passthroughLengthPrefixedItem(wrapper, lengthPrefixedItemType, mappedLengthPrefixedItemType);
|
||||
});
|
||||
@@ -249,12 +255,12 @@ public class ItemRewriter<C extends ClientboundPacketType, S extends Serverbound
|
||||
wrapper.passthrough(Types.SHORT); // Slot
|
||||
wrapper.passthrough(Types.BYTE); // Button
|
||||
wrapper.passthrough(Types.VAR_INT); // Mode
|
||||
passthroughHashedItem(wrapper); // Carried item
|
||||
final int affectedItems = Limit.max(wrapper.passthrough(Types.VAR_INT), 128);
|
||||
for (int i = 0; i < affectedItems; i++) {
|
||||
wrapper.passthrough(Types.SHORT); // Slot
|
||||
passthroughHashedItem(wrapper);
|
||||
}
|
||||
passthroughHashedItem(wrapper); // Carried item
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@@ -25,12 +25,16 @@ import com.viaversion.nbt.tag.Tag;
|
||||
import com.viaversion.viaversion.api.Via;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.logging.Level;
|
||||
import net.lenni0451.mcstructs.text.ATextComponent;
|
||||
import net.lenni0451.mcstructs.text.Style;
|
||||
import net.lenni0451.mcstructs.text.events.hover.AHoverEvent;
|
||||
import net.lenni0451.mcstructs.text.events.hover.impl.TextHoverEvent;
|
||||
import net.lenni0451.mcstructs.text.serializer.LegacyStringDeserializer;
|
||||
import net.lenni0451.mcstructs.text.TextComponent;
|
||||
import net.lenni0451.mcstructs.text.components.StringComponent;
|
||||
import net.lenni0451.mcstructs.text.events.hover.HoverEvent;
|
||||
import net.lenni0451.mcstructs.text.events.hover.impl.EntityHoverEvent;
|
||||
import net.lenni0451.mcstructs.text.events.hover.impl.ItemHoverEvent;
|
||||
import net.lenni0451.mcstructs.text.serializer.TextComponentSerializer;
|
||||
import net.lenni0451.mcstructs.text.stringformat.StringFormat;
|
||||
import net.lenni0451.mcstructs.text.stringformat.handling.ColorHandling;
|
||||
import net.lenni0451.mcstructs.text.stringformat.handling.DeserializerUnknownHandling;
|
||||
import net.lenni0451.mcstructs.text.utils.TextUtils;
|
||||
import org.checkerframework.checker.nullness.qual.Nullable;
|
||||
|
||||
@@ -57,7 +61,7 @@ public final class ComponentUtil {
|
||||
|
||||
public static @Nullable JsonElement tagToJson(@Nullable final Tag tag) {
|
||||
try {
|
||||
final ATextComponent component = SerializerVersion.V1_20_3.toComponent(tag);
|
||||
final TextComponent component = SerializerVersion.V1_20_3.toComponent(tag);
|
||||
return component != null ? SerializerVersion.V1_19_4.toJson(component) : null;
|
||||
} catch (final Exception e) {
|
||||
if (!Via.getConfig().isSuppressConversionWarnings()) {
|
||||
@@ -73,7 +77,7 @@ public final class ComponentUtil {
|
||||
}
|
||||
|
||||
try {
|
||||
final ATextComponent component = SerializerVersion.V1_19_4.toComponent(element);
|
||||
final TextComponent component = SerializerVersion.V1_19_4.toComponent(element);
|
||||
return trimStrings(SerializerVersion.V1_20_3.toTag(component));
|
||||
} catch (final Exception e) {
|
||||
if (!Via.getConfig().isSuppressConversionWarnings()) {
|
||||
@@ -83,7 +87,7 @@ public final class ComponentUtil {
|
||||
}
|
||||
}
|
||||
|
||||
private static Tag trimStrings(final Tag input) {
|
||||
public static Tag trimStrings(final Tag input) {
|
||||
// Dirty fix for https://github.com/ViaVersion/ViaVersion/issues/3650
|
||||
// Usually tripped by hover event data being too long, e.g. book or shulker box contents, which have to be held in full as SNBT
|
||||
if (input == null) {
|
||||
@@ -102,7 +106,7 @@ public final class ComponentUtil {
|
||||
|
||||
public static @Nullable String tagToJsonString(@Nullable final Tag tag) {
|
||||
try {
|
||||
final ATextComponent component = SerializerVersion.V1_20_5.toComponent(tag);
|
||||
final TextComponent component = SerializerVersion.V1_20_5.toComponent(tag);
|
||||
return component != null ? SerializerVersion.V1_20_3.toString(component) : null;
|
||||
} catch (final Exception e) {
|
||||
if (!Via.getConfig().isSuppressConversionWarnings()) {
|
||||
@@ -132,27 +136,41 @@ public final class ComponentUtil {
|
||||
}
|
||||
|
||||
public static @Nullable JsonElement convertJsonOrEmpty(@Nullable final String json, final SerializerVersion from, final SerializerVersion to) {
|
||||
final ATextComponent component = from.toComponent(json);
|
||||
final TextComponent component = from.toComponent(json);
|
||||
if (component == null) {
|
||||
return emptyJsonComponent();
|
||||
}
|
||||
return to.toJson(component);
|
||||
}
|
||||
|
||||
private static JsonElement convert(final SerializerVersion from, final SerializerVersion to, final ATextComponent component) {
|
||||
private static JsonElement convert(final SerializerVersion from, final SerializerVersion to, final TextComponent component) {
|
||||
if (from.ordinal() >= SerializerVersion.V1_16.ordinal() && to.ordinal() < SerializerVersion.V1_16.ordinal()) {
|
||||
// Convert hover event to legacy format
|
||||
final Style style = component.getStyle();
|
||||
final AHoverEvent hoverEvent = style.getHoverEvent();
|
||||
if (hoverEvent != null && !(hoverEvent instanceof TextHoverEvent)) {
|
||||
style.setHoverEvent(hoverEvent.toLegacy(to.jsonSerializer, to.snbtSerializer));
|
||||
final HoverEvent hoverEvent = style.getHoverEvent();
|
||||
if (hoverEvent instanceof EntityHoverEvent entityHoverEvent && entityHoverEvent.isModern()) {
|
||||
final EntityHoverEvent.ModernHolder entityData = entityHoverEvent.asModern();
|
||||
final CompoundTag tag = new CompoundTag();
|
||||
tag.putString("type", entityData.getType().get());
|
||||
tag.putString("id", entityData.getUuid().toString());
|
||||
tag.putString("name", to.toString(entityData.getName() != null ? entityData.getName() : new StringComponent("")));
|
||||
entityHoverEvent.setLegacyData(new StringComponent(to.toSNBT(tag)));
|
||||
} else if (hoverEvent instanceof ItemHoverEvent itemHoverEvent && itemHoverEvent.isModern()) {
|
||||
final ItemHoverEvent.ModernHolder itemData = itemHoverEvent.asModern();
|
||||
final CompoundTag tag = new CompoundTag();
|
||||
tag.putString("id", itemData.getId().get());
|
||||
tag.putByte("Count", (byte) itemData.getCount());
|
||||
if (itemData.getTag() != null) {
|
||||
tag.put("tag", itemData.getTag());
|
||||
}
|
||||
itemHoverEvent.setLegacyData(to.toSNBT(tag));
|
||||
}
|
||||
}
|
||||
return to.toJson(component);
|
||||
}
|
||||
|
||||
public static JsonElement legacyToJson(final String message) {
|
||||
return SerializerVersion.V1_12.toJson(LegacyStringDeserializer.parse(message, true));
|
||||
return SerializerVersion.V1_12.toJson(StringFormat.vanilla().fromString(message, ColorHandling.RESET, DeserializerUnknownHandling.WHITE));
|
||||
}
|
||||
|
||||
public static String legacyToJsonString(final String message) {
|
||||
@@ -160,7 +178,7 @@ public final class ComponentUtil {
|
||||
}
|
||||
|
||||
public static String legacyToJsonString(final String message, final boolean itemData) {
|
||||
final ATextComponent component = LegacyStringDeserializer.parse(message, true);
|
||||
final TextComponent component = StringFormat.vanilla().fromString(message, ColorHandling.RESET, DeserializerUnknownHandling.WHITE);
|
||||
if (itemData) {
|
||||
TextUtils.iterateAll(component, c -> {
|
||||
if (!c.getStyle().isEmpty()) {
|
||||
|
||||
@@ -20,10 +20,10 @@ package com.viaversion.viaversion.util;
|
||||
import com.google.gson.JsonElement;
|
||||
import com.viaversion.nbt.tag.Tag;
|
||||
import com.viaversion.viaversion.rewriter.text.JsonNBTComponentRewriter;
|
||||
import net.lenni0451.mcstructs.snbt.SNbtSerializer;
|
||||
import net.lenni0451.mcstructs.snbt.SNbt;
|
||||
import net.lenni0451.mcstructs.snbt.exceptions.SNbtDeserializeException;
|
||||
import net.lenni0451.mcstructs.snbt.exceptions.SNbtSerializeException;
|
||||
import net.lenni0451.mcstructs.text.ATextComponent;
|
||||
import net.lenni0451.mcstructs.text.TextComponent;
|
||||
import net.lenni0451.mcstructs.text.serializer.TextComponentCodec;
|
||||
import net.lenni0451.mcstructs.text.serializer.TextComponentSerializer;
|
||||
|
||||
@@ -36,57 +36,59 @@ import net.lenni0451.mcstructs.text.serializer.TextComponentSerializer;
|
||||
*/
|
||||
public enum SerializerVersion {
|
||||
V1_6(TextComponentSerializer.V1_6, null),
|
||||
V1_7(TextComponentSerializer.V1_7, SNbtSerializer.V1_7),
|
||||
V1_8(TextComponentSerializer.V1_8, SNbtSerializer.V1_8),
|
||||
V1_9(TextComponentSerializer.V1_9, SNbtSerializer.V1_8),
|
||||
V1_12(TextComponentSerializer.V1_12, SNbtSerializer.V1_12),
|
||||
V1_13(TextComponentSerializer.V1_12, SNbtSerializer.V1_13),
|
||||
V1_14(TextComponentSerializer.V1_14, SNbtSerializer.V1_14),
|
||||
V1_15(TextComponentSerializer.V1_15, SNbtSerializer.V1_14),
|
||||
V1_16(TextComponentSerializer.V1_16, SNbtSerializer.V1_14),
|
||||
V1_17(TextComponentSerializer.V1_17, SNbtSerializer.V1_14),
|
||||
V1_18(TextComponentSerializer.V1_18, SNbtSerializer.V1_14),
|
||||
V1_19_4(TextComponentSerializer.V1_19_4, SNbtSerializer.V1_14),
|
||||
V1_20_3(TextComponentCodec.V1_20_3, SNbtSerializer.V1_14),
|
||||
V1_20_5(TextComponentCodec.V1_20_5, SNbtSerializer.V1_14),
|
||||
V1_21_4(TextComponentCodec.V1_21_4, SNbtSerializer.V1_14);
|
||||
V1_7(TextComponentSerializer.V1_7, SNbt.V1_7),
|
||||
V1_8(TextComponentSerializer.V1_8, SNbt.V1_8),
|
||||
V1_9(TextComponentSerializer.V1_9, SNbt.V1_8),
|
||||
V1_12(TextComponentSerializer.V1_12, SNbt.V1_12),
|
||||
V1_13(TextComponentSerializer.V1_12, SNbt.V1_13),
|
||||
V1_14(TextComponentSerializer.V1_14, SNbt.V1_14),
|
||||
V1_15(TextComponentSerializer.V1_15, SNbt.V1_14),
|
||||
V1_16(TextComponentSerializer.V1_16, SNbt.V1_14),
|
||||
V1_17(TextComponentSerializer.V1_17, SNbt.V1_14),
|
||||
V1_18(TextComponentSerializer.V1_18, SNbt.V1_14),
|
||||
V1_19_4(TextComponentSerializer.V1_19_4, SNbt.V1_14),
|
||||
V1_20_3(TextComponentCodec.V1_20_3, SNbt.V1_14),
|
||||
V1_20_5(TextComponentCodec.V1_20_5, SNbt.V1_14),
|
||||
V1_21_4(TextComponentCodec.V1_21_4, SNbt.V1_14),
|
||||
V1_21_5(TextComponentCodec.V1_21_5, null/*Currently not needed and also not implemented 100% in MCStructs*/);
|
||||
|
||||
final TextComponentSerializer jsonSerializer;
|
||||
final SNbtSerializer<? extends Tag> snbtSerializer;
|
||||
final SNbt<? extends Tag> sNbt;
|
||||
final TextComponentCodec codec;
|
||||
|
||||
SerializerVersion(final TextComponentSerializer jsonSerializer, final SNbtSerializer<? extends Tag> snbtSerializer) {
|
||||
SerializerVersion(final TextComponentSerializer jsonSerializer, final SNbt<? extends Tag> sNbt) {
|
||||
this.jsonSerializer = jsonSerializer;
|
||||
this.snbtSerializer = snbtSerializer;
|
||||
this.sNbt = sNbt;
|
||||
this.codec = null;
|
||||
}
|
||||
|
||||
SerializerVersion(final TextComponentCodec codec, final SNbtSerializer<? extends Tag> snbtSerializer) {
|
||||
SerializerVersion(final TextComponentCodec codec, final SNbt<? extends Tag> sNbt) {
|
||||
this.codec = codec;
|
||||
this.jsonSerializer = codec.asSerializer();
|
||||
this.snbtSerializer = snbtSerializer;
|
||||
this.sNbt = sNbt;
|
||||
}
|
||||
|
||||
public String toString(final ATextComponent component) {
|
||||
public String toString(final TextComponent component) {
|
||||
return jsonSerializer.serialize(component);
|
||||
}
|
||||
|
||||
public JsonElement toJson(final ATextComponent component) {
|
||||
public JsonElement toJson(final TextComponent component) {
|
||||
return jsonSerializer.serializeJson(component);
|
||||
}
|
||||
|
||||
public Tag toTag(final ATextComponent component) {
|
||||
public Tag toTag(final TextComponent component) {
|
||||
if (codec == null) {
|
||||
throw new IllegalStateException("Cannot convert component to NBT with this version");
|
||||
}
|
||||
return codec.serializeNbt(component);
|
||||
|
||||
return codec.serializeNbtTree(component);
|
||||
}
|
||||
|
||||
public ATextComponent toComponent(final JsonElement json) {
|
||||
public TextComponent toComponent(final JsonElement json) {
|
||||
return jsonSerializer.deserialize(json);
|
||||
}
|
||||
|
||||
public ATextComponent toComponent(final String json) {
|
||||
public TextComponent toComponent(final String json) {
|
||||
if (ordinal() >= SerializerVersion.V1_20_3.ordinal()) {
|
||||
return jsonSerializer.deserializeParser(json);
|
||||
} else if (ordinal() >= SerializerVersion.V1_9.ordinal()) {
|
||||
@@ -96,7 +98,7 @@ public enum SerializerVersion {
|
||||
}
|
||||
}
|
||||
|
||||
public ATextComponent toComponent(final Tag tag) {
|
||||
public TextComponent toComponent(final Tag tag) {
|
||||
if (codec == null) {
|
||||
throw new IllegalStateException("Cannot convert NBT to component with this version");
|
||||
}
|
||||
@@ -104,22 +106,24 @@ public enum SerializerVersion {
|
||||
}
|
||||
|
||||
public Tag toTag(final String snbt) {
|
||||
if (snbtSerializer == null) {
|
||||
if (sNbt == null) {
|
||||
throw new IllegalStateException("Cannot convert SNBT to NBT with this version");
|
||||
}
|
||||
|
||||
try {
|
||||
return snbtSerializer.deserialize(snbt);
|
||||
return sNbt.deserialize(snbt);
|
||||
} catch (SNbtDeserializeException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
public String toSNBT(final Tag tag) {
|
||||
if (snbtSerializer == null) {
|
||||
if (sNbt == null) {
|
||||
throw new IllegalStateException("Cannot convert SNBT to NBT with this version");
|
||||
}
|
||||
|
||||
try {
|
||||
return snbtSerializer.serialize(tag);
|
||||
return sNbt.serialize(tag);
|
||||
} catch (SNbtSerializeException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
|
||||
+2
-2
@@ -1,8 +1,8 @@
|
||||
# Project properties - we put these here so they can be modified without causing a recompile of the build scripts
|
||||
projectVersion=5.3.0
|
||||
projectVersion=5.3.2
|
||||
|
||||
# Smile emoji
|
||||
mcVersions=1.21.5,1.21.4, 1.21.3, 1.21.2, 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
|
||||
mcVersions=1.21.5, 1.21.4, 1.21.3, 1.21.2, 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.5
|
||||
velocityVersion=3.4
|
||||
|
||||
|
||||
@@ -5,7 +5,7 @@ metadata.format.version = "1.1"
|
||||
gson = "2.12.1"
|
||||
fastutil = "8.5.15"
|
||||
vianbt = "5.1.0"
|
||||
mcstructs = "5-2.5.5-SNAPSHOT"
|
||||
mcstructs = "5-3.1.0-SNAPSHOT"
|
||||
|
||||
# Common provided
|
||||
netty = "4.0.20.Final"
|
||||
@@ -19,7 +19,7 @@ checkerQual = "3.49.1"
|
||||
paper = "1.20.4-R0.1-SNAPSHOT"
|
||||
legacyBukkit = "1.8.8-R0.1-SNAPSHOT"
|
||||
velocity = "3.1.1"
|
||||
viaProxy = "3.4.0-SNAPSHOT"
|
||||
viaProxy = "3.4.2-SNAPSHOT"
|
||||
|
||||
[libraries]
|
||||
|
||||
|
||||
+4
-2
@@ -32,8 +32,10 @@ public class ConnectionDetailsListener {
|
||||
|
||||
@Subscribe
|
||||
public void onPostServerJoin(final ServerPostConnectEvent event) {
|
||||
final UserConnection connection = Via.getAPI().getConnection(event.getPlayer().getUniqueId());
|
||||
ConnectionDetails.sendConnectionDetails(connection, ConnectionDetails.PROXY_CHANNEL);
|
||||
final UserConnection connection = Via.getManager().getConnectionManager().getClientConnection(event.getPlayer().getUniqueId());
|
||||
if (connection != null) {
|
||||
ConnectionDetails.sendConnectionDetails(connection, ConnectionDetails.PROXY_CHANNEL);
|
||||
}
|
||||
}
|
||||
|
||||
@Subscribe
|
||||
|
||||
Reference in new issue
Block a user