Compare commits

..
86 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
Nassim Jahnke 48d5aaf8fa 5.0.2 Release 2024-07-28 14:37:59 +02:00
EnZaXD 41b0d95d70 Fix horse/llama's armor/carpet not visible in 1.20.3->1.20.5 (#4052) 2024-07-27 20:26:53 +02:00
EnZaXD b599399c48 Cleanup 1.20->1.20.2 item and recipe rewriter (#4050) 2024-07-27 19:53:59 +02:00
EnZaXD 721e27eb39 Rewrite show_item in translation components in 1.11.1->1.12 (#4053)
Fixes https://github.com/ViaVersion/ViaVersion/issues/4051
2024-07-27 19:53:44 +02:00
EnZaXD c9d6fbfcd0 Add VersionProvider#getServerProtocol (#4049)
Most platforms won't ever throw an error and usually ViaVersion shouldn't even load when the server version can't be found. Therefore, I added this bouncer function, so I don't need to try catch my code in ViaLoader/VFP where an exception is never thrown
2024-07-27 19:53:33 +02:00
RK_01 b1f64fd081 Use enhanced switches in more places (#4043) 2024-07-24 14:32:36 +02:00
EnZaXD 2b508567db Move damage types 1.20.3 into nbt file (#4026) 2024-07-24 13:13:36 +02:00
EnZaXD 24d0ae7607 Add ViaManager#addPostEnableListener (#4038) 2024-07-22 18:24:06 +02:00
EnZaXD 40a44d5dc5 Remove version type from dump (#4036) 2024-07-22 17:45:21 +02:00
EnZaXD b5a06181d4 Fix item projectile hierarchy in 1.14+ (#4034) 2024-07-22 17:44:07 +02:00
EnZaXD 35fa7e78a0 Handle attribute_modifiers inside container components in 1.21->1.20.5 (#4035)
Closes https://github.com/ViaVersion/ViaVersion/issues/3968
2024-07-22 17:42:25 +02:00
EnZaXD 7f4faab4ab Add 1.21 to the version table (#4037) 2024-07-22 17:40:37 +02:00
EnZaXD 3906b47654 Apply required changes for ViaAprilFools (#4033)
1. Allow the version provider to get the client version sent through the handshake packet
2. Allow platform to override provider instead
2024-07-21 17:45:13 +02:00
Nassim Jahnke 1476adb281 Slightly improve logging on config loading errors 2024-07-21 12:12:06 +02:00
EnZaXD 6fb072120b Removes VFP as well and recommends ViaBackwards/ViaRewind on both platforms (#4032) 2024-07-21 09:43:40 +02:00
EnZaXD f2f0be0581 Allow base protocols to set client version (#4029) 2024-07-20 09:15:15 +02:00
EnZaXD 5ec30ef18a Expose origin version in RedirectProtocolVersion (#4030) 2024-07-20 09:12:44 +02:00
Nassim Jahnke 0915afe43b Handle 1.21 attribute id changes
Fixes #4005
2024-07-19 11:26:28 +02:00
EnZaXD 87b041bf3a Fix block predicate conversion in 1.20.3->1.20.5 (#4025) 2024-07-19 11:00:00 +02:00
EnZaXD 275b09bdbb Use SerializerVersion#toTag when converting 1.20.5->1.20.3 block predicates (#4024) 2024-07-19 10:54:40 +02:00
Nassim Jahnke cc87c02020 Add shulker box block entity id if missing 2024-07-17 18:48:07 +02:00
EnZaXD a45985ed58 Validate index when reading structured data type (#4020) 2024-07-16 09:59:33 +02:00
Nassim Jahnke 92dedfb950 Update Gradle wrapper 2024-07-14 21:31:38 +02:00
RK_01 6bbcf7d784 Fix respawn "keep data" translation (#4015) 2024-07-13 11:00:12 +02:00
EnZaXD 465a2354c0 Call component rewriter in pre 1.20.3 advancement handler (#4014)
Required for ViaBackwards where we need to rewrite the translation key (and it also doesn't hurt to have this in forward protocols).

Closes https://github.com/ViaVersion/ViaBackwards/issues/819
2024-07-13 11:00:00 +02:00
EnZaXD c59c15d6f3 [ci skip] Fix player combat packet value comments (#4013) 2024-07-13 10:59:47 +02:00
EnZaXD 20f7738f08 Add cancel-block-sounds option for 1.8->1.9 place/break fix (#4011) 2024-07-12 00:11:11 +02:00
EnZaXD 323f0fa087 Remove minimize-cooldown config option (#4009) 2024-07-07 18:03:35 +02:00
RK_01 3138d667a6 Fix crossbow max damage and 1.8 sword blocking using item data components (#4010) 2024-07-07 18:02:51 +02:00
EnZaXD 365040f59d Handle rarity changes in trident/banner pattern item in 1.20.5->1.21 (#4001) 2024-07-07 17:39:30 +02:00
lowercasebtwandEnZaXD 303d9ecf51 Hide cooldown indicator completely in 1.8->1.9 (#4006)
* Change 1.8 to 1.9 Attack Speed

* Fix The Attack Speed Value Type

* Change Attack Speed to 20

Requested/Suggested change from FlorianMichael

Co-authored-by: EnZaXD <florian.michael07@gmail.com>

---------

Co-authored-by: EnZaXD <florian.michael07@gmail.com>
2024-07-06 23:12:01 +02:00
EnZaXD 463381b84e Rename missing metadata references to entity data (#4007) 2024-07-06 21:05:40 +02:00
Nassim Jahnke 7fef96d77e Remove unneeded 1.13 enchantment translatable mappings 2024-07-03 11:32:25 +02:00
Gegy 17358120cd Fix: delay chat acknowledgements instead of spoofing (#3997)
An easy reproduction case is to mute a player using the Social Interactions screen, let them chat, and then send a message. As ViaVersion produces its own acknowledgements, this now does not match with what the client produced and signed its messages with - so the signature will fail verification.

As an alternative, we *always* pass through the same acknowledgement bit set - and for 'spoofed' messages, we reuse the last one that we received. In the case of the chat ack packet with just an offset, we need to hold back the window by at least 20 messages to ensure we don't start making claims about whether the client saw a message that ViaVersion cannot yet make a judgement on.
2024-07-03 10:52:01 +02:00
EnZaXD e6da77cf47 Handle Slot tag inside CONTAINER tag in 1.20.3->1.20.5 (#3995)
Fixes shulker box tooltips not showing all items for 1.20.3 clients on 1.20.5+ servers
2024-07-02 11:53:34 +02:00
EnZaXD dc503cd613 Update legacy Minecraft version warning (#3989) 2024-06-30 11:30:54 +02:00
Nassim Jahnke 8aa2f4be46 Handle show item hovers in more component packets
Because servers do weird things
2024-06-30 11:10:44 +02:00
Nassim Jahnke c5dc5b2bf8 Actually restrict velocity change to fishing hooks 2024-06-28 15:29:06 +02:00
EnZaXD f4d6659760 Only print broken json in component type when debug mode is enabled (#3990) 2024-06-28 13:44:31 +02:00
EnZaXD bfbb80f708 Update unsupported java version warning (#3988)
Now links to the release which contains a guide on how to update
2024-06-27 14:56:15 +02:00
EnZaXD 248da118a9 Move bukkit-only settings into BukkitViaConfig (#3985) 2024-06-27 09:56:50 +02:00
EnZaXD a987882132 Rework unsupported config options in AbstractViaConfig (#3986) 2024-06-27 09:54:44 +02:00
EnZaXD bca25d4744 Rewrite filtered_pages in 1.20.2->1.20.3 (#3983) 2024-06-26 10:58:50 +02:00
EnZaXD 2417ffe483 Fixup horse inventory translation in 1.20.5->1.21 (#3980)
Fixes #3978
2024-06-25 15:27:02 +02:00
EnZaXD 8606e5d663 Handle both json and plain text in CommonBoss (#3981) 2024-06-25 15:21:34 +02:00
EnZaXD 5a0ca55b97 Add test command handler to DummyInitializer test (#3970) 2024-06-25 15:21:26 +02:00
Nassim Jahnke ceb1cffb00 Cancel "message not delivered" messages
Fixes #3438
2024-06-25 15:19:03 +02:00
Nassim Jahnke 1ff3035bc0 Make 1.10->1.11 fishing hook position desync slightly less bad 2024-06-25 15:17:29 +02:00
Nassim Jahnke 1f221ea828 Bump version to 5.0.2-SNAPSHOT 2024-06-25 15:16:36 +02:00
Nassim Jahnke dd1fad2dd7 5.0.1 Release 2024-06-22 15:53:57 +02:00
EnZaXD 245f7e24e4 Fix DummyInitializer unit test to bootstrap without errors (#3965) 2024-06-22 11:04:11 +02:00
EnZaXD 9d3db4cf97 Improve performance in ProtocolVersionRange#contains (#3964) 2024-06-22 11:02:16 +02:00
EnZaXD b67ebecce8 [ci skip] Advertise ViaLoader in README file (#3966) 2024-06-22 11:01:55 +02:00
EnZaXD d03207289e Backup original book pages for creative mode clients in 1.8->1.9 (#3952) 2024-06-21 14:38:00 +02:00
Nassim Jahnke 64497b305a Fix enchantment order 2024-06-20 17:42:27 +02:00
Nassim Jahnke f5b3799db9 Use default dimension data for defaulted registry entry 2024-06-20 17:32:19 +02:00
Nassim Jahnke 00fedc7656 Also handle aqua affinity 2024-06-20 16:08:46 +02:00
Nassim Jahnke 05aa05c5b4 Disable soul speed check for now 2024-06-20 15:31:18 +02:00
Nassim Jahnke 5243c1800e entity effect magic
Fixes #3927
2024-06-20 12:51:35 +02:00
Nassim Jahnke 77d702bc9b Also handle movement related enchantments
Fixes #3960
2024-06-20 12:12:29 +02:00
RK_01 c098e24c4f Return generic Item array in StructuredItem#emptyArray (#3955) 2024-06-17 20:08:34 +02:00
EnZaXD 3d083cf463 Add handleMenuType function to ItemRewriter (#3953) 2024-06-17 16:39:01 +02:00
Nassim Jahnke 2ab62a8f4f Protected 2024-06-17 12:48:52 +02:00
Nassim Jahnke 296f42086f Also handle item_name item data for component rewriting 2024-06-17 12:43:18 +02:00
Nassim Jahnke e9f547f7ba Add ArrayUtil 2024-06-17 11:48:21 +02:00
CamotoyandAJ Ferguson b7f388b9ee 1.20.5 -> 1.20.3: nullify empty tags (#3949)
Co-authored-by: AJ Ferguson <AJ-Ferguson@users.noreply.github.com>
2024-06-17 09:42:09 +02:00
EnZaXD 824ff375d4 Fix GameMode#getById behaviour in 1.8->1.9 (#3947)
Vanilla fallbacks to SURVIVAL and doesn't throw any errors,
also NOT_SET was missing previously.
2024-06-16 22:28:50 +02:00
Leon 8bec05ed38 Fixup hardcore handling on join in 1.8->1.9 (#3946)
* Fix players crashing when logging into a 1.8 server on hardcore mode, Fixes #3944

* Requested change to #3944 fix
2024-06-16 22:06:39 +02:00
Nassim Jahnke b367caa4b2 Add Charged item tag if there's charged projectiles
Closes ViaVersion/ViaBackwards#787
2024-06-16 21:58:07 +02:00
Nassim Jahnke 1c281abf65 Bump version to 5.0.1-SNAPSHOT 2024-06-16 21:38:32 +02:00
159 changed files with 1879 additions and 1587 deletions

No files matched your search

+2 -2
View File
@@ -2,7 +2,7 @@
charset = utf-8
indent_size = 4
indent_style = space
insert_final_newline = false
insert_final_newline = true
tab_width = 4
[*.java]
@@ -13,4 +13,4 @@ ij_java_generate_final_locals = true
ij_java_generate_final_parameters = true
[{*.json,*.yml}]
indent_size = 2
indent_size = 2
@@ -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:
+7 -2
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 -
@@ -11,9 +11,12 @@ The base ViaVersion jar runs on Paper and Velocity. We also have projects integr
on Fabric, Forge, Bungee, Sponge, or as a standalone proxy to join from basically any client version on
any server version from the past decade. **See [HERE](https://github.com/ViaVersion) for an overview of the different Via\* projects.**
Note that ViaVersion will be able to **run best on either Paper servers or Fabric clients** due to having
direct access to client/server state and more extensive API.
Supported Versions:
![Table (https://i.imgur.com/sTrVnC2.png)](https://i.imgur.com/sTrVnC2.png)
![Table (https://i.imgur.com/zrQTcf0.png)](https://i.imgur.com/zrQTcf0.png)
**User Docs:** https://docs.viaversion.com/display/VIAVERSION/
@@ -67,6 +70,8 @@ dependencies {
If you need access to the existing protocol or platform implementations, use the parent artifact `viaversion`.
Please note the [differences in licensing](#license).
Note: If you want to make your own platform implementation of ViaVersion (and additional addons),
you can use the [ViaLoader](https://github.com/ViaVersion/ViaLoader) project.
Building
--------
+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)
@@ -140,6 +140,13 @@ public interface ViaManager {
*/
void addEnableListener(Runnable runnable);
/**
* Adds a runnable to be executed when ViaVersion has finished its init after the full server load.
*
* @param runnable runnable to be executed
*/
void addPostEnableListener(Runnable runnable);
/**
* Returns whether the manager has been initialized (and protocols have been loaded).
*
@@ -67,9 +67,9 @@ public interface ViaVersionConfig extends Config {
boolean isShowNewDeathMessages();
/**
* Get if metadata errors will be suppressed
* Get if entity data errors will be suppressed
*
* @return true if metadata errors suppression is enabled
* @return true if entity data errors suppression is enabled
*/
boolean isSuppressMetadataErrors();
@@ -292,13 +292,6 @@ public interface ViaVersionConfig extends Config {
*/
boolean isDisable1_13AutoComplete();
/**
* Tries to minimize cooldown animation.
*
* @return true if enabled
*/
boolean isMinimizeCooldown();
/**
* Enable the serverside blockconnections for 1.13+ clients
*
@@ -464,4 +457,11 @@ public interface ViaVersionConfig extends Config {
* @return true if enabled
*/
boolean handleInvalidItemCount();
/**
* Tries to cancel block break/place sounds sent by 1.8 servers to 1.9+ clients to prevent them from playing twice
*
* @return true if enabled
*/
boolean cancelBlockSounds();
}
@@ -46,6 +46,7 @@ public class MappingDataBase implements MappingData {
protected ParticleMappings particleMappings;
protected BiMappings itemMappings;
protected BiMappings blockMappings;
protected BiMappings attributeMappings;
protected Mappings blockStateMappings;
protected Mappings blockEntityMappings;
protected Mappings soundMappings;
@@ -53,7 +54,6 @@ public class MappingDataBase implements MappingData {
protected Mappings enchantmentMappings;
protected Mappings paintingMappings;
protected Mappings menuMappings;
protected Mappings attributeMappings;
protected Map<RegistryType, List<TagData>> tags;
public MappingDataBase(final String unmappedVersion, final String mappedVersion) {
@@ -76,7 +76,7 @@ public class MappingDataBase implements MappingData {
menuMappings = loadMappings(data, "menus");
enchantmentMappings = loadMappings(data, "enchantments");
paintingMappings = loadMappings(data, "paintings");
attributeMappings = loadMappings(data, "attributes");
attributeMappings = loadBiMappings(data, "attributes");
final CompoundTag unmappedIdentifierData = readUnmappedIdentifiersFile("identifiers-" + unmappedVersion + ".nbt");
@@ -24,6 +24,7 @@ package com.viaversion.viaversion.api.minecraft;
public enum GameMode {
NOT_SET(""),
SURVIVAL("Survival Mode"),
CREATIVE("Creative Mode"),
ADVENTURE("Adventure Mode"),
@@ -41,11 +42,11 @@ public enum GameMode {
public static GameMode getById(int id) {
return switch (id) {
case 0 -> SURVIVAL;
case -1 -> NOT_SET;
case 1 -> CREATIVE;
case 2 -> ADVENTURE;
case 3 -> SPECTATOR;
default -> throw new IllegalArgumentException("Unknown gamemode id: " + id);
default /*0*/ -> SURVIVAL;
};
}
}
@@ -25,6 +25,12 @@ package com.viaversion.viaversion.api.minecraft;
import com.viaversion.nbt.tag.Tag;
import org.checkerframework.checker.nullness.qual.Nullable;
/**
* Represents an entry in a registry.
*
* @param key key of the registry entry
* @param tag data of the registry entry, or null if the client should use its default
*/
public record RegistryEntry(String key, @Nullable Tag tag) {
public RegistryEntry withKey(final String key) {
@@ -212,6 +212,8 @@ public final class StructuredDataContainer {
public String toString() {
return "StructuredDataContainer{" +
"data=" + data +
", lookup=" + lookup +
", mappedNames=" + mappedNames +
'}';
}
}
@@ -51,11 +51,12 @@ public enum EntityTypes1_14 implements EntityType {
// Projectiles
PROJECTILE(ENTITY, null), // Not actually its own abstract type, but useful for categorizing
SNOWBALL(PROJECTILE),
ENDER_PEARL(PROJECTILE),
EGG(PROJECTILE),
ITEM_PROJECTILE(PROJECTILE, null),
SNOWBALL(ITEM_PROJECTILE),
ENDER_PEARL(ITEM_PROJECTILE),
EGG(ITEM_PROJECTILE),
POTION(PROJECTILE),
EXPERIENCE_BOTTLE(PROJECTILE),
EXPERIENCE_BOTTLE(ITEM_PROJECTILE),
FIREWORK_ROCKET(PROJECTILE),
LLAMA_SPIT(PROJECTILE),
SHULKER_BULLET(PROJECTILE),
@@ -51,11 +51,12 @@ public enum EntityTypes1_15 implements EntityType {
// Projectiles
PROJECTILE(ENTITY, null), // Not actually its own abstract type, but useful for categorizing
SNOWBALL(PROJECTILE),
ENDER_PEARL(PROJECTILE),
EGG(PROJECTILE),
ITEM_PROJECTILE(PROJECTILE, null),
SNOWBALL(ITEM_PROJECTILE),
ENDER_PEARL(ITEM_PROJECTILE),
EGG(ITEM_PROJECTILE),
POTION(PROJECTILE),
EXPERIENCE_BOTTLE(PROJECTILE),
EXPERIENCE_BOTTLE(ITEM_PROJECTILE),
FIREWORK_ROCKET(PROJECTILE),
LLAMA_SPIT(PROJECTILE),
SHULKER_BULLET(PROJECTILE),
@@ -51,11 +51,12 @@ public enum EntityTypes1_16 implements EntityType {
// Projectiles
PROJECTILE(ENTITY, null), // Not actually its own abstract type, but useful for categorizing
SNOWBALL(PROJECTILE),
ENDER_PEARL(PROJECTILE),
EGG(PROJECTILE),
POTION(PROJECTILE),
EXPERIENCE_BOTTLE(PROJECTILE),
ITEM_PROJECTILE(PROJECTILE, null),
SNOWBALL(ITEM_PROJECTILE),
ENDER_PEARL(ITEM_PROJECTILE),
EGG(ITEM_PROJECTILE),
POTION(ITEM_PROJECTILE),
EXPERIENCE_BOTTLE(ITEM_PROJECTILE),
FIREWORK_ROCKET(PROJECTILE),
LLAMA_SPIT(PROJECTILE),
SHULKER_BULLET(PROJECTILE),
@@ -51,11 +51,12 @@ public enum EntityTypes1_16_2 implements EntityType {
// Projectiles
PROJECTILE(ENTITY, null), // Not actually its own abstract type, but useful for categorizing
SNOWBALL(PROJECTILE),
ENDER_PEARL(PROJECTILE),
EGG(PROJECTILE),
POTION(PROJECTILE),
EXPERIENCE_BOTTLE(PROJECTILE),
ITEM_PROJECTILE(PROJECTILE, null),
SNOWBALL(ITEM_PROJECTILE),
ENDER_PEARL(ITEM_PROJECTILE),
EGG(ITEM_PROJECTILE),
POTION(ITEM_PROJECTILE),
EXPERIENCE_BOTTLE(ITEM_PROJECTILE),
FIREWORK_ROCKET(PROJECTILE),
LLAMA_SPIT(PROJECTILE),
SHULKER_BULLET(PROJECTILE),
@@ -53,11 +53,12 @@ public enum EntityTypes1_17 implements EntityType {
// Projectiles
PROJECTILE(ENTITY, null), // Not actually its own abstract type, but useful for categorizing
SNOWBALL(PROJECTILE),
ENDER_PEARL(PROJECTILE),
EGG(PROJECTILE),
POTION(PROJECTILE),
EXPERIENCE_BOTTLE(PROJECTILE),
ITEM_PROJECTILE(PROJECTILE, null),
SNOWBALL(ITEM_PROJECTILE),
ENDER_PEARL(ITEM_PROJECTILE),
EGG(ITEM_PROJECTILE),
POTION(ITEM_PROJECTILE),
EXPERIENCE_BOTTLE(ITEM_PROJECTILE),
FIREWORK_ROCKET(PROJECTILE),
LLAMA_SPIT(PROJECTILE),
SHULKER_BULLET(PROJECTILE),
@@ -53,11 +53,12 @@ public enum EntityTypes1_19 implements EntityType {
// Projectiles
PROJECTILE(ENTITY, null), // Not actually its own abstract type, but useful for categorizing
SNOWBALL(PROJECTILE),
ENDER_PEARL(PROJECTILE),
EGG(PROJECTILE),
POTION(PROJECTILE),
EXPERIENCE_BOTTLE(PROJECTILE),
ITEM_PROJECTILE(PROJECTILE, null),
SNOWBALL(ITEM_PROJECTILE),
ENDER_PEARL(ITEM_PROJECTILE),
EGG(ITEM_PROJECTILE),
POTION(ITEM_PROJECTILE),
EXPERIENCE_BOTTLE(ITEM_PROJECTILE),
FIREWORK_ROCKET(PROJECTILE),
LLAMA_SPIT(PROJECTILE),
SHULKER_BULLET(PROJECTILE),
@@ -53,11 +53,12 @@ public enum EntityTypes1_19_3 implements EntityType {
// Projectiles
PROJECTILE(ENTITY, null), // Not actually its own abstract type, but useful for categorizing
SNOWBALL(PROJECTILE),
ENDER_PEARL(PROJECTILE),
EGG(PROJECTILE),
POTION(PROJECTILE),
EXPERIENCE_BOTTLE(PROJECTILE),
ITEM_PROJECTILE(PROJECTILE, null),
SNOWBALL(ITEM_PROJECTILE),
ENDER_PEARL(ITEM_PROJECTILE),
EGG(ITEM_PROJECTILE),
POTION(ITEM_PROJECTILE),
EXPERIENCE_BOTTLE(ITEM_PROJECTILE),
FIREWORK_ROCKET(PROJECTILE),
LLAMA_SPIT(PROJECTILE),
SHULKER_BULLET(PROJECTILE),
@@ -59,11 +59,12 @@ public enum EntityTypes1_19_4 implements EntityType {
// Projectiles
PROJECTILE(ENTITY, null), // Not actually its own abstract type, but useful for categorizing
SNOWBALL(PROJECTILE),
ENDER_PEARL(PROJECTILE),
EGG(PROJECTILE),
POTION(PROJECTILE),
EXPERIENCE_BOTTLE(PROJECTILE),
ITEM_PROJECTILE(PROJECTILE, null),
SNOWBALL(ITEM_PROJECTILE),
ENDER_PEARL(ITEM_PROJECTILE),
EGG(ITEM_PROJECTILE),
POTION(ITEM_PROJECTILE),
EXPERIENCE_BOTTLE(ITEM_PROJECTILE),
FIREWORK_ROCKET(PROJECTILE),
LLAMA_SPIT(PROJECTILE),
SHULKER_BULLET(PROJECTILE),
@@ -59,11 +59,12 @@ public enum EntityTypes1_20_3 implements EntityType {
// Projectiles
PROJECTILE(ENTITY, null), // Not actually its own abstract type, but useful for categorizing
SNOWBALL(PROJECTILE),
ENDER_PEARL(PROJECTILE),
EGG(PROJECTILE),
POTION(PROJECTILE),
EXPERIENCE_BOTTLE(PROJECTILE),
ITEM_PROJECTILE(PROJECTILE, null),
SNOWBALL(ITEM_PROJECTILE),
ENDER_PEARL(ITEM_PROJECTILE),
EGG(ITEM_PROJECTILE),
POTION(ITEM_PROJECTILE),
EXPERIENCE_BOTTLE(ITEM_PROJECTILE),
FIREWORK_ROCKET(PROJECTILE),
LLAMA_SPIT(PROJECTILE),
SHULKER_BULLET(PROJECTILE),
@@ -59,12 +59,13 @@ public enum EntityTypes1_20_5 implements EntityType {
GLOW_ITEM_FRAME(ITEM_FRAME),
// Projectiles
PROJECTILE(ENTITY, null), // Not actually its own abstract type, but useful for categorizing
SNOWBALL(PROJECTILE),
ENDER_PEARL(PROJECTILE),
EGG(PROJECTILE),
POTION(PROJECTILE),
EXPERIENCE_BOTTLE(PROJECTILE),
PROJECTILE(ENTITY, null),
ITEM_PROJECTILE(PROJECTILE, null),
SNOWBALL(ITEM_PROJECTILE),
ENDER_PEARL(ITEM_PROJECTILE),
EGG(ITEM_PROJECTILE),
POTION(ITEM_PROJECTILE),
EXPERIENCE_BOTTLE(ITEM_PROJECTILE),
FIREWORK_ROCKET(PROJECTILE),
LLAMA_SPIT(PROJECTILE),
SHULKER_BULLET(PROJECTILE),
@@ -93,7 +93,7 @@ public class EntityTypes1_8 {
LIVING_ENTITY_BASE(ENTITY),
ARMOR_STAND(30, LIVING_ENTITY_BASE),
PLAYER(LIVING_ENTITY_BASE), // Needed for entity (un)tracking and metadata indexing
PLAYER(LIVING_ENTITY_BASE), // Needed for entity (un)tracking and entity data indexing
// Living entities as a larger subclass
LIVING_ENTITY(48, LIVING_ENTITY_BASE),
@@ -28,21 +28,21 @@ import org.checkerframework.checker.nullness.qual.Nullable;
public final class EntityData {
private int id;
private EntityDataType metaType;
private EntityDataType dataType;
private Object value;
/**
* Creates a new metadata instance.
* Creates a new entity data instance.
*
* @param id metadata index
* @param metaType metadata type
* @param id data index
* @param dataType data type
* @param value value if present
* @throws IllegalArgumentException if the value and metaType are incompatible
* @throws IllegalArgumentException if the value and dataType are incompatible
*/
public EntityData(int id, EntityDataType metaType, @Nullable Object value) {
public EntityData(int id, EntityDataType dataType, @Nullable Object value) {
this.id = id;
this.metaType = metaType;
this.value = checkValue(metaType, value);
this.dataType = dataType;
this.value = checkValue(dataType, value);
}
public int id() {
@@ -54,19 +54,19 @@ public final class EntityData {
}
public EntityDataType dataType() {
return metaType;
return dataType;
}
/**
* Sets the metadata type if compatible with the current value.
* Sets the entity data type if compatible with the current value.
*
* @param metaType metadata type
* @throws IllegalArgumentException if the metadata type and current value are incompatible
* @param dataType entity data type
* @throws IllegalArgumentException if the entity data type and current value are incompatible
* @see #setTypeAndValue(EntityDataType, Object)
*/
public void setDataType(EntityDataType metaType) {
checkValue(metaType, this.value);
this.metaType = metaType;
public void setDataType(EntityDataType dataType) {
checkValue(dataType, this.value);
this.dataType = dataType;
}
public @Nullable <T> T value() {
@@ -78,32 +78,32 @@ public final class EntityData {
}
/**
* Sets the metadata value if compatible with the current meta type.
* Sets the entity data value if compatible with the current data type.
*
* @param value value
* @throws IllegalArgumentException if the value and current metaType are incompatible
* @throws IllegalArgumentException if the value and current dataType are incompatible
* @see #setTypeAndValue(EntityDataType, Object)
*/
public void setValue(@Nullable Object value) {
this.value = checkValue(this.metaType, value);
this.value = checkValue(this.dataType, value);
}
/**
* Sets metadata type and value.
* Sets entity data type and value.
*
* @param metaType metadata type
* @param dataType entity data type
* @param value value
* @throws IllegalArgumentException if the value and metaType are incompatible
* @throws IllegalArgumentException if the value and dataType are incompatible
*/
public void setTypeAndValue(EntityDataType metaType, @Nullable Object value) {
this.value = checkValue(metaType, value);
this.metaType = metaType;
public void setTypeAndValue(EntityDataType dataType, @Nullable Object value) {
this.value = checkValue(dataType, value);
this.dataType = dataType;
}
private Object checkValue(EntityDataType metaType, @Nullable Object value) {
Preconditions.checkNotNull(metaType);
if (value != null && !metaType.type().getOutputClass().isAssignableFrom(value.getClass())) {
throw new IllegalArgumentException("Metadata value and metaType are incompatible. Type=" + metaType
private Object checkValue(EntityDataType dataType, @Nullable Object value) {
Preconditions.checkNotNull(dataType);
if (value != null && !dataType.type().getOutputClass().isAssignableFrom(value.getClass())) {
throw new IllegalArgumentException("Entity data value and dataType are incompatible. Type=" + dataType
+ ", value=" + value + " (" + value.getClass().getSimpleName() + ")");
}
return value;
@@ -111,32 +111,32 @@ public final class EntityData {
@Deprecated
public void setDataTypeUnsafe(EntityDataType type) {
this.metaType = type;
this.dataType = type;
}
@Override
public boolean equals(final Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
EntityData metadata = (EntityData) o;
if (id != metadata.id) return false;
if (metaType != metadata.metaType) return false;
return Objects.equals(value, metadata.value);
EntityData entityData = (EntityData) o;
if (id != entityData.id) return false;
if (dataType != entityData.dataType) return false;
return Objects.equals(value, entityData.value);
}
@Override
public int hashCode() {
int result = id;
result = 31 * result + metaType.hashCode();
result = 31 * result + dataType.hashCode();
result = 31 * result + (value != null ? value.hashCode() : 0);
return result;
}
@Override
public String toString() {
return "Metadata{" +
return "EntityData{" +
"id=" + id +
", metaType=" + metaType +
", dataType=" + dataType +
", value=" + value +
'}';
}
@@ -35,7 +35,7 @@ public interface EntityDataType {
Type type();
/**
* Get type id from the specific MetaDataType
* Get type id from the specific EntityDataType
*
* @return Type id as an integer
*/
@@ -67,7 +67,7 @@ public interface EntityDataType {
@Override
public String toString() {
return "EntityDataType{" +
return "EntityDataTypeImpl{" +
"typeId=" + typeId +
", type=" + type +
'}';
@@ -77,9 +77,9 @@ public interface EntityDataType {
public boolean equals(final Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
final EntityDataTypeImpl metaType = (EntityDataTypeImpl) o;
if (typeId != metaType.typeId) return false;
return type.equals(metaType.type);
final EntityDataTypeImpl dataType = (EntityDataTypeImpl) o;
if (typeId != dataType.typeId) return false;
return type.equals(dataType.type);
}
@Override
@@ -44,8 +44,8 @@ public abstract class AbstractEntityDataTypes implements EntityDataTypes {
}
protected EntityDataType add(final int typeId, final Type<?> type) {
final EntityDataType metaType = EntityDataType.create(typeId, type);
values[typeId] = metaType;
return metaType;
final EntityDataType dataType = EntityDataType.create(typeId, type);
values[typeId] = dataType;
return dataType;
}
}
@@ -27,18 +27,18 @@ import com.viaversion.viaversion.api.minecraft.entitydata.EntityDataType;
public interface EntityDataTypes {
/**
* Returns the meta type by the given id.
* Returns the data type by the given id.
*
* @param id type id
* @return meta type by id
* @return data type by id
* @throws IndexOutOfBoundsException if id is out of bounds
*/
EntityDataType byId(int id);
/**
* Returns an array of meta types.
* Returns an array of data types.
*
* @return array of meta types
* @return array of data types
*/
EntityDataType[] values();
}
@@ -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 +
'}';
}
}
}
@@ -46,8 +46,8 @@ public class StructuredItem implements Item {
return new StructuredItem(0, 0);
}
public static StructuredItem[] emptyArray(final int size) {
final StructuredItem[] items = new StructuredItem[size];
public static Item[] emptyArray(final int size) {
final Item[] items = new Item[size];
for (int i = 0; i < items.length; i++) {
items[i] = empty();
}
@@ -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;
}
}
@@ -104,7 +104,10 @@ public class ProtocolVersionRange {
*/
public boolean contains(final ProtocolVersion version) {
if (this.ranges == null) return true;
return this.ranges.stream().anyMatch(range -> range.contains(version));
for (Range<ProtocolVersion> range : this.ranges) {
if (range.contains(version)) return true;
}
return false;
}
@Override
@@ -28,6 +28,31 @@ import com.viaversion.viaversion.api.platform.providers.Provider;
@FunctionalInterface
public interface VersionProvider extends Provider {
/**
* Optionally allows platforms to specify the client version of a user. This is needed when the platform supports
* connecting other version types then {@link VersionType#RELEASE} to the server.
*
* @param connection connection
* @return client protocol version, or null if handshake packet should be used
*/
default ProtocolVersion getClientProtocol(UserConnection connection) {
return null;
}
/**
* Calls {@link #getClosestServerProtocol(UserConnection)} and catches any exceptions by returning null.
*
* @param connection connection
* @return closest server protocol version to the user's protocol version
*/
default ProtocolVersion getServerProtocol(UserConnection connection) {
try {
return getClosestServerProtocol(connection);
} catch (Exception e) {
return null;
}
}
/**
* Returns the closest server protocol version to the user's protocol version.
* On non-proxy servers, this returns the actual server version.
@@ -59,13 +59,13 @@ public interface EntityRewriter<T extends Protocol<?, ?, ?, ?>> extends Rewriter
int newEntityId(int id);
/**
* Handles and transforms metadata of an entity.
* Handles and transforms entity data of an entity.
*
* @param entityId entity id
* @param metadataList full, mutable list of metadata
* @param dataList full, mutable list of entity data
* @param connection user connection
*/
void handleEntityData(int entityId, List<EntityData> metadataList, UserConnection connection);
void handleEntityData(int entityId, List<EntityData> dataList, UserConnection connection);
/**
* Returns the entity tracker for the current protocol.
@@ -44,7 +44,9 @@ public class ComponentType extends Type<JsonElement> {
try {
return JsonParser.parseString(s);
} catch (JsonSyntaxException e) {
Via.getPlatform().getLogger().severe("Error when trying to parse json: " + s);
if (Via.getManager().isDebug()) {
Via.getPlatform().getLogger().severe("Error when trying to parse json: " + s);
}
throw e;
}
}
@@ -40,20 +40,20 @@ public final class EntityDataListType extends EntityDataListTypeTemplate {
@Override
public List<EntityData> read(final ByteBuf buffer) {
final List<EntityData> list = new ArrayList<>();
EntityData meta;
EntityData data;
do {
meta = this.type.read(buffer);
if (meta != null) {
list.add(meta);
data = this.type.read(buffer);
if (data != null) {
list.add(data);
}
} while (meta != null);
} while (data != null);
return list;
}
@Override
public void write(final ByteBuf buffer, final List<EntityData> object) {
for (final EntityData metadata : object) {
this.type.write(buffer, metadata);
for (final EntityData data : object) {
this.type.write(buffer, data);
}
this.type.write(buffer, null);
}
@@ -26,14 +26,14 @@ import com.viaversion.viaversion.api.minecraft.entitydata.types.EntityDataTypes;
public final class EntityDataType extends ModernEntityDataType {
private final EntityDataTypes metaTypes;
private final EntityDataTypes dataTypes;
public EntityDataType(final EntityDataTypes metaTypes) {
this.metaTypes = metaTypes;
public EntityDataType(final EntityDataTypes dataTypes) {
this.dataTypes = dataTypes;
}
@Override
protected com.viaversion.viaversion.api.minecraft.entitydata.EntityDataType getType(final int index) {
return metaTypes.byId(index);
return dataTypes.byId(index);
}
}
@@ -33,7 +33,7 @@ public abstract class ModernEntityDataType extends EntityDataTypeTemplate {
@Override
public EntityData read(final ByteBuf buffer) {
final short index = buffer.readUnsignedByte();
if (index == END) return null; // End of metadata
if (index == END) return null; // End of data
final EntityDataType type = this.getType(Types.VAR_INT.readPrimitive(buffer));
return new EntityData(index, type, type.type().read(buffer));
}
@@ -32,7 +32,7 @@ public abstract class OldEntityDataType extends EntityDataTypeTemplate {
@Override
public EntityData read(final ByteBuf buffer) {
final byte index = buffer.readByte();
if (index == END) return null; // End of metadata
if (index == END) return null; // End of data
final EntityDataType type = this.getType((index & 224) >> 5);
return new EntityData(index & 31, type, type.type().read(buffer));
}
@@ -50,7 +50,7 @@ public class StructuredDataType extends Type<StructuredData<?>> {
public StructuredData<?> read(final ByteBuf buffer) {
Preconditions.checkNotNull(types, "StructuredDataType has not been initialized");
final int id = Types.VAR_INT.readPrimitive(buffer);
final StructuredDataKey<?> key = this.types[id];
final StructuredDataKey<?> key = key(id);
if (key == null) {
throw new IllegalArgumentException("No data component serializer found for id " + id);
}
@@ -31,11 +31,11 @@ import java.util.List;
public final class Types1_12 {
/**
* Metadata type for 1.12
* Entity data type for 1.12
*/
public static final Type<EntityData> ENTITY_DATA = new EntityDataType1_12();
/**
* Metadata list type for 1.12
* Entity data list type for 1.12
*/
public static final Type<List<EntityData>> ENTITY_DATA_LIST = new EntityDataListType(ENTITY_DATA);
}
@@ -33,11 +33,11 @@ import java.util.List;
public final class Types1_8 {
/**
* Metadata type for 1.8
* Entity data type for 1.8
*/
public static final Type<EntityData> ENTITY_DATA = new EntityDataType1_8();
/**
* Metadata list type for 1.8
* Entity data list type for 1.8
*/
public static final Type<List<EntityData>> ENTITY_DATA_LIST = new EntityDataListType(ENTITY_DATA);
@@ -32,11 +32,11 @@ import java.util.List;
public final class Types1_9 {
/**
* Metadata type for 1.9
* Entity data type for 1.9
*/
public static final Type<EntityData> ENTITY_DATA = new EntityDataType1_9();
/**
* Metadata list type for 1.9
* Entity data list type for 1.9
*/
public static final Type<List<EntityData>> ENTITY_DATA_LIST = new EntityDataListType(ENTITY_DATA);
@@ -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;
}
@@ -51,13 +51,13 @@ public class EntityToggleGlideListener extends ViaBukkitListener {
if (!isOnPipe(player)) return;
// Cancelling can only be done by updating the player's metadata
// Cancelling can only be done by updating the player's entity data
if (event.isGliding() && event.isCancelled()) {
PacketWrapper packet = PacketWrapper.create(ClientboundPackets1_15.SET_ENTITY_DATA, null, getUserConnection(player));
packet.write(Types.VAR_INT, player.getEntityId());
byte bitmask = 0;
// Collect other metadata for the mitmask
// Collect other entity data for the mitmask
if (player.getFireTicks() > 0) {
bitmask |= 0x01;
}
@@ -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,8 +23,6 @@ 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;
@@ -37,31 +35,27 @@ 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"));
// 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();
if (event.getSlot() == player.getInventory().getHeldItemSlot()) {
sendAttributeUpdate(player, item);
}
}
@EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true)
public void onPlayerItemHeld(final PlayerItemHeldEvent event) {
final Player player = event.getPlayer();
final ItemStack item = player.getInventory().getItem(event.getNewSlot());
sendAttributeUpdate(player, item);
sendAttributeUpdate(player, item, Slot.HAND);
}
private void sendAttributeUpdate(final Player player, @Nullable final ItemStack item) {
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;
@@ -72,7 +66,35 @@ public final class PlayerChangeItemListener extends ViaBukkitListener {
return;
}
final int efficiencyLevel = item != null ? item.getEnchantmentLevel(efficiency) : 0;
storage.setEfficiencyLevel(new EfficiencyAttributeStorage.StoredEfficiency(player.getEntityId(), efficiencyLevel), connection);
final EfficiencyAttributeStorage.ActiveEnchants activeEnchants = storage.activeEnchants();
int efficiencyLevel = activeEnchants.efficiency().level();
int aquaAffinityLevel = activeEnchants.aquaAffinity().level();
int soulSpeedLevel = activeEnchants.soulSpeed().level();
int swiftSneakLevel = activeEnchants.swiftSneak().level();
int depthStriderLevel = activeEnchants.depthStrider().level();
switch (slot) {
case HAND -> efficiencyLevel = item != null ? item.getEnchantmentLevel(efficiency) : 0;
case HELMET -> aquaAffinityLevel = item != null ? item.getEnchantmentLevel(aquaAffinity) : 0;
case LEGGINGS -> swiftSneakLevel = item != null && swiftSneak != null ? item.getEnchantmentLevel(swiftSneak) : 0;
case BOOTS -> {
depthStriderLevel = item != null && depthStrider != null ? item.getEnchantmentLevel(depthStrider) : 0;
// TODO This needs continuous ticking for the supporting block as a conditional effect
// and is even more prone to desync from high ping than the other attributes
//soulSpeedLevel = item != null && soulSpeed != null ? item.getEnchantmentLevel(soulSpeed) : 0;
}
}
storage.setEnchants(player.getEntityId(), connection, efficiencyLevel, soulSpeedLevel, swiftSneakLevel, aquaAffinityLevel, depthStriderLevel);
}
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;
}
}
@@ -19,19 +19,20 @@ package com.viaversion.viaversion.bukkit.platform;
import com.viaversion.viaversion.configuration.AbstractViaConfig;
import java.io.File;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.logging.Logger;
public class BukkitViaConfig extends AbstractViaConfig {
private static final List<String> UNSUPPORTED = Arrays.asList("velocity-ping-interval", "velocity-ping-save", "velocity-servers");
private boolean quickMoveActionFix;
private boolean hitboxFix1_9;
private boolean hitboxFix1_14;
private String blockConnectionMethod;
private boolean armorToggleFix;
private boolean registerUserConnectionOnJoin;
private boolean useNewDeathMessages;
private boolean itemCache;
private boolean nmsPlayerTicking;
public BukkitViaConfig(final File folder, final Logger logger) {
super(new File(folder, "config.yml"), logger);
@@ -46,6 +47,9 @@ public class BukkitViaConfig extends AbstractViaConfig {
hitboxFix1_14 = getBoolean("change-1_14-hitbox", false);
blockConnectionMethod = getString("blockconnection-method", "packet");
armorToggleFix = getBoolean("armor-toggle-fix", true);
useNewDeathMessages = getBoolean("use-new-deathmessages", true);
itemCache = getBoolean("item-cache", true);
nmsPlayerTicking = getBoolean("nms-player-ticking", true);
}
@Override
@@ -82,8 +86,23 @@ public class BukkitViaConfig extends AbstractViaConfig {
return armorToggleFix;
}
@Override
public boolean isShowNewDeathMessages() {
return useNewDeathMessages;
}
@Override
public boolean isItemCache() {
return itemCache;
}
@Override
public boolean isNMSPlayerTicking() {
return nmsPlayerTicking;
}
@Override
public List<String> getUnsupportedOptions() {
return UNSUPPORTED;
return VELOCITY_ONLY_OPTIONS;
}
}
@@ -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;
@@ -87,7 +88,9 @@ public class BukkitViaLoader implements ViaPlatformLoader {
if (serverProtocolVersion.olderThan(ProtocolVersion.v1_9)) {
new ArmorListener(plugin).register();
new DeathListener(plugin).register();
new BlockListener(plugin).register();
if (plugin.getConf().cancelBlockSounds()) {
new BlockListener(plugin).register();
}
if (plugin.getConf().isItemCache()) {
handItemCache = new HandItemCache();
@@ -177,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)
}
@@ -67,6 +67,7 @@ public class ViaManagerImpl implements ViaManager {
private final ViaPlatformLoader loader;
private final Set<String> subPlatforms = new HashSet<>();
private List<Runnable> enableListeners = new ArrayList<>();
private List<Runnable> postEnableListeners = new ArrayList<>();
private PlatformTask<?> mappingLoadingTask;
private boolean initialized;
@@ -150,7 +151,7 @@ public class ViaManagerImpl implements ViaManager {
platform.getLogger().warning("and if you're still unsure, feel free to join our Discord-Server for further assistance.");
} else if (protocolVersion.highestSupportedProtocolVersion().olderThan(ProtocolVersion.v1_13)) {
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 are unlikely to provide any further fixes or help with problems specific to legacy Minecraft versions. "
+ "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.");
}
}
@@ -184,6 +185,11 @@ public class ViaManagerImpl implements ViaManager {
// Refresh Versions
protocolManager.refreshVersions();
for (final Runnable listener : postEnableListeners) {
listener.run();
}
postEnableListeners = null;
}
private void loadServerProtocol() {
@@ -204,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) {
@@ -214,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
@@ -235,7 +245,8 @@ public class ViaManagerImpl implements ViaManager {
if (version < 17) {
platform.getLogger().warning("You are running an outdated Java version, please update it to at least Java 17 (your version is " + javaVersion + ").");
platform.getLogger().warning("Starting with Minecraft 1.21, ViaVersion will no longer officially be compatible with this version of Java, only offering unsupported compatibility builds.");
platform.getLogger().warning("ViaVersion no longer officially supports this version of Java, only offering unsupported compatibility builds.");
platform.getLogger().warning("See https://github.com/ViaVersion/ViaVersion/releases/tag/5.0.0 for more information.");
}
}
@@ -316,25 +327,21 @@ public class ViaManagerImpl implements ViaManager {
return configurationProvider;
}
/**
* Returns a mutable set of self-added subplatform version strings.
* This set is expanded by the subplatform itself (e.g. ViaBackwards), and may not contain all running ones.
*
* @return mutable set of subplatform versions
*/
@Override
public Set<String> getSubPlatforms() {
return subPlatforms;
}
/**
* Adds a runnable to be executed when ViaVersion has finished its init before the full server load.
*
* @param runnable runnable to be executed
*/
@Override
public void addEnableListener(Runnable runnable) {
enableListeners.add(runnable);
}
@Override
public void addPostEnableListener(final Runnable runnable) {
postEnableListeners.add(runnable);
}
@Override
public boolean isInitialized() {
return initialized;
@@ -26,6 +26,7 @@ import com.viaversion.viaversion.api.protocol.version.ProtocolVersion;
import com.viaversion.viaversion.protocol.BlockedProtocolVersionsImpl;
import com.viaversion.viaversion.util.Config;
import java.io.File;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
@@ -35,11 +36,15 @@ import it.unimi.dsi.fastutil.objects.ObjectSet;
import org.checkerframework.checker.nullness.qual.Nullable;
public abstract class AbstractViaConfig extends Config implements ViaVersionConfig {
public static final List<String> BUKKIT_ONLY_OPTIONS = Arrays.asList("register-userconnections-on-join", "quick-move-action-fix",
"change-1_9-hitbox", "change-1_14-hitbox", "blockconnection-method", "armor-toggle-fix", "use-new-deathmessages",
"item-cache", "nms-player-ticking");
public static final List<String> VELOCITY_ONLY_OPTIONS = Arrays.asList("velocity-ping-interval", "velocity-ping-save", "velocity-servers");
private boolean checkForUpdates;
private boolean preventCollision;
private boolean useNewEffectIndicator;
private boolean useNewDeathmessages;
private boolean suppressMetadataErrors;
private boolean shieldBlocking;
private boolean noDelayShieldBlocking;
@@ -57,8 +62,6 @@ public abstract class AbstractViaConfig extends Config implements ViaVersionConf
private String maxPPSWarningsKickMessage;
private boolean sendSupportedVersions;
private boolean simulatePlayerTick;
private boolean itemCache;
private boolean nmsPlayerTicking;
private boolean replacePistons;
private int pistonReplacementId;
private boolean chunkBorderFix;
@@ -69,7 +72,6 @@ public abstract class AbstractViaConfig extends Config implements ViaVersionConf
private String reloadDisconnectMessage;
private boolean suppressConversionWarnings;
private boolean disable1_13TabComplete;
private boolean minimizeCooldown;
private boolean teamColourFix;
private boolean serversideBlockConnections;
private boolean reduceBlockStorageMemory;
@@ -91,6 +93,7 @@ public abstract class AbstractViaConfig extends Config implements ViaVersionConf
private boolean translateOcelotToCat;
private boolean enforceSecureChat;
private boolean handleInvalidItemCount;
private boolean cancelBlockSounds;
protected AbstractViaConfig(final File configFile, final Logger logger) {
super(configFile, logger);
@@ -106,7 +109,6 @@ public abstract class AbstractViaConfig extends Config implements ViaVersionConf
checkForUpdates = getBoolean("check-for-updates", true);
preventCollision = getBoolean("prevent-collision", true);
useNewEffectIndicator = getBoolean("use-new-effect-indicator", true);
useNewDeathmessages = getBoolean("use-new-deathmessages", true);
suppressMetadataErrors = getBoolean("suppress-metadata-errors", false);
shieldBlocking = getBoolean("shield-blocking", true);
noDelayShieldBlocking = getBoolean("no-delay-shield-blocking", false);
@@ -124,8 +126,6 @@ public abstract class AbstractViaConfig extends Config implements ViaVersionConf
maxPPSWarningsKickMessage = getString("tracking-max-kick-msg", "You are sending too many packets, :(");
sendSupportedVersions = getBoolean("send-supported-versions", false);
simulatePlayerTick = getBoolean("simulate-pt", true);
itemCache = getBoolean("item-cache", true);
nmsPlayerTicking = getBoolean("nms-player-ticking", true);
replacePistons = getBoolean("replace-pistons", false);
pistonReplacementId = getInt("replacement-piston-id", 0);
chunkBorderFix = getBoolean("chunk-border-fix", false);
@@ -134,7 +134,6 @@ public abstract class AbstractViaConfig extends Config implements ViaVersionConf
blockedProtocolVersions = loadBlockedProtocolVersions();
blockedDisconnectMessage = getString("block-disconnect-msg", "You are using an unsupported Minecraft version!");
reloadDisconnectMessage = getString("reload-disconnect-msg", "Server reload, please rejoin!");
minimizeCooldown = getBoolean("minimize-cooldown", true);
teamColourFix = getBoolean("team-colour-fix", true);
suppressConversionWarnings = getBoolean("suppress-conversion-warnings", false);
disable1_13TabComplete = getBoolean("disable-1_13-auto-complete", false);
@@ -161,6 +160,7 @@ public abstract class AbstractViaConfig extends Config implements ViaVersionConf
translateOcelotToCat = getBoolean("translate-ocelot-to-cat", true);
enforceSecureChat = getBoolean("enforce-secure-chat", false);
handleInvalidItemCount = getBoolean("handle-invalid-item-count", false);
cancelBlockSounds = getBoolean("cancel-block-sounds", true);
}
private BlockedProtocolVersions loadBlockedProtocolVersions() {
@@ -254,7 +254,7 @@ public abstract class AbstractViaConfig extends Config implements ViaVersionConf
@Override
public boolean isShowNewDeathMessages() {
return useNewDeathmessages;
return false;
}
@Override
@@ -344,12 +344,12 @@ public abstract class AbstractViaConfig extends Config implements ViaVersionConf
@Override
public boolean isItemCache() {
return itemCache;
return false;
}
@Override
public boolean isNMSPlayerTicking() {
return nmsPlayerTicking;
return false;
}
@Override
@@ -403,11 +403,6 @@ public abstract class AbstractViaConfig extends Config implements ViaVersionConf
return reloadDisconnectMessage;
}
@Override
public boolean isMinimizeCooldown() {
return minimizeCooldown;
}
@Override
public boolean is1_13TeamColourFix() {
return teamColourFix;
@@ -542,4 +537,9 @@ public abstract class AbstractViaConfig extends Config implements ViaVersionConf
public boolean handleInvalidItemCount() {
return handleInvalidItemCount;
}
@Override
public boolean cancelBlockSounds() {
return cancelBlockSounds;
}
}
@@ -48,6 +48,14 @@ public final class DimensionDataImpl implements DimensionData {
this.minY = minY.asInt();
}
public static DimensionData withDefaultsFor(final String key, final int id) {
return switch (key) {
case "overworld", "overworld_caves" -> new DimensionDataImpl(id, -64, 384);
case "the_nether", "the_end" -> new DimensionDataImpl(id, 0, 256);
default -> throw new IllegalArgumentException("Missing registry data for unknown dimension: " + key);
};
}
@Override
public int id() {
return id;
@@ -65,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 +
'}';
}
@@ -17,10 +17,9 @@
*/
package com.viaversion.viaversion.dump;
import com.viaversion.viaversion.api.protocol.version.VersionType;
import java.util.Set;
public record VersionInfo(String javaVersion, String operatingSystem, VersionType versionType,
public record VersionInfo(String javaVersion, String operatingSystem,
int serverProtocol, String serverVersion,
Set<String> enabledProtocols, String platformName,
String platformVersion, String pluginVersion,
@@ -19,6 +19,7 @@ package com.viaversion.viaversion.legacy.bossbar;
import com.google.common.base.Preconditions;
import com.google.common.collect.MapMaker;
import com.google.gson.JsonParser;
import com.viaversion.viaversion.api.Via;
import com.viaversion.viaversion.api.connection.UserConnection;
import com.viaversion.viaversion.api.legacy.bossbar.BossBar;
@@ -26,7 +27,6 @@ import com.viaversion.viaversion.api.legacy.bossbar.BossColor;
import com.viaversion.viaversion.api.legacy.bossbar.BossFlag;
import com.viaversion.viaversion.api.legacy.bossbar.BossStyle;
import com.viaversion.viaversion.api.protocol.packet.PacketWrapper;
import com.viaversion.viaversion.api.type.Type;
import com.viaversion.viaversion.api.type.Types;
import com.viaversion.viaversion.protocols.v1_8to1_9.Protocol1_8To1_9;
import com.viaversion.viaversion.protocols.v1_8to1_9.packet.ClientboundPackets1_9;
@@ -246,28 +246,32 @@ public class CommonBoss implements BossBar {
wrapper.write(Types.UUID, uuid);
wrapper.write(Types.VAR_INT, action.getId());
switch (action) {
case ADD:
wrapper.write(Types.COMPONENT, ComponentUtil.plainToJson(title));
case ADD -> {
try {
wrapper.write(Types.COMPONENT, JsonParser.parseString(this.title));
} catch (Exception e) {
wrapper.write(Types.COMPONENT, ComponentUtil.plainToJson(this.title));
}
wrapper.write(Types.FLOAT, health);
wrapper.write(Types.VAR_INT, color.getId());
wrapper.write(Types.VAR_INT, style.getId());
wrapper.write(Types.BYTE, (byte) flagToBytes());
break;
case REMOVE:
break;
case UPDATE_HEALTH:
wrapper.write(Types.FLOAT, health);
break;
case UPDATE_TITLE:
wrapper.write(Types.COMPONENT, ComponentUtil.plainToJson(title));
break;
case UPDATE_STYLE:
}
case REMOVE -> {
}
case UPDATE_HEALTH -> wrapper.write(Types.FLOAT, health);
case UPDATE_TITLE -> {
try {
wrapper.write(Types.COMPONENT, JsonParser.parseString(this.title));
} catch (Exception e) {
wrapper.write(Types.COMPONENT, ComponentUtil.plainToJson(this.title));
}
}
case UPDATE_STYLE -> {
wrapper.write(Types.VAR_INT, color.getId());
wrapper.write(Types.VAR_INT, style.getId());
break;
case UPDATE_FLAGS:
wrapper.write(Types.BYTE, (byte) flagToBytes());
break;
}
case UPDATE_FLAGS -> wrapper.write(Types.BYTE, (byte) flagToBytes());
}
return wrapper;
@@ -52,4 +52,7 @@ public class RedirectProtocolVersion extends ProtocolVersion {
};
}
public ProtocolVersion getOrigin() {
return origin;
}
}
@@ -61,15 +61,21 @@ public class BaseProtocol extends AbstractProtocol<BaseClientboundPacket, BaseCl
wrapper.passthrough(Types.UNSIGNED_SHORT); // Server Port
int state = wrapper.passthrough(Types.VAR_INT);
ProtocolInfo info = wrapper.user().getProtocolInfo();
info.setProtocolVersion(ProtocolVersion.getProtocol(protocolVersion));
// Ensure the server has a version provider
VersionProvider versionProvider = Via.getManager().getProviders().get(VersionProvider.class);
// Ensure the server has a version provider
if (versionProvider == null) {
wrapper.user().setActive(false);
return;
}
ProtocolInfo info = wrapper.user().getProtocolInfo();
info.setProtocolVersion(ProtocolVersion.getProtocol(protocolVersion));
ProtocolVersion clientVersion = versionProvider.getClientProtocol(wrapper.user());
if (clientVersion != null) {
info.setProtocolVersion(clientVersion);
}
// Choose the pipe
ProtocolVersion serverProtocol;
try {
@@ -20,6 +20,7 @@ package com.viaversion.viaversion.protocols.v1_10to1_11.rewriter;
import com.viaversion.nbt.tag.CompoundTag;
import com.viaversion.nbt.tag.StringTag;
import com.viaversion.viaversion.api.Via;
import com.viaversion.viaversion.api.minecraft.entities.EntityTypes1_10;
import com.viaversion.viaversion.api.minecraft.entities.EntityTypes1_11;
import com.viaversion.viaversion.api.minecraft.entities.EntityTypes1_11.EntityType;
import com.viaversion.viaversion.api.minecraft.item.DataItem;
@@ -53,8 +54,20 @@ public class EntityPacketRewriter1_11 extends EntityRewriter<ClientboundPackets1
map(Types.VAR_INT); // 0 - Entity id
map(Types.UUID); // 1 - UUID
map(Types.BYTE); // 2 - Type
map(Types.DOUBLE); // 3 - X
map(Types.DOUBLE); // 4 - Y
map(Types.DOUBLE); // 5 - Z
map(Types.BYTE); // 6 - Pitch
map(Types.BYTE); // 7 - Yaw
map(Types.INT); // 8 - Data
// Track Entity
handler(wrapper -> {
byte type = wrapper.get(Types.BYTE, 0);
if (type == EntityTypes1_10.ObjectType.FISHIHNG_HOOK.getId()) {
tryFixFishingHookVelocity(wrapper);
}
});
handler(objectTrackerHandler());
}
});
@@ -74,7 +87,7 @@ public class EntityPacketRewriter1_11 extends EntityRewriter<ClientboundPackets1
map(Types.SHORT); // 9 - Velocity X
map(Types.SHORT); // 10 - Velocity Y
map(Types.SHORT); // 11 - Velocity Z
map(Types1_9.ENTITY_DATA_LIST); // 12 - Metadata
map(Types1_9.ENTITY_DATA_LIST); // 12 - Entity data
handler(wrapper -> {
int entityId = wrapper.get(Types.VAR_INT, 0);
@@ -132,6 +145,13 @@ public class EntityPacketRewriter1_11 extends EntityRewriter<ClientboundPackets1
}
});
protocol.registerClientbound(ClientboundPackets1_9_3.SET_ENTITY_MOTION, wrapper -> {
final int entityId = wrapper.passthrough(Types.VAR_INT);
if (tracker(wrapper.user()).entityType(entityId) == EntityTypes1_10.EntityType.FISHING_HOOK) {
tryFixFishingHookVelocity(wrapper);
}
});
registerRemoveEntities(ClientboundPackets1_9_3.REMOVE_ENTITIES);
protocol.registerClientbound(ClientboundPackets1_9_3.BLOCK_ENTITY_DATA, new PacketHandlers() {
@@ -159,50 +179,50 @@ public class EntityPacketRewriter1_11 extends EntityRewriter<ClientboundPackets1
@Override
protected void registerRewrites() {
filter().handler((event, meta) -> {
if (meta.getValue() instanceof DataItem) {
filter().handler((event, data) -> {
if (data.getValue() instanceof DataItem) {
// Apply rewrite
EntityMappings1_11.toClientItem(meta.value());
EntityMappings1_11.toClientItem(data.value());
}
});
filter().type(EntityType.GUARDIAN).index(12).handler((event, meta) -> {
boolean value = (((byte) meta.getValue()) & 0x02) == 0x02;
meta.setTypeAndValue(EntityDataTypes1_9.BOOLEAN, value);
filter().type(EntityType.GUARDIAN).index(12).handler((event, data) -> {
boolean value = (((byte) data.getValue()) & 0x02) == 0x02;
data.setTypeAndValue(EntityDataTypes1_9.BOOLEAN, value);
});
filter().type(EntityType.ABSTRACT_SKELETON).removeIndex(12);
filter().type(EntityType.ZOMBIE).handler((event, meta) -> {
if ((event.entityType() == EntityType.ZOMBIE || event.entityType() == EntityType.HUSK) && meta.id() == 14) {
filter().type(EntityType.ZOMBIE).handler((event, data) -> {
if ((event.entityType() == EntityType.ZOMBIE || event.entityType() == EntityType.HUSK) && data.id() == 14) {
event.cancel();
} else if (meta.id() == 15) {
meta.setId(14);
} else if (data.id() == 15) {
data.setId(14);
}
});
filter().type(EntityType.ABSTRACT_HORSE).handler((event, metadata) -> {
filter().type(EntityType.ABSTRACT_HORSE).handler((event, data) -> {
final com.viaversion.viaversion.api.minecraft.entities.EntityType type = event.entityType();
int id = metadata.id();
int id = data.id();
if (id == 14) { // Type
event.cancel();
return;
}
if (id == 16) { // Owner
metadata.setId(14);
data.setId(14);
} else if (id == 17) { // Armor
metadata.setId(16);
data.setId(16);
}
// Process per type
if (!type.is(EntityType.HORSE) && metadata.id() == 15 || metadata.id() == 16) {
if (!type.is(EntityType.HORSE) && data.id() == 15 || data.id() == 16) {
event.cancel();
return;
}
if ((type == EntityType.DONKEY || type == EntityType.MULE) && metadata.id() == 13) {
if ((((byte) metadata.getValue()) & 0x08) == 0x08) {
if ((type == EntityType.DONKEY || type == EntityType.MULE) && data.id() == 13) {
if ((((byte) data.getValue()) & 0x08) == 0x08) {
event.createExtraData(new EntityData(15, EntityDataTypes1_9.BOOLEAN, true));
} else {
event.createExtraData(new EntityData(15, EntityDataTypes1_9.BOOLEAN, false));
@@ -210,7 +230,7 @@ public class EntityPacketRewriter1_11 extends EntityRewriter<ClientboundPackets1
}
});
filter().type(EntityType.ARMOR_STAND).index(0).handler((event, meta) -> {
filter().type(EntityType.ARMOR_STAND).index(0).handler((event, data) -> {
if (!Via.getConfig().isHologramPatch()) {
return;
}
@@ -222,9 +242,9 @@ public class EntityPacketRewriter1_11 extends EntityRewriter<ClientboundPackets1
return;
}
byte data = meta.value();
byte value = data.value();
// Check invisible | Check small | Check if custom name is empty | Check if custom name visible is true
if ((data & 0x20) == 0x20 && ((byte) flags.getValue() & 0x01) == 0x01
if ((value & 0x20) == 0x20 && ((byte) flags.getValue() & 0x01) == 0x01
&& !((String) customName.getValue()).isEmpty() && (boolean) customNameVisible.getValue()) {
EntityTracker1_11 tracker = tracker(event.user());
int entityId = event.entityId();
@@ -243,6 +263,17 @@ public class EntityPacketRewriter1_11 extends EntityRewriter<ClientboundPackets1
});
}
private void tryFixFishingHookVelocity(final PacketWrapper wrapper) {
// TODO Fix properly
// Velocity handling of this changed on the client, this code still isn't entirely correct
final short x = wrapper.read(Types.SHORT);
final short y = wrapper.read(Types.SHORT);
final short z = wrapper.read(Types.SHORT);
wrapper.write(Types.SHORT, (short) (x * 1.33));
wrapper.write(Types.SHORT, (short) (y * 1.2));
wrapper.write(Types.SHORT, (short) (z * 1.33));
}
@Override
public com.viaversion.viaversion.api.minecraft.entities.EntityType typeFromId(int type) {
return EntityTypes1_11.getTypeFromId(type, false);
@@ -253,17 +284,17 @@ public class EntityPacketRewriter1_11 extends EntityRewriter<ClientboundPackets1
return EntityTypes1_11.getTypeFromId(type, true);
}
public EntityType rewriteEntityType(int numType, List<EntityData> metadata) {
public EntityType rewriteEntityType(int numType, List<EntityData> entityData) {
EntityType type = EntityType.findById(numType);
if (type == null) {
Via.getManager().getPlatform().getLogger().severe("Error: could not find Entity type " + numType + " with metadata: " + metadata);
Via.getManager().getPlatform().getLogger().severe("Error: could not find Entity type " + numType + " with entity data: " + entityData);
return null;
}
try {
if (type.is(EntityType.GUARDIAN)) {
// ElderGuardian - 4
Optional<EntityData> options = getById(metadata, 12);
Optional<EntityData> options = getById(entityData, 12);
if (options.isPresent()) {
if ((((byte) options.get().getValue()) & 0x04) == 0x04) {
return EntityType.ELDER_GUARDIAN;
@@ -273,7 +304,7 @@ public class EntityPacketRewriter1_11 extends EntityRewriter<ClientboundPackets1
if (type.is(EntityType.SKELETON)) {
// WitherSkeleton - 5
// Stray - 6
Optional<EntityData> options = getById(metadata, 12);
Optional<EntityData> options = getById(entityData, 12);
if (options.isPresent()) {
if (((int) options.get().getValue()) == 1) {
return EntityType.WITHER_SKELETON;
@@ -286,11 +317,11 @@ public class EntityPacketRewriter1_11 extends EntityRewriter<ClientboundPackets1
if (type.is(EntityType.ZOMBIE)) {
// ZombieVillager - 27
// Husk - 23
Optional<EntityData> options = getById(metadata, 13);
Optional<EntityData> options = getById(entityData, 13);
if (options.isPresent()) {
int value = (int) options.get().getValue();
if (value > 0 && value < 6) {
metadata.add(new EntityData(16, EntityDataTypes1_9.VAR_INT, value - 1)); // Add profession type to new metadata
entityData.add(new EntityData(16, EntityDataTypes1_9.VAR_INT, value - 1)); // Add profession type to new entity data
return EntityType.ZOMBIE_VILLAGER;
}
if (value == 6) {
@@ -303,7 +334,7 @@ public class EntityPacketRewriter1_11 extends EntityRewriter<ClientboundPackets1
// ZombieHorse - 29
// Donkey - 31
// Mule - 32
Optional<EntityData> options = getById(metadata, 14);
Optional<EntityData> options = getById(entityData, 14);
if (options.isPresent()) {
if (((int) options.get().getValue()) == 0) {
return EntityType.HORSE;
@@ -325,7 +356,7 @@ public class EntityPacketRewriter1_11 extends EntityRewriter<ClientboundPackets1
} catch (Exception e) {
if (!Via.getConfig().isSuppressMetadataErrors() || Via.getManager().isDebug()) {
protocol.getLogger().warning("An error occurred with entity type rewriter");
protocol.getLogger().warning("Metadata: " + metadata);
protocol.getLogger().warning("Entity data: " + entityData);
protocol.getLogger().log(Level.WARNING, "Error: ", e);
}
}
@@ -333,9 +364,9 @@ public class EntityPacketRewriter1_11 extends EntityRewriter<ClientboundPackets1
return type;
}
public Optional<EntityData> getById(List<EntityData> metadatas, int id) {
for (EntityData metadata : metadatas) {
if (metadata.id() == id) return Optional.of(metadata);
public Optional<EntityData> getById(List<EntityData> entityData, int id) {
for (EntityData data : entityData) {
if (data.id() == id) return Optional.of(data);
}
return Optional.empty();
}
@@ -46,6 +46,8 @@ public final class ChatItemRewriter {
}
} else if (obj.has("extra")) {
toClient(obj.get("extra"));
} else if (obj.has("translate") && obj.has("with")) {
toClient(obj.get("with"));
}
} else if (element instanceof final JsonArray array) {
for (JsonElement value : array) {
@@ -62,9 +62,9 @@ public class EntityPacketRewriter1_12 extends EntityRewriter<ClientboundPackets1
map(Types.SHORT); // 9 - Velocity X
map(Types.SHORT); // 10 - Velocity Y
map(Types.SHORT); // 11 - Velocity Z
map(Types1_12.ENTITY_DATA_LIST); // 12 - Metadata
map(Types1_12.ENTITY_DATA_LIST); // 12 - Entity data
// Track mob and rewrite metadata
// Track mob and rewrite entity data
handler(trackerAndRewriterHandler(Types1_12.ENTITY_DATA_LIST));
}
});
@@ -75,9 +75,9 @@ public class EntityPacketRewriter1_12 extends EntityRewriter<ClientboundPackets1
@Override
protected void registerRewrites() {
filter().handler((event, meta) -> {
if (meta.getValue() instanceof Item) {
meta.setValue(protocol.getItemRewriter().handleItemToClient(event.user(), meta.value()));
filter().handler((event, data) -> {
if (data.getValue() instanceof Item) {
data.setValue(protocol.getItemRewriter().handleItemToClient(event.user(), data.value()));
}
});
@@ -779,7 +779,7 @@ public class Protocol1_12_2To1_13 extends AbstractProtocol<ClientboundPackets1_1
// Clone item arrays because array and item are mutable, also make sure the array type is the interface
switch (recipe.type()) {
case "crafting_shapeless": {
case "crafting_shapeless" -> {
recipesPacket.write(Types.STRING, recipe.group());
recipesPacket.write(Types.VAR_INT, recipe.ingredients().length);
for (Item[] ingredient : recipe.ingredients()) {
@@ -791,9 +791,8 @@ public class Protocol1_12_2To1_13 extends AbstractProtocol<ClientboundPackets1_1
recipesPacket.write(Types.ITEM1_13_ARRAY, clone);
}
recipesPacket.write(Types.ITEM1_13, recipe.result().copy());
break;
}
case "crafting_shaped": {
case "crafting_shaped" -> {
recipesPacket.write(Types.VAR_INT, recipe.width());
recipesPacket.write(Types.VAR_INT, recipe.height());
recipesPacket.write(Types.STRING, recipe.group());
@@ -806,9 +805,8 @@ public class Protocol1_12_2To1_13 extends AbstractProtocol<ClientboundPackets1_1
recipesPacket.write(Types.ITEM1_13_ARRAY, clone);
}
recipesPacket.write(Types.ITEM1_13, recipe.result().copy());
break;
}
case "smelting": {
case "smelting" -> {
recipesPacket.write(Types.STRING, recipe.group());
Item[] ingredient = new Item[recipe.ingredient().length];
for (int i = 0; i < ingredient.length; i++) {
@@ -819,7 +817,6 @@ public class Protocol1_12_2To1_13 extends AbstractProtocol<ClientboundPackets1_1
recipesPacket.write(Types.ITEM1_13, recipe.result().copy());
recipesPacket.write(Types.FLOAT, recipe.experience());
recipesPacket.write(Types.VAR_INT, recipe.cookingTime());
break;
}
}
}
@@ -922,4 +919,4 @@ public class Protocol1_12_2To1_13 extends AbstractProtocol<ClientboundPackets1_1
public ComponentRewriter1_13 getComponentRewriter() {
return componentRewriter;
}
}
}
@@ -61,23 +61,14 @@ public class StairConnectionHandler implements ConnectionHandler {
byte shape;
switch (blockData.getValue("shape")) {
case "straight":
shape = 0;
break;
case "inner_left":
shape = 1;
break;
case "inner_right":
shape = 2;
break;
case "outer_left":
shape = 3;
break;
case "outer_right":
shape = 4;
break;
default:
case "straight" -> shape = 0;
case "inner_left" -> shape = 1;
case "inner_right" -> shape = 2;
case "outer_left" -> shape = 3;
case "outer_right" -> shape = 4;
default -> {
return;
}
}
StairData stairData = new StairData(
@@ -102,7 +102,7 @@ public class EntityPacketRewriter1_13 extends EntityRewriter<ClientboundPackets1
map(Types.SHORT); // 9 - Velocity X
map(Types.SHORT); // 10 - Velocity Y
map(Types.SHORT); // 11 - Velocity Z
map(Types1_12.ENTITY_DATA_LIST, Types1_13.ENTITY_DATA_LIST); // 12 - Metadata
map(Types1_12.ENTITY_DATA_LIST, Types1_13.ENTITY_DATA_LIST); // 12 - Entity data
handler(trackerAndRewriterHandler(Types1_13.ENTITY_DATA_LIST));
}
@@ -118,7 +118,7 @@ public class EntityPacketRewriter1_13 extends EntityRewriter<ClientboundPackets1
map(Types.DOUBLE); // 4 - Z
map(Types.BYTE); // 5 - Yaw
map(Types.BYTE); // 6 - Pitch
map(Types1_12.ENTITY_DATA_LIST, Types1_13.ENTITY_DATA_LIST); // 7 - Metadata
map(Types1_12.ENTITY_DATA_LIST, Types1_13.ENTITY_DATA_LIST); // 7 - Entity data
handler(trackerAndRewriterHandler(Types1_13.ENTITY_DATA_LIST, EntityTypes1_13.EntityType.PLAYER));
}
@@ -167,55 +167,55 @@ public class EntityPacketRewriter1_13 extends EntityRewriter<ClientboundPackets1
@Override
protected void registerRewrites() {
filter().mapDataType(typeId -> Types1_13.ENTITY_DATA_TYPES.byId(typeId > 4 ? typeId + 1 : typeId));
filter().dataType(Types1_13.ENTITY_DATA_TYPES.itemType).handler(((event, meta) -> protocol.getItemRewriter().handleItemToClient(event.user(), meta.value())));
filter().dataType(Types1_13.ENTITY_DATA_TYPES.optionalBlockStateType).handler(((event, meta) -> {
final int oldId = meta.value();
filter().dataType(Types1_13.ENTITY_DATA_TYPES.itemType).handler(((event, data) -> protocol.getItemRewriter().handleItemToClient(event.user(), data.value())));
filter().dataType(Types1_13.ENTITY_DATA_TYPES.optionalBlockStateType).handler(((event, data) -> {
final int oldId = data.value();
if (oldId != 0) {
final int combined = (((oldId & 4095) << 4) | (oldId >> 12 & 15));
final int newId = WorldPacketRewriter1_13.toNewId(combined);
meta.setValue(newId);
data.setValue(newId);
}
}));
// Previously unused, now swimming
filter().index(0).handler((event, meta) -> meta.setValue((byte) ((byte) meta.getValue() & ~0x10)));
filter().index(0).handler((event, data) -> data.setValue((byte) ((byte) data.getValue() & ~0x10)));
filter().index(2).handler(((event, meta) -> {
if (meta.getValue() != null && !((String) meta.getValue()).isEmpty()) {
meta.setTypeAndValue(Types1_13.ENTITY_DATA_TYPES.optionalComponentType, ComponentUtil.legacyToJson((String) meta.getValue()));
filter().index(2).handler(((event, data) -> {
if (data.getValue() != null && !((String) data.getValue()).isEmpty()) {
data.setTypeAndValue(Types1_13.ENTITY_DATA_TYPES.optionalComponentType, ComponentUtil.legacyToJson((String) data.getValue()));
} else {
meta.setTypeAndValue(Types1_13.ENTITY_DATA_TYPES.optionalComponentType, null);
data.setTypeAndValue(Types1_13.ENTITY_DATA_TYPES.optionalComponentType, null);
}
}));
filter().type(EntityTypes1_13.EntityType.WOLF).index(17).handler((event, meta) -> {
filter().type(EntityTypes1_13.EntityType.WOLF).index(17).handler((event, data) -> {
// Handle new colors
meta.setValue(15 - (int) meta.getValue());
data.setValue(15 - (int) data.getValue());
});
filter().type(EntityTypes1_13.EntityType.ZOMBIE).addIndex(15); // Shaking
filter().type(EntityTypes1_13.EntityType.ABSTRACT_MINECART).index(9).handler((event, meta) -> {
final int oldId = meta.value();
filter().type(EntityTypes1_13.EntityType.ABSTRACT_MINECART).index(9).handler((event, data) -> {
final int oldId = data.value();
final int combined = (((oldId & 4095) << 4) | (oldId >> 12 & 15));
final int newId = WorldPacketRewriter1_13.toNewId(combined);
meta.setValue(newId);
data.setValue(newId);
});
filter().type(EntityTypes1_13.EntityType.AREA_EFFECT_CLOUD).handler((event, meta) -> {
if (meta.id() == 9) {
int particleId = meta.value();
EntityData parameter1Meta = event.dataAtIndex(10);
EntityData parameter2Meta = event.dataAtIndex(11);
int parameter1 = parameter1Meta != null ? parameter1Meta.value() : 0;
int parameter2 = parameter2Meta != null ? parameter2Meta.value() : 0;
filter().type(EntityTypes1_13.EntityType.AREA_EFFECT_CLOUD).handler((event, data) -> {
if (data.id() == 9) {
int particleId = data.value();
EntityData parameter1Data = event.dataAtIndex(10);
EntityData parameter2Data = event.dataAtIndex(11);
int parameter1 = parameter1Data != null ? parameter1Data.value() : 0;
int parameter2 = parameter2Data != null ? parameter2Data.value() : 0;
Particle particle = ParticleIdMappings1_13.rewriteParticle(particleId, new Integer[]{parameter1, parameter2});
if (particle != null && particle.id() != -1) {
event.createExtraData(new EntityData(9, Types1_13.ENTITY_DATA_TYPES.particleType, particle));
}
}
if (meta.id() >= 9) {
if (data.id() >= 9) {
event.cancel();
}
});
@@ -453,30 +453,22 @@ public class ItemPacketRewriter1_13 extends ItemRewriter<ClientboundPackets1_12_
public static String getNewPluginChannelId(String old) {
// Default channels that should not be modifiable
switch (old) {
case "MC|TrList":
return "minecraft:trader_list";
case "MC|Brand":
return "minecraft:brand";
case "MC|BOpen":
return "minecraft:book_open";
case "MC|DebugPath":
return "minecraft:debug/paths";
case "MC|DebugNeighborsUpdate":
return "minecraft:debug/neighbors_update";
case "REGISTER":
return "minecraft:register";
case "UNREGISTER":
return "minecraft:unregister";
case "BungeeCord":
return "bungeecord:main";
case "bungeecord:main":
return null;
default:
return switch (old) {
case "MC|TrList" -> "minecraft:trader_list";
case "MC|Brand" -> "minecraft:brand";
case "MC|BOpen" -> "minecraft:book_open";
case "MC|DebugPath" -> "minecraft:debug/paths";
case "MC|DebugNeighborsUpdate" -> "minecraft:debug/neighbors_update";
case "REGISTER" -> "minecraft:register";
case "UNREGISTER" -> "minecraft:unregister";
case "BungeeCord" -> "bungeecord:main";
case "bungeecord:main" -> null;
default -> {
String mappedChannel = Protocol1_12_2To1_13.MAPPINGS.getChannelMappings().get(old);
if (mappedChannel != null) return mappedChannel;
return MappingData1_13.validateNewChannel(old);
}
if (mappedChannel != null) yield mappedChannel;
yield MappingData1_13.validateNewChannel(old);
}
};
}
@Override
@@ -687,28 +679,21 @@ public class ItemPacketRewriter1_13 extends ItemRewriter<ClientboundPackets1_12_
if (newId == null) return null;
// Default channels that should not be modifiable
switch (newId) {
case "minecraft:trader_list":
return "MC|TrList";
case "minecraft:book_open":
return "MC|BOpen";
case "minecraft:debug/paths":
return "MC|DebugPath";
case "minecraft:debug/neighbors_update":
return "MC|DebugNeighborsUpdate";
case "minecraft:register":
return "REGISTER";
case "minecraft:unregister":
return "UNREGISTER";
case "minecraft:brand":
return "MC|Brand";
case "bungeecord:main":
return "BungeeCord";
default:
return switch (newId) {
case "minecraft:trader_list" -> "MC|TrList";
case "minecraft:book_open" -> "MC|BOpen";
case "minecraft:debug/paths" -> "MC|DebugPath";
case "minecraft:debug/neighbors_update" -> "MC|DebugNeighborsUpdate";
case "minecraft:register" -> "REGISTER";
case "minecraft:unregister" -> "UNREGISTER";
case "minecraft:brand" -> "MC|Brand";
case "bungeecord:main" -> "BungeeCord";
default -> {
String mappedChannel = Protocol1_12_2To1_13.MAPPINGS.getChannelMappings().inverse().get(newId);
if (mappedChannel != null) return mappedChannel;
return newId.length() > 20 ? newId.substring(0, 20) : newId;
}
if (mappedChannel != null) yield mappedChannel;
yield newId.length() > 20 ? newId.substring(0, 20) : newId;
}
};
}
public static boolean isDamageable(int id) {
@@ -724,4 +709,4 @@ public class ItemPacketRewriter1_13 extends ItemRewriter<ClientboundPackets1_12_
|| id == 442 // shield
|| id == 443; // elytra
}
}
}
@@ -29,9 +29,9 @@ import com.viaversion.viaversion.protocols.v1_13_1to1_13_2.Protocol1_13_1To1_13_
public class EntityPacketRewriter1_13_2 {
public static void register(Protocol1_13_1To1_13_2 protocol) {
final PacketHandler metaTypeHandler = wrapper -> {
for (EntityData metadata : wrapper.get(Types1_13_2.ENTITY_DATA_LIST, 0)) {
metadata.setDataType(Types1_13_2.ENTITY_DATA_TYPES.byId(metadata.dataType().typeId()));
final PacketHandler dataTypeHandler = wrapper -> {
for (EntityData data : wrapper.get(Types1_13_2.ENTITY_DATA_LIST, 0)) {
data.setDataType(Types1_13_2.ENTITY_DATA_TYPES.byId(data.dataType().typeId()));
}
};
@@ -50,9 +50,9 @@ public class EntityPacketRewriter1_13_2 {
map(Types.SHORT); // 9 - Velocity X
map(Types.SHORT); // 10 - Velocity Y
map(Types.SHORT); // 11 - Velocity Z
map(Types1_13.ENTITY_DATA_LIST, Types1_13_2.ENTITY_DATA_LIST); // 12 - Metadata
map(Types1_13.ENTITY_DATA_LIST, Types1_13_2.ENTITY_DATA_LIST); // 12 - Entity data
handler(metaTypeHandler);
handler(dataTypeHandler);
}
});
@@ -66,9 +66,9 @@ public class EntityPacketRewriter1_13_2 {
map(Types.DOUBLE); // 4 - Z
map(Types.BYTE); // 5 - Yaw
map(Types.BYTE); // 6 - Pitch
map(Types1_13.ENTITY_DATA_LIST, Types1_13_2.ENTITY_DATA_LIST); // 7 - Metadata
map(Types1_13.ENTITY_DATA_LIST, Types1_13_2.ENTITY_DATA_LIST); // 7 - Entity data
handler(metaTypeHandler);
handler(dataTypeHandler);
}
});
@@ -76,9 +76,9 @@ public class EntityPacketRewriter1_13_2 {
@Override
public void register() {
map(Types.VAR_INT); // 0 - Entity ID
map(Types1_13.ENTITY_DATA_LIST, Types1_13_2.ENTITY_DATA_LIST); // 1 - Metadata list
map(Types1_13.ENTITY_DATA_LIST, Types1_13_2.ENTITY_DATA_LIST); // 1 - Entity data list
handler(metaTypeHandler);
handler(dataTypeHandler);
}
});
}
@@ -105,7 +105,7 @@ public class EntityPacketRewriter1_14 extends EntityRewriter<ClientboundPackets1
wrapper.set(Types.INT, 0, data - 1);
}
// send velocity in separate packet, 1.14 is now ignoring the velocity
PacketWrapper velocity = wrapper.create(0x45);
PacketWrapper velocity = wrapper.create(ClientboundPackets1_14.SET_ENTITY_MOTION);
velocity.write(Types.VAR_INT, entityId);
velocity.write(Types.SHORT, wrapper.get(Types.SHORT, 0));
velocity.write(Types.SHORT, wrapper.get(Types.SHORT, 1));
@@ -137,7 +137,7 @@ public class EntityPacketRewriter1_14 extends EntityRewriter<ClientboundPackets1
map(Types.SHORT); // 9 - Velocity X
map(Types.SHORT); // 10 - Velocity Y
map(Types.SHORT); // 11 - Velocity Z
map(Types1_13_2.ENTITY_DATA_LIST, Types1_14.ENTITY_DATA_LIST); // 12 - Metadata
map(Types1_13_2.ENTITY_DATA_LIST, Types1_14.ENTITY_DATA_LIST); // 12 - Entity data
handler(trackerAndRewriterHandler(Types1_14.ENTITY_DATA_LIST));
}
@@ -165,7 +165,7 @@ public class EntityPacketRewriter1_14 extends EntityRewriter<ClientboundPackets1
map(Types.DOUBLE); // 4 - Z
map(Types.BYTE); // 5 - Yaw
map(Types.BYTE); // 6 - Pitch
map(Types1_13_2.ENTITY_DATA_LIST, Types1_14.ENTITY_DATA_LIST); // 7 - Metadata
map(Types1_13_2.ENTITY_DATA_LIST, Types1_14.ENTITY_DATA_LIST); // 7 - Entity data
handler(trackerAndRewriterHandler(Types1_14.ENTITY_DATA_LIST, EntityTypes1_14.PLAYER));
}
@@ -182,15 +182,15 @@ public class EntityPacketRewriter1_14 extends EntityRewriter<ClientboundPackets1
int entityId = wrapper.get(Types.VAR_INT, 0);
tracker.setSleeping(entityId, false);
PacketWrapper metadataPacket = wrapper.create(ClientboundPackets1_14.SET_ENTITY_DATA);
metadataPacket.write(Types.VAR_INT, entityId);
List<EntityData> metadataList = new ArrayList<>();
PacketWrapper entityDataPacket = wrapper.create(ClientboundPackets1_14.SET_ENTITY_DATA);
entityDataPacket.write(Types.VAR_INT, entityId);
List<EntityData> entityDataList = new ArrayList<>();
if (tracker.clientEntityId() != entityId) {
metadataList.add(new EntityData(6, Types1_14.ENTITY_DATA_TYPES.poseType, EntityPacketRewriter1_14.recalculatePlayerPose(entityId, tracker)));
entityDataList.add(new EntityData(6, Types1_14.ENTITY_DATA_TYPES.poseType, EntityPacketRewriter1_14.recalculatePlayerPose(entityId, tracker)));
}
metadataList.add(new EntityData(12, Types1_14.ENTITY_DATA_TYPES.optionalBlockPositionType, null));
metadataPacket.write(Types1_14.ENTITY_DATA_LIST, metadataList);
metadataPacket.scheduleSend(Protocol1_13_2To1_14.class);
entityDataList.add(new EntityData(12, Types1_14.ENTITY_DATA_TYPES.optionalBlockPositionType, null));
entityDataPacket.write(Types1_14.ENTITY_DATA_LIST, entityDataList);
entityDataPacket.scheduleSend(Protocol1_13_2To1_14.class);
}
});
}
@@ -242,12 +242,12 @@ public class EntityPacketRewriter1_14 extends EntityRewriter<ClientboundPackets1
tracker.setSleeping(entityId, true);
BlockPosition position = wrapper.read(Types.BLOCK_POSITION1_8);
List<EntityData> metadataList = new ArrayList<>();
metadataList.add(new EntityData(12, Types1_14.ENTITY_DATA_TYPES.optionalBlockPositionType, position));
List<EntityData> entityDataList = new ArrayList<>();
entityDataList.add(new EntityData(12, Types1_14.ENTITY_DATA_TYPES.optionalBlockPositionType, position));
if (tracker.clientEntityId() != entityId) {
metadataList.add(new EntityData(6, Types1_14.ENTITY_DATA_TYPES.poseType, EntityPacketRewriter1_14.recalculatePlayerPose(entityId, tracker)));
entityDataList.add(new EntityData(6, Types1_14.ENTITY_DATA_TYPES.poseType, EntityPacketRewriter1_14.recalculatePlayerPose(entityId, tracker)));
}
wrapper.write(Types1_14.ENTITY_DATA_LIST, metadataList);
wrapper.write(Types1_14.ENTITY_DATA_LIST, entityDataList);
});
}
});
@@ -267,55 +267,55 @@ public class EntityPacketRewriter1_14 extends EntityRewriter<ClientboundPackets1
filter().type(EntityTypes1_14.LIVING_ENTITY).addIndex(12);
filter().type(EntityTypes1_14.LIVING_ENTITY).index(8).handler((event, meta) -> {
float value = ((Number) meta.getValue()).floatValue();
filter().type(EntityTypes1_14.LIVING_ENTITY).index(8).handler((event, data) -> {
float value = ((Number) data.getValue()).floatValue();
if (Float.isNaN(value) && Via.getConfig().is1_14HealthNaNFix()) {
meta.setValue(1F);
data.setValue(1F);
}
});
filter().type(EntityTypes1_14.MOB).index(13).handler((event, meta) -> {
filter().type(EntityTypes1_14.MOB).index(13).handler((event, data) -> {
EntityTracker1_14 tracker = tracker(event.user());
int entityId = event.entityId();
tracker.setInsentientData(entityId, (byte) ((((Number) meta.getValue()).byteValue() & ~0x4)
| (tracker.getInsentientData(entityId) & 0x4))); // New attacking metadata
meta.setValue(tracker.getInsentientData(entityId));
tracker.setInsentientData(entityId, (byte) ((((Number) data.getValue()).byteValue() & ~0x4)
| (tracker.getInsentientData(entityId) & 0x4))); // New attacking entity data
data.setValue(tracker.getInsentientData(entityId));
});
filter().type(EntityTypes1_14.PLAYER).handler((event, meta) -> {
filter().type(EntityTypes1_14.PLAYER).handler((event, data) -> {
EntityTracker1_14 tracker = tracker(event.user());
int entityId = event.entityId();
if (entityId != tracker.clientEntityId()) {
if (meta.id() == 0) {
byte flags = ((Number) meta.getValue()).byteValue();
if (data.id() == 0) {
byte flags = ((Number) data.getValue()).byteValue();
// Mojang overrides the client-side pose updater, see OtherPlayerEntity#updateSize
tracker.setEntityFlags(entityId, flags);
} else if (meta.id() == 7) {
tracker.setRiptide(entityId, (((Number) meta.getValue()).byteValue() & 0x4) != 0);
} else if (data.id() == 7) {
tracker.setRiptide(entityId, (((Number) data.getValue()).byteValue() & 0x4) != 0);
}
if (meta.id() == 0 || meta.id() == 7) {
if (data.id() == 0 || data.id() == 7) {
event.createExtraData(new EntityData(6, Types1_14.ENTITY_DATA_TYPES.poseType, recalculatePlayerPose(entityId, tracker)));
}
}
});
filter().type(EntityTypes1_14.ZOMBIE).handler((event, meta) -> {
if (meta.id() == 16) {
filter().type(EntityTypes1_14.ZOMBIE).handler((event, data) -> {
if (data.id() == 16) {
EntityTracker1_14 tracker = tracker(event.user());
int entityId = event.entityId();
tracker.setInsentientData(entityId, (byte) ((tracker.getInsentientData(entityId) & ~0x4)
| ((boolean) meta.getValue() ? 0x4 : 0))); // New attacking
| ((boolean) data.getValue() ? 0x4 : 0))); // New attacking
event.createExtraData(new EntityData(13, Types1_14.ENTITY_DATA_TYPES.byteType, tracker.getInsentientData(entityId)));
event.cancel(); // "Are hands held up"
} else if (meta.id() > 16) {
meta.setId(meta.id() - 1);
} else if (data.id() > 16) {
data.setId(data.id() - 1);
}
});
filter().type(EntityTypes1_14.HORSE).index(18).handler((event, meta) -> {
filter().type(EntityTypes1_14.HORSE).index(18).handler((event, data) -> {
event.cancel();
int armorType = meta.value();
int armorType = data.value();
Item armorItem = null;
if (armorType == 1) { //iron armor
armorItem = new DataItem(protocol.getMappingData().getNewItemId(727), (byte) 1, null);
@@ -336,42 +336,42 @@ public class EntityPacketRewriter1_14 extends EntityRewriter<ClientboundPackets1
}
});
filter().type(EntityTypes1_14.VILLAGER).index(15).handler((event, meta) -> {
meta.setTypeAndValue(Types1_14.ENTITY_DATA_TYPES.villagerDatatType, new VillagerData(2, getNewProfessionId(meta.value()), 0));
filter().type(EntityTypes1_14.VILLAGER).index(15).handler((event, data) -> {
data.setTypeAndValue(Types1_14.ENTITY_DATA_TYPES.villagerDatatType, new VillagerData(2, getNewProfessionId(data.value()), 0));
});
filter().type(EntityTypes1_14.ZOMBIE_VILLAGER).index(18).handler((event, meta) -> {
meta.setTypeAndValue(Types1_14.ENTITY_DATA_TYPES.villagerDatatType, new VillagerData(2, getNewProfessionId(meta.value()), 0));
filter().type(EntityTypes1_14.ZOMBIE_VILLAGER).index(18).handler((event, data) -> {
data.setTypeAndValue(Types1_14.ENTITY_DATA_TYPES.villagerDatatType, new VillagerData(2, getNewProfessionId(data.value()), 0));
});
filter().type(EntityTypes1_14.ABSTRACT_ARROW).addIndex(9); // Piercing level added
filter().type(EntityTypes1_14.FIREWORK_ROCKET).index(8).handler((event, meta) -> {
meta.setDataType(Types1_14.ENTITY_DATA_TYPES.optionalVarIntType);
if (meta.getValue().equals(0)) {
meta.setValue(null); // https://bugs.mojang.com/browse/MC-111480
filter().type(EntityTypes1_14.FIREWORK_ROCKET).index(8).handler((event, data) -> {
data.setDataType(Types1_14.ENTITY_DATA_TYPES.optionalVarIntType);
if (data.getValue().equals(0)) {
data.setValue(null); // https://bugs.mojang.com/browse/MC-111480
}
});
filter().type(EntityTypes1_14.ABSTRACT_SKELETON).index(14).handler((event, meta) -> {
filter().type(EntityTypes1_14.ABSTRACT_SKELETON).index(14).handler((event, data) -> {
EntityTracker1_14 tracker = tracker(event.user());
int entityId = event.entityId();
tracker.setInsentientData(entityId, (byte) ((tracker.getInsentientData(entityId) & ~0x4)
| ((boolean) meta.getValue() ? 0x4 : 0))); // New attacking
| ((boolean) data.getValue() ? 0x4 : 0))); // New attacking
event.createExtraData(new EntityData(13, Types1_14.ENTITY_DATA_TYPES.byteType, tracker.getInsentientData(entityId)));
event.cancel(); // "Is swinging arms"
});
filter().type(EntityTypes1_14.ABSTRACT_ILLAGER).handler((event, meta) -> {
filter().type(EntityTypes1_14.ABSTRACT_ILLAGER).handler((event, data) -> {
if (event.index() == 14) {
EntityTracker1_14 tracker = tracker(event.user());
int entityId = event.entityId();
tracker.setInsentientData(entityId, (byte) ((tracker.getInsentientData(entityId) & ~0x4)
| (((Number) meta.getValue()).byteValue() != 0 ? 0x4 : 0))); // New attacking
| (((Number) data.getValue()).byteValue() != 0 ? 0x4 : 0))); // New attacking
event.createExtraData(new EntityData(13, Types1_14.ENTITY_DATA_TYPES.byteType, tracker.getInsentientData(entityId)));
event.cancel(); // "Has target (aggressive state)"
} else if (event.index() > 14) {
meta.setId(meta.id() - 1);
data.setId(data.id() - 1);
}
});
@@ -86,42 +86,21 @@ public class ItemPacketRewriter1_14 extends ItemRewriter<ClientboundPackets1_13,
int typeId = -1;
switch (type) {
case "minecraft:crafting_table":
typeId = 11;
break;
case "minecraft:furnace":
typeId = 13;
break;
case "minecraft:dropper", "minecraft:dispenser":
typeId = 6;
break;
case "minecraft:enchanting_table":
typeId = 12;
break;
case "minecraft:brewing_stand":
typeId = 10;
break;
case "minecraft:villager":
typeId = 18;
break;
case "minecraft:beacon":
typeId = 8;
break;
case "minecraft:anvil":
typeId = 7;
break;
case "minecraft:hopper":
typeId = 15;
break;
case "minecraft:shulker_box":
typeId = 19;
break;
case "minecraft:container", "minecraft:chest":
default:
case "minecraft:crafting_table" -> typeId = 11;
case "minecraft:furnace" -> typeId = 13;
case "minecraft:dropper", "minecraft:dispenser" -> typeId = 6;
case "minecraft:enchanting_table" -> typeId = 12;
case "minecraft:brewing_stand" -> typeId = 10;
case "minecraft:villager" -> typeId = 18;
case "minecraft:beacon" -> typeId = 8;
case "minecraft:anvil" -> typeId = 7;
case "minecraft:hopper" -> typeId = 15;
case "minecraft:shulker_box" -> typeId = 19;
default -> {
if (slots > 0 && slots <= 54) {
typeId = slots / 9 - 1;
}
break;
}
}
if (typeId == -1) {
@@ -80,7 +80,7 @@ public class EntityPacketRewriter1_13_1 extends EntityRewriter<ClientboundPacket
map(Types.SHORT); // 9 - Velocity X
map(Types.SHORT); // 10 - Velocity Y
map(Types.SHORT); // 11 - Velocity Z
map(Types1_13.ENTITY_DATA_LIST); // 12 - Metadata
map(Types1_13.ENTITY_DATA_LIST); // 12 - Entity data
handler(trackerAndRewriterHandler(Types1_13.ENTITY_DATA_LIST));
}
@@ -96,7 +96,7 @@ public class EntityPacketRewriter1_13_1 extends EntityRewriter<ClientboundPacket
map(Types.DOUBLE); // 4 - Z
map(Types.BYTE); // 5 - Yaw
map(Types.BYTE); // 6 - Pitch
map(Types1_13.ENTITY_DATA_LIST); // 7 - Metadata
map(Types1_13.ENTITY_DATA_LIST); // 7 - Entity data
handler(trackerAndRewriterHandler(Types1_13.ENTITY_DATA_LIST, EntityTypes1_13.EntityType.PLAYER));
}
@@ -58,7 +58,7 @@ public class EntityPacketRewriter1_15 extends EntityRewriter<ClientboundPackets1
map(Types.SHORT); // 11 - Velocity Z
handler(trackerHandler());
handler(wrapper -> sendMetadataPacket(wrapper, wrapper.get(Types.VAR_INT, 0)));
handler(wrapper -> sendEntityDataPacket(wrapper, wrapper.get(Types.VAR_INT, 0)));
}
});
@@ -77,7 +77,7 @@ public class EntityPacketRewriter1_15 extends EntityRewriter<ClientboundPackets1
int entityId = wrapper.get(Types.VAR_INT, 0);
wrapper.user().getEntityTracker(Protocol1_14_4To1_15.class).addEntity(entityId, EntityTypes1_15.PLAYER);
sendMetadataPacket(wrapper, entityId);
sendEntityDataPacket(wrapper, entityId);
});
}
});
@@ -122,10 +122,10 @@ public class EntityPacketRewriter1_15 extends EntityRewriter<ClientboundPackets1
}
private void sendMetadataPacket(PacketWrapper wrapper, int entityId) {
// Meta is no longer included in the spawn packets, but sent separately
List<EntityData> metadata = wrapper.read(Types1_14.ENTITY_DATA_LIST);
if (metadata.isEmpty()) {
private void sendEntityDataPacket(PacketWrapper wrapper, int entityId) {
// Data is no longer included in the spawn packets, but sent separately
List<EntityData> entityData = wrapper.read(Types1_14.ENTITY_DATA_LIST);
if (entityData.isEmpty()) {
return;
}
@@ -133,13 +133,13 @@ public class EntityPacketRewriter1_15 extends EntityRewriter<ClientboundPackets1
wrapper.send(Protocol1_14_4To1_15.class);
wrapper.cancel();
// Handle meta
handleEntityData(entityId, metadata, wrapper.user());
// Handle data
handleEntityData(entityId, entityData, wrapper.user());
PacketWrapper metadataPacket = PacketWrapper.create(ClientboundPackets1_15.SET_ENTITY_DATA, wrapper.user());
metadataPacket.write(Types.VAR_INT, entityId);
metadataPacket.write(Types1_14.ENTITY_DATA_LIST, metadata);
metadataPacket.send(Protocol1_14_4To1_15.class);
PacketWrapper entityDataPacket = PacketWrapper.create(ClientboundPackets1_15.SET_ENTITY_DATA, wrapper.user());
entityDataPacket.write(Types.VAR_INT, entityId);
entityDataPacket.write(Types1_14.ENTITY_DATA_LIST, entityData);
entityDataPacket.send(Protocol1_14_4To1_15.class);
}
@Override
@@ -49,7 +49,7 @@ public class EntityPacketRewriter1_14_1 extends EntityRewriter<ClientboundPacket
map(Types.SHORT); // 9 - Velocity X
map(Types.SHORT); // 10 - Velocity Y
map(Types.SHORT); // 11 - Velocity Z
map(Types1_14.ENTITY_DATA_LIST); // 12 - Metadata
map(Types1_14.ENTITY_DATA_LIST); // 12 - Entity data
handler(trackerAndRewriterHandler(Types1_14.ENTITY_DATA_LIST));
}
@@ -67,7 +67,7 @@ public class EntityPacketRewriter1_14_1 extends EntityRewriter<ClientboundPacket
map(Types.DOUBLE); // 4 - Z
map(Types.BYTE); // 5 - Yaw
map(Types.BYTE); // 6 - Pitch
map(Types1_14.ENTITY_DATA_LIST); // 7 - Metadata
map(Types1_14.ENTITY_DATA_LIST); // 7 - Entity data
handler(trackerAndRewriterHandler(Types1_14.ENTITY_DATA_LIST, EntityTypes1_14.PLAYER));
}
@@ -24,6 +24,7 @@ import com.viaversion.viaversion.api.minecraft.entities.EntityTypes1_16;
import com.viaversion.viaversion.api.minecraft.entitydata.EntityData;
import com.viaversion.viaversion.api.protocol.remapper.PacketHandler;
import com.viaversion.viaversion.api.protocol.remapper.PacketHandlers;
import com.viaversion.viaversion.api.protocol.version.ProtocolVersion;
import com.viaversion.viaversion.api.type.Types;
import com.viaversion.viaversion.api.type.types.version.Types1_14;
import com.viaversion.viaversion.api.type.types.version.Types1_16;
@@ -50,22 +51,23 @@ public class EntityPacketRewriter1_16 extends EntityRewriter<ClientboundPackets1
String dimensionName;
String outputName;
switch (dimension) {
case -1:
case -1 -> {
dimensionName = "minecraft:the_nether";
outputName = map.nether();
break;
case 0:
}
case 0 -> {
dimensionName = "minecraft:overworld";
outputName = map.overworld();
break;
case 1:
}
case 1 -> {
dimensionName = "minecraft:the_end";
outputName = map.end();
break;
default:
}
default -> {
protocol.getLogger().warning("Invalid dimension id: " + dimension);
dimensionName = "minecraft:overworld";
outputName = map.overworld();
}
}
wrapper.write(Types.STRING, dimensionName); // dimension
@@ -119,10 +121,13 @@ public class EntityPacketRewriter1_16 extends EntityRewriter<ClientboundPackets1
handler(wrapper -> {
wrapper.write(Types.BYTE, (byte) -1); // Previous gamemode, set to none
// <= 1.14.4 didn't keep attributes on respawn and 1.15.x always kept them
final boolean keepAttributes = wrapper.user().getProtocolInfo().serverProtocolVersion().newerThanOrEqualTo(ProtocolVersion.v1_15);
String levelType = wrapper.read(Types.STRING);
wrapper.write(Types.BOOLEAN, false); // debug
wrapper.write(Types.BOOLEAN, levelType.equals("flat"));
wrapper.write(Types.BOOLEAN, true); // keep all playerdata
wrapper.write(Types.BOOLEAN, keepAttributes); // keep player attributes
});
}
});
@@ -211,8 +216,8 @@ public class EntityPacketRewriter1_16 extends EntityRewriter<ClientboundPackets1
registerBlockStateHandler(EntityTypes1_16.ABSTRACT_MINECART, 10);
filter().type(EntityTypes1_16.ABSTRACT_ARROW).removeIndex(8);
filter().type(EntityTypes1_16.WOLF).index(16).handler((event, meta) -> {
byte mask = meta.value();
filter().type(EntityTypes1_16.WOLF).index(16).handler((event, data) -> {
byte mask = data.value();
int angerTime = (mask & 0x02) != 0 ? Integer.MAX_VALUE : 0;
event.createExtraData(new EntityData(20, Types1_16.ENTITY_DATA_TYPES.varIntType, angerTime));
});
@@ -80,11 +80,11 @@ public class EntityPacketRewriter1_16_2 extends EntityRewriter<ClientboundPacket
registerEntityDataTypeHandler(Types1_16.ENTITY_DATA_TYPES.itemType, Types1_16.ENTITY_DATA_TYPES.optionalBlockStateType, Types1_16.ENTITY_DATA_TYPES.particleType);
registerBlockStateHandler(EntityTypes1_16_2.ABSTRACT_MINECART, 10);
filter().type(EntityTypes1_16_2.ABSTRACT_PIGLIN).handler((metadatas, meta) -> {
if (meta.id() == 15) {
meta.setId(16);
} else if (meta.id() == 16) {
meta.setId(15);
filter().type(EntityTypes1_16_2.ABSTRACT_PIGLIN).handler((event, data) -> {
if (data.id() == 15) {
data.setId(16);
} else if (data.id() == 16) {
data.setId(15);
}
});
}
@@ -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();
@@ -136,11 +160,11 @@ public final class EntityPacketRewriter1_17 extends EntityRewriter<ClientboundPa
@Override
protected void registerRewrites() {
filter().mapDataType(Types1_17.ENTITY_DATA_TYPES::byId);
filter().dataType(Types1_17.ENTITY_DATA_TYPES.poseType).handler((event, meta) -> {
int pose = meta.value();
filter().dataType(Types1_17.ENTITY_DATA_TYPES.poseType).handler((event, data) -> {
int pose = data.value();
if (pose > 5) {
// Added LONG_JUMP at 6
meta.setValue(pose + 1);
data.setValue(pose + 1);
}
});
registerEntityDataTypeHandler(Types1_17.ENTITY_DATA_TYPES.itemType, Types1_17.ENTITY_DATA_TYPES.optionalBlockStateType, Types1_17.ENTITY_DATA_TYPES.particleType);
@@ -82,8 +82,8 @@ public final class EntityPacketRewriter1_18 extends EntityRewriter<ClientboundPa
@Override
protected void registerRewrites() {
filter().mapDataType(Types1_18.ENTITY_DATA_TYPES::byId);
filter().dataType(Types1_18.ENTITY_DATA_TYPES.particleType).handler((event, meta) -> {
final Particle particle = (Particle) meta.getValue();
filter().dataType(Types1_18.ENTITY_DATA_TYPES.particleType).handler((event, data) -> {
final Particle particle = (Particle) data.getValue();
if (particle.id() == 2) { // Barrier
particle.setId(3); // Block marker
particle.add(Types.VAR_INT, 7754); // Barrier state
@@ -26,8 +26,8 @@ import com.viaversion.nbt.tag.NumberTag;
import com.viaversion.viaversion.api.Via;
import com.viaversion.viaversion.api.data.ParticleMappings;
import com.viaversion.viaversion.api.data.entity.DimensionData;
import com.viaversion.viaversion.api.minecraft.Particle;
import com.viaversion.viaversion.api.minecraft.BlockPosition;
import com.viaversion.viaversion.api.minecraft.Particle;
import com.viaversion.viaversion.api.minecraft.entities.EntityType;
import com.viaversion.viaversion.api.minecraft.entities.EntityTypes1_19;
import com.viaversion.viaversion.api.minecraft.entitydata.EntityData;
@@ -115,13 +115,13 @@ public final class EntityPacketRewriter1_19 extends EntityRewriter<ClientboundPa
wrapper.send(Protocol1_18_2To1_19.class);
wrapper.cancel();
// Send motive in metadata
final PacketWrapper metaPacket = wrapper.create(ClientboundPackets1_19.SET_ENTITY_DATA);
metaPacket.write(Types.VAR_INT, wrapper.get(Types.VAR_INT, 0)); // Entity id
final List<EntityData> metadata = new ArrayList<>();
metadata.add(new EntityData(8, Types1_19.ENTITY_DATA_TYPES.paintingVariantType, protocol.getMappingData().getPaintingMappings().getNewIdOrDefault(motive, 0)));
metaPacket.write(Types1_19.ENTITY_DATA_LIST, metadata);
metaPacket.send(Protocol1_18_2To1_19.class);
// Send motive in entity data
final PacketWrapper entityDataPacket = wrapper.create(ClientboundPackets1_19.SET_ENTITY_DATA);
entityDataPacket.write(Types.VAR_INT, wrapper.get(Types.VAR_INT, 0)); // Entity id
final List<EntityData> entityData = new ArrayList<>();
entityData.add(new EntityData(8, Types1_19.ENTITY_DATA_TYPES.paintingVariantType, protocol.getMappingData().getPaintingMappings().getNewIdOrDefault(motive, 0)));
entityDataPacket.write(Types1_19.ENTITY_DATA_LIST, entityData);
entityDataPacket.send(Protocol1_18_2To1_19.class);
});
}
});
@@ -227,7 +227,7 @@ public final class EntityPacketRewriter1_19 extends EntityRewriter<ClientboundPa
map(Types.BYTE); // Previous gamemode
map(Types.BOOLEAN); // Debug
map(Types.BOOLEAN); // Flat
map(Types.BOOLEAN); // Keep player data
map(Types.BOOLEAN); // Keep player attributes
create(Types.OPTIONAL_GLOBAL_POSITION, null); // Last death location
handler(worldDataTrackerHandlerByKey());
}
@@ -317,8 +317,8 @@ public final class EntityPacketRewriter1_19 extends EntityRewriter<ClientboundPa
@Override
protected void registerRewrites() {
filter().mapDataType(Types1_19.ENTITY_DATA_TYPES::byId);
filter().dataType(Types1_19.ENTITY_DATA_TYPES.particleType).handler((event, meta) -> {
final Particle particle = (Particle) meta.getValue();
filter().dataType(Types1_19.ENTITY_DATA_TYPES.particleType).handler((event, data) -> {
final Particle particle = (Particle) data.getValue();
final ParticleMappings particleMappings = protocol.getMappingData().getParticleMappings();
if (particle.id() == particleMappings.id("vibration")) {
// Remove the position
@@ -349,4 +349,4 @@ public final class EntityPacketRewriter1_19 extends EntityRewriter<ClientboundPa
public EntityType typeFromId(final int type) {
return EntityTypes1_19.getTypeFromId(type);
}
}
}
@@ -155,11 +155,11 @@ public final class EntityPacketRewriter1_19_3 extends EntityRewriter<Clientbound
registerEntityDataTypeHandler(Types1_19_3.ENTITY_DATA_TYPES.itemType, Types1_19_3.ENTITY_DATA_TYPES.optionalBlockStateType, Types1_19_3.ENTITY_DATA_TYPES.particleType);
registerBlockStateHandler(EntityTypes1_19_3.ABSTRACT_MINECART, 11);
filter().type(EntityTypes1_19_3.ENTITY).index(6).handler((event, meta) -> {
filter().type(EntityTypes1_19_3.ENTITY).index(6).handler((event, data) -> {
// Sitting pose added
final int pose = meta.value();
final int pose = data.value();
if (pose >= 10) {
meta.setValue(pose + 1);
data.setValue(pose + 1);
}
});
}
@@ -19,7 +19,6 @@ package com.viaversion.viaversion.protocols.v1_19_1to1_19_3.rewriter;
import com.viaversion.viaversion.api.minecraft.item.Item;
import com.viaversion.viaversion.api.protocol.remapper.PacketHandlers;
import com.viaversion.viaversion.api.type.Type;
import com.viaversion.viaversion.api.type.Types;
import com.viaversion.viaversion.api.type.types.chunk.ChunkType1_18;
import com.viaversion.viaversion.protocols.v1_19_1to1_19_3.Protocol1_19_1To1_19_3;
@@ -66,7 +65,7 @@ public final class ItemPacketRewriter1_19_3 extends ItemRewriter<ClientboundPack
final String type = Key.stripMinecraftNamespace(wrapper.passthrough(Types.STRING));
wrapper.passthrough(Types.STRING); // Recipe Identifier
switch (type) {
case "crafting_shapeless": {
case "crafting_shapeless" -> {
wrapper.passthrough(Types.STRING); // Group
wrapper.write(Types.VAR_INT, MISC_CRAFTING_BOOK_CATEGORY);
final int ingredients = wrapper.passthrough(Types.VAR_INT);
@@ -77,9 +76,8 @@ public final class ItemPacketRewriter1_19_3 extends ItemRewriter<ClientboundPack
}
}
handleItemToClient(wrapper.user(), wrapper.passthrough(Types.ITEM1_13_2)); // Result
break;
}
case "crafting_shaped": {
case "crafting_shaped" -> {
final int ingredients = wrapper.passthrough(Types.VAR_INT) * wrapper.passthrough(Types.VAR_INT);
wrapper.passthrough(Types.STRING); // Group
wrapper.write(Types.VAR_INT, MISC_CRAFTING_BOOK_CATEGORY);
@@ -90,12 +88,8 @@ public final class ItemPacketRewriter1_19_3 extends ItemRewriter<ClientboundPack
}
}
handleItemToClient(wrapper.user(), wrapper.passthrough(Types.ITEM1_13_2)); // Result
break;
}
case "smelting":
case "campfire_cooking":
case "blasting":
case "smoking":
case "smelting", "campfire_cooking", "blasting", "smoking" -> {
wrapper.passthrough(Types.STRING); // Group
wrapper.write(Types.VAR_INT, MISC_CRAFTING_BOOK_CATEGORY);
final Item[] items = wrapper.passthrough(Types.ITEM1_13_2_ARRAY); // Ingredients
@@ -105,25 +99,12 @@ public final class ItemPacketRewriter1_19_3 extends ItemRewriter<ClientboundPack
handleItemToClient(wrapper.user(), wrapper.passthrough(Types.ITEM1_13_2)); // Result
wrapper.passthrough(Types.FLOAT); // EXP
wrapper.passthrough(Types.VAR_INT); // Cooking time
break;
case "crafting_special_armordye":
case "crafting_special_bookcloning":
case "crafting_special_mapcloning":
case "crafting_special_mapextending":
case "crafting_special_firework_rocket":
case "crafting_special_firework_star":
case "crafting_special_firework_star_fade":
case "crafting_special_tippedarrow":
case "crafting_special_bannerduplicate":
case "crafting_special_shielddecoration":
case "crafting_special_shulkerboxcoloring":
case "crafting_special_suspiciousstew":
case "crafting_special_repairitem":
wrapper.write(Types.VAR_INT, MISC_CRAFTING_BOOK_CATEGORY);
break;
default:
recipeRewriter.handleRecipeType(wrapper, type);
break;
}
case "crafting_special_armordye", "crafting_special_bookcloning", "crafting_special_mapcloning", "crafting_special_mapextending",
"crafting_special_firework_rocket", "crafting_special_firework_star", "crafting_special_firework_star_fade", "crafting_special_tippedarrow",
"crafting_special_bannerduplicate", "crafting_special_shielddecoration", "crafting_special_shulkerboxcoloring", "crafting_special_suspiciousstew",
"crafting_special_repairitem" -> wrapper.write(Types.VAR_INT, MISC_CRAFTING_BOOK_CATEGORY);
default -> recipeRewriter.handleRecipeType(wrapper, type);
}
}
});
@@ -223,10 +223,10 @@ public final class EntityPacketRewriter1_19_4 extends EntityRewriter<Clientbound
registerEntityDataTypeHandler(Types1_19_4.ENTITY_DATA_TYPES.itemType, Types1_19_4.ENTITY_DATA_TYPES.blockStateType, Types1_19_4.ENTITY_DATA_TYPES.optionalBlockStateType, Types1_19_4.ENTITY_DATA_TYPES.particleType, null);
registerBlockStateHandler(EntityTypes1_19_4.ABSTRACT_MINECART, 11);
filter().type(EntityTypes1_19_4.BOAT).index(11).handler((event, meta) -> {
final int boatType = meta.value();
filter().type(EntityTypes1_19_4.BOAT).index(11).handler((event, data) -> {
final int boatType = data.value();
if (boatType > 4) { // Cherry added
meta.setValue(boatType + 1);
data.setValue(boatType + 1);
}
});
@@ -63,7 +63,7 @@ public final class Protocol1_19_4To1_20 extends AbstractProtocol<ClientboundPack
wrapper.read(Types.INT); // Killer ID
});
registerClientbound(ClientboundPackets1_19_4.PLAYER_COMBAT_KILL, wrapper -> {
wrapper.passthrough(Types.VAR_INT); // Duration
wrapper.passthrough(Types.VAR_INT); // Player ID
wrapper.read(Types.INT); // Killer ID
});
}
@@ -132,7 +132,7 @@ public final class EntityPacketRewriter1_20 extends EntityRewriter<ClientboundPa
registerBlockStateHandler(EntityTypes1_19_4.ABSTRACT_MINECART, 11);
// Rotate item display by 180 degrees around the Y axis
filter().type(EntityTypes1_19_4.ITEM_DISPLAY).handler((event, meta) -> {
filter().type(EntityTypes1_19_4.ITEM_DISPLAY).handler((event, data) -> {
if (event.trackedEntity().hasSentEntityData() || event.hasExtraData()) {
return;
}
@@ -141,9 +141,9 @@ public final class EntityPacketRewriter1_20 extends EntityRewriter<ClientboundPa
event.createExtraData(new EntityData(12, Types1_20.ENTITY_DATA_TYPES.quaternionType, Y_FLIPPED_ROTATION));
}
});
filter().type(EntityTypes1_19_4.ITEM_DISPLAY).index(12).handler((event, meta) -> {
final Quaternion quaternion = meta.value();
meta.setValue(rotateY180(quaternion));
filter().type(EntityTypes1_19_4.ITEM_DISPLAY).index(12).handler((event, data) -> {
final Quaternion quaternion = data.value();
data.setValue(rotateY180(quaternion));
});
}
@@ -399,19 +399,13 @@ public final class Protocol1_19To1_19_1 extends AbstractProtocol<ClientboundPack
for (final StringTag element : parameters) {
JsonElement argument = null;
switch (element.getValue()) {
case "sender":
argument = senderName;
break;
case "content":
argument = message;
break;
case "team_name":
case "target": // So that this method can also be used in VB
case "sender" -> argument = senderName;
case "content" -> argument = message;
case "team_name", "target" /*So that this method can also be used in VB*/ -> {
Preconditions.checkNotNull(targetName, "Team name is null");
argument = targetName;
break;
default:
LOGGER.warning("Unknown parameter for chat decoration: " + element.getValue());
}
default -> LOGGER.warning("Unknown parameter for chat decoration: " + element.getValue());
}
if (argument != null) {
arguments.add(SerializerVersion.V1_18.toComponent(argument));
@@ -258,7 +258,7 @@ public final class Protocol1_20_2To1_20_3 extends AbstractProtocol<ClientboundPa
registerClientbound(ClientboundPackets1_20_2.PLAYER_COMBAT_KILL, new PacketHandlers() {
@Override
public void register() {
map(Types.VAR_INT); // Duration
map(Types.VAR_INT); // Player ID
handler(wrapper -> convertComponent(wrapper));
}
});
@@ -146,25 +146,28 @@ public final class BlockItemPacketRewriter1_20_3 extends ItemRewriter<Clientboun
final CompoundTag tag = item.tag();
if (tag != null && item.identifier() == 1047) { // Written book
updatePages(tag, "pages");
updatePages(tag, "filtered_pages"); // TODO This isn't a list
final ListTag<StringTag> pages = tag.getListTag("pages", StringTag.class);
if (pages != null) {
for (final StringTag pageTag : pages) {
updatePageTag(pageTag);
}
}
final CompoundTag filteredPages = tag.getCompoundTag("filtered_pages");
if (filteredPages != null) {
for (final String string : filteredPages.keySet()) {
updatePageTag(filteredPages.getStringTag(string));
}
}
}
return super.handleItemToClient(connection, item);
}
private void updatePages(final CompoundTag tag, final String key) {
final ListTag<StringTag> pages = tag.getListTag(key, StringTag.class);
if (pages == null) {
return;
}
for (final StringTag pageTag : pages) {
try {
final JsonElement updatedComponent = ComponentUtil.convertJson(pageTag.getValue(), SerializerVersion.V1_19_4, SerializerVersion.V1_20_3);
pageTag.setValue(updatedComponent.toString());
} catch (final Exception e) {
Via.getManager().debugHandler().error("Error during book conversion", e);
}
private void updatePageTag(final StringTag pageTag) {
try {
final JsonElement updatedComponent = ComponentUtil.convertJson(pageTag.getValue(), SerializerVersion.V1_19_4, SerializerVersion.V1_20_3);
pageTag.setValue(updatedComponent.toString());
} catch (final Exception e) {
Via.getManager().debugHandler().error("Error during book conversion", e);
}
}
}
@@ -103,18 +103,18 @@ public final class EntityPacketRewriter1_20_3 extends EntityRewriter<Clientbound
@Override
protected void registerRewrites() {
filter().handler((event, meta) -> {
final EntityDataType type = meta.dataType();
filter().handler((event, data) -> {
final EntityDataType type = data.dataType();
if (type == Types1_20_2.ENTITY_DATA_TYPES.componentType) {
meta.setTypeAndValue(Types1_20_3.ENTITY_DATA_TYPES.componentType, ComponentUtil.jsonToTag(meta.value()));
data.setTypeAndValue(Types1_20_3.ENTITY_DATA_TYPES.componentType, ComponentUtil.jsonToTag(data.value()));
} else if (type == Types1_20_2.ENTITY_DATA_TYPES.optionalComponentType) {
meta.setTypeAndValue(Types1_20_3.ENTITY_DATA_TYPES.optionalComponentType, ComponentUtil.jsonToTag(meta.value()));
data.setTypeAndValue(Types1_20_3.ENTITY_DATA_TYPES.optionalComponentType, ComponentUtil.jsonToTag(data.value()));
} else {
meta.setDataType(Types1_20_3.ENTITY_DATA_TYPES.byId(type.typeId()));
data.setDataType(Types1_20_3.ENTITY_DATA_TYPES.byId(type.typeId()));
}
});
filter().dataType(Types1_20_3.ENTITY_DATA_TYPES.particleType).handler((event, meta) -> {
final Particle particle = meta.value();
filter().dataType(Types1_20_3.ENTITY_DATA_TYPES.particleType).handler((event, data) -> {
final Particle particle = data.value();
final ParticleMappings particleMappings = protocol.getMappingData().getParticleMappings();
if (particle.id() == particleMappings.id("vibration")) {
// Change the type of the resource key argument
@@ -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,12 +50,14 @@ 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;
import com.viaversion.viaversion.rewriter.StatisticsRewriter;
import com.viaversion.viaversion.rewriter.TagRewriter;
import com.viaversion.viaversion.util.ProtocolLogger;
import java.util.BitSet;
import java.util.UUID;
import static com.viaversion.viaversion.util.ProtocolUtil.packetTypeMap;
@@ -93,6 +95,16 @@ public final class Protocol1_20_3To1_20_5 extends AbstractProtocol<ClientboundPa
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...
componentRewriter.registerOpenScreen(ClientboundPackets1_20_3.OPEN_SCREEN);
componentRewriter.registerComponentPacket(ClientboundPackets1_20_3.SET_ACTION_BAR_TEXT);
componentRewriter.registerComponentPacket(ClientboundPackets1_20_3.SET_TITLE_TEXT);
componentRewriter.registerComponentPacket(ClientboundPackets1_20_3.SET_SUBTITLE_TEXT);
componentRewriter.registerBossEvent(ClientboundPackets1_20_3.BOSS_EVENT);
componentRewriter.registerComponentPacket(ClientboundPackets1_20_3.DISCONNECT);
componentRewriter.registerTabList(ClientboundPackets1_20_3.TAB_LIST);
componentRewriter.registerPing();
registerClientbound(State.LOGIN, ClientboundLoginPackets.HELLO, wrapper -> {
wrapper.passthrough(Types.STRING); // Server ID
wrapper.passthrough(Types.BYTE_ARRAY_PRIMITIVE); // Public key
@@ -114,26 +126,6 @@ public final class Protocol1_20_3To1_20_5 extends AbstractProtocol<ClientboundPa
}
});
// Big problem with this update: Without access to the client, this cannot 100% predict the
// correct offset. This means we have to entirely discard client acknowledgements and fake them.
registerClientbound(ClientboundPackets1_20_3.PLAYER_CHAT, wrapper -> {
wrapper.passthrough(Types.UUID); // Sender
wrapper.passthrough(Types.VAR_INT); // Index
final byte[] signature = wrapper.passthrough(Types.OPTIONAL_SIGNATURE_BYTES);
if (signature == null) {
return;
}
// Mimic client behavior for acknowledgements
final AcknowledgedMessagesStorage storage = wrapper.user().get(AcknowledgedMessagesStorage.class);
if (storage.add(signature) && storage.offset() > 64) {
final PacketWrapper chatAck = wrapper.create(ServerboundPackets1_20_3.CHAT_ACK);
chatAck.write(Types.VAR_INT, storage.offset());
chatAck.sendToServer(Protocol1_20_3To1_20_5.class);
storage.clearOffset();
}
});
registerServerbound(ServerboundPackets1_20_5.CHAT, wrapper -> {
wrapper.passthrough(Types.STRING); // Message
wrapper.passthrough(Types.LONG); // Timestamp
@@ -151,7 +143,7 @@ public final class Protocol1_20_3To1_20_5 extends AbstractProtocol<ClientboundPa
wrapper.write(Types.OPTIONAL_SIGNATURE_BYTES, null);
}
replaceChatAck(wrapper, storage);
fixChatAck(wrapper, storage);
});
registerServerbound(ServerboundPackets1_20_5.CHAT_COMMAND_SIGNED, ServerboundPackets1_20_3.CHAT_COMMAND, wrapper -> {
wrapper.passthrough(Types.STRING); // Command
@@ -178,7 +170,16 @@ public final class Protocol1_20_3To1_20_5 extends AbstractProtocol<ClientboundPa
}
}
replaceChatAck(wrapper, storage);
fixChatAck(wrapper, storage);
});
registerServerbound(ServerboundPackets1_20_5.CHAT_ACK, wrapper -> {
final int offset = wrapper.read(Types.VAR_INT);
final int fixedOffset = wrapper.user().get(AcknowledgedMessagesStorage.class).accumulateAckCount(offset);
if (fixedOffset > 0) {
wrapper.write(Types.VAR_INT, fixedOffset);
} else {
wrapper.cancel();
}
});
registerServerbound(ServerboundPackets1_20_5.CHAT_COMMAND, wrapper -> {
wrapper.passthrough(Types.STRING); // Command
@@ -187,7 +188,7 @@ public final class Protocol1_20_3To1_20_5 extends AbstractProtocol<ClientboundPa
wrapper.write(Types.LONG, 0L); // Salt
wrapper.write(Types.VAR_INT, 0); // No signatures
writeChatAck(wrapper, wrapper.user().get(AcknowledgedMessagesStorage.class));
writeSpoofedChatAck(wrapper, wrapper.user().get(AcknowledgedMessagesStorage.class));
});
registerServerbound(ServerboundPackets1_20_5.CHAT_SESSION_UPDATE, wrapper -> {
// Delay this until we know whether the server enforces secure chat
@@ -204,7 +205,6 @@ public final class Protocol1_20_3To1_20_5 extends AbstractProtocol<ClientboundPa
wrapper.cancel();
});
cancelServerbound(ServerboundPackets1_20_5.CHAT_ACK);
registerClientbound(ClientboundPackets1_20_3.START_CONFIGURATION, wrapper -> wrapper.user().put(new AcknowledgedMessagesStorage()));
@@ -231,16 +231,19 @@ public final class Protocol1_20_3To1_20_5 extends AbstractProtocol<ClientboundPa
cancelServerbound(ServerboundPackets1_20_5.DEBUG_SAMPLE_SUBSCRIPTION);
}
private void replaceChatAck(final PacketWrapper wrapper, final AcknowledgedMessagesStorage storage) {
wrapper.read(Types.VAR_INT); // Offset
wrapper.read(Types.ACKNOWLEDGED_BIT_SET); // Acknowledged
writeChatAck(wrapper, storage);
private void fixChatAck(final PacketWrapper wrapper, final AcknowledgedMessagesStorage storage) {
final int offset = wrapper.read(Types.VAR_INT);
final BitSet acknowledged = wrapper.read(Types.ACKNOWLEDGED_BIT_SET);
final int fixedOffset = storage.updateFromMessage(offset, acknowledged);
wrapper.write(Types.VAR_INT, fixedOffset);
// Never change this, as this message (and future ones) are signed with it
wrapper.write(Types.ACKNOWLEDGED_BIT_SET, acknowledged);
}
private void writeChatAck(final PacketWrapper wrapper, final AcknowledgedMessagesStorage storage) {
wrapper.write(Types.VAR_INT, storage.offset());
wrapper.write(Types.ACKNOWLEDGED_BIT_SET, storage.toAck());
storage.clearOffset();
private void writeSpoofedChatAck(final PacketWrapper wrapper, final AcknowledgedMessagesStorage storage) {
// As we don't have the new state from the client, replay what we last received
wrapper.write(Types.VAR_INT, 0); // Offset
wrapper.write(Types.ACKNOWLEDGED_BIT_SET, storage.createSpoofedAck()); // Acknowledged
}
@Override
@@ -290,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
@@ -330,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,110 +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.nbt.tag.CompoundTag;
import it.unimi.dsi.fastutil.objects.Object2ObjectMap;
import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap;
import it.unimi.dsi.fastutil.objects.ObjectSet;
public final class DamageTypes1_20_3 {
private static final Object2ObjectMap<String, CompoundTag> DAMAGE_TYPES = new Object2ObjectOpenHashMap<>();
static {
DAMAGE_TYPES.put("in_fire", create("inFire", 0.1F));
DAMAGE_TYPES.put("lightning_bolt", create("lightningBolt", 0.1F));
DAMAGE_TYPES.put("on_fire", create("onFire", 0.0F, "burning"));
DAMAGE_TYPES.put("lava", create("lava", 0.1F, "burning"));
DAMAGE_TYPES.put("hot_floor", create("hotFloor", 0.1F, "burning"));
DAMAGE_TYPES.put("in_wall", create("inWall", 0.0F));
DAMAGE_TYPES.put("cramming", create("cramming", 0.0F));
DAMAGE_TYPES.put("drown", create("drown", 0.0F, "drowning"));
DAMAGE_TYPES.put("starve", create("starve", 0.0F));
DAMAGE_TYPES.put("cactus", create("cactus", 0.1F));
DAMAGE_TYPES.put("fall", create("fall", "when_caused_by_living_non_player", 0.0F, null, "fall_variants"));
DAMAGE_TYPES.put("fly_into_wall", create("flyIntoWall", 0.0F));
DAMAGE_TYPES.put("out_of_world", create("outOfWorld", 0.0F));
DAMAGE_TYPES.put("generic", create("generic", 0.0F));
DAMAGE_TYPES.put("magic", create("magic", 0.0F));
DAMAGE_TYPES.put("wither", create("wither", 0.0F));
DAMAGE_TYPES.put("dragon_breath", create("dragonBreath", 0.0F));
DAMAGE_TYPES.put("dry_out", create("dryout", 0.1F));
DAMAGE_TYPES.put("sweet_berry_bush", create("sweetBerryBush", 0.1F, "poking"));
DAMAGE_TYPES.put("freeze", create("freeze", 0.0F, "freezing"));
DAMAGE_TYPES.put("stalagmite", create("stalagmite", 0.0F));
DAMAGE_TYPES.put("falling_block", create("fallingBlock", 0.1F));
DAMAGE_TYPES.put("falling_anvil", create("anvil", 0.1F));
DAMAGE_TYPES.put("falling_stalactite", create("fallingStalactite", 0.1F));
DAMAGE_TYPES.put("sting", create("sting", 0.1F));
DAMAGE_TYPES.put("mob_attack", create("mob", 0.1F));
DAMAGE_TYPES.put("mob_attack_no_aggro", create("mob", 0.1F));
DAMAGE_TYPES.put("player_attack", create("player", 0.1F));
DAMAGE_TYPES.put("arrow", create("arrow", 0.1F));
DAMAGE_TYPES.put("trident", create("trident", 0.1F));
DAMAGE_TYPES.put("mob_projectile", create("mob", 0.1F));
DAMAGE_TYPES.put("fireworks", create("fireworks", 0.1F));
DAMAGE_TYPES.put("unattributed_fireball", create("onFire", 0.1F, "burning"));
DAMAGE_TYPES.put("fireball", create("fireball", 0.1F, "burning"));
DAMAGE_TYPES.put("wither_skull", create("witherSkull", 0.1F));
DAMAGE_TYPES.put("thrown", create("thrown", 0.1F));
DAMAGE_TYPES.put("indirect_magic", create("indirectMagic", 0.0F));
DAMAGE_TYPES.put("thorns", create("thorns", 0.1F, "thorns"));
DAMAGE_TYPES.put("explosion", create("explosion", "always", 0.1F));
DAMAGE_TYPES.put("player_explosion", create("explosion.player", "always", 0.1F));
DAMAGE_TYPES.put("sonic_boom", create("sonic_boom", "always", 0.0F));
DAMAGE_TYPES.put("bad_respawn_point", create("badRespawnPoint", "always", 0.1F, "hurt", "intentional_game_design"));
DAMAGE_TYPES.put("outside_border", create("outsideBorder", 0.0F));
DAMAGE_TYPES.put("generic_kill", create("genericKill", 0.0F));
}
public static CompoundTag get(String key) {
return DAMAGE_TYPES.get(key);
}
public static ObjectSet<String> keys() {
return DAMAGE_TYPES.keySet();
}
private static CompoundTag create(String messageId, String scaling, float exhaustion) {
return create(messageId, scaling, exhaustion, null, null);
}
private static CompoundTag create(String messageId, float exhaustion, String effects) {
return create(messageId, "when_caused_by_living_non_player", exhaustion, effects, null);
}
private static CompoundTag create(String messageId, float exhaustion) {
return create(messageId, "when_caused_by_living_non_player", exhaustion);
}
private static CompoundTag create(String messageId, String scaling, float exhaustion, String damageEffects, String deathMessageType) {
final CompoundTag tag = new CompoundTag();
tag.putString("message_id", messageId);
tag.putString("scaling", scaling);
tag.putFloat("exhaustion", exhaustion);
if (damageEffects != null) {
tag.putString("effects", damageEffects);
}
if (deathMessageType != null) {
tag.putString("death_message_type", deathMessageType);
}
return tag;
}
}
@@ -22,10 +22,14 @@ import com.viaversion.nbt.tag.StringTag;
import com.viaversion.viaversion.api.data.MappingDataBase;
import com.viaversion.viaversion.api.data.MappingDataLoader;
import com.viaversion.viaversion.util.KeyMappings;
import it.unimi.dsi.fastutil.objects.Object2ObjectMap;
import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap;
import it.unimi.dsi.fastutil.objects.ObjectSet;
import org.checkerframework.checker.nullness.qual.Nullable;
public class MappingData1_20_5 extends MappingDataBase {
private final Object2ObjectMap<String, CompoundTag> damageTypes = new Object2ObjectOpenHashMap<>();
private KeyMappings blocks;
private KeyMappings sounds;
@@ -40,6 +44,11 @@ public class MappingData1_20_5 extends MappingDataBase {
final CompoundTag extraMappings = MappingDataLoader.INSTANCE.loadNBT("extra-identifiers-1.20.3.nbt");
blocks = new KeyMappings(extraMappings.getListTag("blocks", StringTag.class));
sounds = new KeyMappings(extraMappings.getListTag("sounds", StringTag.class));
final CompoundTag damageTypes = MappingDataLoader.INSTANCE.loadNBT("damage-types-1.20.3.nbt");
for (final String key : damageTypes.keySet()) {
this.damageTypes.put(key, damageTypes.getCompoundTag(key));
}
}
public int blockId(final String name) {
@@ -57,4 +66,12 @@ public class MappingData1_20_5 extends MappingDataBase {
public @Nullable String soundName(final int id) {
return sounds.idToKey(id);
}
public CompoundTag damageType(final String key) {
return damageTypes.get(key).copy();
}
public ObjectSet<String> damageKeys() {
return damageTypes.keySet();
}
}
@@ -17,7 +17,6 @@
*/
package com.viaversion.viaversion.protocols.v1_20_3to1_20_5.rewriter;
import com.viaversion.nbt.stringified.SNBT;
import com.viaversion.nbt.tag.ByteTag;
import com.viaversion.nbt.tag.CompoundTag;
import com.viaversion.nbt.tag.IntArrayTag;
@@ -75,6 +74,7 @@ import com.viaversion.viaversion.api.minecraft.item.data.ToolProperties;
import com.viaversion.viaversion.api.minecraft.item.data.ToolRule;
import com.viaversion.viaversion.api.minecraft.item.data.Unbreakable;
import com.viaversion.viaversion.api.minecraft.item.data.WrittenBook;
import com.viaversion.viaversion.api.protocol.version.ProtocolVersion;
import com.viaversion.viaversion.api.type.Types;
import com.viaversion.viaversion.api.type.types.chunk.ChunkType1_20_2;
import com.viaversion.viaversion.api.type.types.version.Types1_20_3;
@@ -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;
@@ -174,10 +173,10 @@ public final class BlockItemPacketRewriter1_20_5 extends ItemRewriter<Clientboun
registerCooldown(ClientboundPackets1_20_3.COOLDOWN);
registerSetContent1_17_1(ClientboundPackets1_20_3.CONTAINER_SET_CONTENT);
registerSetSlot1_17_1(ClientboundPackets1_20_3.CONTAINER_SET_SLOT);
registerSetEquipment(ClientboundPackets1_20_3.SET_EQUIPMENT);
registerContainerClick1_17_1(ServerboundPackets1_20_5.CONTAINER_CLICK);
registerContainerSetData(ClientboundPackets1_20_3.CONTAINER_SET_DATA);
registerSetCreativeModeSlot(ServerboundPackets1_20_5.SET_CREATIVE_MODE_SLOT);
protocol.registerServerbound(ServerboundPackets1_20_5.CONTAINER_BUTTON_CLICK, wrapper -> {
final byte containerId = wrapper.read(Types.VAR_INT).byteValue();
final byte buttonId = wrapper.read(Types.VAR_INT).byteValue();
@@ -225,18 +224,32 @@ public final class BlockItemPacketRewriter1_20_5 extends ItemRewriter<Clientboun
wrapper.passthrough(Types.DOUBLE); // X
wrapper.passthrough(Types.DOUBLE); // Y
wrapper.passthrough(Types.DOUBLE); // Z
wrapper.passthrough(Types.FLOAT); // Offset X
wrapper.passthrough(Types.FLOAT); // Offset Y
wrapper.passthrough(Types.FLOAT); // Offset Z
final float offX = wrapper.passthrough(Types.FLOAT);
final float offY = wrapper.passthrough(Types.FLOAT);
final float offZ = wrapper.passthrough(Types.FLOAT);
final float data = wrapper.passthrough(Types.FLOAT);
wrapper.passthrough(Types.INT); // Particle Count
final int count = wrapper.passthrough(Types.INT);
// Read data and add it to Particle
final ParticleMappings mappings = protocol.getMappingData().getParticleMappings();
final int mappedId = mappings.getNewId(particleId);
final Particle particle = new Particle(mappedId);
if (mappedId == mappings.mappedId("entity_effect")) {
particle.add(Types.INT, data != 0 ? ThreadLocalRandom.current().nextInt() : 0); // rgb
final int color;
if (data == 0) {
// Black
color = 0;
} else if (count != 0) {
// Randomized color
color = ThreadLocalRandom.current().nextInt();
} else {
// From offset
final int red = Math.round(offX * 255);
final int green = Math.round(offY * 255);
final int blue = Math.round(offZ * 255);
color = (red << 16) | (green << 8) | blue;
}
particle.add(Types.INT, EntityPacketRewriter1_20_5.withAlpha(color));
} else if (particleId == mappings.id("dust_color_transition")) {
for (int i = 0; i < 7; i++) {
particle.add(Types.FLOAT, wrapper.read(Types.FLOAT));
@@ -370,6 +383,8 @@ public final class BlockItemPacketRewriter1_20_5 extends ItemRewriter<Clientboun
}
final Item structuredItem = toStructuredItem(connection, item);
// Add data components to fix issues in older protocols
appendItemDataFixComponents(connection, structuredItem);
if (Via.getConfig().handleInvalidItemCount()) {
// Server can send amounts which are higher than vanilla's default, and 1.20.4 will still accept them,
@@ -393,7 +408,7 @@ public final class BlockItemPacketRewriter1_20_5 extends ItemRewriter<Clientboun
}
public Item toOldItem(final UserConnection connection, final Item item, final StructuredDataConverter dataConverter) {
// Start out with custom data and add the rest on top, or short-curcuit with the original item
// Start out with custom data and add the rest on top, or short-circuit with the original item
final StructuredDataContainer data = item.dataContainer();
data.setIdLookup(protocol, true);
@@ -408,6 +423,10 @@ public final class BlockItemPacketRewriter1_20_5 extends ItemRewriter<Clientboun
dataConverter.writeToTag(connection, structuredData, tag);
}
if (tag.isEmpty()) {
dataItem.setTag(null);
}
return dataItem;
}
@@ -479,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");
@@ -591,6 +610,22 @@ public final class BlockItemPacketRewriter1_20_5 extends ItemRewriter<Clientboun
return item;
}
private void appendItemDataFixComponents(final UserConnection connection, final Item item) {
final ProtocolVersion serverVersion = connection.getProtocolInfo().serverProtocolVersion();
if (serverVersion.olderThanOrEqualTo(ProtocolVersion.v1_17_1)) {
if (item.identifier() == 1182) { // crossbow
// Change crossbow damage to value used in 1.17.1 and lower
item.dataContainer().set(StructuredDataKey.MAX_DAMAGE, 326);
}
}
if (serverVersion.olderThanOrEqualTo(ProtocolVersion.v1_8)) {
if (item.identifier() == 814 || item.identifier() == 819 || item.identifier() == 824 || item.identifier() == 829 || item.identifier() == 834) { // swords
// Make sword "eatable" to enable clientside instant blocking on 1.8. Consume time is set really high, so the eating animation doesn't play
item.dataContainer().set(StructuredDataKey.FOOD1_20_5, new FoodProperties(0, 0F, true, 3600, null, new FoodEffect[0]));
}
}
}
private int unmappedItemId(final String name) {
return protocol.getMappingData().getFullItemMappings().id(name);
}
@@ -822,7 +857,7 @@ public final class BlockItemPacketRewriter1_20_5 extends ItemRewriter<Clientboun
CompoundTag tag = null;
if (tagStartIndex != -1 && tagEndIndex != -1) {
try {
tag = SNBT.deserializeCompoundTag(rawPredicate.substring(tagStartIndex, tagEndIndex + 1));
tag = (CompoundTag) SerializerVersion.V1_20_3.toTag(rawPredicate.substring(tagStartIndex, tagEndIndex + 1));
} catch (final Exception e) {
if (Via.getManager().isDebug()) {
Protocol1_20_3To1_20_5.LOGGER.log(Level.SEVERE, "Failed to parse block predicate tag: " + rawPredicate.substring(tagStartIndex, tagEndIndex + 1), e);
@@ -931,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;
}
@@ -984,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");
@@ -1071,13 +1106,13 @@ public final class BlockItemPacketRewriter1_20_5 extends ItemRewriter<Clientboun
data.set(StructuredDataKey.SUSPICIOUS_STEW_EFFECTS, suspiciousStewEffects);
}
private void updateLodestoneTracker(final boolean tracked, final CompoundTag lodestonePosTag, final String lodestoneDimensionTag, final StructuredDataContainer data) {
private void updateLodestoneTracker(final boolean tracked, final CompoundTag lodestonePosTag, final String lodestoneDimension, final StructuredDataContainer data) {
GlobalBlockPosition position = null;
if (lodestonePosTag != null && lodestoneDimensionTag != null) {
if (lodestonePosTag != null && lodestoneDimension != null) {
final int x = lodestonePosTag.getInt("X");
final int y = lodestonePosTag.getInt("Y");
final int z = lodestonePosTag.getInt("Z");
position = new GlobalBlockPosition(lodestoneDimensionTag, x, y, z);
position = new GlobalBlockPosition(lodestoneDimension, x, y, z);
}
data.set(StructuredDataKey.LODESTONE_TRACKER, new LodestoneTracker(position, tracked));
}
@@ -1443,7 +1478,10 @@ public final class BlockItemPacketRewriter1_20_5 extends ItemRewriter<Clientboun
data.set(StructuredDataKey.BASE_COLOR, baseColorIntTag.asInt());
}
updateItemList(connection, data, tag, "Items", StructuredDataKey.CONTAINER1_20_5, true);
if (tag.contains("Items")) {
updateItemList(connection, data, tag, "Items", StructuredDataKey.CONTAINER1_20_5, true);
addBlockEntityId(tag, "shulker_box"); // Won't happen to the others and doesn't actually have to be correct otherwise
}
}
final Tag skullOwnerTag = tag.remove("SkullOwner");
@@ -1558,4 +1596,4 @@ public final class BlockItemPacketRewriter1_20_5 extends ItemRewriter<Clientboun
return true;
}
}
}
@@ -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) {
}
}
}
Loaded 100 of 159 files, more files were not shown because too many files have changed in this diff. Show more