Compare commits

...
91 Commits
Author SHA1 Message Date
Nassim Jahnke a08de7ccc3 5.0.4 Release 2024-10-14 17:25:39 +02:00
EnZaXD cb9179c873 Update required ViaFabric version, don't require fabric-loader (#895) 2024-10-10 12:45:14 +02:00
EnZaXD 904c83f341 Define as Sponge plugin for ViaSponge (#892) 2024-10-02 10:43:15 +02:00
Nassim Jahnke f4253641e1 Update VV usage 2024-09-29 13:42:26 +02:00
github-actions[bot]andgradle-update-robot 1d1e9bc040 Update Gradle Wrapper from 8.10.1 to 8.10.2 (#891)
Signed-off-by: gradle-update-robot <gradle-update-robot@regolo.cc>
Co-authored-by: gradle-update-robot <gradle-update-robot@regolo.cc>
2024-09-29 04:19:27 +02:00
dependabot[bot] f57f22502e Bump gradle-update/update-gradle-wrapper-action from 1 to 2 (#889)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-09-25 17:11:36 +02:00
EnZaXD b376b52ce8 Refactor dimension switch handling across all protocols (#884) 2024-09-15 22:09:03 +02:00
EnZaXD 36baf6ed24 Fix body set equipment in 1.20.5->.3 if value is not the last (#886) 2024-09-15 19:17:45 +02:00
github-actions[bot]andgradle-update-robot 733bd9aa9b Update Gradle Wrapper from 8.10 to 8.10.1 (#885)
Signed-off-by: gradle-update-robot <gradle-update-robot@regolo.cc>
Co-authored-by: gradle-update-robot <gradle-update-robot@regolo.cc>
2024-09-15 09:51:23 +02:00
EnZaXD 66a1748573 Remove transaction tracking (and cancelling) in 1.17->1.16.4 (#883) 2024-09-12 14:45:44 +02:00
Nassim Jahnke 0bac9201ac Don't remove configuration packet storage on login
Needed with proxies if a server is doing nonstandard optimizations
Fixes #881
2024-09-08 11:12:34 +02:00
EnZaXD ffb98523e6 Don't process component twice in 1.19.4->1.19.3 text display handler (#878) 2024-08-30 21:05:03 +02:00
Nassim Jahnke 830ccce303 Update VV usage 2024-08-30 19:45:02 +02:00
Nassim Jahnke a5d0e4baff Strip new attributes in 1.21->1.20.5 item hover events 2024-08-30 11:05:07 +02:00
Nassim Jahnke 4066b9b52b More cleanup to structured enchantment rewriter 2024-08-29 19:53:47 +02:00
Nassim Jahnke 678775ab9d Move the iterator remove down 2024-08-29 19:45:43 +02:00
Nassim Jahnke db47040543 Fix 1.21->1.20.5 enchantment lore format and add show_in_tooltip check
Fixes #877
2024-08-29 19:18:43 +02:00
EnZaXD 47b1508f66 Clean up LOGIN/STATUS/CONFIGURATION handlers (#876) 2024-08-28 15:55:40 +02:00
Nassim Jahnke 6cc4990b6e Update VV usage 2024-08-25 19:03:59 +02:00
Nassim Jahnke d6279757bb Also explicitly map entity data list type in 1.12 2024-08-24 17:20:42 +02:00
EnZaXD 24f67ffe80 Fix compressed id overlap in legacy block item rewriter (#874) 2024-08-20 16:12:19 +02:00
Nassim Jahnke 0b3a792a51 Properly read unused light data in 1.17->1.16
Some servers for some reason do this
2024-08-18 15:13:51 +02:00
github-actions[bot]andgradle-update-robot ef2621c917 Update Gradle Wrapper from 8.9 to 8.10 (#872)
Signed-off-by: gradle-update-robot <gradle-update-robot@regolo.cc>
Co-authored-by: gradle-update-robot <gradle-update-robot@regolo.cc>
2024-08-18 11:33:23 +02:00
Nassim Jahnke eb4d30ae73 Always map command to signed command in 1.20.5->1.20.3
Sending any message, any non-message command, and again any message would kick the client with a chat validation error. Let's see if this is better
2024-08-15 13:35:37 +02:00
Nassim Jahnke 9ca523620d Map wind charges to shulker bullets instead of llama spit
Spit has gravity by default and a short lifespan
Fixes #868
2024-08-15 13:10:48 +02:00
EnZaXD 4f7acf211b [ci skip] Setup dependabot for GH Actions and add workflow for updati… (#867) 2024-08-14 15:14:11 +02:00
EnZaXD 585ab030b5 [ci skip] Link to our new website instead (#866) 2024-08-14 09:53:38 +02:00
Nassim Jahnke 5ce7857d49 Actually remove template submodule 2024-08-14 09:52:24 +02:00
Nassim Jahnke 5539ff99cb Update supported version range 2024-08-14 09:48:54 +02:00
Nassim Jahnke c2b5a5f545 Update template protocol classes 2024-08-14 09:42:32 +02:00
EnZaXD 9c3255d5a4 Only play totem animation for dying player in 1.11->1.10 (#860) 2024-08-14 09:38:27 +02:00
EnZaXD b03be8ecfe Properly handle custom item data in 1.20.5->1.20.3 (#865) 2024-08-14 09:36:44 +02:00
Nassim Jahnke 609205f9fd [ci skip] Update shadow 2024-08-08 10:45:56 +02:00
Nassim Jahnke 4c56605ca0 5.0.3 Release 2024-08-07 17:56:17 +02:00
Nassim Jahnke 55ea81f9c7 Hotfix item ids in 1.21 item hover events 2024-08-07 17:37:24 +02:00
Kichura 9c2021b947 Update Ubuntu, Change wrapper-validation in publish (#857) 2024-08-07 15:25:13 +02:00
EnZaXD ad1b8b71a5 Rename CI workflow and update gradle wrapper validation (#855) 2024-08-07 13:03:15 +02:00
Nassim Jahnke 6a766f2467 Handle custom armor trims in 1.20.5->1.20.3
Fixes #847, closes #850
2024-08-07 12:47:26 +02:00
Nassim Jahnke 87d05ae487 Only change container data for enchantment tables
Fixes #853
2024-08-06 15:37:28 +02:00
EnZaXD 29a7b01937 Use GH repository description in platforms and README.md file (#851) 2024-08-05 09:09:43 +02:00
EnZaXD bc06d9ecc1 Handle experience orb spawn via add entity packet in 1.14->1.13.2 (#849) 2024-08-03 10:41:03 +02:00
EnZaXD a0d063d93e Handle data->pitch/yaw item frame rotation change in 1.17->1.16.4 (#848) 2024-08-02 10:29:54 +02:00
EnZaXD 24f994ff2a Convert components in sign block entities in 1.12->1.11 (#845) 2024-07-31 18:21:42 +02:00
Nassim Jahnke f4bc485408 Only create custom data tag in enchantment rewriter if necessary 2024-07-31 17:07:45 +02:00
Nassim Jahnke b4a4b540cc Always remap body armor slot 2024-07-30 22:39:56 +02:00
Nassim Jahnke 8add9677a8 Bump version to 5.0.3-SNAPSHOT 2024-07-30 22:35:57 +02:00
Nassim Jahnke 9fed88c1a3 5.0.2 Release 2024-07-28 14:38:59 +02:00
EnZaXD 2df954de90 Cleanup 1.20.5->1.20.3 SET_EQUIPMENT translation (#841) 2024-07-27 21:47:30 +02:00
EnZaXD d3721307b1 Cleanup 1.20.2->1.20 item and recipe rewriter (#840) 2024-07-27 19:58:29 +02:00
RK_01 0ed3efc643 Fix typo (#837) 2024-07-27 19:54:16 +02:00
EnZaXD 4536ca41e2 Fix enchantment rewriter description conversion in 1.21->1.20.5 (#833) 2024-07-24 20:39:15 +02:00
Nassim Jahnke 09e862383a Fix editorconfig new lines 2024-07-24 14:34:35 +02:00
EnZaXD 1413bd63ef Handle attribute_modifiers inside container components in 1.21->1.20.5 (#829) 2024-07-24 14:33:56 +02:00
EnZaXD 136678b0b7 Use enhanced switch in more places, fix typo (#831) 2024-07-24 14:33:16 +02:00
Nassim Jahnke 99618af747 Fix enchantment table hints 2024-07-22 18:00:28 +02:00
EnZaXD ede8b877b5 Remove ViaFabricPlus as required dependency (#827) 2024-07-21 09:43:32 +02:00
EnZaXD b5319dbb32 Check if item is null in 1.17.1->1.17 book conversion (#826) 2024-07-20 17:09:34 +02:00
EnZaXD 94c755166c Change modrinth/hangar publishing dependencies (#825) 2024-07-20 09:15:57 +02:00
EnZaXD b6caa30c16 Add alternative sculk shrieker mapping in 1.19->1.18.2 (#820) 2024-07-17 19:06:44 +02:00
EnZaXD bb2f26a5eb Handle keep all player attributes boolean in LOGIN in 1.16->1.15.2 (#822) 2024-07-17 19:02:34 +02:00
Nassim Jahnke b10b161fe7 Update Gradle wrapper 2024-07-14 21:33:19 +02:00
EnZaXD c9d57aab8d Fix possible NPE in 1.17->1.16.4 bedrock at 0 emulation (#821) 2024-07-14 10:10:03 +02:00
EnZaXD 7e08534f4f [ci skip] Fix player combat packet value comments (#818) 2024-07-13 10:59:39 +02:00
EnZaXD d7e7992ca4 Include new bedrock-at-0 config option in world height warning (#815) 2024-07-09 18:26:49 +02:00
EnZaXD e56920c7b1 Fix possible BannerHandler NPE in 1.13->1.12.2 (#814) 2024-07-09 17:59:06 +02:00
EnZaXD e0ec308fa0 Handle rarity changes in trident/banner pattern item in 1.21->1.20.5 (#813) 2024-07-08 12:34:37 +02:00
EnZaXD 1c8438d2a6 Change BlockEntityHandler#handleOrNewCompoundTag to a void function (#812) 2024-07-07 17:31:15 +02:00
EnZaXD 33d8485852 Rename missing metadata references to entity data (#811) 2024-07-06 21:13:55 +02:00
EnZaXD 16f1bdff02 Put enchantment level into translatables in enchantment rewriters (#807) 2024-07-05 16:10:00 +02:00
EnZaXD dd6bc4f1db Handle translatables in lore tag conversion in 1.14->1.13.2 (#810) 2024-07-05 16:09:43 +02:00
Nassim Jahnke 22508f6ab7 Add setting to send bedrock at y 0
Closes #670
2024-07-04 08:58:42 +02:00
Nassim Jahnke 520552fe69 Properly swift sneak in lore 2024-07-03 11:31:02 +02:00
EnZaXD 355ca898d7 Rewrite falling block state ids in 1.20.3->1.20.2 (#806) 2024-07-02 11:50:23 +02:00
EnZaXD 2159dea31d Remove ViaRewind recommendation in fabric.mod.json (#804) 2024-06-30 11:31:34 +02:00
EnZaXD 793bedf4e2 [ci skip] Update supported versions section in README (#805) 2024-06-30 11:31:28 +02:00
Nassim Jahnke 2cb3fd186b Move bee entity mapping to onMappingDataLoaded method 2024-06-26 10:55:59 +02:00
EnZaXD 7ccb5634ff Rewrite title/player_combat components in 1.17->1.16.4 (#801) 2024-06-24 22:17:24 +02:00
Nassim Jahnke f461a0b14c 5.0.1 Release 2024-06-22 15:54:10 +02:00
Nassim Jahnke 2daa1aa39e Handle infinite effect duration in 1.19.4->1.19.3
Fixes #796
2024-06-20 13:53:33 +02:00
Nassim Jahnke 38af6f883b Fix 1.21 enchantment remapping
Fixes #795
2024-06-20 13:21:54 +02:00
Nassim Jahnke 418357d8eb Add empty axolotl_tempt_items tag 2024-06-19 23:01:11 +02:00
Nassim Jahnke 13a74f43ef Remove old particles type handling code 2024-06-18 18:42:39 +02:00
Nassim Jahnke a921337178 Add music_discs item tag for 1.20.5 clients
Needed back in 1.17
Fixes #794
2024-06-18 10:03:13 +02:00
Nassim Jahnke da5837d794 Move particles type handling into generic handler
This allows for handling of data for untracked entities
2024-06-18 10:00:20 +02:00
EnZaXD 4dded860ce Rewrite window title in 1.20->1.19.4 (#792) 2024-06-17 16:52:05 +02:00
EnZaXD 8e99dddb91 Write player rotation on USE_ITEM in 1.21->1.20.5 (#791) 2024-06-17 16:27:55 +02:00
Nassim Jahnke e662640377 Handle item_name item data for component rewriting 2024-06-17 12:58:39 +02:00
Nassim Jahnke bba0a3a3a6 Handle new trial chamber map decoration type
Fixes #789
2024-06-17 12:26:27 +02:00
Nassim Jahnke 4061e91e53 Update translations 2024-06-17 12:12:36 +02:00
Nassim Jahnke 14e208e9d7 Enable experimental 1.21 features for 1.20 clients
Fixes #790
2024-06-17 11:59:38 +02:00
Nassim Jahnke c5dacad81e Bump version to 5.0.1-SNAPSHOT 2024-06-16 21:48:18 +02:00
109 changed files with 1652 additions and 1260 deletions

No files matched your search

+1 -1
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]
+6
View File
@@ -0,0 +1,6 @@
version: 2
updates:
- package-ecosystem: "github-actions"
directory: "/"
schedule:
interval: "weekly"
@@ -6,13 +6,13 @@ jobs:
build:
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/wrapper-validation-action@v2
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/wrapper-validation-action@v2
uses: gradle/actions/wrapper-validation@v4
- name: Set up JDK 17
uses: actions/setup-java@v4
with:
@@ -0,0 +1,14 @@
name: Update Gradle Wrapper
on:
workflow_dispatch:
schedule:
- cron: "0 0 * * 0"
jobs:
update-gradle-wrapper:
runs-on: ubuntu-24.04
steps:
- name: Checkout Repository
uses: actions/checkout@v4
- name: Update Gradle Wrapper
uses: gradle-update/update-gradle-wrapper-action@v2
+5 -4
View File
@@ -4,16 +4,17 @@
[![Build Status](https://github.com/ViaVersion/ViaBackwards/actions/workflows/gradle.yml/badge.svg?branch=master)](https://github.com/ViaVersion/ViaBackwards/actions)
[![Discord](https://img.shields.io/badge/chat-on%20discord-blue.svg)](https://viaversion.com/discord)
**Allows older Minecraft client versions to connect to newer server versions.**
**Allows the connection of older clients to newer server versions for Minecraft servers.**
Requires [ViaVersion](https://hangar.papermc.io/ViaVersion/ViaVersion) to be installed..
Supported Versions
-
As a plugin, ViaBackwards runs on servers on releases 1.10-latest. Versions from the dev branch will also support the
latest snapshot. You can also use ViaBackwards in ViaFabric or ViaFabricPlus.
As a plugin, ViaBackwards runs on servers on releases 1.10-latest. You can also use ViaBackwards in ViaFabric or ViaFabricPlus.
- in **ViaFabric**, put ViaBackwards into the `mods` folder
- in **ViaFabricPlus**, put ViaBackwards into the `ViaFabricPlus/jars` folder
See [HERE](https://github.com/ViaVersion) for an overview of the different Via* projects.
See [HERE](https://viaversion.com) for an overview of the different Via* projects.
Releases/Dev Builds
-
+1 -1
View File
@@ -8,5 +8,5 @@ repositories {
dependencies {
// version must be manually kept in sync with the one in root project settings.gradle.kts
implementation("com.github.johnrengelman", "shadow", "8.1.1")
implementation("com.gradleup.shadow", "shadow-gradle-plugin", "8.3.0")
}
@@ -5,7 +5,7 @@ plugins {
tasks {
// Variable replacements
processResources {
filesMatching(listOf("plugin.yml", "fabric.mod.json")) {
filesMatching(listOf("plugin.yml", "META-INF/sponge_plugins.json", "fabric.mod.json")) {
expand("version" to project.version, "description" to project.description, "url" to "https://viaversion.com/backwards")
}
}
@@ -22,4 +22,4 @@ tasks {
java {
javaTarget(17)
withSourcesJar()
}
}
@@ -5,7 +5,7 @@ import org.gradle.kotlin.dsl.named
plugins {
id("vb.base-conventions")
id("maven-publish")
id("com.github.johnrengelman.shadow")
id("com.gradleup.shadow")
}
tasks {
+2 -1
View File
@@ -6,7 +6,7 @@ plugins {
allprojects {
group = "com.viaversion"
version = property("projectVersion") as String // from gradle.properties
description = "Allows older Minecraft client versions to connect to newer server versions."
description = "Allows the connection of older clients to newer server versions for Minecraft servers."
}
val main = setOf(
@@ -14,6 +14,7 @@ val main = setOf(
projects.viabackwardsCommon,
projects.viabackwardsBukkit,
projects.viabackwardsVelocity,
projects.viabackwardsSponge,
projects.viabackwardsFabric
).map { it.dependencyProject }
@@ -27,8 +27,8 @@ public final class BukkitAdvancementCriteriaProvider extends AdvancementCriteria
private static final String[] EMPTY_CRITERIA = new String[0];
@Override
public String[] getCriteria(final String key) {
final Advancement advancement = Bukkit.getAdvancement(NamespacedKey.fromString(key));
public String[] getCriteria(final String advancementKey) {
final Advancement advancement = Bukkit.getAdvancement(NamespacedKey.fromString(advancementKey));
return advancement == null ? EMPTY_CRITERIA : advancement.getCriteria().toArray(EMPTY_CRITERIA);
}
}
@@ -34,6 +34,8 @@ public class ViaBackwardsConfig extends Config implements com.viaversion.viaback
private boolean alwaysShowOriginalMobName;
private boolean fix1_13FormattedInventoryTitles;
private boolean handlePingsAsInvAcknowledgements;
private boolean bedrockAtY0;
private boolean sculkShriekersToCryingObsidian;
private boolean suppressEmulationWarnings;
public ViaBackwardsConfig(File configFile, Logger logger) {
@@ -53,6 +55,8 @@ public class ViaBackwardsConfig extends Config implements com.viaversion.viaback
fix1_13FormattedInventoryTitles = getBoolean("fix-formatted-inventory-titles", true);
alwaysShowOriginalMobName = getBoolean("always-show-original-mob-name", true);
handlePingsAsInvAcknowledgements = getBoolean("handle-pings-as-inv-acknowledgements", false);
bedrockAtY0 = getBoolean("bedrock-at-y-0", false);
sculkShriekersToCryingObsidian = getBoolean("sculk-shriekers-to-crying-obsidian", false);
suppressEmulationWarnings = getBoolean("suppress-emulation-warnings", false);
}
@@ -86,6 +90,16 @@ public class ViaBackwardsConfig extends Config implements com.viaversion.viaback
return handlePingsAsInvAcknowledgements || Boolean.getBoolean("com.viaversion.handlePingsAsInvAcknowledgements");
}
@Override
public boolean bedrockAtY0() {
return bedrockAtY0;
}
@Override
public boolean sculkShriekerToCryingObsidian() {
return sculkShriekersToCryingObsidian;
}
@Override
public boolean suppressEmulationWarnings() {
return suppressEmulationWarnings;
@@ -64,6 +64,20 @@ public interface ViaBackwardsConfig extends Config {
*/
boolean handlePingsAsInvAcknowledgements();
/**
* Adds bedrock at y=0 for sub 1.17 clients.
*
* @return true if enabled
*/
boolean bedrockAtY0();
/**
* Shows sculk shriekers as crying obsidian for 1.18.2 clients on 1.19+ servers. This fixes collision and block breaking issues.
*
* @return true if enabled
*/
boolean sculkShriekerToCryingObsidian();
/**
* Suppresses warnings of missing emulations for certain features that are not supported (e.g. world height in 1.17+).
*
@@ -69,7 +69,7 @@ import java.util.logging.Logger;
public interface ViaBackwardsPlatform {
String MINIMUM_VV_VERSION = "5.0.0";
String MINIMUM_VV_VERSION = "5.0.4";
/**
* Initialize ViaBackwards.
@@ -71,7 +71,7 @@ public class MappedLegacyBlockItem {
@FunctionalInterface
public interface BlockEntityHandler {
CompoundTag handleOrNewCompoundTag(int block, CompoundTag tag);
void handleCompoundTag(int block, CompoundTag tag);
}
public enum Type {
@@ -31,7 +31,7 @@ public class EntityReplacement {
private final int replacementId;
private final String key;
private ComponentType componentType = ComponentType.NONE;
private MetaCreator defaultMeta;
private EntityDataCreator defaultData;
public EntityReplacement(BackwardsProtocol<?, ?, ?, ?> protocol, EntityType type, int replacementId) {
this(protocol, type.name(), type.getId(), replacementId);
@@ -59,13 +59,13 @@ public class EntityReplacement {
return this;
}
public EntityReplacement spawnMetadata(MetaCreator handler) {
this.defaultMeta = handler;
public EntityReplacement spawnEntityData(EntityDataCreator handler) {
this.defaultData = handler;
return this;
}
public boolean hasBaseMeta() {
return this.defaultMeta != null;
public boolean hasBaseData() {
return this.defaultData != null;
}
public int typeId() {
@@ -97,8 +97,8 @@ public class EntityReplacement {
return replacementId;
}
public @Nullable MetaCreator defaultMeta() {
return defaultMeta;
public @Nullable EntityDataCreator defaultData() {
return defaultData;
}
public boolean isObjectType() {
@@ -111,18 +111,20 @@ public class EntityReplacement {
@Override
public String toString() {
return "EntityData{" +
"id=" + id +
", mobName='" + key + '\'' +
return "EntityReplacement{" +
"protocol=" + protocol +
", id=" + id +
", replacementId=" + replacementId +
", defaultMeta=" + defaultMeta +
", key='" + key + '\'' +
", componentType=" + componentType +
", defaultData=" + defaultData +
'}';
}
@FunctionalInterface
public interface MetaCreator {
public interface EntityDataCreator {
void createMeta(WrappedMetadata storage);
void createData(WrappedEntityData storage);
}
private enum ComponentType {
@@ -22,28 +22,28 @@ import com.viaversion.viaversion.api.minecraft.entitydata.EntityData;
import java.util.List;
import org.checkerframework.checker.nullness.qual.Nullable;
public record WrappedMetadata(List<EntityData> metadataList) {
public record WrappedEntityData(List<EntityData> entityDataList) {
public boolean has(EntityData data) {
return this.metadataList.contains(data);
return this.entityDataList.contains(data);
}
public void remove(EntityData data) {
this.metadataList.remove(data);
this.entityDataList.remove(data);
}
public void remove(int index) {
metadataList.removeIf(meta -> meta.id() == index);
entityDataList.removeIf(data -> data.id() == index);
}
public void add(EntityData data) {
this.metadataList.add(data);
this.entityDataList.add(data);
}
public @Nullable EntityData get(int index) {
for (EntityData meta : this.metadataList) {
if (index == meta.id()) {
return meta;
for (EntityData data : this.entityDataList) {
if (index == data.id()) {
return data;
}
}
return null;
@@ -20,21 +20,18 @@ package com.viaversion.viabackwards.api.rewriters;
import com.viaversion.nbt.tag.CompoundTag;
import com.viaversion.nbt.tag.IntTag;
import com.viaversion.nbt.tag.ListTag;
import com.viaversion.nbt.tag.NumberTag;
import com.viaversion.nbt.tag.Tag;
import com.viaversion.viabackwards.api.BackwardsProtocol;
import com.viaversion.viabackwards.api.data.BackwardsMappingData;
import com.viaversion.viabackwards.api.data.MappedItem;
import com.viaversion.viaversion.api.connection.UserConnection;
import com.viaversion.viaversion.api.data.FullMappings;
import com.viaversion.viaversion.api.minecraft.data.StructuredData;
import com.viaversion.viaversion.api.minecraft.Particle;
import com.viaversion.viaversion.api.minecraft.data.StructuredDataContainer;
import com.viaversion.viaversion.api.minecraft.data.StructuredDataKey;
import com.viaversion.viaversion.api.minecraft.item.Item;
import com.viaversion.viaversion.api.protocol.packet.ClientboundPacketType;
import com.viaversion.viaversion.api.protocol.packet.ServerboundPacketType;
import com.viaversion.viaversion.api.type.Type;
import com.viaversion.viaversion.libs.fastutil.ints.Int2IntFunction;
import com.viaversion.viaversion.rewriter.StructuredItemRewriter;
import java.util.ArrayList;
import java.util.List;
@@ -43,14 +40,23 @@ import org.checkerframework.checker.nullness.qual.Nullable;
public class BackwardsStructuredItemRewriter<C extends ClientboundPacketType, S extends ServerboundPacketType,
T extends BackwardsProtocol<C, ?, ?, S>> extends StructuredItemRewriter<C, S, T> {
public BackwardsStructuredItemRewriter(final T protocol, final Type<Item> itemType, final Type<Item[]> itemArrayType) {
super(protocol, itemType, itemArrayType);
public BackwardsStructuredItemRewriter(
T protocol,
Type<Item> itemType, Type<Item[]> itemArrayType, Type<Item> mappedItemType, Type<Item[]> mappedItemArrayType,
Type<Item> itemCostType, Type<Item> optionalItemCostType, Type<Item> mappedItemCostType, Type<Item> mappedOptionalItemCostType,
Type<Particle> particleType, Type<Particle> mappedParticleType
) {
super(protocol, itemType, itemArrayType, mappedItemType, mappedItemArrayType, itemCostType, optionalItemCostType, mappedItemCostType, mappedOptionalItemCostType, particleType, mappedParticleType);
}
public BackwardsStructuredItemRewriter(final T protocol, final Type<Item> itemType, final Type<Item[]> itemArrayType, final Type<Item> mappedItemType, final Type<Item[]> mappedItemArrayType) {
super(protocol, itemType, itemArrayType, mappedItemType, mappedItemArrayType);
}
public BackwardsStructuredItemRewriter(final T protocol, final Type<Item> itemType, final Type<Item[]> itemArrayType) {
super(protocol, itemType, itemArrayType);
}
@Override
public Item handleItemToClient(final UserConnection connection, final Item item) {
if (item.isEmpty()) {
@@ -58,39 +64,9 @@ public class BackwardsStructuredItemRewriter<C extends ClientboundPacketType, S
}
final StructuredDataContainer dataContainer = item.dataContainer();
updateItemDataComponentTypeIds(dataContainer, true);
final BackwardsMappingData mappingData = protocol.getMappingData();
if (mappingData != null && mappingData.getDataComponentSerializerMappings() != null) {
final FullMappings mappings = mappingData.getDataComponentSerializerMappings();
dataContainer.setIdLookup(protocol, true);
dataContainer.updateIds(protocol, mappings::getNewId);
}
if (protocol.getComponentRewriter() != null) {
// Handle name and lore components
final StructuredData<Tag> customNameData = dataContainer.getNonEmpty(StructuredDataKey.CUSTOM_NAME);
if (customNameData != null) {
final Tag originalName = customNameData.value().copy();
protocol.getComponentRewriter().processTag(connection, customNameData.value());
if (!customNameData.value().equals(originalName)) {
saveTag(createCustomTag(item), originalName, "Name");
}
}
final StructuredData<Tag[]> loreData = dataContainer.getNonEmpty(StructuredDataKey.LORE);
if (loreData != null) {
for (final Tag tag : loreData.value()) {
protocol.getComponentRewriter().processTag(connection, tag);
}
}
}
Int2IntFunction itemIdRewriter = null;
Int2IntFunction blockIdRewriter = null;
if (mappingData != null) {
itemIdRewriter = mappingData.getItemMappings() != null ? mappingData::getNewItemId : null;
blockIdRewriter = mappingData.getBlockMappings() != null ? mappingData::getNewBlockId : null;
}
final MappedItem mappedItem = mappingData != null ? mappingData.getMappedItem(item.identifier()) : null;
if (mappedItem == null) {
// Just rewrite the id
@@ -98,7 +74,7 @@ public class BackwardsStructuredItemRewriter<C extends ClientboundPacketType, S
item.setIdentifier(mappingData.getNewItemId(item.identifier()));
}
updateItemComponents(connection, dataContainer, this::handleItemToClient, itemIdRewriter, blockIdRewriter);
updateItemDataComponents(connection, item, true);
return item;
}
@@ -108,17 +84,17 @@ public class BackwardsStructuredItemRewriter<C extends ClientboundPacketType, S
item.setIdentifier(mappedItem.id());
// Add custom model data
if (mappedItem.customModelData() != null && !dataContainer.contains(StructuredDataKey.CUSTOM_MODEL_DATA)) {
if (mappedItem.customModelData() != null && !dataContainer.has(StructuredDataKey.CUSTOM_MODEL_DATA)) {
dataContainer.set(StructuredDataKey.CUSTOM_MODEL_DATA, mappedItem.customModelData());
}
// Set custom name - only done if there is no original one
if (!dataContainer.contains(StructuredDataKey.CUSTOM_NAME)) {
if (!dataContainer.has(StructuredDataKey.CUSTOM_NAME)) {
dataContainer.set(StructuredDataKey.CUSTOM_NAME, mappedItem.tagName());
tag.putBoolean(nbtTagName("customName"), true);
tag.putBoolean(nbtTagName("added_custom_name"), true);
}
updateItemComponents(connection, dataContainer, this::handleItemToClient, itemIdRewriter, blockIdRewriter);
updateItemDataComponents(connection, item, true);
return item;
}
@@ -128,46 +104,26 @@ public class BackwardsStructuredItemRewriter<C extends ClientboundPacketType, S
return item;
}
final BackwardsMappingData mappingData = protocol.getMappingData();
final StructuredDataContainer dataContainer = item.dataContainer();
if (mappingData != null) {
if (mappingData.getItemMappings() != null) {
item.setIdentifier(mappingData.getOldItemId(item.identifier()));
}
updateItemDataComponentTypeIds(dataContainer, false);
final FullMappings dataComponentMappings = mappingData.getDataComponentSerializerMappings();
if (dataComponentMappings != null) {
dataContainer.setIdLookup(protocol, false);
dataContainer.updateIds(protocol, id -> dataComponentMappings.inverse().getNewId(id));
}
final BackwardsMappingData mappingData = protocol.getMappingData();
if (mappingData != null && mappingData.getItemMappings() != null) {
item.setIdentifier(mappingData.getOldItemId(item.identifier()));
}
final CompoundTag tag = customTag(item);
if (tag != null) {
final Tag originalId = tag.remove(nbtTagName("id"));
if (originalId instanceof IntTag) {
item.setIdentifier(((NumberTag) originalId).asInt());
final CompoundTag customData = dataContainer.get(StructuredDataKey.CUSTOM_DATA);
if (customData != null) {
if (customData.remove(nbtTagName("id")) instanceof final IntTag originalTag) {
item.setIdentifier(originalTag.asInt());
}
}
restoreTextComponents(item);
Int2IntFunction itemIdRewriter = null;
Int2IntFunction blockIdRewriter = null;
if (mappingData != null) {
itemIdRewriter = mappingData.getItemMappings() != null ? mappingData::getOldItemId : null;
blockIdRewriter = mappingData.getBlockMappings() != null ? mappingData::getOldBlockId : null;
}
updateItemComponents(connection, dataContainer, this::handleItemToServer, itemIdRewriter, blockIdRewriter);
updateItemDataComponents(connection, item, false);
return item;
}
protected @Nullable CompoundTag customTag(final Item item) {
final StructuredData<CompoundTag> customData = item.dataContainer().getNonEmpty(StructuredDataKey.CUSTOM_DATA);
return customData != null ? customData.value() : null;
}
protected void saveListTag(CompoundTag tag, ListTag<?> original, String name) {
// Multiple places might try to backup data
String backupName = nbtTagName(name);
@@ -17,12 +17,12 @@
*/
package com.viaversion.viabackwards.api.rewriters;
import com.viaversion.viabackwards.utils.ChatUtil;
import com.viaversion.viaversion.api.minecraft.item.Item;
import com.viaversion.nbt.tag.CompoundTag;
import com.viaversion.nbt.tag.ListTag;
import com.viaversion.nbt.tag.NumberTag;
import com.viaversion.nbt.tag.StringTag;
import com.viaversion.viaversion.util.ComponentUtil;
import com.viaversion.viaversion.util.Key;
import java.util.ArrayList;
import java.util.HashMap;
@@ -35,6 +35,8 @@ import java.util.Map;
*/
public class EnchantmentRewriter {
public static final String ENCHANTMENT_LEVEL_TRANSLATION = "enchantment.level.%s";
protected final Map<String, String> enchantmentMappings = new HashMap<>();
protected final BackwardsItemRewriter<?, ?, ?> itemRewriter;
private final boolean jsonFormat;
@@ -103,9 +105,11 @@ public class EnchantmentRewriter {
NumberTag levelTag = enchantmentEntry.getNumberTag("lvl");
int level = levelTag != null ? levelTag.asInt() : 1;
String loreValue = remappedName + " " + getRomanNumber(level);
String loreValue;
if (jsonFormat) {
loreValue = ComponentUtil.legacyToJsonString(loreValue);
loreValue = ChatUtil.legacyToJsonString(remappedName, ENCHANTMENT_LEVEL_TRANSLATION.formatted(level), true);
} else {
loreValue = remappedName + " " + getRomanNumber(level);
}
loreToAdd.add(new StringTag(loreValue));
@@ -157,7 +161,7 @@ public class EnchantmentRewriter {
case 8 -> "VIII";
case 9 -> "IX";
case 10 -> "X";
default -> Integer.toString(number);
default -> ENCHANTMENT_LEVEL_TRANSLATION.formatted(number); // Fallback to translation to match vanilla style
};
}
}
@@ -127,7 +127,6 @@ public abstract class EntityRewriter<C extends ClientboundPacketType, T extends
String world = wrapper.get(Types.STRING, 1);
if (tracker.currentWorld() != null && !tracker.currentWorld().equals(world)) {
tracker.clearEntities();
tracker.trackClientEntity();
}
tracker.setCurrentWorld(world);
};
@@ -21,8 +21,9 @@ import com.google.common.base.Preconditions;
import com.viaversion.viabackwards.ViaBackwards;
import com.viaversion.viabackwards.api.BackwardsProtocol;
import com.viaversion.viabackwards.api.entities.storage.EntityReplacement;
import com.viaversion.viabackwards.api.entities.storage.WrappedMetadata;
import com.viaversion.viabackwards.api.entities.storage.WrappedEntityData;
import com.viaversion.viaversion.api.connection.UserConnection;
import com.viaversion.viaversion.api.data.entity.EntityTracker;
import com.viaversion.viaversion.api.data.entity.StoredEntityData;
import com.viaversion.viaversion.api.data.entity.TrackedEntity;
import com.viaversion.viaversion.api.minecraft.ClientWorld;
@@ -50,24 +51,24 @@ import org.checkerframework.checker.nullness.qual.Nullable;
*/
public abstract class EntityRewriterBase<C extends ClientboundPacketType, T extends BackwardsProtocol<C, ?, ?, ?>> extends EntityRewriter<C, T> {
private final Int2ObjectMap<EntityReplacement> entityDataMappings = new Int2ObjectOpenHashMap<>();
private final EntityDataType displayNameMetaType;
private final EntityDataType displayVisibilityMetaType;
private final EntityDataType displayNameDataType;
private final EntityDataType displayVisibilityDataType;
private final int displayNameIndex;
private final int displayVisibilityIndex;
EntityRewriterBase(T protocol, EntityDataType displayNameMetaType, int displayNameIndex,
EntityDataType displayVisibilityMetaType, int displayVisibilityIndex) {
EntityRewriterBase(T protocol, EntityDataType displayNameDataType, int displayNameIndex,
EntityDataType displayVisibilityDataType, int displayVisibilityIndex) {
super(protocol, false);
this.displayNameMetaType = displayNameMetaType;
this.displayNameDataType = displayNameDataType;
this.displayNameIndex = displayNameIndex;
this.displayVisibilityMetaType = displayVisibilityMetaType;
this.displayVisibilityDataType = displayVisibilityDataType;
this.displayVisibilityIndex = displayVisibilityIndex;
}
@Override
public void handleEntityData(int entityId, List<EntityData> entityDataList, UserConnection connection) {
final TrackedEntity entity = tracker(connection).entity(entityId);
final boolean initialMetadata = !(entity != null && entity.hasSentEntityData());
final boolean initialEntityData = !(entity != null && entity.hasSentEntityData());
super.handleEntityData(entityId, entityDataList, connection);
@@ -80,37 +81,37 @@ public abstract class EntityRewriterBase<C extends ClientboundPacketType, T exte
final Object displayNameObject;
if (entityMapping != null && (displayNameObject = entityMapping.entityName()) != null) {
final EntityData displayName = getData(displayNameIndex, entityDataList);
if (initialMetadata) {
if (initialEntityData) {
if (displayName == null) {
// Add it as new metadata
entityDataList.add(new EntityData(displayNameIndex, displayNameMetaType, displayNameObject));
addDisplayVisibilityMeta(entityDataList);
// Add it as new entity data
entityDataList.add(new EntityData(displayNameIndex, displayNameDataType, displayNameObject));
addDisplayVisibilityData(entityDataList);
} else if (displayName.getValue() == null || displayName.getValue().toString().isEmpty()) {
// Overwrite the existing null/empty display name
displayName.setValue(displayNameObject);
addDisplayVisibilityMeta(entityDataList);
addDisplayVisibilityData(entityDataList);
}
} else if (displayName != null && (displayName.getValue() == null || displayName.getValue().toString().isEmpty())) {
// Overwrite null/empty display name
displayName.setValue(displayNameObject);
addDisplayVisibilityMeta(entityDataList);
addDisplayVisibilityData(entityDataList);
}
}
// Add any other extra meta for mapped entities
if (entityMapping != null && entityMapping.hasBaseMeta() && initialMetadata) {
entityMapping.defaultMeta().createMeta(new WrappedMetadata(entityDataList));
// Add any other extra data for mapped entities
if (entityMapping != null && entityMapping.hasBaseData() && initialEntityData) {
entityMapping.defaultData().createData(new WrappedEntityData(entityDataList));
}
}
private void addDisplayVisibilityMeta(List<EntityData> metadataList) {
private void addDisplayVisibilityData(List<EntityData> entityDataList) {
if (alwaysShowOriginalMobName()) {
removeMeta(displayVisibilityIndex, metadataList);
metadataList.add(new EntityData(displayVisibilityIndex, displayVisibilityMetaType, getDisplayVisibilityMetaValue()));
removeData(displayVisibilityIndex, entityDataList);
entityDataList.add(new EntityData(displayVisibilityIndex, displayVisibilityDataType, getDisplayVisibilityDataValue()));
}
}
protected Object getDisplayVisibilityMetaValue() {
protected Object getDisplayVisibilityDataValue() {
return true;
}
@@ -118,17 +119,17 @@ public abstract class EntityRewriterBase<C extends ClientboundPacketType, T exte
return ViaBackwards.getConfig().alwaysShowOriginalMobName();
}
protected @Nullable EntityData getData(int metaIndex, List<EntityData> metadataList) {
for (EntityData metadata : metadataList) {
if (metadata.id() == metaIndex) {
return metadata;
protected @Nullable EntityData getData(int dataIndex, List<EntityData> entityDataList) {
for (EntityData entityData : entityDataList) {
if (entityData.id() == dataIndex) {
return entityData;
}
}
return null;
}
protected void removeMeta(int metaIndex, List<EntityData> metadataList) {
metadataList.removeIf(meta -> meta.id() == metaIndex);
protected void removeData(int dataIndex, List<EntityData> entityDataList) {
entityDataList.removeIf(data -> data.id() == dataIndex);
}
protected boolean hasData(EntityType type) {
@@ -163,7 +164,7 @@ public abstract class EntityRewriterBase<C extends ClientboundPacketType, T exte
return data;
}
public void registerMetaTypeHandler(
public void registerEntityDataTypeHandler(
@Nullable EntityDataType itemType,
@Nullable EntityDataType blockStateType,
@Nullable EntityDataType optionalBlockStateType,
@@ -171,28 +172,28 @@ public abstract class EntityRewriterBase<C extends ClientboundPacketType, T exte
@Nullable EntityDataType componentType,
@Nullable EntityDataType optionalComponentType
) {
filter().handler((event, meta) -> {
EntityDataType type = meta.dataType();
filter().handler((event, data) -> {
EntityDataType type = data.dataType();
if (type == itemType) {
protocol.getItemRewriter().handleItemToClient(event.user(), meta.value());
protocol.getItemRewriter().handleItemToClient(event.user(), data.value());
} else if (type == blockStateType) {
int data = meta.value();
meta.setValue(protocol.getMappingData().getNewBlockStateId(data));
int value = data.value();
data.setValue(protocol.getMappingData().getNewBlockStateId(value));
} else if (type == optionalBlockStateType) {
int data = meta.value();
if (data != 0) {
meta.setValue(protocol.getMappingData().getNewBlockStateId(data));
int value = data.value();
if (value != 0) {
data.setValue(protocol.getMappingData().getNewBlockStateId(value));
}
} else if (type == particleType) {
rewriteParticle(event.user(), meta.value());
rewriteParticle(event.user(), data.value());
} else if (type == optionalComponentType || type == componentType) {
JsonElement text = meta.value();
JsonElement text = data.value();
protocol.getComponentRewriter().processText(event.user(), text);
}
});
}
public void registerMetaTypeHandler1_20_3(
public void registerEntityDataTypeHandler1_20_3(
@Nullable EntityDataType itemType,
@Nullable EntityDataType blockStateType,
@Nullable EntityDataType optionalBlockStateType,
@@ -201,27 +202,27 @@ public abstract class EntityRewriterBase<C extends ClientboundPacketType, T exte
@Nullable EntityDataType componentType,
@Nullable EntityDataType optionalComponentType
) {
filter().handler((event, meta) -> {
EntityDataType type = meta.dataType();
filter().handler((event, data) -> {
EntityDataType type = data.dataType();
if (type == itemType) {
meta.setValue(protocol.getItemRewriter().handleItemToClient(event.user(), meta.value()));
data.setValue(protocol.getItemRewriter().handleItemToClient(event.user(), data.value()));
} else if (type == blockStateType) {
int data = meta.value();
meta.setValue(protocol.getMappingData().getNewBlockStateId(data));
int value = data.value();
data.setValue(protocol.getMappingData().getNewBlockStateId(value));
} else if (type == optionalBlockStateType) {
int data = meta.value();
if (data != 0) {
meta.setValue(protocol.getMappingData().getNewBlockStateId(data));
int value = data.value();
if (value != 0) {
data.setValue(protocol.getMappingData().getNewBlockStateId(value));
}
} else if (type == particleType) {
rewriteParticle(event.user(), meta.value());
rewriteParticle(event.user(), data.value());
} else if (type == particlesType) {
Particle[] particles = meta.value();
Particle[] particles = data.value();
for (final Particle particle : particles) {
rewriteParticle(event.user(), particle);
}
} else if (type == optionalComponentType || type == componentType) {
protocol.getComponentRewriter().processTag(event.user(), meta.value());
protocol.getComponentRewriter().processTag(event.user(), data.value());
}
});
}
@@ -238,15 +239,27 @@ public abstract class EntityRewriterBase<C extends ClientboundPacketType, T exte
return getTrackerHandler(Types.VAR_INT, 1);
}
protected PacketHandler getTrackerHandler(EntityType entityType, Type<? extends Number> intType) {
return wrapper -> tracker(wrapper.user()).addEntity((int) wrapper.get(intType, 0), entityType);
protected PacketHandler getTrackerHandler(EntityType entityType) {
return wrapper -> tracker(wrapper.user()).addEntity((int) wrapper.get(Types.VAR_INT, 0), entityType);
}
protected PacketHandler getPlayerTrackerHandler() {
return wrapper -> {
final int entityId = wrapper.get(Types.INT, 0);
final EntityTracker tracker = tracker(wrapper.user());
tracker(wrapper.user()).setClientEntityId(entityId);
tracker.addEntity(entityId, tracker.playerType());
};
}
protected PacketHandler getDimensionHandler(int index) {
return wrapper -> {
ClientWorld clientWorld = wrapper.user().get(ClientWorld.class);
ClientWorld clientWorld = wrapper.user().getClientWorld(this.protocol.getClass());
int dimensionId = wrapper.get(Types.INT, index);
clientWorld.setEnvironment(dimensionId);
if (clientWorld.setEnvironment(dimensionId)) {
tracker(wrapper.user()).clearEntities();
}
};
}
}
@@ -51,7 +51,6 @@ import com.viaversion.nbt.tag.Tag;
import com.viaversion.viaversion.util.ComponentUtil;
import java.util.HashMap;
import java.util.Map;
import java.util.Optional;
import com.viaversion.viaversion.util.IdAndData;
import org.checkerframework.checker.nullness.qual.Nullable;
@@ -104,9 +103,9 @@ public abstract class LegacyBlockItemRewriter<C extends ClientboundPacketType, S
// Include data
short unmappedData = Short.parseShort(key.substring(dataSeparatorIndex + 1));
unmappedId = Integer.parseInt(key.substring(0, dataSeparatorIndex));
unmappedId = IdAndData.toRawData(unmappedId, unmappedData);
unmappedId = compress(unmappedId, unmappedData);
} else {
unmappedId = IdAndData.toRawData(Integer.parseInt(key), -1);
unmappedId = compress(Integer.parseInt(key), -1);
}
mappings.put(unmappedId, new MappedLegacyBlockItem(id, data, name, type));
@@ -121,12 +120,12 @@ public abstract class LegacyBlockItemRewriter<C extends ClientboundPacketType, S
// Special block color handling
if (name != null && name.contains("%color%")) {
for (int i = from; i <= to; i++) {
mappings.put(IdAndData.toRawData(i, -1), new MappedLegacyBlockItem(id, data, name.replace("%color%", BlockColors1_11_1.get(i - from)), type));
mappings.put(compress(i, -1), new MappedLegacyBlockItem(id, data, name.replace("%color%", BlockColors1_11_1.get(i - from)), type));
}
} else {
MappedLegacyBlockItem mappedBlockItem = new MappedLegacyBlockItem(id, data, name, type);
for (int i = from; i <= to; i++) {
mappings.put(IdAndData.toRawData(i, -1), mappedBlockItem);
mappings.put(compress(i, -1), mappedBlockItem);
}
}
}
@@ -289,7 +288,7 @@ public abstract class LegacyBlockItemRewriter<C extends ClientboundPacketType, S
MappedLegacyBlockItem settings = getMappedBlock(block);
if (settings != null && settings.hasBlockEntityHandler()) {
settings.getBlockEntityHandler().handleOrNewCompoundTag(block, tag);
settings.getBlockEntityHandler().handleCompoundTag(block, tag);
}
}
@@ -343,7 +342,7 @@ public abstract class LegacyBlockItemRewriter<C extends ClientboundPacketType, S
tag.putInt("y", y + (i << 4));
tag.putInt("z", z + (chunk.getZ() << 4));
settings.getBlockEntityHandler().handleOrNewCompoundTag(block, tag);
settings.getBlockEntityHandler().handleCompoundTag(block, tag);
chunk.getBlockEntities().add(tag);
}
}
@@ -361,13 +360,13 @@ public abstract class LegacyBlockItemRewriter<C extends ClientboundPacketType, S
}
private @Nullable MappedLegacyBlockItem getMappedBlock(int id, int data) {
MappedLegacyBlockItem mapping = blockReplacements.get(IdAndData.toRawData(id, data));
return mapping != null ? mapping : blockReplacements.get(IdAndData.toRawData(id, -1));
MappedLegacyBlockItem mapping = blockReplacements.get(compress(id, data));
return mapping != null ? mapping : blockReplacements.get(compress(id, -1));
}
private @Nullable MappedLegacyBlockItem getMappedItem(int id, int data) {
MappedLegacyBlockItem mapping = itemReplacements.get(IdAndData.toRawData(id, data));
return mapping != null ? mapping : itemReplacements.get(IdAndData.toRawData(id, -1));
MappedLegacyBlockItem mapping = itemReplacements.get(compress(id, data));
return mapping != null ? mapping : itemReplacements.get(compress(id, -1));
}
private @Nullable MappedLegacyBlockItem getMappedBlock(int rawId) {
@@ -380,6 +379,11 @@ public abstract class LegacyBlockItemRewriter<C extends ClientboundPacketType, S
return BackwardsMappingDataLoader.INSTANCE.loadFromDataDir(name);
}
protected int compress(final int id, final int data) {
// Using IdAndData for the internal storage can cause id overlaps in edge cases and would lead to wrong data
return (id << 16) | (data & 0xFFFF);
}
private record Pos(int x, short y, int z) {
public Pos(int x, int y, int z) {
@@ -18,9 +18,9 @@
package com.viaversion.viabackwards.api.rewriters;
import com.viaversion.viabackwards.api.BackwardsProtocol;
import com.viaversion.viabackwards.api.entities.storage.EntityReplacement;
import com.viaversion.viabackwards.api.entities.storage.EntityObjectData;
import com.viaversion.viabackwards.api.entities.storage.WrappedMetadata;
import com.viaversion.viabackwards.api.entities.storage.EntityReplacement;
import com.viaversion.viabackwards.api.entities.storage.WrappedEntityData;
import com.viaversion.viaversion.api.minecraft.ClientWorld;
import com.viaversion.viaversion.api.minecraft.entities.EntityType;
import com.viaversion.viaversion.api.minecraft.entities.ObjectType;
@@ -66,8 +66,10 @@ public abstract class LegacyEntityRewriter<C extends ClientboundPacketType, T ex
public void register() {
map(Types.INT);
handler(wrapper -> {
ClientWorld clientWorld = wrapper.user().get(ClientWorld.class);
clientWorld.setEnvironment(wrapper.get(Types.INT, 0));
ClientWorld clientWorld = wrapper.user().getClientWorld(protocol.getClass());
if (clientWorld.setEnvironment(wrapper.get(Types.INT, 0))) {
tracker(wrapper.user()).clearEntities();
}
});
}
});
@@ -81,73 +83,52 @@ public abstract class LegacyEntityRewriter<C extends ClientboundPacketType, T ex
map(Types.UNSIGNED_BYTE); // 1 - Gamemode
map(Types.INT); // 2 - Dimension
handler(wrapper -> {
ClientWorld clientChunks = wrapper.user().get(ClientWorld.class);
clientChunks.setEnvironment(wrapper.get(Types.INT, 1));
addTrackedEntity(wrapper, wrapper.get(Types.INT, 0), playerType);
ClientWorld clientWorld = wrapper.user().getClientWorld(protocol.getClass());
clientWorld.setEnvironment(wrapper.get(Types.INT, 1));
final int entityId = wrapper.get(Types.INT, 0);
addTrackedEntity(wrapper, entityId, playerType);
tracker(wrapper.user()).setClientEntityId(entityId);
});
}
});
}
@Override
public void registerSetEntityData(C packetType, Type<List<EntityData>> oldMetaType, Type<List<EntityData>> newMetaType) {
protocol.registerClientbound(packetType, new PacketHandlers() {
@Override
public void register() {
map(Types.VAR_INT); // 0 - Entity ID
if (oldMetaType != null) {
map(oldMetaType, newMetaType);
} else {
map(newMetaType);
}
handler(wrapper -> {
List<EntityData> metadata = wrapper.get(newMetaType, 0);
handleEntityData(wrapper.get(Types.VAR_INT, 0), metadata, wrapper.user());
});
}
});
}
@Override
public void registerSetEntityData(C packetType, Type<List<EntityData>> metaType) {
registerSetEntityData(packetType, null, metaType);
}
protected PacketHandler getMobSpawnRewriter(Type<List<EntityData>> metaType, IdSetter idSetter) {
protected PacketHandler getMobSpawnRewriter(Type<List<EntityData>> dataType, IdSetter idSetter) {
return wrapper -> {
int entityId = wrapper.get(Types.VAR_INT, 0);
EntityType type = tracker(wrapper.user()).entityType(entityId);
List<EntityData> metadata = wrapper.get(metaType, 0);
handleEntityData(entityId, metadata, wrapper.user());
List<EntityData> entityDataList = wrapper.get(dataType, 0);
handleEntityData(entityId, entityDataList, wrapper.user());
EntityReplacement entityReplacement = entityDataForType(type);
if (entityReplacement != null) {
idSetter.setId(wrapper, entityReplacement.replacementId());
if (entityReplacement.hasBaseMeta()) {
entityReplacement.defaultMeta().createMeta(new WrappedMetadata(metadata));
if (entityReplacement.hasBaseData()) {
entityReplacement.defaultData().createData(new WrappedEntityData(entityDataList));
}
}
};
}
public PacketHandler getMobSpawnRewriter(Type<List<EntityData>> metaType) {
return getMobSpawnRewriter(metaType, (wrapper, id) -> wrapper.set(Types.UNSIGNED_BYTE, 0, (short) id));
public PacketHandler getMobSpawnRewriter(Type<List<EntityData>> dataType) {
return getMobSpawnRewriter(dataType, (wrapper, id) -> wrapper.set(Types.UNSIGNED_BYTE, 0, (short) id));
}
public PacketHandler getMobSpawnRewriter1_11(Type<List<EntityData>> metaType) {
return getMobSpawnRewriter(metaType, (wrapper, id) -> wrapper.set(Types.VAR_INT, 1, id));
public PacketHandler getMobSpawnRewriter1_11(Type<List<EntityData>> dataType) {
return getMobSpawnRewriter(dataType, (wrapper, id) -> wrapper.set(Types.VAR_INT, 1, id));
}
protected PacketHandler getObjectTrackerHandler() {
return wrapper -> addTrackedEntity(wrapper, wrapper.get(Types.VAR_INT, 0), objectTypeFromId(wrapper.get(Types.BYTE, 0)));
}
protected PacketHandler getTrackerAndMetaHandler(Type<List<EntityData>> metaType, EntityType entityType) {
protected PacketHandler getTrackerAndDataHandler(Type<List<EntityData>> dataType, EntityType entityType) {
return wrapper -> {
addTrackedEntity(wrapper, wrapper.get(Types.VAR_INT, 0), entityType);
List<EntityData> metadata = wrapper.get(metaType, 0);
handleEntityData(wrapper.get(Types.VAR_INT, 0), metadata, wrapper.user());
List<EntityData> entityDataList = wrapper.get(dataType, 0);
handleEntityData(wrapper.get(Types.VAR_INT, 0), entityDataList, wrapper.user());
};
}
@@ -155,7 +136,7 @@ public abstract class LegacyEntityRewriter<C extends ClientboundPacketType, T ex
return wrapper -> {
ObjectType type = objectGetter.apply(wrapper.get(Types.BYTE, 0));
if (type == null) {
protocol.getLogger().warning("Could not find Entity Type" + wrapper.get(Types.BYTE, 0));
protocol.getLogger().warning("Could not find entity type " + wrapper.get(Types.BYTE, 0));
return;
}
@@ -23,14 +23,13 @@ import com.viaversion.nbt.tag.ListTag;
import com.viaversion.nbt.tag.NumberTag;
import com.viaversion.nbt.tag.Tag;
import com.viaversion.viabackwards.api.data.BackwardsMappingData;
import com.viaversion.viabackwards.utils.ChatUtil;
import com.viaversion.viaversion.api.data.Mappings;
import com.viaversion.viaversion.api.minecraft.data.StructuredData;
import com.viaversion.viaversion.api.minecraft.data.StructuredDataContainer;
import com.viaversion.viaversion.api.minecraft.data.StructuredDataKey;
import com.viaversion.viaversion.api.minecraft.item.Item;
import com.viaversion.viaversion.api.minecraft.item.data.Enchantments;
import com.viaversion.viaversion.libs.fastutil.ints.Int2IntMap;
import com.viaversion.viaversion.libs.fastutil.ints.IntIntPair;
import com.viaversion.viaversion.libs.fastutil.objects.ObjectIterator;
import com.viaversion.viaversion.rewriter.IdRewriteFunction;
import com.viaversion.viaversion.util.ComponentUtil;
@@ -38,6 +37,8 @@ import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import static com.viaversion.viabackwards.api.rewriters.EnchantmentRewriter.ENCHANTMENT_LEVEL_TRANSLATION;
public class StructuredEnchantmentRewriter {
protected final BackwardsStructuredItemRewriter<?, ?, ?> itemRewriter;
@@ -56,7 +57,7 @@ public class StructuredEnchantmentRewriter {
};
final DescriptionSupplier descriptionSupplier = (id, level) -> {
final String remappedName = mappingData.mappedEnchantmentName(id);
return ComponentUtil.jsonStringToTag(ComponentUtil.legacyToJsonString("§7" + remappedName + " " + EnchantmentRewriter.getRomanNumber(level), true));
return ComponentUtil.jsonStringToTag(ChatUtil.legacyToJsonString("§7" + remappedName, ENCHANTMENT_LEVEL_TRANSLATION.formatted(level), true));
};
rewriteEnchantmentsToClient(data, StructuredDataKey.ENCHANTMENTS, idRewriteFunction, descriptionSupplier, false);
rewriteEnchantmentsToClient(data, StructuredDataKey.STORED_ENCHANTMENTS, idRewriteFunction, descriptionSupplier, true);
@@ -64,91 +65,102 @@ public class StructuredEnchantmentRewriter {
public void handleToServer(final Item item) {
final StructuredDataContainer data = item.dataContainer();
final StructuredData<CompoundTag> customData = data.getNonEmpty(StructuredDataKey.CUSTOM_DATA);
if (customData == null) {
return;
final CompoundTag customData = data.get(StructuredDataKey.CUSTOM_DATA);
if (customData != null) {
rewriteEnchantmentsToServer(data, customData, StructuredDataKey.ENCHANTMENTS);
rewriteEnchantmentsToServer(data, customData, StructuredDataKey.STORED_ENCHANTMENTS);
}
final CompoundTag tag = customData.value();
rewriteEnchantmentsToServer(data, tag, StructuredDataKey.ENCHANTMENTS);
rewriteEnchantmentsToServer(data, tag, StructuredDataKey.STORED_ENCHANTMENTS);
}
public void rewriteEnchantmentsToClient(final StructuredDataContainer data, final StructuredDataKey<Enchantments> key, final IdRewriteFunction rewriteFunction, final DescriptionSupplier descriptionSupplier, final boolean storedEnchant) {
final StructuredData<Enchantments> enchantmentsData = data.getNonEmpty(key);
if (enchantmentsData == null) {
final Enchantments enchantments = data.get(key);
if (enchantments == null || enchantments.size() == 0) {
return;
}
final CompoundTag tag = data.computeIfAbsent(StructuredDataKey.CUSTOM_DATA, $ -> new CompoundTag()).value();
final Enchantments enchantments = enchantmentsData.value();
final List<Tag> loreToAdd = new ArrayList<>();
boolean changed = false;
boolean removedEnchantments = false;
boolean updatedLore = false;
final ObjectIterator<Int2IntMap.Entry> iterator = enchantments.enchantments().int2IntEntrySet().iterator();
final List<IntIntPair> updatedIds = new ArrayList<>();
final List<PendingIdChange> updatedIds = new ArrayList<>();
while (iterator.hasNext()) {
final Int2IntMap.Entry entry = iterator.next();
final int id = entry.getIntKey();
final int mappedId = rewriteFunction.rewrite(id);
final int level = entry.getIntValue();
if (mappedId != -1) {
if (rewriteIds) {
// Update the map after to iteration to preserve the current ids before possibly saving the original, avoid CME
updatedIds.add(IntIntPair.of(id, mappedId));
updatedIds.add(new PendingIdChange(id, mappedId, level));
}
continue;
}
final int level = entry.getIntValue();
if (!removedEnchantments) {
// Backup original before doing modifications
final CompoundTag customData = customData(data);
itemRewriter.saveListTag(customData, asTag(enchantments), key.identifier());
removedEnchantments = true;
}
final Tag description = descriptionSupplier.get(id, level);
if (description != null) {
if (!changed) {
// Backup original before doing modifications
itemRewriter.saveListTag(tag, asTag(enchantments), key.identifier());
changed = true;
}
if (description != null && enchantments.showInTooltip()) {
loreToAdd.add(description);
iterator.remove();
updatedLore = true;
}
iterator.remove();
}
// Remove all first, then add the new ones
for (final PendingIdChange change : updatedIds) {
enchantments.remove(change.id());
}
for (final PendingIdChange change : updatedIds) {
enchantments.add(change.mappedId(), change.level());
}
if (removedEnchantments) {
final CompoundTag tag = customData(data);
if (!storedEnchant && enchantments.size() == 0) {
// Add glint override if there are no enchantments left
final Boolean glintOverride = data.get(StructuredDataKey.ENCHANTMENT_GLINT_OVERRIDE);
if (glintOverride != null) {
tag.putBoolean(itemRewriter.nbtTagName("glint"), glintOverride);
} else {
tag.putBoolean(itemRewriter.nbtTagName("noglint"), true);
}
data.set(StructuredDataKey.ENCHANTMENT_GLINT_OVERRIDE, true);
}
if (enchantments.showInTooltip()) {
tag.putBoolean(itemRewriter.nbtTagName("show_" + key.identifier()), true);
}
}
for (final IntIntPair pair : updatedIds) {
final int level = enchantments.enchantments().remove(pair.firstInt());
enchantments.add(pair.secondInt(), level);
}
if (loreToAdd.isEmpty()) {
// No removed enchantments
return;
}
// Add glint override if there are no enchantments left
if (!storedEnchant && enchantments.size() == 0) {
final StructuredData<Boolean> glintOverride = data.getNonEmpty(StructuredDataKey.ENCHANTMENT_GLINT_OVERRIDE);
if (glintOverride != null) {
tag.putBoolean(itemRewriter.nbtTagName("glint"), glintOverride.value());
if (updatedLore) {
// Save original lore
final CompoundTag tag = customData(data);
final Tag[] lore = data.get(StructuredDataKey.LORE);
if (lore != null) {
final List<Tag> loreList = Arrays.asList(lore);
itemRewriter.saveGenericTagList(tag, loreList, "lore");
loreToAdd.addAll(loreList);
} else {
tag.putBoolean(itemRewriter.nbtTagName("noglint"), true);
tag.putBoolean(itemRewriter.nbtTagName("nolore"), true);
}
data.set(StructuredDataKey.ENCHANTMENT_GLINT_OVERRIDE, true);
data.set(StructuredDataKey.LORE, loreToAdd.toArray(new Tag[0]));
}
}
// Save original lore
final StructuredData<Tag[]> loreData = data.getNonEmpty(StructuredDataKey.LORE);
if (loreData != null) {
final List<Tag> loreList = Arrays.asList(loreData.value());
itemRewriter.saveGenericTagList(tag, loreList, "lore");
loreToAdd.addAll(loreList);
} else {
tag.putBoolean(itemRewriter.nbtTagName("nolore"), true);
private CompoundTag customData(final StructuredDataContainer data) {
CompoundTag tag = data.get(StructuredDataKey.CUSTOM_DATA);
if (tag == null) {
tag = new CompoundTag();
data.set(StructuredDataKey.CUSTOM_DATA, tag);
}
if (enchantments.showInTooltip()) {
tag.putBoolean(itemRewriter.nbtTagName("show_" + key.identifier()), true);
}
data.set(StructuredDataKey.LORE, loreToAdd.toArray(new Tag[0]));
return tag;
}
private ListTag<CompoundTag> asTag(final Enchantments enchantments) {
@@ -198,4 +210,7 @@ public class StructuredEnchantmentRewriter {
Tag get(int id, int level);
}
private record PendingIdChange(int id, int mappedId, int level) {
}
}
@@ -87,7 +87,7 @@ public class TranslatableRewriter<C extends ClientboundPacketType> extends Compo
return translatables.get(translationKey);
}
public Map<String, String> getTranslatableMappings(final String sectionIdentifier) {
public static Map<String, String> getTranslatableMappings(final String sectionIdentifier) {
return TRANSLATABLES.get(sectionIdentifier);
}
}
@@ -15,51 +15,56 @@
* 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.viabackwards.template.protocol.rewriter;
package com.viaversion.viabackwards.protocol.template;
import com.viaversion.viabackwards.api.rewriters.BackwardsStructuredItemRewriter;
import com.viaversion.viabackwards.template.protocol.Protocol1_98To1_99;
import com.viaversion.viaversion.api.type.types.chunk.ChunkType1_20_2;
import com.viaversion.viaversion.api.type.types.version.Types1_20_5;
import com.viaversion.viaversion.api.type.types.version.Types1_21;
import com.viaversion.viaversion.protocols.v1_20_2to1_20_3.rewriter.RecipeRewriter1_20_3;
import com.viaversion.viaversion.protocols.v1_20_3to1_20_5.packet.ClientboundPacket1_20_5;
import com.viaversion.viaversion.protocols.v1_20_3to1_20_5.packet.ClientboundPackets1_20_5;
import com.viaversion.viaversion.protocols.v1_20_3to1_20_5.packet.ServerboundPacket1_20_5;
import com.viaversion.viaversion.protocols.v1_20_3to1_20_5.packet.ServerboundPackets1_20_5;
import com.viaversion.viaversion.protocols.v1_20_5to1_21.packet.ClientboundPacket1_21;
import com.viaversion.viaversion.protocols.v1_20_5to1_21.packet.ClientboundPackets1_21;
import com.viaversion.viaversion.rewriter.BlockRewriter;
// To replace if needed:
// ChunkType1_20_2
// RecipeRewriter1_20_3
public final class BlockItemPacketRewriter1_99 extends BackwardsStructuredItemRewriter<ClientboundPacket1_20_5, ServerboundPacket1_20_5, Protocol1_98To1_99> {
// Types1_21
final class BlockItemPacketRewriter1_99 extends BackwardsStructuredItemRewriter<ClientboundPacket1_21, ServerboundPacket1_20_5, Protocol1_98To1_99> {
public BlockItemPacketRewriter1_99(final Protocol1_98To1_99 protocol) {
super(protocol, /*old types*/Types1_20_5.ITEM, Types1_20_5.ITEM_ARRAY);
super(protocol, Types1_21.ITEM, Types1_21.ITEM_ARRAY);
/*super(protocol,
Types1_21.ITEM, Types1_21.ITEM_ARRAY, Types1_OLD.ITEM, Types1_OLD.ITEM_ARRAY,
Types1_21.ITEM_COST, Types1_21.OPTIONAL_ITEM_COST, Types1_OLD.ITEM_COST, Types1_OLD.OPTIONAL_ITEM_COST,
Types1_21.PARTICLE, Types1_OLD.PARTICLE
);*/
}
@Override
public void registerPackets() {
final BlockRewriter<ClientboundPacket1_20_5> blockRewriter = BlockRewriter.for1_20_2(protocol);
blockRewriter.registerBlockEvent(ClientboundPackets1_20_5.BLOCK_EVENT);
blockRewriter.registerBlockUpdate(ClientboundPackets1_20_5.BLOCK_UPDATE);
blockRewriter.registerSectionBlocksUpdate1_20(ClientboundPackets1_20_5.SECTION_BLOCKS_UPDATE);
blockRewriter.registerLevelEvent1_21(ClientboundPackets1_20_5.LEVEL_EVENT, 2001);
blockRewriter.registerLevelChunk1_19(ClientboundPackets1_20_5.LEVEL_CHUNK_WITH_LIGHT, ChunkType1_20_2::new);
blockRewriter.registerBlockEntityData(ClientboundPackets1_20_5.BLOCK_ENTITY_DATA);
final BlockRewriter<ClientboundPacket1_21> blockRewriter = BlockRewriter.for1_20_2(protocol);
blockRewriter.registerBlockEvent(ClientboundPackets1_21.BLOCK_EVENT);
blockRewriter.registerBlockUpdate(ClientboundPackets1_21.BLOCK_UPDATE);
blockRewriter.registerSectionBlocksUpdate1_20(ClientboundPackets1_21.SECTION_BLOCKS_UPDATE);
blockRewriter.registerLevelEvent1_21(ClientboundPackets1_21.LEVEL_EVENT, 2001);
blockRewriter.registerLevelChunk1_19(ClientboundPackets1_21.LEVEL_CHUNK_WITH_LIGHT, ChunkType1_20_2::new);
blockRewriter.registerBlockEntityData(ClientboundPackets1_21.BLOCK_ENTITY_DATA);
// registerOpenWindow(ClientboundPackets1_20_5.OPEN_WINDOW);
registerCooldown(ClientboundPackets1_20_5.COOLDOWN);
registerSetContent1_17_1(ClientboundPackets1_20_5.CONTAINER_SET_CONTENT);
registerSetSlot1_17_1(ClientboundPackets1_20_5.CONTAINER_SET_SLOT);
registerAdvancements1_20_3(ClientboundPackets1_20_5.UPDATE_ADVANCEMENTS);
registerSetEquipment(ClientboundPackets1_20_5.SET_EQUIPMENT);
// registerOpenWindow(ClientboundPackets1_21.OPEN_WINDOW);
registerCooldown(ClientboundPackets1_21.COOLDOWN);
registerSetContent1_17_1(ClientboundPackets1_21.CONTAINER_SET_CONTENT);
registerSetSlot1_17_1(ClientboundPackets1_21.CONTAINER_SET_SLOT);
registerAdvancements1_20_3(ClientboundPackets1_21.UPDATE_ADVANCEMENTS);
registerSetEquipment(ClientboundPackets1_21.SET_EQUIPMENT);
registerContainerClick1_17_1(ServerboundPackets1_20_5.CONTAINER_CLICK);
registerMerchantOffers1_20_5(ClientboundPackets1_20_5.MERCHANT_OFFERS, Types1_20_5.ITEM_COST, Types1_20_5.ITEM_COST, Types1_20_5.OPTIONAL_ITEM_COST, Types1_20_5.OPTIONAL_ITEM_COST);
registerMerchantOffers1_20_5(ClientboundPackets1_21.MERCHANT_OFFERS);
registerSetCreativeModeSlot(ServerboundPackets1_20_5.SET_CREATIVE_MODE_SLOT);
registerContainerSetData(ClientboundPackets1_20_5.CONTAINER_SET_DATA);
registerLevelParticles1_20_5(ClientboundPackets1_20_5.LEVEL_PARTICLES, Types1_20_5.PARTICLE, Types1_20_5.PARTICLE);
registerExplosion(ClientboundPackets1_20_5.EXPLODE, Types1_20_5.PARTICLE, Types1_20_5.PARTICLE);
registerContainerSetData(ClientboundPackets1_21.CONTAINER_SET_DATA);
registerLevelParticles1_20_5(ClientboundPackets1_21.LEVEL_PARTICLES);
registerExplosion(ClientboundPackets1_21.EXPLODE);
new RecipeRewriter1_20_3<>(protocol).register1_20_5(ClientboundPackets1_20_5.UPDATE_RECIPES);
new RecipeRewriter1_20_3<>(protocol).register1_20_5(ClientboundPackets1_21.UPDATE_RECIPES);
}
}
}
@@ -15,25 +15,24 @@
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.viaversion.viabackwards.template.protocol.rewriter;
package com.viaversion.viabackwards.protocol.template;
import com.viaversion.viabackwards.api.rewriters.EntityRewriter;
import com.viaversion.viabackwards.template.protocol.Protocol1_98To1_99;
import com.viaversion.viaversion.api.minecraft.RegistryEntry;
import com.viaversion.viaversion.api.minecraft.entities.EntityType;
import com.viaversion.viaversion.api.minecraft.entities.EntityTypes1_20_5;
import com.viaversion.viaversion.api.protocol.remapper.PacketHandlers;
import com.viaversion.viaversion.api.type.Types;
import com.viaversion.viaversion.api.type.types.version.Types1_20_5;
import com.viaversion.viaversion.protocols.v1_20_3to1_20_5.packet.ClientboundConfigurationPackets1_20_5;
import com.viaversion.viaversion.protocols.v1_20_3to1_20_5.packet.ClientboundPacket1_20_5;
import com.viaversion.viaversion.protocols.v1_20_3to1_20_5.packet.ClientboundPackets1_20_5;
import com.viaversion.viaversion.protocols.v1_20_5to1_21.packet.ClientboundConfigurationPackets1_21;
import com.viaversion.viaversion.protocols.v1_20_5to1_21.packet.ClientboundPacket1_21;
import com.viaversion.viaversion.protocols.v1_20_5to1_21.packet.ClientboundPackets1_21;
import com.viaversion.viaversion.util.Key;
// Replace if needed
// Types1_OLD
// Types1_20_5
public final class EntityPacketRewriter1_99 extends EntityRewriter<ClientboundPacket1_20_5, Protocol1_98To1_99> {
// Types1_21
final class EntityPacketRewriter1_99 extends EntityRewriter<ClientboundPacket1_21, Protocol1_98To1_99> {
public EntityPacketRewriter1_99(final Protocol1_98To1_99 protocol) {
super(protocol, Types1_20_5.ENTITY_DATA_TYPES.optionalComponentType, Types1_20_5.ENTITY_DATA_TYPES.booleanType);
@@ -41,18 +40,18 @@ public final class EntityPacketRewriter1_99 extends EntityRewriter<ClientboundPa
@Override
public void registerPackets() {
registerTrackerWithData1_19(ClientboundPackets1_20_5.ADD_ENTITY, EntityTypes1_20_5.FALLING_BLOCK);
registerSetEntityData(ClientboundPackets1_20_5.SET_ENTITY_DATA, /*Types1_OLD.METADATA_LIST, */Types1_20_5.ENTITY_DATA_LIST); // Specify old and new metadata list if changed
registerRemoveEntities(ClientboundPackets1_20_5.REMOVE_ENTITIES);
registerTrackerWithData1_19(ClientboundPackets1_21.ADD_ENTITY, EntityTypes1_20_5.FALLING_BLOCK);
registerSetEntityData(ClientboundPackets1_21.SET_ENTITY_DATA, /*Types1_OLD.ENTITY_DATA_LIST, */Types1_20_5.ENTITY_DATA_LIST); // Specify old and new entity data list if changed
registerRemoveEntities(ClientboundPackets1_21.REMOVE_ENTITIES);
// TODO Item and sound id changes in registries, probably others as well
protocol.registerClientbound(ClientboundConfigurationPackets1_20_5.REGISTRY_DATA, wrapper -> {
protocol.registerClientbound(ClientboundConfigurationPackets1_21.REGISTRY_DATA, wrapper -> {
final String registryKey = Key.stripMinecraftNamespace(wrapper.passthrough(Types.STRING));
final RegistryEntry[] entries = wrapper.passthrough(Types.REGISTRY_ENTRY_ARRAY);
handleRegistryData1_20_5(wrapper.user(), registryKey, entries); // Caches dimensions to access data like height later and tracks the amount of biomes sent for chunk data
});
protocol.registerClientbound(ClientboundPackets1_20_5.LOGIN, new PacketHandlers() {
protocol.registerClientbound(ClientboundPackets1_21.LOGIN, new PacketHandlers() {
@Override
public void register() {
map(Types.INT); // Entity id
@@ -70,7 +69,7 @@ public final class EntityPacketRewriter1_99 extends EntityRewriter<ClientboundPa
}
});
protocol.registerClientbound(ClientboundPackets1_20_5.RESPAWN, wrapper -> {
protocol.registerClientbound(ClientboundPackets1_21.RESPAWN, wrapper -> {
final int dimensionId = wrapper.passthrough(Types.VAR_INT);
final String world = wrapper.passthrough(Types.STRING);
trackWorldDataByKey1_20_5(wrapper.user(), dimensionId, world); // Tracks world height and name for chunk data and entity (un)tracking
@@ -87,10 +86,10 @@ public final class EntityPacketRewriter1_99 extends EntityRewriter<ClientboundPa
id--;
}
data.setDataType(Types1_20_5.ENTITY_DATA_TYPES.byId(id));
data.setDataType(Types1_21.ENTITY_DATA_TYPES.byId(id));
});*/
registerMetaTypeHandler1_20_3(
registerEntityDataTypeHandler1_20_3(
Types1_20_5.ENTITY_DATA_TYPES.itemType,
Types1_20_5.ENTITY_DATA_TYPES.blockStateType,
Types1_20_5.ENTITY_DATA_TYPES.optionalBlockStateType,
@@ -101,7 +100,7 @@ public final class EntityPacketRewriter1_99 extends EntityRewriter<ClientboundPa
);
registerBlockStateHandler(EntityTypes1_20_5.ABSTRACT_MINECART, 11);
// Remove metadata of new entity type
// Remove entity data of new entity type
// filter().type(EntityTypes1_20_5.SNIFFER).removeIndex(newIndex);
}
@@ -117,4 +116,4 @@ public final class EntityPacketRewriter1_99 extends EntityRewriter<ClientboundPa
public EntityType typeFromId(final int type) {
return EntityTypes1_20_5.getTypeFromId(type);
}
}
}
@@ -15,26 +15,24 @@
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.viaversion.viabackwards.template.protocol;
package com.viaversion.viabackwards.protocol.template;
import com.viaversion.viabackwards.api.BackwardsProtocol;
import com.viaversion.viabackwards.api.data.BackwardsMappingData;
import com.viaversion.viabackwards.api.rewriters.SoundRewriter;
import com.viaversion.viabackwards.api.rewriters.TranslatableRewriter;
import com.viaversion.viabackwards.template.protocol.rewriter.BlockItemPacketRewriter1_99;
import com.viaversion.viabackwards.template.protocol.rewriter.EntityPacketRewriter1_99;
import com.viaversion.viaversion.api.connection.UserConnection;
import com.viaversion.viaversion.api.minecraft.entities.EntityTypes1_20_5;
import com.viaversion.viaversion.api.protocol.packet.provider.PacketTypesProvider;
import com.viaversion.viaversion.api.protocol.packet.provider.SimplePacketTypesProvider;
import com.viaversion.viaversion.data.entity.EntityTrackerBase;
import com.viaversion.viaversion.protocols.v1_20_3to1_20_5.Protocol1_20_3To1_20_5;
import com.viaversion.viaversion.protocols.v1_20_3to1_20_5.packet.ClientboundConfigurationPackets1_20_5;
import com.viaversion.viaversion.protocols.v1_20_3to1_20_5.packet.ClientboundPacket1_20_5;
import com.viaversion.viaversion.protocols.v1_20_3to1_20_5.packet.ClientboundPackets1_20_5;
import com.viaversion.viaversion.protocols.v1_20_3to1_20_5.packet.ServerboundConfigurationPackets1_20_5;
import com.viaversion.viaversion.protocols.v1_20_3to1_20_5.packet.ServerboundPacket1_20_5;
import com.viaversion.viaversion.protocols.v1_20_3to1_20_5.packet.ServerboundPackets1_20_5;
import com.viaversion.viaversion.protocols.v1_20_5to1_21.Protocol1_20_5To1_21;
import com.viaversion.viaversion.protocols.v1_20_5to1_21.packet.ClientboundConfigurationPackets1_21;
import com.viaversion.viaversion.protocols.v1_20_5to1_21.packet.ClientboundPacket1_21;
import com.viaversion.viaversion.protocols.v1_20_5to1_21.packet.ClientboundPackets1_21;
import com.viaversion.viaversion.rewriter.ComponentRewriter.ReadType;
import com.viaversion.viaversion.rewriter.StatisticsRewriter;
import com.viaversion.viaversion.rewriter.TagRewriter;
@@ -42,53 +40,53 @@ import com.viaversion.viaversion.rewriter.TagRewriter;
import static com.viaversion.viaversion.util.ProtocolUtil.packetTypeMap;
// Placeholders to replace (in the entire package):
// Protocol1_98To_99, EntityPacketRewriter1_99, BlockItemPacketRewriter1_99
// Protocol1_20_5To1_20_3 (the ViaVersion protocol class the mappings depend on)
// ClientboundPacket1_20_5
// Protocol1_98To1_99, EntityPacketRewriter1_99, BlockItemPacketRewriter1_99
// Protocol1_20_5To1_21 (the ViaVersion protocol class the mappings depend on)
// ClientboundPacket1_21
// ServerboundPacket1_20_5
// ClientboundConfigurationPackets1_20_5
// ClientboundConfigurationPackets1_21
// ServerboundConfigurationPackets1_20_5
// EntityTypes1_20_5 (UNMAPPED type)
// 1.99, 1.98
public final class Protocol1_98To1_99 extends BackwardsProtocol<ClientboundPacket1_20_5, ClientboundPacket1_20_5, ServerboundPacket1_20_5, ServerboundPacket1_20_5> {
final class Protocol1_98To1_99 extends BackwardsProtocol<ClientboundPacket1_21, ClientboundPacket1_21, ServerboundPacket1_20_5, ServerboundPacket1_20_5> {
// ViaBackwards uses its own mappings and also needs a translatablerewriter for translation mappings
public static final BackwardsMappingData MAPPINGS = new BackwardsMappingData("1.99", "1.98", Protocol1_20_3To1_20_5.class);
public static final BackwardsMappingData MAPPINGS = new BackwardsMappingData("1.99", "1.98", Protocol1_20_5To1_21.class);
private final EntityPacketRewriter1_99 entityRewriter = new EntityPacketRewriter1_99(this);
private final BlockItemPacketRewriter1_99 itemRewriter = new BlockItemPacketRewriter1_99(this);
private final TranslatableRewriter<ClientboundPacket1_20_5> translatableRewriter = new TranslatableRewriter<>(this, ReadType.NBT);
private final TagRewriter<ClientboundPacket1_20_5> tagRewriter = new TagRewriter<>(this);
private final TranslatableRewriter<ClientboundPacket1_21> translatableRewriter = new TranslatableRewriter<>(this, ReadType.NBT);
private final TagRewriter<ClientboundPacket1_21> tagRewriter = new TagRewriter<>(this);
public Protocol1_98To1_99() {
super(ClientboundPacket1_20_5.class, ClientboundPacket1_20_5.class, ServerboundPacket1_20_5.class, ServerboundPacket1_20_5.class);
super(ClientboundPacket1_21.class, ClientboundPacket1_21.class, ServerboundPacket1_20_5.class, ServerboundPacket1_20_5.class);
}
@Override
protected void registerPackets() {
super.registerPackets();
tagRewriter.registerGeneric(ClientboundPackets1_20_5.UPDATE_TAGS);
tagRewriter.registerGeneric(ClientboundConfigurationPackets1_20_5.UPDATE_TAGS);
tagRewriter.registerGeneric(ClientboundPackets1_21.UPDATE_TAGS);
tagRewriter.registerGeneric(ClientboundConfigurationPackets1_21.UPDATE_TAGS);
final SoundRewriter<ClientboundPacket1_20_5> soundRewriter = new SoundRewriter<>(this);
soundRewriter.registerSound1_19_3(ClientboundPackets1_20_5.SOUND);
soundRewriter.registerSound1_19_3(ClientboundPackets1_20_5.SOUND_ENTITY);
soundRewriter.registerStopSound(ClientboundPackets1_20_5.STOP_SOUND);
final SoundRewriter<ClientboundPacket1_21> soundRewriter = new SoundRewriter<>(this);
soundRewriter.registerSound1_19_3(ClientboundPackets1_21.SOUND);
soundRewriter.registerSound1_19_3(ClientboundPackets1_21.SOUND_ENTITY);
soundRewriter.registerStopSound(ClientboundPackets1_21.STOP_SOUND);
new StatisticsRewriter<>(this).register(ClientboundPackets1_20_5.AWARD_STATS);
//new AttributeRewriter<>(this).register1_21(ClientboundPackets1_20_5.ENTITY_PROPERTIES);
new StatisticsRewriter<>(this).register(ClientboundPackets1_21.AWARD_STATS);
//new AttributeRewriter<>(this).register1_21(ClientboundPackets1_21.ENTITY_PROPERTIES);
// Registers translatable mappings (missing a whole bunch still)
//translatableRewriter.registerOpenWindow(ClientboundPackets1_20_5.OPEN_WINDOW); // Handled by registerOpenWindow in item rewriters
translatableRewriter.registerComponentPacket(ClientboundPackets1_20_5.SET_ACTION_BAR_TEXT);
translatableRewriter.registerComponentPacket(ClientboundPackets1_20_5.SET_TITLE_TEXT);
translatableRewriter.registerComponentPacket(ClientboundPackets1_20_5.SET_SUBTITLE_TEXT);
translatableRewriter.registerBossEvent(ClientboundPackets1_20_5.BOSS_EVENT);
translatableRewriter.registerComponentPacket(ClientboundPackets1_20_5.DISCONNECT);
translatableRewriter.registerTabList(ClientboundPackets1_20_5.TAB_LIST);
translatableRewriter.registerPlayerCombatKill1_20(ClientboundPackets1_20_5.PLAYER_COMBAT_KILL);
translatableRewriter.registerComponentPacket(ClientboundPackets1_20_5.SYSTEM_CHAT);
translatableRewriter.registerComponentPacket(ClientboundPackets1_20_5.DISGUISED_CHAT);
//translatableRewriter.registerOpenWindow(ClientboundPackets1_21.OPEN_WINDOW); // Handled by registerOpenWindow in item rewriters
translatableRewriter.registerComponentPacket(ClientboundPackets1_21.SET_ACTION_BAR_TEXT);
translatableRewriter.registerComponentPacket(ClientboundPackets1_21.SET_TITLE_TEXT);
translatableRewriter.registerComponentPacket(ClientboundPackets1_21.SET_SUBTITLE_TEXT);
translatableRewriter.registerBossEvent(ClientboundPackets1_21.BOSS_EVENT);
translatableRewriter.registerComponentPacket(ClientboundPackets1_21.DISCONNECT);
translatableRewriter.registerTabList(ClientboundPackets1_21.TAB_LIST);
translatableRewriter.registerPlayerCombatKill1_20(ClientboundPackets1_21.PLAYER_COMBAT_KILL);
translatableRewriter.registerComponentPacket(ClientboundPackets1_21.SYSTEM_CHAT);
translatableRewriter.registerComponentPacket(ClientboundPackets1_21.DISGUISED_CHAT);
translatableRewriter.registerPing();
}
@@ -113,22 +111,22 @@ public final class Protocol1_98To1_99 extends BackwardsProtocol<ClientboundPacke
}
@Override
public TranslatableRewriter<ClientboundPacket1_20_5> getComponentRewriter() {
public TranslatableRewriter<ClientboundPacket1_21> getComponentRewriter() {
return translatableRewriter;
}
@Override
public TagRewriter<ClientboundPacket1_20_5> getTagRewriter() {
public TagRewriter<ClientboundPacket1_21> getTagRewriter() {
return tagRewriter;
}
@Override
protected PacketTypesProvider<ClientboundPacket1_20_5, ClientboundPacket1_20_5, ServerboundPacket1_20_5, ServerboundPacket1_20_5> createPacketTypesProvider() {
protected PacketTypesProvider<ClientboundPacket1_21, ClientboundPacket1_21, ServerboundPacket1_20_5, ServerboundPacket1_20_5> createPacketTypesProvider() {
return new SimplePacketTypesProvider<>(
packetTypeMap(unmappedClientboundPacketType, ClientboundPackets1_20_5.class, ClientboundConfigurationPackets1_20_5.class),
packetTypeMap(mappedClientboundPacketType, ClientboundPackets1_20_5.class, ClientboundConfigurationPackets1_20_5.class),
packetTypeMap(unmappedClientboundPacketType, ClientboundPackets1_21.class, ClientboundConfigurationPackets1_21.class),
packetTypeMap(mappedClientboundPacketType, ClientboundPackets1_21.class, ClientboundConfigurationPackets1_21.class),
packetTypeMap(mappedServerboundPacketType, ServerboundPackets1_20_5.class, ServerboundConfigurationPackets1_20_5.class),
packetTypeMap(unmappedServerboundPacketType, ServerboundPackets1_20_5.class, ServerboundConfigurationPackets1_20_5.class)
);
}
}
}
@@ -98,11 +98,8 @@ public class Protocol1_10To1_9_3 extends BackwardsProtocol<ClientboundPackets1_9
@Override
public void init(UserConnection user) {
if (!user.has(ClientWorld.class)) {
user.put(new ClientWorld());
}
user.addEntityTracker(this.getClass(), new EntityTrackerBase(user, EntityTypes1_10.EntityType.PLAYER));
user.addClientWorld(this.getClass(), new ClientWorld());
}
@Override
@@ -50,7 +50,7 @@ public class BlockItemPacketRewriter1_10 extends LegacyBlockItemRewriter<Clientb
registerSetCreativeModeSlot(ServerboundPackets1_9_3.SET_CREATIVE_MODE_SLOT);
protocol.registerClientbound(ClientboundPackets1_9_3.LEVEL_CHUNK, wrapper -> {
ClientWorld clientWorld = wrapper.user().get(ClientWorld.class);
ClientWorld clientWorld = wrapper.user().getClientWorld(Protocol1_10To1_9_3.class);
ChunkType1_9_3 type = ChunkType1_9_3.forEnvironment(clientWorld.getEnvironment());
Chunk chunk = wrapper.passthrough(type);
@@ -58,10 +58,10 @@ public class BlockItemPacketRewriter1_10 extends LegacyBlockItemRewriter<Clientb
handleChunk(chunk);
});
// Rewrite metadata items
protocol.getEntityRewriter().filter().handler((event, meta) -> {
if (meta.dataType().type().equals(Types.ITEM1_8)) // Is Item
meta.setValue(handleItemToClient(event.user(), (Item) meta.getValue()));
// Rewrite entity data items
protocol.getEntityRewriter().filter().handler((event, data) -> {
if (data.dataType().type().equals(Types.ITEM1_8)) // Is Item
data.setValue(handleItemToClient(event.user(), (Item) data.getValue()));
});
// Particle
@@ -19,7 +19,7 @@
package com.viaversion.viabackwards.protocol.v1_10to1_9_3.rewriter;
import com.viaversion.viabackwards.api.entities.storage.EntityReplacement;
import com.viaversion.viabackwards.api.entities.storage.WrappedMetadata;
import com.viaversion.viabackwards.api.entities.storage.WrappedEntityData;
import com.viaversion.viabackwards.api.rewriters.LegacyEntityRewriter;
import com.viaversion.viabackwards.protocol.v1_10to1_9_3.Protocol1_10To1_9_3;
import com.viaversion.viaversion.api.minecraft.entities.EntityType;
@@ -80,25 +80,25 @@ public class EntityPacketRewriter1_10 extends LegacyEntityRewriter<ClientboundPa
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
// Track entity
handler(getTrackerHandler(Types.UNSIGNED_BYTE, 0));
// Rewrite entity type / metadata
// Rewrite entity type / data
handler(wrapper -> {
int entityId = wrapper.get(Types.VAR_INT, 0);
EntityType type = tracker(wrapper.user()).entityType(entityId);
List<EntityData> metadata = wrapper.get(Types1_9.ENTITY_DATA_LIST, 0);
handleEntityData(wrapper.get(Types.VAR_INT, 0), metadata, wrapper.user());
List<EntityData> entityDataList = wrapper.get(Types1_9.ENTITY_DATA_LIST, 0);
handleEntityData(wrapper.get(Types.VAR_INT, 0), entityDataList, wrapper.user());
EntityReplacement entityReplacement = entityDataForType(type);
if (entityReplacement != null) {
WrappedMetadata storage = new WrappedMetadata(metadata);
WrappedEntityData storage = new WrappedEntityData(entityDataList);
wrapper.set(Types.UNSIGNED_BYTE, 0, (short) entityReplacement.replacementId());
if (entityReplacement.hasBaseMeta())
entityReplacement.defaultMeta().createMeta(storage);
if (entityReplacement.hasBaseData())
entityReplacement.defaultData().createData(storage);
}
});
@@ -119,9 +119,9 @@ public class EntityPacketRewriter1_10 extends LegacyEntityRewriter<ClientboundPa
map(Types.DOUBLE); // 4 - Z
map(Types.BYTE); // 5 - Yaw
map(Types.BYTE); // 6 - Pitch
map(Types1_9.ENTITY_DATA_LIST); // 7 - Metadata list
map(Types1_9.ENTITY_DATA_LIST); // 7 - Entity data list
handler(getTrackerAndMetaHandler(Types1_9.ENTITY_DATA_LIST, EntityTypes1_11.EntityType.PLAYER));
handler(getTrackerAndDataHandler(Types1_9.ENTITY_DATA_LIST, EntityTypes1_11.EntityType.PLAYER));
}
});
@@ -134,28 +134,28 @@ public class EntityPacketRewriter1_10 extends LegacyEntityRewriter<ClientboundPa
mapEntityTypeWithData(EntityTypes1_10.EntityType.POLAR_BEAR, EntityTypes1_10.EntityType.SHEEP).plainName();
// Change the sheep color when the polar bear is standing up (index 13 -> Standing up)
filter().type(EntityTypes1_10.EntityType.POLAR_BEAR).index(13).handler((event, meta) -> {
boolean b = (boolean) meta.getValue();
filter().type(EntityTypes1_10.EntityType.POLAR_BEAR).index(13).handler((event, data) -> {
boolean b = (boolean) data.getValue();
meta.setTypeAndValue(EntityDataTypes1_9.BYTE, b ? (byte) (14 & 0x0F) : (byte) (0));
data.setTypeAndValue(EntityDataTypes1_9.BYTE, b ? (byte) (14 & 0x0F) : (byte) (0));
});
// Handle husk (index 13 -> Zombie Type)
filter().type(EntityTypes1_10.EntityType.ZOMBIE).index(13).handler((event, meta) -> {
if ((int) meta.getValue() == 6) { // Is type Husk
meta.setValue(0);
filter().type(EntityTypes1_10.EntityType.ZOMBIE).index(13).handler((event, data) -> {
if ((int) data.getValue() == 6) { // Is type Husk
data.setValue(0);
}
});
// Handle Stray (index 12 -> Skeleton Type)
filter().type(EntityTypes1_10.EntityType.SKELETON).index(12).handler((event, meta) -> {
if ((int) meta.getValue() == 2) {
meta.setValue(0); // Change to default skeleton
filter().type(EntityTypes1_10.EntityType.SKELETON).index(12).handler((event, data) -> {
if ((int) data.getValue() == 2) {
data.setValue(0); // Change to default skeleton
}
});
// Handle the missing NoGravity tag for every metadata
// Handle the missing NoGravity tag for every entity data
filter().removeIndex(5);
}
@@ -39,11 +39,8 @@ public class Protocol1_11_1To1_11 extends BackwardsProtocol<ClientboundPackets1_
@Override
public void init(UserConnection user) {
if (!user.has(ClientWorld.class)) {
user.put(new ClientWorld());
}
user.addEntityTracker(this.getClass(), new EntityTrackerBase(user, EntityTypes1_11.EntityType.PLAYER));
user.addClientWorld(this.getClass(), new ClientWorld());
}
@Override
@@ -23,7 +23,6 @@ import com.viaversion.viabackwards.protocol.v1_11_1to1_11.Protocol1_11_1To1_11;
import com.viaversion.viaversion.api.minecraft.entities.EntityType;
import com.viaversion.viaversion.api.minecraft.entities.EntityTypes1_11;
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.version.Types1_9;
import com.viaversion.viaversion.protocols.v1_9_1to1_9_3.packet.ClientboundPackets1_9_3;
@@ -73,12 +72,12 @@ public class EntityPacketRewriter1_11_1 extends LegacyEntityRewriter<Clientbound
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
// Track entity
handler(getTrackerHandler());
// Rewrite entity type / metadata
// Rewrite entity type / data
handler(getMobSpawnRewriter1_11(Types1_9.ENTITY_DATA_LIST));
}
});
@@ -97,9 +96,9 @@ public class EntityPacketRewriter1_11_1 extends LegacyEntityRewriter<Clientbound
map(Types.DOUBLE); // 4 - Z
map(Types.BYTE); // 5 - Yaw
map(Types.BYTE); // 6 - Pitch
map(Types1_9.ENTITY_DATA_LIST); // 7 - Metadata list
map(Types1_9.ENTITY_DATA_LIST); // 7 - Entity data list
handler(getTrackerAndMetaHandler(Types1_9.ENTITY_DATA_LIST, EntityTypes1_11.EntityType.PLAYER));
handler(getTrackerAndDataHandler(Types1_9.ENTITY_DATA_LIST, EntityTypes1_11.EntityType.PLAYER));
}
});
@@ -109,10 +108,10 @@ public class EntityPacketRewriter1_11_1 extends LegacyEntityRewriter<Clientbound
@Override
protected void registerRewrites() {
// Handle non-existing firework metadata (index 7 entity id for boosting)
// Handle non-existing firework entity data (index 7 entity id for boosting)
filter().type(EntityTypes1_11.EntityType.FIREWORK_ROCKET).cancel(7);
// Handle non-existing pig metadata (index 14 - boost time)
// Handle non-existing pig entity data (index 14 - boost time)
filter().type(EntityTypes1_11.EntityType.PIG).cancel(14);
}
@@ -47,10 +47,10 @@ public class ItemPacketRewriter1_11_1 extends LegacyBlockItemRewriter<Clientboun
registerContainerClick(ServerboundPackets1_9_3.CONTAINER_CLICK);
registerSetCreativeModeSlot(ServerboundPackets1_9_3.SET_CREATIVE_MODE_SLOT);
// Handle item metadata
protocol.getEntityRewriter().filter().handler((event, meta) -> {
if (meta.dataType().type().equals(Types.ITEM1_8)) { // Is Item
meta.setValue(handleItemToClient(event.user(), (Item) meta.getValue()));
// Handle item entity data
protocol.getEntityRewriter().filter().handler((event, data) -> {
if (data.dataType().type().equals(Types.ITEM1_8)) { // Is Item
data.setValue(handleItemToClient(event.user(), (Item) data.getValue()));
}
});
}
@@ -62,11 +62,8 @@ public class Protocol1_11To1_10 extends BackwardsProtocol<ClientboundPackets1_9_
@Override
public void init(UserConnection user) {
if (!user.has(ClientWorld.class)) {
user.put(new ClientWorld());
}
user.addEntityTracker(this.getClass(), new EntityTrackerBase(user, EntityTypes1_11.EntityType.PLAYER));
user.addClientWorld(this.getClass(), new ClientWorld());
if (!user.has(WindowTracker.class)) {
user.put(new WindowTracker());
@@ -147,7 +147,7 @@ public class BlockItemPacketRewriter1_11 extends LegacyBlockItemRewriter<Clientb
registerSetCreativeModeSlot(ServerboundPackets1_9_3.SET_CREATIVE_MODE_SLOT);
protocol.registerClientbound(ClientboundPackets1_9_3.LEVEL_CHUNK, wrapper -> {
ClientWorld clientWorld = wrapper.user().get(ClientWorld.class);
ClientWorld clientWorld = wrapper.user().getClientWorld(Protocol1_11To1_10.class);
ChunkType1_9_3 type = ChunkType1_9_3.forEnvironment(clientWorld.getEnvironment()); // Use the 1.10 Chunk type since nothing changed.
Chunk chunk = wrapper.passthrough(type);
@@ -243,9 +243,9 @@ public class BlockItemPacketRewriter1_11 extends LegacyBlockItemRewriter<Clientb
}
});
protocol.getEntityRewriter().filter().handler((event, meta) -> {
if (meta.dataType().type().equals(Types.ITEM1_8)) // Is Item
meta.setValue(handleItemToClient(event.user(), (Item) meta.getValue()));
protocol.getEntityRewriter().filter().handler((event, data) -> {
if (data.dataType().type().equals(Types.ITEM1_8)) // Is Item
data.setValue(handleItemToClient(event.user(), (Item) data.getValue()));
});
}
@@ -253,10 +253,7 @@ public class BlockItemPacketRewriter1_11 extends LegacyBlockItemRewriter<Clientb
protected void registerRewrites() {
// Handle spawner block entity (map to itself with custom handler)
MappedLegacyBlockItem data = itemReplacements.computeIfAbsent(IdAndData.toRawData(52), s -> new MappedLegacyBlockItem(52));
data.setBlockEntityHandler((b, tag) -> {
EntityMappings1_11.toClientSpawner(tag, true);
return tag;
});
data.setBlockEntityHandler((b, tag) -> EntityMappings1_11.toClientSpawner(tag, true));
enchantmentRewriter = new LegacyEnchantmentRewriter(nbtTagName());
enchantmentRewriter.registerEnchantment(71, "§cCurse of Vanishing");
@@ -18,7 +18,7 @@
package com.viaversion.viabackwards.protocol.v1_11to1_10.rewriter;
import com.viaversion.viabackwards.api.entities.storage.WrappedMetadata;
import com.viaversion.viabackwards.api.entities.storage.WrappedEntityData;
import com.viaversion.viabackwards.api.rewriters.LegacyEntityRewriter;
import com.viaversion.viabackwards.protocol.v1_11to1_10.Protocol1_11To1_10;
import com.viaversion.viabackwards.protocol.v1_11to1_10.data.SplashPotionMappings1_10;
@@ -104,19 +104,19 @@ public class EntityPacketRewriter1_11 extends LegacyEntityRewriter<ClientboundPa
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
// Track entity
handler(getTrackerHandler(Types.UNSIGNED_BYTE, 0));
// Rewrite entity type / metadata
// Rewrite entity type / data
handler(getMobSpawnRewriter(Types1_9.ENTITY_DATA_LIST));
// Sub 1.11 clients will error if the list is empty
handler(wrapper -> {
List<EntityData> metadata = wrapper.get(Types1_9.ENTITY_DATA_LIST, 0);
if (metadata.isEmpty()) {
metadata.add(new EntityData(0, EntityDataTypes1_9.BYTE, (byte) 0));
List<EntityData> entityDataList = wrapper.get(Types1_9.ENTITY_DATA_LIST, 0);
if (entityDataList.isEmpty()) {
entityDataList.add(new EntityData(0, EntityDataTypes1_9.BYTE, (byte) 0));
}
});
}
@@ -136,14 +136,14 @@ public class EntityPacketRewriter1_11 extends LegacyEntityRewriter<ClientboundPa
map(Types.DOUBLE); // 4 - Z
map(Types.BYTE); // 5 - Yaw
map(Types.BYTE); // 6 - Pitch
map(Types1_9.ENTITY_DATA_LIST); // 7 - Metadata list
map(Types1_9.ENTITY_DATA_LIST); // 7 - Entity data list
handler(getTrackerAndMetaHandler(Types1_9.ENTITY_DATA_LIST, EntityTypes1_11.EntityType.PLAYER));
handler(getTrackerAndDataHandler(Types1_9.ENTITY_DATA_LIST, EntityTypes1_11.EntityType.PLAYER));
handler(wrapper -> {
// Sub 1.11 clients will cry if the list is empty
List<EntityData> metadata = wrapper.get(Types1_9.ENTITY_DATA_LIST, 0);
if (metadata.isEmpty()) {
metadata.add(new EntityData(0, EntityDataTypes1_9.BYTE, (byte) 0));
List<EntityData> entityDataList = wrapper.get(Types1_9.ENTITY_DATA_LIST, 0);
if (entityDataList.isEmpty()) {
entityDataList.add(new EntityData(0, EntityDataTypes1_9.BYTE, (byte) 0));
}
});
}
@@ -159,9 +159,15 @@ public class EntityPacketRewriter1_11 extends LegacyEntityRewriter<ClientboundPa
map(Types.BYTE); // 1 - Entity Status
handler(wrapper -> {
byte b = wrapper.get(Types.BYTE, 0);
final int entityId = wrapper.get(Types.INT, 0);
if (entityId != tracker(wrapper.user()).clientEntityId()) {
// Entity events are sent for all players, but we only want to apply this for the self player
return;
}
if (b == 35) {
final byte entityStatus = wrapper.get(Types.BYTE, 0);
if (entityStatus == 35) {
// TODO spawn particles?
wrapper.clearPacket();
wrapper.setPacketType(ClientboundPackets1_9_3.GAME_EVENT);
wrapper.write(Types.UNSIGNED_BYTE, (short) 10); // Play Elder Guardian animation
@@ -177,39 +183,39 @@ public class EntityPacketRewriter1_11 extends LegacyEntityRewriter<ClientboundPa
// Guardian
mapEntityTypeWithData(EntityTypes1_11.EntityType.ELDER_GUARDIAN, EntityTypes1_11.EntityType.GUARDIAN);
// Skeletons
mapEntityTypeWithData(EntityTypes1_11.EntityType.WITHER_SKELETON, EntityTypes1_11.EntityType.SKELETON).spawnMetadata(storage -> storage.add(getSkeletonTypeMeta(1)));
mapEntityTypeWithData(EntityTypes1_11.EntityType.STRAY, EntityTypes1_11.EntityType.SKELETON).plainName().spawnMetadata(storage -> storage.add(getSkeletonTypeMeta(2)));
mapEntityTypeWithData(EntityTypes1_11.EntityType.WITHER_SKELETON, EntityTypes1_11.EntityType.SKELETON).spawnEntityData(storage -> storage.add(getSkeletonTypeData(1)));
mapEntityTypeWithData(EntityTypes1_11.EntityType.STRAY, EntityTypes1_11.EntityType.SKELETON).plainName().spawnEntityData(storage -> storage.add(getSkeletonTypeData(2)));
// Zombies
mapEntityTypeWithData(EntityTypes1_11.EntityType.HUSK, EntityTypes1_11.EntityType.ZOMBIE).plainName().spawnMetadata(storage -> handleZombieType(storage, 6));
mapEntityTypeWithData(EntityTypes1_11.EntityType.ZOMBIE_VILLAGER, EntityTypes1_11.EntityType.ZOMBIE).spawnMetadata(storage -> handleZombieType(storage, 1));
mapEntityTypeWithData(EntityTypes1_11.EntityType.HUSK, EntityTypes1_11.EntityType.ZOMBIE).plainName().spawnEntityData(storage -> handleZombieType(storage, 6));
mapEntityTypeWithData(EntityTypes1_11.EntityType.ZOMBIE_VILLAGER, EntityTypes1_11.EntityType.ZOMBIE).spawnEntityData(storage -> handleZombieType(storage, 1));
// Horses
mapEntityTypeWithData(EntityTypes1_11.EntityType.HORSE, EntityTypes1_11.EntityType.HORSE).spawnMetadata(storage -> storage.add(getHorseMetaType(0))); // Nob able to ride the horse without having the MetaType sent.
mapEntityTypeWithData(EntityTypes1_11.EntityType.DONKEY, EntityTypes1_11.EntityType.HORSE).spawnMetadata(storage -> storage.add(getHorseMetaType(1)));
mapEntityTypeWithData(EntityTypes1_11.EntityType.MULE, EntityTypes1_11.EntityType.HORSE).spawnMetadata(storage -> storage.add(getHorseMetaType(2)));
mapEntityTypeWithData(EntityTypes1_11.EntityType.SKELETON_HORSE, EntityTypes1_11.EntityType.HORSE).spawnMetadata(storage -> storage.add(getHorseMetaType(4)));
mapEntityTypeWithData(EntityTypes1_11.EntityType.ZOMBIE_HORSE, EntityTypes1_11.EntityType.HORSE).spawnMetadata(storage -> storage.add(getHorseMetaType(3)));
mapEntityTypeWithData(EntityTypes1_11.EntityType.HORSE, EntityTypes1_11.EntityType.HORSE).spawnEntityData(storage -> storage.add(getHorseDataType(0))); // Nob able to ride the horse without having the EntityDataType sent.
mapEntityTypeWithData(EntityTypes1_11.EntityType.DONKEY, EntityTypes1_11.EntityType.HORSE).spawnEntityData(storage -> storage.add(getHorseDataType(1)));
mapEntityTypeWithData(EntityTypes1_11.EntityType.MULE, EntityTypes1_11.EntityType.HORSE).spawnEntityData(storage -> storage.add(getHorseDataType(2)));
mapEntityTypeWithData(EntityTypes1_11.EntityType.SKELETON_HORSE, EntityTypes1_11.EntityType.HORSE).spawnEntityData(storage -> storage.add(getHorseDataType(4)));
mapEntityTypeWithData(EntityTypes1_11.EntityType.ZOMBIE_HORSE, EntityTypes1_11.EntityType.HORSE).spawnEntityData(storage -> storage.add(getHorseDataType(3)));
// New mobs
mapEntityTypeWithData(EntityTypes1_11.EntityType.EVOKER_FANGS, EntityTypes1_11.EntityType.SHULKER);
mapEntityTypeWithData(EntityTypes1_11.EntityType.EVOKER, EntityTypes1_11.EntityType.VILLAGER).plainName();
mapEntityTypeWithData(EntityTypes1_11.EntityType.VEX, EntityTypes1_11.EntityType.BAT).plainName();
mapEntityTypeWithData(EntityTypes1_11.EntityType.VINDICATOR, EntityTypes1_11.EntityType.VILLAGER).plainName().spawnMetadata(storage -> storage.add(new EntityData(13, EntityDataTypes1_9.VAR_INT, 4))); // Base Profession
mapEntityTypeWithData(EntityTypes1_11.EntityType.LLAMA, EntityTypes1_11.EntityType.HORSE).plainName().spawnMetadata(storage -> storage.add(getHorseMetaType(1)));
mapEntityTypeWithData(EntityTypes1_11.EntityType.VINDICATOR, EntityTypes1_11.EntityType.VILLAGER).plainName().spawnEntityData(storage -> storage.add(new EntityData(13, EntityDataTypes1_9.VAR_INT, 4))); // Base Profession
mapEntityTypeWithData(EntityTypes1_11.EntityType.LLAMA, EntityTypes1_11.EntityType.HORSE).plainName().spawnEntityData(storage -> storage.add(getHorseDataType(1)));
mapEntityTypeWithData(EntityTypes1_11.EntityType.LLAMA_SPIT, EntityTypes1_11.EntityType.SNOWBALL);
mapObjectType(EntityTypes1_11.ObjectType.LLAMA_SPIT, EntityTypes1_11.ObjectType.SNOWBALL, -1);
// Replace with endertorchthingies
mapObjectType(EntityTypes1_11.ObjectType.EVOKER_FANGS, EntityTypes1_11.ObjectType.FALLING_BLOCK, 198 | 1 << 12);
// Handle ElderGuardian & target metadata
filter().type(EntityTypes1_11.EntityType.GUARDIAN).index(12).handler((event, meta) -> {
boolean b = (boolean) meta.getValue();
// Handle ElderGuardian & target entity data
filter().type(EntityTypes1_11.EntityType.GUARDIAN).index(12).handler((event, data) -> {
boolean b = (boolean) data.getValue();
int bitmask = b ? 0x02 : 0;
if (event.entityType() == EntityTypes1_11.EntityType.ELDER_GUARDIAN) {
bitmask |= 0x04;
}
meta.setTypeAndValue(EntityDataTypes1_9.BYTE, (byte) bitmask);
data.setTypeAndValue(EntityDataTypes1_9.BYTE, (byte) bitmask);
});
// Handle skeleton swing
@@ -218,34 +224,34 @@ public class EntityPacketRewriter1_11 extends LegacyEntityRewriter<ClientboundPa
/*
ZOMBIE CHANGES
*/
filter().type(EntityTypes1_11.EntityType.ZOMBIE).handler((event, meta) -> {
switch (meta.id()) {
filter().type(EntityTypes1_11.EntityType.ZOMBIE).handler((event, data) -> {
switch (data.id()) {
case 13 -> event.cancel();
case 14 -> event.setIndex(15);
case 15 -> event.setIndex(14);
case 16 -> {
// Profession
event.setIndex(13);
meta.setValue(1 + (int) meta.getValue());
data.setValue(1 + (int) data.getValue());
}
}
});
// Handle Evocation Illager
filter().type(EntityTypes1_11.EntityType.EVOKER).index(12).handler((event, meta) -> {
filter().type(EntityTypes1_11.EntityType.EVOKER).index(12).handler((event, data) -> {
event.setIndex(13);
meta.setTypeAndValue(EntityDataTypes1_9.VAR_INT, ((Byte) meta.getValue()).intValue()); // Change the profession for the states
data.setTypeAndValue(EntityDataTypes1_9.VAR_INT, ((Byte) data.getValue()).intValue()); // Change the profession for the states
});
// Handle Vex (Remove this field completely since the position is not updated correctly when idling for bats. Sad ):
filter().type(EntityTypes1_11.EntityType.VEX).index(12).handler((event, meta) -> {
meta.setValue((byte) 0x00);
filter().type(EntityTypes1_11.EntityType.VEX).index(12).handler((event, data) -> {
data.setValue((byte) 0x00);
});
// Handle VindicationIllager
filter().type(EntityTypes1_11.EntityType.VINDICATOR).index(12).handler((event, meta) -> {
filter().type(EntityTypes1_11.EntityType.VINDICATOR).index(12).handler((event, data) -> {
event.setIndex(13);
meta.setTypeAndValue(EntityDataTypes1_9.VAR_INT, ((Number) meta.getValue()).intValue() == 1 ? 2 : 4);
data.setTypeAndValue(EntityDataTypes1_9.VAR_INT, ((Number) data.getValue()).intValue() == 1 ? 2 : 4);
});
/*
@@ -253,20 +259,20 @@ public class EntityPacketRewriter1_11 extends LegacyEntityRewriter<ClientboundPa
*/
// Handle horse flags
filter().type(EntityTypes1_11.EntityType.ABSTRACT_HORSE).index(13).handler((event, meta) -> {
StoredEntityData data = storedEntityData(event);
byte b = (byte) meta.getValue();
if (data.has(ChestedHorseStorage.class) && data.get(ChestedHorseStorage.class).isChested()) {
filter().type(EntityTypes1_11.EntityType.ABSTRACT_HORSE).index(13).handler((event, data) -> {
StoredEntityData entityData = storedEntityData(event);
byte b = (byte) data.getValue();
if (entityData.has(ChestedHorseStorage.class) && entityData.get(ChestedHorseStorage.class).isChested()) {
b |= 0x08; // Chested
meta.setValue(b);
data.setValue(b);
}
});
// Create chested horse storage
filter().type(EntityTypes1_11.EntityType.CHESTED_HORSE).handler((event, meta) -> {
StoredEntityData data = storedEntityData(event);
if (!data.has(ChestedHorseStorage.class)) {
data.put(new ChestedHorseStorage());
filter().type(EntityTypes1_11.EntityType.CHESTED_HORSE).handler((event, data) -> {
StoredEntityData entityData = storedEntityData(event);
if (!entityData.has(ChestedHorseStorage.class)) {
entityData.put(new ChestedHorseStorage());
}
});
@@ -274,32 +280,32 @@ public class EntityPacketRewriter1_11 extends LegacyEntityRewriter<ClientboundPa
filter().type(EntityTypes1_11.EntityType.HORSE).index(16).toIndex(17);
// Handle chested horse
filter().type(EntityTypes1_11.EntityType.CHESTED_HORSE).index(15).handler((event, meta) -> {
StoredEntityData data = storedEntityData(event);
ChestedHorseStorage storage = data.get(ChestedHorseStorage.class);
boolean b = (boolean) meta.getValue();
filter().type(EntityTypes1_11.EntityType.CHESTED_HORSE).index(15).handler((event, data) -> {
StoredEntityData entityData = storedEntityData(event);
ChestedHorseStorage storage = entityData.get(ChestedHorseStorage.class);
boolean b = (boolean) data.getValue();
storage.setChested(b);
event.cancel();
});
// Get rid of Liama metadata
filter().type(EntityTypes1_11.EntityType.LLAMA).handler((event, meta) -> {
StoredEntityData data = storedEntityData(event);
ChestedHorseStorage storage = data.get(ChestedHorseStorage.class);
// Get rid of Liama entity data
filter().type(EntityTypes1_11.EntityType.LLAMA).handler((event, data) -> {
StoredEntityData entityData = storedEntityData(event);
ChestedHorseStorage storage = entityData.get(ChestedHorseStorage.class);
int index = event.index();
// Store them for later (:
switch (index) {
case 16 -> {
storage.setLiamaStrength((int) meta.getValue());
storage.setLiamaStrength((int) data.getValue());
event.cancel();
}
case 17 -> {
storage.setLiamaCarpetColor((int) meta.getValue());
storage.setLiamaCarpetColor((int) data.getValue());
event.cancel();
}
case 18 -> {
storage.setLiamaVariant((int) meta.getValue());
storage.setLiamaVariant((int) data.getValue());
event.cancel();
}
}
@@ -309,13 +315,13 @@ public class EntityPacketRewriter1_11 extends LegacyEntityRewriter<ClientboundPa
filter().type(EntityTypes1_11.EntityType.ABSTRACT_HORSE).index(14).toIndex(16);
// Handle villager - Change non-existing profession
filter().type(EntityTypes1_11.EntityType.VILLAGER).index(13).handler((event, meta) -> {
if ((int) meta.getValue() == 5) {
meta.setValue(0);
filter().type(EntityTypes1_11.EntityType.VILLAGER).index(13).handler((event, data) -> {
if ((int) data.getValue() == 5) {
data.setValue(0);
}
});
// handle new Shulker color meta
// handle new Shulker color data
filter().type(EntityTypes1_11.EntityType.SHULKER).cancel(15);
}
@@ -325,7 +331,7 @@ public class EntityPacketRewriter1_11 extends LegacyEntityRewriter<ClientboundPa
2 - Stray
*/
private EntityData getSkeletonTypeMeta(int type) {
private EntityData getSkeletonTypeData(int type) {
return new EntityData(12, EntityDataTypes1_9.VAR_INT, type);
}
@@ -334,14 +340,14 @@ public class EntityPacketRewriter1_11 extends LegacyEntityRewriter<ClientboundPa
1-5 - Villager with profession
6 - Husk
*/
private EntityData getZombieTypeMeta(int type) {
private EntityData getZombieTypeData(int type) {
return new EntityData(13, EntityDataTypes1_9.VAR_INT, type);
}
private void handleZombieType(WrappedMetadata storage, int type) {
private void handleZombieType(WrappedEntityData storage, int type) {
EntityData meta = storage.get(13);
if (meta == null) {
storage.add(getZombieTypeMeta(type));
storage.add(getZombieTypeData(type));
}
}
@@ -352,7 +358,7 @@ public class EntityPacketRewriter1_11 extends LegacyEntityRewriter<ClientboundPa
Zombie horse 3
Skeleton horse 4
*/
private EntityData getHorseMetaType(int type) {
private EntityData getHorseDataType(int type) {
return new EntityData(14, EntityDataTypes1_9.VAR_INT, type);
}
@@ -71,11 +71,8 @@ public class Protocol1_12To1_11_1 extends BackwardsProtocol<ClientboundPackets1_
@Override
public void init(UserConnection user) {
if (!user.has(ClientWorld.class)) {
user.put(new ClientWorld());
}
user.addEntityTracker(this.getClass(), new EntityTrackerBase(user, EntityTypes1_12.EntityType.PLAYER));
user.addClientWorld(this.getClass(), new ClientWorld());
user.put(new ShoulderTracker(user));
}
@@ -18,6 +18,7 @@
package com.viaversion.viabackwards.protocol.v1_12to1_11_1.rewriter;
import com.viaversion.nbt.tag.StringTag;
import com.viaversion.viabackwards.api.rewriters.LegacyBlockItemRewriter;
import com.viaversion.viabackwards.protocol.v1_12to1_11_1.Protocol1_12To1_11_1;
import com.viaversion.viabackwards.protocol.v1_12to1_11_1.data.MapColorMappings1_11_1;
@@ -38,6 +39,9 @@ import com.viaversion.viaversion.protocols.v1_11_1to1_12.packet.ServerboundPacke
import com.viaversion.viaversion.protocols.v1_9_1to1_9_3.packet.ServerboundPackets1_9_3;
import java.util.Iterator;
import java.util.Map;
import com.viaversion.viaversion.util.ComponentUtil;
import com.viaversion.viaversion.util.Key;
import com.viaversion.viaversion.util.SerializerVersion;
import org.checkerframework.checker.nullness.qual.Nullable;
public class BlockItemPacketRewriter1_12 extends LegacyBlockItemRewriter<ClientboundPackets1_12, ServerboundPackets1_9_3, Protocol1_12To1_11_1> {
@@ -127,12 +131,21 @@ public class BlockItemPacketRewriter1_12 extends LegacyBlockItemRewriter<Clientb
registerSetCreativeModeSlot(ServerboundPackets1_9_3.SET_CREATIVE_MODE_SLOT);
protocol.registerClientbound(ClientboundPackets1_12.LEVEL_CHUNK, wrapper -> {
ClientWorld clientWorld = wrapper.user().get(ClientWorld.class);
ClientWorld clientWorld = wrapper.user().getClientWorld(Protocol1_12To1_11_1.class);
ChunkType1_9_3 type = ChunkType1_9_3.forEnvironment(clientWorld.getEnvironment()); // Use the 1.9.4 Chunk type since nothing changed.
Chunk chunk = wrapper.passthrough(type);
handleChunk(chunk);
for (final CompoundTag tag : chunk.getBlockEntities()) {
final String id = tag.getString("id");
if (id == null) {
continue;
}
if (Key.stripMinecraftNamespace(id).equals("sign")) {
handleSignText(tag);
}
}
});
protocol.registerClientbound(ClientboundPackets1_12.BLOCK_ENTITY_DATA, new PacketHandlers() {
@@ -143,16 +156,21 @@ public class BlockItemPacketRewriter1_12 extends LegacyBlockItemRewriter<Clientb
map(Types.NAMED_COMPOUND_TAG); // 2 - NBT
handler(wrapper -> {
// Remove bed color
if (wrapper.get(Types.UNSIGNED_BYTE, 0) == 11)
final short type = wrapper.get(Types.UNSIGNED_BYTE, 0);
if (type == 9) {
final CompoundTag tag = wrapper.get(Types.NAMED_COMPOUND_TAG, 0);
handleSignText(tag);
} else if (type == 11) {
// Remove bed color
wrapper.cancel();
}
});
}
});
protocol.getEntityRewriter().filter().handler((event, meta) -> {
if (meta.dataType().type().equals(Types.ITEM1_8)) // Is Item
meta.setValue(handleItemToClient(event.user(), (Item) meta.getValue()));
protocol.getEntityRewriter().filter().handler((event, data) -> {
if (data.dataType().type().equals(Types.ITEM1_8)) // Is Item
data.setValue(handleItemToClient(event.user(), (Item) data.getValue()));
});
protocol.registerServerbound(ServerboundPackets1_9_3.CLIENT_COMMAND, new PacketHandlers() {
@@ -170,6 +188,18 @@ public class BlockItemPacketRewriter1_12 extends LegacyBlockItemRewriter<Clientb
});
}
private void handleSignText(final CompoundTag tag) {
// Push signs through component conversion, fixes https://github.com/ViaVersion/ViaBackwards/issues/835
for (int i = 0; i < 4; i++) {
final StringTag lineTag = tag.getStringTag("Text" + (i + 1));
if (lineTag == null) {
continue;
}
lineTag.setValue(ComponentUtil.convertJsonOrEmpty(lineTag.getValue(), SerializerVersion.V1_12, SerializerVersion.V1_9).toString());
}
}
@Override
public @Nullable Item handleItemToClient(UserConnection connection, Item item) {
if (item == null) return null;
@@ -31,6 +31,7 @@ import com.viaversion.viaversion.api.protocol.packet.PacketWrapper;
import com.viaversion.viaversion.api.protocol.remapper.PacketHandlers;
import com.viaversion.viaversion.api.type.Types;
import com.viaversion.viaversion.api.type.types.version.Types1_12;
import com.viaversion.viaversion.api.type.types.version.Types1_9;
import com.viaversion.viaversion.libs.gson.JsonElement;
import com.viaversion.viaversion.protocols.v1_11_1to1_12.packet.ClientboundPackets1_12;
import com.viaversion.viaversion.protocols.v1_9_1to1_9_3.packet.ClientboundPackets1_9_3;
@@ -83,13 +84,13 @@ public class EntityPacketRewriter1_12 extends LegacyEntityRewriter<ClientboundPa
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, Types1_9.ENTITY_DATA_LIST); // 12 - Entity data
// Track entity
handler(getTrackerHandler());
// Rewrite entity type / metadata
handler(getMobSpawnRewriter1_11(Types1_12.ENTITY_DATA_LIST));
// Rewrite entity type / data
handler(getMobSpawnRewriter1_11(Types1_9.ENTITY_DATA_LIST));
}
});
@@ -105,9 +106,9 @@ public class EntityPacketRewriter1_12 extends LegacyEntityRewriter<ClientboundPa
map(Types.DOUBLE); // 4 - Z
map(Types.BYTE); // 5 - Yaw
map(Types.BYTE); // 6 - Pitch
map(Types1_12.ENTITY_DATA_LIST); // 7 - Metadata list
map(Types1_12.ENTITY_DATA_LIST, Types1_9.ENTITY_DATA_LIST); // 7 - Entity data list
handler(getTrackerAndMetaHandler(Types1_12.ENTITY_DATA_LIST, EntityTypes1_12.EntityType.PLAYER));
handler(getTrackerAndDataHandler(Types1_9.ENTITY_DATA_LIST, EntityTypes1_12.EntityType.PLAYER));
}
});
@@ -118,9 +119,8 @@ public class EntityPacketRewriter1_12 extends LegacyEntityRewriter<ClientboundPa
map(Types.UNSIGNED_BYTE); // 1 - Gamemode
map(Types.INT); // 2 - Dimension
handler(getTrackerHandler(EntityTypes1_12.EntityType.PLAYER, Types.INT));
handler(getDimensionHandler(1));
handler(getPlayerTrackerHandler());
handler(wrapper -> {
ShoulderTracker tracker = wrapper.user().get(ShoulderTracker.class);
@@ -142,7 +142,7 @@ public class EntityPacketRewriter1_12 extends LegacyEntityRewriter<ClientboundPa
registerRespawn(ClientboundPackets1_12.RESPAWN);
registerRemoveEntities(ClientboundPackets1_12.REMOVE_ENTITIES);
registerSetEntityData(ClientboundPackets1_12.SET_ENTITY_DATA, Types1_12.ENTITY_DATA_LIST);
registerSetEntityData(ClientboundPackets1_12.SET_ENTITY_DATA, Types1_12.ENTITY_DATA_LIST, Types1_9.ENTITY_DATA_LIST);
protocol.registerClientbound(ClientboundPackets1_12.UPDATE_ATTRIBUTES, new PacketHandlers() {
@Override
@@ -186,42 +186,42 @@ public class EntityPacketRewriter1_12 extends LegacyEntityRewriter<ClientboundPa
@Override
protected void registerRewrites() {
mapEntityTypeWithData(EntityTypes1_12.EntityType.PARROT, EntityTypes1_12.EntityType.BAT).plainName().spawnMetadata(storage -> storage.add(new EntityData(12, EntityDataTypes1_12.BYTE, (byte) 0x00)));
mapEntityTypeWithData(EntityTypes1_12.EntityType.PARROT, EntityTypes1_12.EntityType.BAT).plainName().spawnEntityData(storage -> storage.add(new EntityData(12, EntityDataTypes1_12.BYTE, (byte) 0x00)));
mapEntityTypeWithData(EntityTypes1_12.EntityType.ILLUSIONER, EntityTypes1_12.EntityType.EVOKER).plainName();
filter().handler((event, meta) -> {
if (meta.dataType() == EntityDataTypes1_12.COMPONENT) {
protocol.getComponentRewriter().processText(event.user(), (JsonElement) meta.getValue());
filter().handler((event, data) -> {
if (data.dataType() == EntityDataTypes1_12.COMPONENT) {
protocol.getComponentRewriter().processText(event.user(), (JsonElement) data.getValue());
}
});
// Handle Illager
filter().type(EntityTypes1_12.EntityType.EVOKER).removeIndex(12);
filter().type(EntityTypes1_12.EntityType.ILLUSIONER).index(0).handler((event, meta) -> {
byte mask = (byte) meta.getValue();
filter().type(EntityTypes1_12.EntityType.ILLUSIONER).index(0).handler((event, data) -> {
byte mask = (byte) data.getValue();
if ((mask & 0x20) == 0x20) {
mask &= ~0x20;
}
meta.setValue(mask);
data.setValue(mask);
});
// Create Parrot storage
filter().type(EntityTypes1_12.EntityType.PARROT).handler((event, meta) -> {
StoredEntityData data = storedEntityData(event);
if (!data.has(ParrotStorage.class)) {
data.put(new ParrotStorage());
filter().type(EntityTypes1_12.EntityType.PARROT).handler((event, data) -> {
StoredEntityData entityData = storedEntityData(event);
if (!entityData.has(ParrotStorage.class)) {
entityData.put(new ParrotStorage());
}
});
// Parrot remove animal metadata
// Parrot remove animal entity data
filter().type(EntityTypes1_12.EntityType.PARROT).cancel(12); // Is baby
filter().type(EntityTypes1_12.EntityType.PARROT).index(13).handler((event, meta) -> {
StoredEntityData data = storedEntityData(event);
ParrotStorage storage = data.get(ParrotStorage.class);
boolean isSitting = (((byte) meta.getValue()) & 0x01) == 0x01;
boolean isTamed = (((byte) meta.getValue()) & 0x04) == 0x04;
filter().type(EntityTypes1_12.EntityType.PARROT).index(13).handler((event, data) -> {
StoredEntityData entityData = storedEntityData(event);
ParrotStorage storage = entityData.get(ParrotStorage.class);
boolean isSitting = (((byte) data.getValue()) & 0x01) == 0x01;
boolean isTamed = (((byte) data.getValue()) & 0x04) == 0x04;
if (!storage.isTamed() && isTamed) {
// TODO do something to let the user know it's done
@@ -231,11 +231,11 @@ public class EntityPacketRewriter1_12 extends LegacyEntityRewriter<ClientboundPa
if (isSitting) {
event.setIndex(12);
meta.setValue((byte) 0x01);
data.setValue((byte) 0x01);
storage.setSitting(true);
} else if (storage.isSitting()) {
event.setIndex(12);
meta.setValue((byte) 0x00);
data.setValue((byte) 0x00);
storage.setSitting(false);
} else {
event.cancel();
@@ -245,8 +245,8 @@ public class EntityPacketRewriter1_12 extends LegacyEntityRewriter<ClientboundPa
filter().type(EntityTypes1_12.EntityType.PARROT).cancel(15); // Variant
// Left shoulder entity data
filter().type(EntityTypes1_12.EntityType.PLAYER).index(15).handler((event, meta) -> {
CompoundTag tag = (CompoundTag) meta.getValue();
filter().type(EntityTypes1_12.EntityType.PLAYER).index(15).handler((event, data) -> {
CompoundTag tag = (CompoundTag) data.getValue();
ShoulderTracker tracker = event.user().get(ShoulderTracker.class);
if (tag.isEmpty() && tracker.getLeftShoulder() != null) {
@@ -264,7 +264,7 @@ public class EntityPacketRewriter1_12 extends LegacyEntityRewriter<ClientboundPa
});
// Right shoulder entity data
filter().type(EntityTypes1_12.EntityType.PLAYER).index(16).handler((event, meta) -> {
filter().type(EntityTypes1_12.EntityType.PLAYER).index(16).handler((event, data) -> {
CompoundTag tag = (CompoundTag) event.data().getValue();
ShoulderTracker tracker = event.user().get(ShoulderTracker.class);
@@ -203,10 +203,7 @@ public class Protocol1_13_1To1_13 extends BackwardsProtocol<ClientboundPackets1_
@Override
public void init(UserConnection user) {
user.addEntityTracker(getClass(), new EntityTrackerBase(user, EntityTypes1_13.EntityType.PLAYER));
if (!user.has(ClientWorld.class)) {
user.put(new ClientWorld());
}
user.addClientWorld(getClass(), new ClientWorld());
}
@Override
@@ -91,15 +91,15 @@ public class EntityPacketRewriter1_13_1 extends LegacyEntityRewriter<Clientbound
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
// Track Entity
handler(getTrackerHandler());
// Rewrite Metadata
// Rewrite Entity data
handler(wrapper -> {
List<EntityData> metadata = wrapper.get(Types1_13.ENTITY_DATA_LIST, 0);
handleEntityData(wrapper.get(Types.VAR_INT, 0), metadata, wrapper.user());
List<EntityData> entityDataList = wrapper.get(Types1_13.ENTITY_DATA_LIST, 0);
handleEntityData(wrapper.get(Types.VAR_INT, 0), entityDataList, wrapper.user());
});
}
});
@@ -114,9 +114,9 @@ public class EntityPacketRewriter1_13_1 extends LegacyEntityRewriter<Clientbound
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(getTrackerAndMetaHandler(Types1_13.ENTITY_DATA_LIST, EntityTypes1_13.EntityType.PLAYER));
handler(getTrackerAndDataHandler(Types1_13.ENTITY_DATA_LIST, EntityTypes1_13.EntityType.PLAYER));
}
});
@@ -130,17 +130,17 @@ public class EntityPacketRewriter1_13_1 extends LegacyEntityRewriter<Clientbound
@Override
protected void registerRewrites() {
// Rewrite items & blocks
filter().handler((event, meta) -> {
if (meta.dataType() == Types1_13.ENTITY_DATA_TYPES.itemType) {
protocol.getItemRewriter().handleItemToClient(event.user(), (Item) meta.getValue());
} else if (meta.dataType() == Types1_13.ENTITY_DATA_TYPES.optionalBlockStateType) {
filter().handler((event, data) -> {
if (data.dataType() == Types1_13.ENTITY_DATA_TYPES.itemType) {
protocol.getItemRewriter().handleItemToClient(event.user(), (Item) data.getValue());
} else if (data.dataType() == Types1_13.ENTITY_DATA_TYPES.optionalBlockStateType) {
// Convert to new block id
int data = (int) meta.getValue();
meta.setValue(protocol.getMappingData().getNewBlockStateId(data));
} else if (meta.dataType() == Types1_13.ENTITY_DATA_TYPES.particleType) {
rewriteParticle(event.user(), (Particle) meta.getValue());
} else if (meta.dataType() == Types1_13.ENTITY_DATA_TYPES.optionalComponentType || meta.dataType() == Types1_13.ENTITY_DATA_TYPES.componentType) {
JsonElement element = meta.value();
int value = (int) data.getValue();
data.setValue(protocol.getMappingData().getNewBlockStateId(value));
} else if (data.dataType() == Types1_13.ENTITY_DATA_TYPES.particleType) {
rewriteParticle(event.user(), (Particle) data.getValue());
} else if (data.dataType() == Types1_13.ENTITY_DATA_TYPES.optionalComponentType || data.dataType() == Types1_13.ENTITY_DATA_TYPES.componentType) {
JsonElement element = data.value();
protocol.translatableRewriter().processText(event.user(), element);
}
});
@@ -34,7 +34,7 @@ public class WorldPacketRewriter1_13_1 {
BlockRewriter<ClientboundPackets1_13> blockRewriter = BlockRewriter.legacy(protocol);
protocol.registerClientbound(ClientboundPackets1_13.LEVEL_CHUNK, wrapper -> {
ClientWorld clientWorld = wrapper.user().get(ClientWorld.class);
ClientWorld clientWorld = wrapper.user().getClientWorld(Protocol1_13_1To1_13.class);
Chunk chunk = wrapper.passthrough(ChunkType1_13.forEnvironment(clientWorld.getEnvironment()));
blockRewriter.handleChunk(chunk);
@@ -45,11 +45,11 @@ 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_2.ENTITY_DATA_LIST, Types1_13.ENTITY_DATA_LIST); // 12 - Metadata
map(Types1_13_2.ENTITY_DATA_LIST, Types1_13.ENTITY_DATA_LIST); // 12 - Entity data
handler(wrapper -> {
for (EntityData metadata : wrapper.get(Types1_13.ENTITY_DATA_LIST, 0)) {
metadata.setDataType(Types1_13.ENTITY_DATA_TYPES.byId(metadata.dataType().typeId()));
for (EntityData entityData : wrapper.get(Types1_13.ENTITY_DATA_LIST, 0)) {
entityData.setDataType(Types1_13.ENTITY_DATA_TYPES.byId(entityData.dataType().typeId()));
}
});
}
@@ -65,11 +65,11 @@ public class EntityPacketRewriter1_13_2 {
map(Types.DOUBLE); // 4 - Z
map(Types.BYTE); // 5 - Yaw
map(Types.BYTE); // 6 - Pitch
map(Types1_13_2.ENTITY_DATA_LIST, Types1_13.ENTITY_DATA_LIST); // 7 - Metadata
map(Types1_13_2.ENTITY_DATA_LIST, Types1_13.ENTITY_DATA_LIST); // 7 - Entity data
handler(wrapper -> {
for (EntityData metadata : wrapper.get(Types1_13.ENTITY_DATA_LIST, 0)) {
metadata.setDataType(Types1_13.ENTITY_DATA_TYPES.byId(metadata.dataType().typeId()));
for (EntityData entityData : wrapper.get(Types1_13.ENTITY_DATA_LIST, 0)) {
entityData.setDataType(Types1_13.ENTITY_DATA_TYPES.byId(entityData.dataType().typeId()));
}
});
}
@@ -79,11 +79,11 @@ public class EntityPacketRewriter1_13_2 {
@Override
public void register() {
map(Types.VAR_INT); // 0 - Entity ID
map(Types1_13_2.ENTITY_DATA_LIST, Types1_13.ENTITY_DATA_LIST); // 1 - Metadata list
map(Types1_13_2.ENTITY_DATA_LIST, Types1_13.ENTITY_DATA_LIST); // 1 - Entity data list
handler(wrapper -> {
for (EntityData metadata : wrapper.get(Types1_13.ENTITY_DATA_LIST, 0)) {
metadata.setDataType(Types1_13.ENTITY_DATA_TYPES.byId(metadata.dataType().typeId()));
for (EntityData entityData : wrapper.get(Types1_13.ENTITY_DATA_LIST, 0)) {
entityData.setDataType(Types1_13.ENTITY_DATA_TYPES.byId(entityData.dataType().typeId()));
}
});
}
@@ -114,11 +114,8 @@ public class Protocol1_13To1_12_2 extends BackwardsProtocol<ClientboundPackets1_
@Override
public void init(UserConnection user) {
if (!user.has(ClientWorld.class)) {
user.put(new ClientWorld());
}
user.addEntityTracker(this.getClass(), new EntityTrackerBase(user, EntityTypes1_13.EntityType.PLAYER));
user.addClientWorld(this.getClass(), new ClientWorld());
user.put(new BackwardsBlockStorage());
user.put(new TabCompleteStorage());
@@ -51,7 +51,9 @@ public class BannerHandler implements BackwardsBlockEntityHandler {
if (patternsTag != null) {
for (CompoundTag pattern : patternsTag) {
NumberTag colorTag = pattern.getNumberTag("Color");
pattern.putInt("Color", 15 - colorTag.asInt()); // Invert color id
if (colorTag != null) {
pattern.putInt("Color", 15 - colorTag.asInt()); // Invert color id
}
}
}
@@ -279,7 +279,7 @@ public class BlockItemPacketRewriter1_13 extends BackwardsItemRewriter<Clientbou
});
protocol.registerClientbound(ClientboundPackets1_13.LEVEL_CHUNK, wrapper -> {
ClientWorld clientWorld = wrapper.user().get(ClientWorld.class);
ClientWorld clientWorld = wrapper.user().getClientWorld(Protocol1_13To1_12_2.class);
ChunkType1_9_3 type_old = ChunkType1_9_3.forEnvironment(clientWorld.getEnvironment());
ChunkType1_13 type = ChunkType1_13.forEnvironment(clientWorld.getEnvironment());
@@ -27,6 +27,7 @@ import com.viaversion.viabackwards.protocol.v1_13to1_12_2.data.ParticleIdMapping
import com.viaversion.viabackwards.protocol.v1_13to1_12_2.storage.BackwardsBlockStorage;
import com.viaversion.viabackwards.protocol.v1_13to1_12_2.storage.NoteBlockStorage;
import com.viaversion.viabackwards.protocol.v1_13to1_12_2.storage.PlayerPositionStorage1_13;
import com.viaversion.viaversion.api.minecraft.ClientWorld;
import com.viaversion.viaversion.api.minecraft.Particle;
import com.viaversion.viaversion.api.minecraft.entities.EntityType;
import com.viaversion.viaversion.api.minecraft.entities.EntityTypes1_13;
@@ -145,7 +146,7 @@ public class EntityPacketRewriter1_13 extends LegacyEntityRewriter<ClientboundPa
}
});
// Rewrite entity type / metadata
// Rewrite entity type / ddata
handler(getMobSpawnRewriter1_11(Types1_12.ENTITY_DATA_LIST));
}
});
@@ -162,7 +163,7 @@ public class EntityPacketRewriter1_13 extends LegacyEntityRewriter<ClientboundPa
map(Types.BYTE);
map(Types1_13.ENTITY_DATA_LIST, Types1_12.ENTITY_DATA_LIST);
handler(getTrackerAndMetaHandler(Types1_12.ENTITY_DATA_LIST, EntityTypes1_13.EntityType.PLAYER));
handler(getTrackerAndDataHandler(Types1_12.ENTITY_DATA_LIST, EntityTypes1_13.EntityType.PLAYER));
}
});
@@ -172,7 +173,7 @@ public class EntityPacketRewriter1_13 extends LegacyEntityRewriter<ClientboundPa
map(Types.VAR_INT);
map(Types.UUID);
handler(getTrackerHandler(EntityTypes1_13.EntityType.PAINTING, Types.VAR_INT));
handler(getTrackerHandler(EntityTypes1_13.EntityType.PAINTING));
handler(wrapper -> {
int motive = wrapper.read(Types.VAR_INT);
String title = PaintingNames1_13.getStringId(motive);
@@ -188,10 +189,15 @@ public class EntityPacketRewriter1_13 extends LegacyEntityRewriter<ClientboundPa
public void register() {
map(Types.INT); // 0 - Dimension ID
handler(getDimensionHandler(0));
handler(wrapper -> {
wrapper.user().get(BackwardsBlockStorage.class).clear();
wrapper.user().get(NoteBlockStorage.class).clear();
ClientWorld clientWorld = wrapper.user().getClientWorld(Protocol1_13To1_12_2.class);
int dimensionId = wrapper.get(Types.INT, 0);
if (clientWorld.setEnvironment(dimensionId)) {
tracker(wrapper.user()).clearEntities();
wrapper.user().get(BackwardsBlockStorage.class).clear();
wrapper.user().get(NoteBlockStorage.class).clear();
}
});
}
});
@@ -258,7 +264,7 @@ public class EntityPacketRewriter1_13 extends LegacyEntityRewriter<ClientboundPa
mapEntityTypeWithData(EntityTypes1_13.EntityType.TROPICAL_FISH, EntityTypes1_13.EntityType.SQUID).plainName();
// Phantom
mapEntityTypeWithData(EntityTypes1_13.EntityType.PHANTOM, EntityTypes1_13.EntityType.PARROT).plainName().spawnMetadata(storage -> {
mapEntityTypeWithData(EntityTypes1_13.EntityType.PHANTOM, EntityTypes1_13.EntityType.PARROT).plainName().spawnEntityData(storage -> {
// The phantom is grey/blue so let's do yellow/blue
storage.add(new EntityData(15, EntityDataTypes1_12.VAR_INT, 3));
});
@@ -269,32 +275,32 @@ public class EntityPacketRewriter1_13 extends LegacyEntityRewriter<ClientboundPa
// Turtle
mapEntityTypeWithData(EntityTypes1_13.EntityType.TURTLE, EntityTypes1_13.EntityType.OCELOT).plainName();
// Rewrite Meta types
filter().handler((event, meta) -> {
int typeId = meta.dataType().typeId();
// Rewrite Data types
filter().handler((event, data) -> {
int typeId = data.dataType().typeId();
if (typeId == 4) {
JsonElement element = meta.value();
JsonElement element = data.value();
protocol.translatableRewriter().processText(event.user(), element);
meta.setDataType(EntityDataTypes1_12.COMPONENT);
data.setDataType(EntityDataTypes1_12.COMPONENT);
} else if (typeId == 5) {
// Rewrite optional chat to string
JsonElement element = meta.value();
meta.setTypeAndValue(EntityDataTypes1_12.STRING, protocol.jsonToLegacy(event.user(), element));
JsonElement element = data.value();
data.setTypeAndValue(EntityDataTypes1_12.STRING, protocol.jsonToLegacy(event.user(), element));
} else if (typeId == 6) {
Item item = (Item) meta.getValue();
meta.setTypeAndValue(EntityDataTypes1_12.ITEM, protocol.getItemRewriter().handleItemToClient(event.user(), item));
Item item = (Item) data.getValue();
data.setTypeAndValue(EntityDataTypes1_12.ITEM, protocol.getItemRewriter().handleItemToClient(event.user(), item));
} else if (typeId == 15) {
// Discontinue particles
event.cancel();
} else {
meta.setDataType(EntityDataTypes1_12.byId(typeId > 5 ? typeId - 1 : typeId));
data.setDataType(EntityDataTypes1_12.byId(typeId > 5 ? typeId - 1 : typeId));
}
});
// Handle zombie metadata
// Handle zombie entity data
filter().type(EntityTypes1_13.EntityType.ZOMBIE).removeIndex(15);
// Handle turtle metadata (Remove them all for now)
// Handle turtle entity data (Remove them all for now)
filter().type(EntityTypes1_13.EntityType.TURTLE).cancel(13); // Home pos
filter().type(EntityTypes1_13.EntityType.TURTLE).cancel(14); // Has egg
filter().type(EntityTypes1_13.EntityType.TURTLE).cancel(15); // Laying egg
@@ -302,7 +308,7 @@ public class EntityPacketRewriter1_13 extends LegacyEntityRewriter<ClientboundPa
filter().type(EntityTypes1_13.EntityType.TURTLE).cancel(17); // Going home
filter().type(EntityTypes1_13.EntityType.TURTLE).cancel(18); // Traveling
// Remove additional fish meta
// Remove additional fish data
filter().type(EntityTypes1_13.EntityType.ABSTRACT_FISH).cancel(12);
filter().type(EntityTypes1_13.EntityType.ABSTRACT_FISH).cancel(13);
@@ -316,21 +322,21 @@ public class EntityPacketRewriter1_13 extends LegacyEntityRewriter<ClientboundPa
filter().type(EntityTypes1_13.EntityType.TRIDENT).cancel(7);
// Handle new wolf colors
filter().type(EntityTypes1_13.EntityType.WOLF).index(17).handler((event, meta) -> {
meta.setValue(15 - (int) meta.getValue());
filter().type(EntityTypes1_13.EntityType.WOLF).index(17).handler((event, data) -> {
data.setValue(15 - (int) data.getValue());
});
// Rewrite AreaEffectCloud
filter().type(EntityTypes1_13.EntityType.AREA_EFFECT_CLOUD).index(9).handler((event, meta) -> {
Particle particle = (Particle) meta.getValue();
filter().type(EntityTypes1_13.EntityType.AREA_EFFECT_CLOUD).index(9).handler((event, data) -> {
Particle particle = (Particle) data.getValue();
ParticleIdMappings1_12_2.ParticleData data = ParticleIdMappings1_12_2.getMapping(particle.id());
ParticleIdMappings1_12_2.ParticleData particleData = ParticleIdMappings1_12_2.getMapping(particle.id());
int firstArg = 0;
int secondArg = 0;
int[] particleArgs = data.rewriteMeta(protocol, particle.getArguments());
int[] particleArgs = particleData.rewriteMeta(protocol, particle.getArguments());
if (particleArgs != null && particleArgs.length != 0) {
if (data.getHandler().isBlockHandler() && particleArgs[0] == 0) {
if (particleData.getHandler().isBlockHandler() && particleArgs[0] == 0) {
// Air doesn't have a break particle for sub 1.13 clients -> glass pane
particleArgs[0] = 102;
}
@@ -339,7 +345,7 @@ public class EntityPacketRewriter1_13 extends LegacyEntityRewriter<ClientboundPa
secondArg = particleArgs.length == 2 ? particleArgs[1] : 0;
}
event.createExtraData(new EntityData(9, EntityDataTypes1_12.VAR_INT, data.getHistoryId()));
event.createExtraData(new EntityData(9, EntityDataTypes1_12.VAR_INT, particleData.getHistoryId()));
event.createExtraData(new EntityData(10, EntityDataTypes1_12.VAR_INT, firstArg));
event.createExtraData(new EntityData(11, EntityDataTypes1_12.VAR_INT, secondArg));
@@ -70,7 +70,7 @@ public class EntityPacketRewriter1_14_1 extends LegacyEntityRewriter<Clientbound
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(wrapper -> {
int entityId = wrapper.get(Types.VAR_INT, 0);
@@ -79,13 +79,13 @@ public class EntityPacketRewriter1_14_1 extends LegacyEntityRewriter<Clientbound
// Register Type ID
tracker(wrapper.user()).addEntity(entityId, EntityTypes1_14.getTypeFromId(type));
List<EntityData> metadata = wrapper.get(Types1_14.ENTITY_DATA_LIST, 0);
handleEntityData(entityId, metadata, wrapper.user());
List<EntityData> entityDataList = wrapper.get(Types1_14.ENTITY_DATA_LIST, 0);
handleEntityData(entityId, entityDataList, wrapper.user());
});
}
});
// Entity Metadata
// Entity data
registerSetEntityData(ClientboundPackets1_14.SET_ENTITY_DATA, Types1_14.ENTITY_DATA_LIST);
}
@@ -162,11 +162,8 @@ public class Protocol1_14To1_13_2 extends BackwardsProtocol<ClientboundPackets1_
@Override
public void init(UserConnection user) {
if (!user.has(ClientWorld.class)) {
user.put(new ClientWorld());
}
user.addEntityTracker(this.getClass(), new EntityTrackerBase(user, EntityTypes1_14.PLAYER));
user.addClientWorld(this.getClass(), new ClientWorld());
if (!user.has(ChunkLightStorage.class)) {
user.put(new ChunkLightStorage());
@@ -20,6 +20,7 @@ package com.viaversion.viabackwards.protocol.v1_14to1_13_2.rewriter;
import com.google.common.collect.ImmutableSet;
import com.viaversion.viabackwards.api.rewriters.BackwardsItemRewriter;
import com.viaversion.viabackwards.api.rewriters.EnchantmentRewriter;
import com.viaversion.viabackwards.api.rewriters.TranslatableRewriter;
import com.viaversion.viabackwards.protocol.v1_14to1_13_2.Protocol1_14To1_13_2;
import com.viaversion.viabackwards.protocol.v1_14to1_13_2.storage.ChunkLightStorage;
import com.viaversion.viaversion.api.Via;
@@ -48,6 +49,8 @@ import com.viaversion.nbt.tag.CompoundTag;
import com.viaversion.nbt.tag.ListTag;
import com.viaversion.nbt.tag.StringTag;
import com.viaversion.viaversion.libs.gson.JsonParseException;
import com.viaversion.viaversion.libs.mcstructs.text.utils.TextUtils;
import com.viaversion.viaversion.protocols.v1_12_2to1_13.Protocol1_12_2To1_13;
import com.viaversion.viaversion.protocols.v1_12_2to1_13.packet.ClientboundPackets1_13;
import com.viaversion.viaversion.protocols.v1_12_2to1_13.packet.ServerboundPackets1_13;
import com.viaversion.viaversion.protocols.v1_13_2to1_14.Protocol1_13_2To1_14;
@@ -239,9 +242,9 @@ public class BlockItemPacketRewriter1_14 extends BackwardsItemRewriter<Clientbou
wrapper.cancel();
return;
}
List<EntityData> metadataList = new ArrayList<>();
metadataList.add(new EntityData(16, Types1_13_2.ENTITY_DATA_TYPES.varIntType, armorType));
wrapper.write(Types1_13.ENTITY_DATA_LIST, metadataList);
List<EntityData> entityDataList = new ArrayList<>();
entityDataList.add(new EntityData(16, Types1_13_2.ENTITY_DATA_TYPES.varIntType, armorType));
wrapper.write(Types1_13.ENTITY_DATA_LIST, entityDataList);
}
});
}
@@ -357,7 +360,7 @@ public class BlockItemPacketRewriter1_14 extends BackwardsItemRewriter<Clientbou
});
protocol.registerClientbound(ClientboundPackets1_14.LEVEL_CHUNK, wrapper -> {
ClientWorld clientWorld = wrapper.user().get(ClientWorld.class);
ClientWorld clientWorld = wrapper.user().getClientWorld(Protocol1_14To1_13_2.class);
Chunk chunk = wrapper.read(ChunkType1_14.TYPE);
wrapper.write(ChunkType1_13.forEnvironment(clientWorld.getEnvironment()), chunk);
@@ -477,6 +480,8 @@ public class BlockItemPacketRewriter1_14 extends BackwardsItemRewriter<Clientbou
each.remove();
continue;
}
TextUtils.setTranslator(component, s -> Protocol1_12_2To1_13.MAPPINGS.getMojangTranslation().
getOrDefault(s, TranslatableRewriter.getTranslatableMappings("1.14").get(s)));
loreEntry.setValue(component.asLegacyFormatString());
}
} catch (final JsonParseException e) {
@@ -153,6 +153,27 @@ public class EntityPacketRewriter1_14 extends LegacyEntityRewriter<ClientboundPa
};
if (data != 0)
wrapper.set(Types.INT, 0, data);
} else if (entityType.is(EntityTypes1_13.EntityType.EXPERIENCE_ORB)) {
// Newer clients can spawn experience orbs via add entity, map to add experience orb and override values via multiple packets
wrapper.cancel();
final int entityId = wrapper.get(Types.VAR_INT, 0);
// Shrug about uuid or rotations
final PacketWrapper addExperienceOrb = PacketWrapper.create(ClientboundPackets1_13.ADD_EXPERIENCE_ORB, wrapper.user());
addExperienceOrb.write(Types.VAR_INT, entityId); // Entity id
addExperienceOrb.write(Types.DOUBLE, wrapper.get(Types.DOUBLE, 0)); // X
addExperienceOrb.write(Types.DOUBLE, wrapper.get(Types.DOUBLE, 1)); // Y
addExperienceOrb.write(Types.DOUBLE, wrapper.get(Types.DOUBLE, 2)); // Z
addExperienceOrb.write(Types.SHORT, (short) 0); // Experience count
addExperienceOrb.send(Protocol1_14To1_13_2.class);
final PacketWrapper setEntityMotion = PacketWrapper.create(ClientboundPackets1_13.SET_ENTITY_MOTION, wrapper.user());
setEntityMotion.write(Types.VAR_INT, entityId); // Entity id
setEntityMotion.write(Types.SHORT, wrapper.get(Types.SHORT, 0));
setEntityMotion.write(Types.SHORT, wrapper.get(Types.SHORT, 1));
setEntityMotion.write(Types.SHORT, wrapper.get(Types.SHORT, 2));
setEntityMotion.send(Protocol1_14To1_13_2.class);
return;
} else {
for (final EntityTypes1_13.ObjectType type : EntityTypes1_13.ObjectType.values()) {
if (type.getType() == entityType) {
@@ -193,7 +214,7 @@ public class EntityPacketRewriter1_14 extends LegacyEntityRewriter<ClientboundPa
map(Types.SHORT); // 9 - Velocity X
map(Types.SHORT); // 10 - Velocity Y
map(Types.SHORT); // 11 - Velocity Z
map(Types1_14.ENTITY_DATA_LIST, Types1_13_2.ENTITY_DATA_LIST); // 12 - Metadata
map(Types1_14.ENTITY_DATA_LIST, Types1_13_2.ENTITY_DATA_LIST); // 12 - Entity data
handler(wrapper -> {
int type = wrapper.get(Types.VAR_INT, 1);
@@ -214,7 +235,7 @@ public class EntityPacketRewriter1_14 extends LegacyEntityRewriter<ClientboundPa
}
});
// Handle entity type & metadata
// Handle entity type & data
handler(getMobSpawnRewriter1_11(Types1_13_2.ENTITY_DATA_LIST));
}
});
@@ -266,9 +287,9 @@ public class EntityPacketRewriter1_14 extends LegacyEntityRewriter<ClientboundPa
map(Types.DOUBLE); // 4 - Z
map(Types.BYTE); // 5 - Yaw
map(Types.BYTE); // 6 - Pitch
map(Types1_14.ENTITY_DATA_LIST, Types1_13_2.ENTITY_DATA_LIST); // 7 - Metadata
map(Types1_14.ENTITY_DATA_LIST, Types1_13_2.ENTITY_DATA_LIST); // 7 - Entity data
handler(getTrackerAndMetaHandler(Types1_13_2.ENTITY_DATA_LIST, EntityTypes1_14.PLAYER));
handler(getTrackerAndDataHandler(Types1_13_2.ENTITY_DATA_LIST, EntityTypes1_14.PLAYER));
handler(wrapper -> positionHandler.cacheEntityPosition(wrapper, true, false));
}
});
@@ -283,8 +304,8 @@ public class EntityPacketRewriter1_14 extends LegacyEntityRewriter<ClientboundPa
map(Types.UNSIGNED_BYTE); // 1 - Gamemode
map(Types.INT); // 2 - Dimension
handler(getTrackerHandler(EntityTypes1_14.PLAYER, Types.INT));
handler(getDimensionHandler(1));
handler(getPlayerTrackerHandler());
handler(wrapper -> {
short difficulty = wrapper.user().get(DifficultyStorage.class).getDifficulty();
wrapper.write(Types.UNSIGNED_BYTE, difficulty);
@@ -308,14 +329,16 @@ public class EntityPacketRewriter1_14 extends LegacyEntityRewriter<ClientboundPa
map(Types.INT); // 0 - Dimension ID
handler(wrapper -> {
ClientWorld clientWorld = wrapper.user().get(ClientWorld.class);
ClientWorld clientWorld = wrapper.user().getClientWorld(Protocol1_14To1_13_2.class);
int dimensionId = wrapper.get(Types.INT, 0);
clientWorld.setEnvironment(dimensionId);
if (clientWorld.setEnvironment(dimensionId)) {
tracker(wrapper.user()).clearEntities();
wrapper.user().get(ChunkLightStorage.class).clear();
}
short difficulty = wrapper.user().get(DifficultyStorage.class).getDifficulty();
wrapper.write(Types.UNSIGNED_BYTE, difficulty);
wrapper.user().get(ChunkLightStorage.class).clear();
});
}
});
@@ -323,14 +346,14 @@ public class EntityPacketRewriter1_14 extends LegacyEntityRewriter<ClientboundPa
@Override
protected void registerRewrites() {
filter().handler((event, meta) -> {
int typeId = meta.dataType().typeId();
filter().handler((event, data) -> {
int typeId = data.dataType().typeId();
if (typeId <= 15) {
meta.setDataType(Types1_13_2.ENTITY_DATA_TYPES.byId(typeId));
data.setDataType(Types1_13_2.ENTITY_DATA_TYPES.byId(typeId));
}
});
registerMetaTypeHandler(Types1_13_2.ENTITY_DATA_TYPES.itemType, null, Types1_13_2.ENTITY_DATA_TYPES.optionalBlockStateType, null,
registerEntityDataTypeHandler(Types1_13_2.ENTITY_DATA_TYPES.itemType, null, Types1_13_2.ENTITY_DATA_TYPES.optionalBlockStateType, null,
Types1_13_2.ENTITY_DATA_TYPES.componentType, Types1_13_2.ENTITY_DATA_TYPES.optionalComponentType);
filter().type(EntityTypes1_14.PILLAGER).cancel(15);
@@ -353,15 +376,15 @@ public class EntityPacketRewriter1_14 extends LegacyEntityRewriter<ClientboundPa
filter().type(EntityTypes1_14.ABSTRACT_RAIDER).removeIndex(14); // Celebrating
filter().type(EntityTypes1_14.AREA_EFFECT_CLOUD).index(10).handler((event, meta) -> {
rewriteParticle(event.user(), (Particle) meta.getValue());
filter().type(EntityTypes1_14.AREA_EFFECT_CLOUD).index(10).handler((event, data) -> {
rewriteParticle(event.user(), (Particle) data.getValue());
});
filter().type(EntityTypes1_14.FIREWORK_ROCKET).index(8).handler((event, meta) -> {
meta.setDataType(Types1_13_2.ENTITY_DATA_TYPES.varIntType);
Integer value = (Integer) meta.getValue();
filter().type(EntityTypes1_14.FIREWORK_ROCKET).index(8).handler((event, data) -> {
data.setDataType(Types1_13_2.ENTITY_DATA_TYPES.varIntType);
Integer value = (Integer) data.getValue();
if (value == null) {
meta.setValue(0);
data.setValue(0);
}
});
@@ -369,10 +392,10 @@ public class EntityPacketRewriter1_14 extends LegacyEntityRewriter<ClientboundPa
filter().type(EntityTypes1_14.VILLAGER).cancel(15); // Head shake timer
EntityDataHandler villagerDataHandler = (event, meta) -> {
VillagerData villagerData = (VillagerData) meta.getValue();
meta.setTypeAndValue(Types1_13_2.ENTITY_DATA_TYPES.varIntType, villagerDataToProfession(villagerData));
if (meta.id() == 16) {
EntityDataHandler villagerDataHandler = (event, data) -> {
VillagerData villagerData = (VillagerData) data.getValue();
data.setTypeAndValue(Types1_13_2.ENTITY_DATA_TYPES.varIntType, villagerDataToProfession(villagerData));
if (data.id() == 16) {
event.setIndex(15); // decreased by 2 again in one of the following handlers
}
};
@@ -381,14 +404,14 @@ public class EntityPacketRewriter1_14 extends LegacyEntityRewriter<ClientboundPa
filter().type(EntityTypes1_14.VILLAGER).index(16).handler(villagerDataHandler);
// Holding arms up - from bitfield into own boolean
filter().type(EntityTypes1_14.ABSTRACT_SKELETON).index(13).handler((event, meta) -> {
byte value = (byte) meta.getValue();
filter().type(EntityTypes1_14.ABSTRACT_SKELETON).index(13).handler((event, data) -> {
byte value = (byte) data.getValue();
if ((value & 4) != 0) {
event.createExtraData(new EntityData(14, Types1_13_2.ENTITY_DATA_TYPES.booleanType, true));
}
});
filter().type(EntityTypes1_14.ZOMBIE).index(13).handler((event, meta) -> {
byte value = (byte) meta.getValue();
filter().type(EntityTypes1_14.ZOMBIE).index(13).handler((event, data) -> {
byte value = (byte) data.getValue();
if ((value & 4) != 0) {
event.createExtraData(new EntityData(16, Types1_13_2.ENTITY_DATA_TYPES.booleanType, true));
}
@@ -397,10 +420,10 @@ public class EntityPacketRewriter1_14 extends LegacyEntityRewriter<ClientboundPa
filter().type(EntityTypes1_14.ZOMBIE).addIndex(16);
// Remove bed location
filter().type(EntityTypes1_14.LIVING_ENTITY).handler((event, meta) -> {
filter().type(EntityTypes1_14.LIVING_ENTITY).handler((event, data) -> {
int index = event.index();
if (index == 12) {
BlockPosition position = (BlockPosition) meta.getValue();
BlockPosition position = (BlockPosition) data.getValue();
if (position != null) {
// Use bed
PacketWrapper wrapper = PacketWrapper.create(ClientboundPackets1_13.PLAYER_SLEEP, null, event.user());
@@ -423,22 +446,22 @@ public class EntityPacketRewriter1_14 extends LegacyEntityRewriter<ClientboundPa
// Pose
filter().removeIndex(6);
filter().type(EntityTypes1_14.OCELOT).index(13).handler((event, meta) -> {
filter().type(EntityTypes1_14.OCELOT).index(13).handler((event, data) -> {
event.setIndex(15);
meta.setTypeAndValue(Types1_13_2.ENTITY_DATA_TYPES.varIntType, 0);
data.setTypeAndValue(Types1_13_2.ENTITY_DATA_TYPES.varIntType, 0);
});
filter().type(EntityTypes1_14.CAT).handler((event, meta) -> {
filter().type(EntityTypes1_14.CAT).handler((event, data) -> {
if (event.index() == 15) {
meta.setValue(1);
data.setValue(1);
} else if (event.index() == 13) {
meta.setValue((byte) ((byte) meta.getValue() & 0x4));
data.setValue((byte) ((byte) data.getValue() & 0x4));
}
});
filter().handler((event, meta) -> {
if (meta.dataType().typeId() > 15) {
throw new IllegalArgumentException("Unhandled metadata: " + meta);
filter().handler((event, data) -> {
if (data.dataType().typeId() > 15) {
throw new IllegalArgumentException("Unhandled entity data: " + data);
}
});
}
@@ -25,6 +25,7 @@ import com.viaversion.viabackwards.protocol.v1_15to1_14_4.storage.ImmediateRespa
import com.viaversion.viabackwards.protocol.v1_15to1_14_4.rewriter.BlockItemPacketRewriter1_15;
import com.viaversion.viabackwards.protocol.v1_15to1_14_4.rewriter.EntityPacketRewriter1_15;
import com.viaversion.viaversion.api.connection.UserConnection;
import com.viaversion.viaversion.api.minecraft.ClientWorld;
import com.viaversion.viaversion.api.minecraft.RegistryType;
import com.viaversion.viaversion.api.minecraft.entities.EntityTypes1_15;
import com.viaversion.viaversion.api.protocol.packet.PacketWrapper;
@@ -102,8 +103,10 @@ public class Protocol1_15To1_14_4 extends BackwardsProtocol<ClientboundPackets1_
@Override
public void init(UserConnection user) {
user.put(new ImmediateRespawnStorage());
user.addEntityTracker(getClass(), new EntityTrackerBase(user, EntityTypes1_15.PLAYER));
user.addClientWorld(getClass(), new ClientWorld());
user.put(new ImmediateRespawnStorage());
}
@Override
@@ -21,7 +21,6 @@ import com.viaversion.viabackwards.api.rewriters.EntityRewriter;
import com.viaversion.viabackwards.protocol.v1_15to1_14_4.Protocol1_15To1_14_4;
import com.viaversion.viabackwards.protocol.v1_15to1_14_4.storage.ImmediateRespawnStorage;
import com.viaversion.viaversion.api.minecraft.entities.EntityType;
import com.viaversion.viaversion.api.minecraft.entities.EntityTypes1_14;
import com.viaversion.viaversion.api.minecraft.entities.EntityTypes1_15;
import com.viaversion.viaversion.api.minecraft.entitydata.EntityData;
import com.viaversion.viaversion.api.protocol.packet.PacketWrapper;
@@ -81,7 +80,7 @@ public class EntityPacketRewriter1_15 extends EntityRewriter<ClientboundPackets1
map(Types.SHORT); // 9 - Velocity X
map(Types.SHORT); // 10 - Velocity Y
map(Types.SHORT); // 11 - Velocity Z
handler(wrapper -> wrapper.write(Types1_14.ENTITY_DATA_LIST, new ArrayList<>())); // Metadata is no longer sent in 1.15, so we have to send an empty one
handler(wrapper -> wrapper.write(Types1_14.ENTITY_DATA_LIST, new ArrayList<>())); // Entity data is no longer sent in 1.15, so we have to send an empty one
handler(wrapper -> {
int type = wrapper.get(Types.VAR_INT, 1);
@@ -97,6 +96,7 @@ public class EntityPacketRewriter1_15 extends EntityRewriter<ClientboundPackets1
public void register() {
map(Types.INT);
read(Types.LONG); // Seed
handler(getDimensionHandler(0));
}
});
@@ -114,7 +114,7 @@ public class EntityPacketRewriter1_15 extends EntityRewriter<ClientboundPackets1
map(Types.VAR_INT); // 5 - View Distance
map(Types.BOOLEAN); // 6 - Reduce Debug Info
handler(getTrackerHandler(EntityTypes1_15.PLAYER, Types.INT));
handler(getPlayerTrackerHandler());
handler(wrapper -> {
boolean immediateRespawn = !wrapper.read(Types.BOOLEAN); // Inverted
@@ -137,9 +137,9 @@ public class EntityPacketRewriter1_15 extends EntityRewriter<ClientboundPackets1
map(Types.DOUBLE); // 4 - Z
map(Types.BYTE); // 5 - Yaw
map(Types.BYTE); // 6 - Pitch
handler(wrapper -> wrapper.write(Types1_14.ENTITY_DATA_LIST, new ArrayList<>())); // Metadata is no longer sent in 1.15, so we have to send an empty one
handler(wrapper -> wrapper.write(Types1_14.ENTITY_DATA_LIST, new ArrayList<>())); // Entity data is no longer sent in 1.15, so we have to send an empty one
handler(getTrackerHandler(EntityTypes1_15.PLAYER, Types.VAR_INT));
handler(getTrackerHandler(EntityTypes1_15.PLAYER));
}
});
@@ -192,7 +192,7 @@ public class EntityPacketRewriter1_15 extends EntityRewriter<ClientboundPackets1
@Override
protected void registerRewrites() {
registerMetaTypeHandler(Types1_14.ENTITY_DATA_TYPES.itemType, null, Types1_14.ENTITY_DATA_TYPES.optionalBlockStateType, Types1_14.ENTITY_DATA_TYPES.particleType,
registerEntityDataTypeHandler(Types1_14.ENTITY_DATA_TYPES.itemType, null, Types1_14.ENTITY_DATA_TYPES.optionalBlockStateType, Types1_14.ENTITY_DATA_TYPES.particleType,
Types1_14.ENTITY_DATA_TYPES.componentType, Types1_14.ENTITY_DATA_TYPES.optionalComponentType);
filter().type(EntityTypes1_15.LIVING_ENTITY).removeIndex(12);
@@ -200,29 +200,28 @@ public class EntityPacketRewriter1_15 extends EntityRewriter<ClientboundPackets1
filter().type(EntityTypes1_15.BEE).cancel(15);
filter().type(EntityTypes1_15.BEE).cancel(16);
mapEntityTypeWithData(EntityTypes1_15.BEE, EntityTypes1_15.PUFFERFISH).jsonName().spawnMetadata(storage -> {
storage.add(new EntityData(14, Types1_14.ENTITY_DATA_TYPES.booleanType, false));
storage.add(new EntityData(15, Types1_14.ENTITY_DATA_TYPES.varIntType, 2));
});
filter().type(EntityTypes1_15.ENDERMAN).cancel(16);
filter().type(EntityTypes1_15.TRIDENT).cancel(10);
// Redundant health removed in 1.15
filter().type(EntityTypes1_15.WOLF).addIndex(17);
filter().type(EntityTypes1_15.WOLF).index(8).handler((event, meta) -> {
filter().type(EntityTypes1_15.WOLF).index(8).handler((event, data) -> {
event.createExtraData(new EntityData(17/*WOLF_HEALTH*/, Types1_14.ENTITY_DATA_TYPES.floatType, event.data().value()));
});
}
@Override
public void onMappingDataLoaded() {
mapTypes();
mapEntityTypeWithData(EntityTypes1_15.BEE, EntityTypes1_15.PUFFERFISH).jsonName().spawnEntityData(storage -> {
storage.add(new EntityData(14, Types1_14.ENTITY_DATA_TYPES.booleanType, false));
storage.add(new EntityData(15, Types1_14.ENTITY_DATA_TYPES.varIntType, 2));
});
}
@Override
public EntityType typeFromId(int typeId) {
return EntityTypes1_15.getTypeFromId(typeId);
}
@Override
public int newEntityId(final int newId) {
if (newId == 4) return EntityTypes1_14.PUFFERFISH.getId(); // Flying pufferfish!
return newId >= 5 ? newId - 1 : newId;
}
}
@@ -101,13 +101,15 @@ public class EntityPacketRewriter1_16_2 extends EntityRewriter<ClientboundPacket
wrapper.write(Types.UNSIGNED_BYTE, (short) Math.min(maxPlayers, 255));
});
// ...
handler(getTrackerHandler(EntityTypes1_16_2.PLAYER, Types.INT));
handler(getPlayerTrackerHandler());
}
});
protocol.registerClientbound(ClientboundPackets1_16_2.RESPAWN, wrapper -> {
CompoundTag dimensionData = wrapper.read(Types.NAMED_COMPOUND_TAG);
wrapper.write(Types.STRING, getDimensionFromData(dimensionData));
tracker(wrapper.user()).clearEntities();
});
}
@@ -120,7 +122,7 @@ public class EntityPacketRewriter1_16_2 extends EntityRewriter<ClientboundPacket
@Override
protected void registerRewrites() {
registerMetaTypeHandler(Types1_16.ENTITY_DATA_TYPES.itemType, null, Types1_16.ENTITY_DATA_TYPES.optionalBlockStateType,
registerEntityDataTypeHandler(Types1_16.ENTITY_DATA_TYPES.itemType, null, Types1_16.ENTITY_DATA_TYPES.optionalBlockStateType,
Types1_16.ENTITY_DATA_TYPES.particleType, Types1_16.ENTITY_DATA_TYPES.componentType, Types1_16.ENTITY_DATA_TYPES.optionalComponentType);
filter().type(EntityTypes1_16_2.ABSTRACT_PIGLIN).index(15).toIndex(16);
@@ -22,6 +22,7 @@ import com.viaversion.viabackwards.api.rewriters.SoundRewriter;
import com.viaversion.viabackwards.protocol.v1_16to1_15_2.rewriter.TranslatableRewriter1_16;
import com.viaversion.viabackwards.protocol.v1_16to1_15_2.data.BackwardsMappingData1_16;
import com.viaversion.viabackwards.protocol.v1_16to1_15_2.rewriter.CommandRewriter1_16;
import com.viaversion.viabackwards.protocol.v1_16to1_15_2.storage.PlayerAttributesStorage;
import com.viaversion.viabackwards.protocol.v1_16to1_15_2.storage.WorldNameTracker;
import com.viaversion.viabackwards.protocol.v1_16to1_15_2.rewriter.BlockItemPacketRewriter1_16;
import com.viaversion.viabackwards.protocol.v1_16to1_15_2.rewriter.EntityPacketRewriter1_16;
@@ -72,7 +73,7 @@ public class Protocol1_16To1_15_2 extends BackwardsProtocol<ClientboundPackets1_
new CommandRewriter1_16(this).registerDeclareCommands(ClientboundPackets1_16.COMMANDS);
registerClientbound(State.STATUS, ClientboundStatusPackets.STATUS_RESPONSE.getId(), ClientboundStatusPackets.STATUS_RESPONSE.getId(), wrapper -> {
registerClientbound(State.STATUS, ClientboundStatusPackets.STATUS_RESPONSE, wrapper -> {
String original = wrapper.passthrough(Types.STRING);
JsonObject object = GsonUtil.getGson().fromJson(original, JsonObject.class);
JsonElement description = object.get("description");
@@ -115,7 +116,7 @@ public class Protocol1_16To1_15_2 extends BackwardsProtocol<ClientboundPackets1_
soundRewriter.registerStopSound(ClientboundPackets1_16.STOP_SOUND);
// Login success
registerClientbound(State.LOGIN, ClientboundLoginPackets.GAME_PROFILE.getId(), ClientboundLoginPackets.GAME_PROFILE.getId(), wrapper -> {
registerClientbound(State.LOGIN, ClientboundLoginPackets.GAME_PROFILE, wrapper -> {
// Transform uuid to plain string
UUID uuid = wrapper.read(Types.UUID);
wrapper.write(Types.STRING, uuid.toString());
@@ -167,13 +168,12 @@ public class Protocol1_16To1_15_2 extends BackwardsProtocol<ClientboundPackets1_
@Override
public void init(UserConnection user) {
if (!user.has(ClientWorld.class)) {
user.put(new ClientWorld());
}
user.addEntityTracker(this.getClass(), new EntityTrackerBase(user, EntityTypes1_16.PLAYER));
user.addClientWorld(this.getClass(), new ClientWorld());
user.put(new PlayerSneakStorage());
user.put(new WorldNameTracker());
user.addEntityTracker(this.getClass(), new EntityTrackerBase(user, EntityTypes1_16.PLAYER));
user.put(new PlayerAttributesStorage());
}
@Override
@@ -21,6 +21,7 @@ import com.viaversion.nbt.tag.CompoundTag;
import com.viaversion.viabackwards.api.data.BackwardsMappingData;
import com.viaversion.viaversion.protocols.v1_15_2to1_16.Protocol1_15_2To1_16;
import com.viaversion.viaversion.protocols.v1_15_2to1_16.data.AttributeMappings1_16;
import com.viaversion.viaversion.util.Key;
import java.util.HashMap;
import java.util.Map;
@@ -35,11 +36,11 @@ public class BackwardsMappingData1_16 extends BackwardsMappingData {
protected void loadExtras(final CompoundTag data) {
super.loadExtras(data);
for (Map.Entry<String, String> entry : AttributeMappings1_16.attributeIdentifierMappings().entrySet()) {
attributeMappings.put(entry.getValue(), entry.getKey());
attributeMappings.put(Key.stripMinecraftNamespace(entry.getValue()), entry.getKey());
}
}
public Map<String, String> attributeIdentifierMappings() {
return attributeMappings;
public String mappedAttributeIdentifier(final String identifier) {
return attributeMappings.getOrDefault(identifier, identifier);
}
}
@@ -19,6 +19,7 @@ package com.viaversion.viabackwards.protocol.v1_16to1_15_2.rewriter;
import com.viaversion.viabackwards.api.rewriters.EntityRewriter;
import com.viaversion.viabackwards.protocol.v1_16to1_15_2.Protocol1_16To1_15_2;
import com.viaversion.viabackwards.protocol.v1_16to1_15_2.storage.PlayerAttributesStorage;
import com.viaversion.viabackwards.protocol.v1_16to1_15_2.storage.WorldNameTracker;
import com.viaversion.viabackwards.protocol.v1_16to1_15_2.storage.WolfDataMaskStorage;
import com.viaversion.viaversion.api.Via;
@@ -41,6 +42,7 @@ import com.viaversion.viaversion.libs.gson.JsonElement;
import com.viaversion.viaversion.protocols.v1_14_4to1_15.packet.ClientboundPackets1_15;
import com.viaversion.viaversion.protocols.v1_15_2to1_16.packet.ClientboundPackets1_16;
import com.viaversion.viaversion.util.Key;
import java.util.UUID;
public class EntityPacketRewriter1_16 extends EntityRewriter<ClientboundPackets1_16, Protocol1_16To1_15_2> {
@@ -109,7 +111,7 @@ public class EntityPacketRewriter1_16 extends EntityRewriter<ClientboundPackets1
wrapper.read(Types.BYTE); // Previous gamemode
// Grab client world
ClientWorld clientWorld = wrapper.user().get(ClientWorld.class);
ClientWorld clientWorld = wrapper.user().getClientWorld(Protocol1_16To1_15_2.class);
int dimension = wrapper.get(Types.INT, 0);
// Send a dummy respawn with a different dimension if the world name was different and the same dimension was used
@@ -125,14 +127,26 @@ public class EntityPacketRewriter1_16 extends EntityRewriter<ClientboundPackets1
packet.send(Protocol1_16To1_15_2.class);
}
clientWorld.setEnvironment(dimension);
if (clientWorld.setEnvironment(dimension)) {
tracker(wrapper.user()).clearEntities();
}
wrapper.write(Types.STRING, "default"); // Level type
wrapper.read(Types.BOOLEAN); // Debug
if (wrapper.read(Types.BOOLEAN)) {
wrapper.set(Types.STRING, 0, "flat");
}
wrapper.read(Types.BOOLEAN); // Keep all playerdata
final PlayerAttributesStorage attributes = wrapper.user().get(PlayerAttributesStorage.class);
final boolean keepPlayerAttributes = wrapper.read(Types.BOOLEAN);
if (keepPlayerAttributes) {
// Ensure packet order
wrapper.send(Protocol1_16To1_15_2.class);
wrapper.cancel();
attributes.sendAttributes(wrapper.user(), tracker(wrapper.user()).clientEntityId());
} else {
attributes.clearAttributes();
}
// Finally update the world name
worldNameTracker.setWorldName(nextWorldName);
@@ -156,9 +170,8 @@ public class EntityPacketRewriter1_16 extends EntityRewriter<ClientboundPackets1
map(Types.LONG); // Seed
map(Types.UNSIGNED_BYTE); // Max players
handler(wrapper -> {
ClientWorld clientChunks = wrapper.user().get(ClientWorld.class);
clientChunks.setEnvironment(wrapper.get(Types.INT, 1));
tracker(wrapper.user()).addEntity(wrapper.get(Types.INT, 0), EntityTypes1_16.PLAYER);
ClientWorld clientWorld = wrapper.user().getClientWorld(Protocol1_16To1_15_2.class);
clientWorld.setEnvironment(wrapper.get(Types.INT, 1));
wrapper.write(Types.STRING, "default"); // Level type
@@ -171,6 +184,7 @@ public class EntityPacketRewriter1_16 extends EntityRewriter<ClientboundPackets1
wrapper.set(Types.STRING, 0, "flat");
}
});
handler(playerTrackerHandler());
}
});
@@ -182,19 +196,29 @@ public class EntityPacketRewriter1_16 extends EntityRewriter<ClientboundPackets1
registerSetEntityData(ClientboundPackets1_16.SET_ENTITY_DATA, Types1_16.ENTITY_DATA_LIST, Types1_14.ENTITY_DATA_LIST);
protocol.registerClientbound(ClientboundPackets1_16.UPDATE_ATTRIBUTES, wrapper -> {
wrapper.passthrough(Types.VAR_INT);
int size = wrapper.passthrough(Types.INT);
for (int i = 0; i < size; i++) {
String attributeIdentifier = wrapper.read(Types.STRING);
String oldKey = protocol.getMappingData().attributeIdentifierMappings().get(attributeIdentifier);
wrapper.write(Types.STRING, oldKey != null ? oldKey : Key.stripMinecraftNamespace(attributeIdentifier));
final PlayerAttributesStorage attributes = wrapper.user().get(PlayerAttributesStorage.class);
wrapper.passthrough(Types.DOUBLE);
int modifierSize = wrapper.passthrough(Types.VAR_INT);
for (int j = 0; j < modifierSize; j++) {
wrapper.passthrough(Types.UUID);
wrapper.passthrough(Types.DOUBLE);
wrapper.passthrough(Types.BYTE);
final int entityId = wrapper.passthrough(Types.VAR_INT);
final int size = wrapper.passthrough(Types.INT);
for (int i = 0; i < size; i++) {
final String identifier = Key.stripMinecraftNamespace(wrapper.read(Types.STRING));
final String mappedIdentifier = protocol.getMappingData().mappedAttributeIdentifier(identifier);
wrapper.write(Types.STRING, mappedIdentifier);
final double value = wrapper.passthrough(Types.DOUBLE);
final int count = wrapper.passthrough(Types.VAR_INT);
final var modifiers = new PlayerAttributesStorage.AttributeModifier[count];
for (int j = 0; j < count; j++) {
final UUID uuid = wrapper.passthrough(Types.UUID);
final double amount = wrapper.passthrough(Types.DOUBLE);
final byte operation = wrapper.passthrough(Types.BYTE);
modifiers[j] = new PlayerAttributesStorage.AttributeModifier(uuid, amount, operation);
}
if (entityId == tracker(wrapper.user()).clientEntityId()) {
attributes.addAttribute(mappedIdentifier, new PlayerAttributesStorage.Attribute(value, modifiers));
}
}
});
@@ -230,18 +254,18 @@ public class EntityPacketRewriter1_16 extends EntityRewriter<ClientboundPackets1
@Override
protected void registerRewrites() {
filter().handler((event, meta) -> {
meta.setDataType(Types1_14.ENTITY_DATA_TYPES.byId(meta.dataType().typeId()));
filter().handler((event, data) -> {
data.setDataType(Types1_14.ENTITY_DATA_TYPES.byId(data.dataType().typeId()));
EntityDataType type = meta.dataType();
EntityDataType type = data.dataType();
if (type == Types1_14.ENTITY_DATA_TYPES.itemType) {
meta.setValue(protocol.getItemRewriter().handleItemToClient(event.user(), (Item) meta.getValue()));
data.setValue(protocol.getItemRewriter().handleItemToClient(event.user(), (Item) data.getValue()));
} else if (type == Types1_14.ENTITY_DATA_TYPES.optionalBlockStateType) {
meta.setValue(protocol.getMappingData().getNewBlockStateId((int) meta.getValue()));
data.setValue(protocol.getMappingData().getNewBlockStateId((int) data.getValue()));
} else if (type == Types1_14.ENTITY_DATA_TYPES.particleType) {
rewriteParticle(event.user(), (Particle) meta.getValue());
rewriteParticle(event.user(), (Particle) data.getValue());
} else if (type == Types1_14.ENTITY_DATA_TYPES.optionalComponentType) {
JsonElement text = meta.value();
JsonElement text = data.value();
if (text != null) {
protocol.getComponentRewriter().processText(event.user(), text);
}
@@ -255,9 +279,9 @@ public class EntityPacketRewriter1_16 extends EntityRewriter<ClientboundPackets1
filter().type(EntityTypes1_16.PIGLIN).cancel(17);
filter().type(EntityTypes1_16.PIGLIN).cancel(18);
filter().type(EntityTypes1_16.STRIDER).index(15).handler((event, meta) -> {
boolean baby = meta.value();
meta.setTypeAndValue(Types1_14.ENTITY_DATA_TYPES.varIntType, baby ? 1 : 3);
filter().type(EntityTypes1_16.STRIDER).index(15).handler((event, data) -> {
boolean baby = data.value();
data.setTypeAndValue(Types1_14.ENTITY_DATA_TYPES.varIntType, baby ? 1 : 3);
});
filter().type(EntityTypes1_16.STRIDER).cancel(16);
filter().type(EntityTypes1_16.STRIDER).cancel(17);
@@ -266,29 +290,29 @@ public class EntityPacketRewriter1_16 extends EntityRewriter<ClientboundPackets1
filter().type(EntityTypes1_16.FISHING_BOBBER).cancel(8);
filter().type(EntityTypes1_16.ABSTRACT_ARROW).cancel(8);
filter().type(EntityTypes1_16.ABSTRACT_ARROW).handler((event, meta) -> {
filter().type(EntityTypes1_16.ABSTRACT_ARROW).handler((event, data) -> {
if (event.index() >= 8) {
event.setIndex(event.index() + 1);
}
});
filter().type(EntityTypes1_16.WOLF).index(16).handler((event, meta) -> {
byte mask = meta.value();
StoredEntityData data = tracker(event.user()).entityData(event.entityId());
data.put(new WolfDataMaskStorage(mask));
filter().type(EntityTypes1_16.WOLF).index(16).handler((event, data) -> {
byte mask = data.value();
StoredEntityData entityData = tracker(event.user()).entityData(event.entityId());
entityData.put(new WolfDataMaskStorage(mask));
});
filter().type(EntityTypes1_16.WOLF).index(20).handler((event, meta) -> {
StoredEntityData data = tracker(event.user()).entityDataIfPresent(event.entityId());
filter().type(EntityTypes1_16.WOLF).index(20).handler((event, data) -> {
StoredEntityData entityData = tracker(event.user()).entityDataIfPresent(event.entityId());
byte previousMask = 0;
if (data != null) {
WolfDataMaskStorage wolfData = data.get(WolfDataMaskStorage.class);
if (entityData != null) {
WolfDataMaskStorage wolfData = entityData.get(WolfDataMaskStorage.class);
if (wolfData != null) {
previousMask = wolfData.tameableMask();
}
}
int angerTime = meta.value();
int angerTime = data.value();
byte tameableMask = (byte) (angerTime > 0 ? previousMask | 2 : previousMask & -3);
event.createExtraData(new EntityData(16, Types1_14.ENTITY_DATA_TYPES.byteType, tameableMask));
event.cancel();
@@ -0,0 +1,67 @@
/*
* This file is part of ViaBackwards - https://github.com/ViaVersion/ViaBackwards
* 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.viabackwards.protocol.v1_16to1_15_2.storage;
import com.viaversion.viabackwards.protocol.v1_16to1_15_2.Protocol1_16To1_15_2;
import com.viaversion.viaversion.api.connection.StorableObject;
import com.viaversion.viaversion.api.connection.UserConnection;
import com.viaversion.viaversion.api.protocol.packet.PacketWrapper;
import com.viaversion.viaversion.api.type.Types;
import com.viaversion.viaversion.protocols.v1_14_4to1_15.packet.ClientboundPackets1_15;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;
public final class PlayerAttributesStorage implements StorableObject {
private final Map<String, Attribute> attributes = new HashMap<>();
public void sendAttributes(final UserConnection connection, final int entityId) {
final PacketWrapper updateAttributes = PacketWrapper.create(ClientboundPackets1_15.UPDATE_ATTRIBUTES, connection);
updateAttributes.write(Types.VAR_INT, entityId);
updateAttributes.write(Types.INT, attributes.size());
for (final Map.Entry<String, Attribute> attributeEntry : attributes.entrySet()) {
final Attribute attribute = attributeEntry.getValue();
updateAttributes.write(Types.STRING, attributeEntry.getKey());
updateAttributes.write(Types.DOUBLE, attribute.value());
updateAttributes.write(Types.VAR_INT, attribute.modifiers().length);
for (final AttributeModifier modifier : attribute.modifiers()) {
updateAttributes.write(Types.UUID, modifier.uuid());
updateAttributes.write(Types.DOUBLE, modifier.amount());
updateAttributes.write(Types.BYTE, modifier.operation());
}
}
updateAttributes.send(Protocol1_16To1_15_2.class);
}
public void clearAttributes() {
attributes.clear();
}
public void addAttribute(final String key, final Attribute attribute) {
attributes.put(key, attribute);
}
public record Attribute(double value, AttributeModifier[] modifiers) {
}
public record AttributeModifier(UUID uuid, double amount, byte operation) {
}
}
@@ -102,6 +102,12 @@ public final class Protocol1_17_1To1_17 extends BackwardsProtocol<ClientboundPac
boolean signing = wrapper.read(Types.BOOLEAN);
wrapper.passthrough(Types.VAR_INT); // Slot comes first
if (item == null) {
wrapper.write(Types.VAR_INT, 0); // Pages length
wrapper.write(Types.BOOLEAN, false); // Optional title
return;
}
CompoundTag tag = item.tag();
ListTag<StringTag> pagesTag;
StringTag titleTag = null;
@@ -24,7 +24,6 @@ import com.viaversion.viabackwards.api.rewriters.SoundRewriter;
import com.viaversion.viabackwards.api.rewriters.TranslatableRewriter;
import com.viaversion.viabackwards.protocol.v1_17to1_16_4.rewriter.BlockItemPacketRewriter1_17;
import com.viaversion.viabackwards.protocol.v1_17to1_16_4.rewriter.EntityPacketRewriter1_17;
import com.viaversion.viabackwards.protocol.v1_17to1_16_4.storage.PingRequests;
import com.viaversion.viabackwards.protocol.v1_17to1_16_4.storage.PlayerLastCursorItem;
import com.viaversion.viaversion.api.connection.UserConnection;
import com.viaversion.viaversion.api.minecraft.RegistryType;
@@ -170,8 +169,6 @@ public final class Protocol1_17To1_16_4 extends BackwardsProtocol<ClientboundPac
int id = wrapper.read(Types.INT);
short shortId = (short) id;
if (id == shortId && ViaBackwards.getConfig().handlePingsAsInvAcknowledgements()) {
wrapper.user().get(PingRequests.class).addId(shortId);
// Send inventory acknowledgement to replace ping packet functionality in the unsigned byte range
PacketWrapper acknowledgementPacket = wrapper.create(ClientboundPackets1_16_2.CONTAINER_ACK);
acknowledgementPacket.write(Types.UNSIGNED_BYTE, (short) 0); // Inventory id
@@ -202,10 +199,10 @@ public final class Protocol1_17To1_16_4 extends BackwardsProtocol<ClientboundPac
}
});
//TODO translatables
mergePacket(ClientboundPackets1_17.SET_TITLE_TEXT, ClientboundPackets1_16_2.SET_TITLES, 0);
mergePacket(ClientboundPackets1_17.SET_SUBTITLE_TEXT, ClientboundPackets1_16_2.SET_TITLES, 1);
mergePacket(ClientboundPackets1_17.SET_ACTION_BAR_TEXT, ClientboundPackets1_16_2.SET_TITLES, 2);
rewriteTitlePacket(ClientboundPackets1_17.SET_TITLE_TEXT, 0);
rewriteTitlePacket(ClientboundPackets1_17.SET_SUBTITLE_TEXT, 1);
rewriteTitlePacket(ClientboundPackets1_17.SET_ACTION_BAR_TEXT, 2);
mergePacket(ClientboundPackets1_17.SET_TITLES_ANIMATION, ClientboundPackets1_16_2.SET_TITLES, 3);
registerClientbound(ClientboundPackets1_17.CLEAR_TITLES, ClientboundPackets1_16_2.SET_TITLES, wrapper -> {
if (wrapper.read(Types.BOOLEAN)) {
@@ -221,7 +218,6 @@ public final class Protocol1_17To1_16_4 extends BackwardsProtocol<ClientboundPac
@Override
public void init(UserConnection user) {
addEntityTracker(user, new EntityTrackerBase(user, EntityTypes1_17.PLAYER));
user.put(new PingRequests());
user.put(new PlayerLastCursorItem());
}
@@ -240,6 +236,14 @@ public final class Protocol1_17To1_16_4 extends BackwardsProtocol<ClientboundPac
registerClientbound(newPacketType, oldPacketType, wrapper -> wrapper.write(Types.VAR_INT, type));
}
private void rewriteTitlePacket(ClientboundPackets1_17 newPacketType, int type) {
// Also handles translations in the title
registerClientbound(newPacketType, ClientboundPackets1_16_2.SET_TITLES, wrapper -> {
wrapper.write(Types.VAR_INT, type);
translatableRewriter.processText(wrapper.user(), wrapper.passthrough(Types.COMPONENT));
});
}
@Override
public EntityPacketRewriter1_17 getEntityRewriter() {
return entityRewriter;
@@ -17,27 +17,28 @@
*/
package com.viaversion.viabackwards.protocol.v1_17to1_16_4.rewriter;
import com.viaversion.nbt.tag.CompoundTag;
import com.viaversion.nbt.tag.LongArrayTag;
import com.viaversion.nbt.tag.NumberTag;
import com.viaversion.nbt.tag.Tag;
import com.viaversion.viabackwards.ViaBackwards;
import com.viaversion.viabackwards.api.rewriters.BackwardsItemRewriter;
import com.viaversion.viabackwards.api.rewriters.MapColorRewriter;
import com.viaversion.viabackwards.protocol.v1_17to1_16_4.Protocol1_17To1_16_4;
import com.viaversion.viabackwards.protocol.v1_17to1_16_4.data.MapColorMappings1_16_4;
import com.viaversion.viabackwards.protocol.v1_17to1_16_4.storage.PingRequests;
import com.viaversion.viabackwards.protocol.v1_17to1_16_4.storage.PlayerLastCursorItem;
import com.viaversion.viaversion.api.data.entity.EntityTracker;
import com.viaversion.viaversion.api.minecraft.BlockChangeRecord;
import com.viaversion.viaversion.api.minecraft.chunks.Chunk;
import com.viaversion.viaversion.api.minecraft.chunks.ChunkSection;
import com.viaversion.viaversion.api.minecraft.chunks.DataPalette;
import com.viaversion.viaversion.api.minecraft.chunks.PaletteType;
import com.viaversion.viaversion.api.minecraft.item.Item;
import com.viaversion.viaversion.api.protocol.packet.PacketWrapper;
import com.viaversion.viaversion.api.protocol.remapper.PacketHandlers;
import com.viaversion.viaversion.api.type.Types;
import com.viaversion.viaversion.api.type.types.chunk.ChunkType1_16_2;
import com.viaversion.viaversion.api.type.types.chunk.ChunkType1_17;
import com.viaversion.nbt.tag.CompoundTag;
import com.viaversion.nbt.tag.LongArrayTag;
import com.viaversion.nbt.tag.NumberTag;
import com.viaversion.nbt.tag.Tag;
import com.viaversion.viaversion.protocols.v1_16_1to1_16_2.packet.ClientboundPackets1_16_2;
import com.viaversion.viaversion.protocols.v1_16_1to1_16_2.packet.ServerboundPackets1_16_2;
import com.viaversion.viaversion.protocols.v1_16_4to1_17.packet.ClientboundPackets1_17;
@@ -53,6 +54,8 @@ import java.util.List;
public final class BlockItemPacketRewriter1_17 extends BackwardsItemRewriter<ClientboundPackets1_17, ServerboundPackets1_16_2, Protocol1_17To1_16_4> {
private static final int BEDROCK_BLOCK_STATE = 33;
public BlockItemPacketRewriter1_17(Protocol1_17To1_16_4 protocol) {
super(protocol, Types.ITEM1_13_2, Types.ITEM1_13_2_SHORT_ARRAY);
}
@@ -163,7 +166,7 @@ public final class BlockItemPacketRewriter1_17 extends BackwardsItemRewriter<Cli
short inventoryId = wrapper.read(Types.UNSIGNED_BYTE);
short confirmationId = wrapper.read(Types.SHORT);
boolean accepted = wrapper.read(Types.BOOLEAN);
if (inventoryId == 0 && accepted && wrapper.user().get(PingRequests.class).removeId(confirmationId)) {
if (inventoryId == 0 && accepted) {
PacketWrapper pongPacket = wrapper.create(ServerboundPackets1_17.PONG);
pongPacket.write(Types.INT, (int) confirmationId);
pongPacket.sendToServer(Protocol1_17To1_16_4.class);
@@ -243,13 +246,14 @@ public final class BlockItemPacketRewriter1_17 extends BackwardsItemRewriter<Cli
private void writeLightArrays(PacketWrapper wrapper, BitSet bitMask, int cutBitMask,
int startFromSection, int sectionHeight) {
wrapper.read(Types.VAR_INT); // Length - throw it away
int packetContentsLength = wrapper.read(Types.VAR_INT);
int read = 0;
List<byte[]> light = new ArrayList<>();
// Remove lower bounds
for (int i = 0; i < startFromSection; i++) {
if (bitMask.get(i)) {
read++;
wrapper.read(Types.BYTE_ARRAY_PRIMITIVE);
}
}
@@ -257,6 +261,7 @@ public final class BlockItemPacketRewriter1_17 extends BackwardsItemRewriter<Cli
// Add the important 18 sections
for (int i = 0; i < 18; i++) {
if (isSet(cutBitMask, i)) {
read++;
light.add(wrapper.read(Types.BYTE_ARRAY_PRIMITIVE));
}
}
@@ -264,6 +269,14 @@ public final class BlockItemPacketRewriter1_17 extends BackwardsItemRewriter<Cli
// Remove upper bounds
for (int i = startFromSection + 18; i < sectionHeight + 2; i++) {
if (bitMask.get(i)) {
read++;
wrapper.read(Types.BYTE_ARRAY_PRIMITIVE);
}
}
if (read != packetContentsLength) {
// Read the rest if the server for some reason sends more than are actually consumed
for (int i = read; i < packetContentsLength; i++) {
wrapper.read(Types.BYTE_ARRAY_PRIMITIVE);
}
}
@@ -295,7 +308,11 @@ public final class BlockItemPacketRewriter1_17 extends BackwardsItemRewriter<Cli
BlockChangeRecord[] records = wrapper.passthrough(Types.VAR_LONG_BLOCK_CHANGE_ARRAY);
for (BlockChangeRecord record : records) {
record.setBlockId(protocol.getMappingData().getNewBlockStateId(record.getBlockId()));
if (ViaBackwards.getConfig().bedrockAtY0() && chunkY == 0 && record.getSectionY() == 0) {
record.setBlockId(BEDROCK_BLOCK_STATE);
} else {
record.setBlockId(protocol.getMappingData().getNewBlockStateId(record.getBlockId()));
}
}
});
}
@@ -313,7 +330,11 @@ public final class BlockItemPacketRewriter1_17 extends BackwardsItemRewriter<Cli
return;
}
wrapper.set(Types.VAR_INT, 0, protocol.getMappingData().getNewBlockStateId(wrapper.get(Types.VAR_INT, 0)));
if (ViaBackwards.getConfig().bedrockAtY0() && y == 0) {
wrapper.set(Types.VAR_INT, 0, BEDROCK_BLOCK_STATE);
} else {
wrapper.set(Types.VAR_INT, 0, protocol.getMappingData().getNewBlockStateId(wrapper.get(Types.VAR_INT, 0)));
}
});
}
});
@@ -350,15 +371,32 @@ public final class BlockItemPacketRewriter1_17 extends BackwardsItemRewriter<Cli
blockRewriter.handleChunk(chunk);
if (ViaBackwards.getConfig().bedrockAtY0()) {
final ChunkSection lowestSection = chunk.getSections()[0];
if (lowestSection != null) {
final DataPalette blocks = lowestSection.palette(PaletteType.BLOCKS);
for (int x = 0; x < 16; x++) {
for (int z = 0; z < 16; z++) {
blocks.setIdAt(x, 0, z, BEDROCK_BLOCK_STATE);
}
}
}
}
chunk.getBlockEntities().removeIf(compound -> {
NumberTag tag = compound.getNumberTag("y");
return tag != null && (tag.asInt() < 0 || tag.asInt() > 255);
if (tag == null) {
return false;
}
final int y = tag.asInt();
return y < 0 || y > 255 || (ViaBackwards.getConfig().bedrockAtY0() && y == 0);
});
});
protocol.registerClientbound(ClientboundPackets1_17.BLOCK_ENTITY_DATA, wrapper -> {
int y = wrapper.passthrough(Types.BLOCK_POSITION1_14).y();
if (y < 0 || y > 255) {
if (y < 0 || y > 255 || (ViaBackwards.getConfig().bedrockAtY0() && y == 0)) {
wrapper.cancel();
}
});
@@ -369,7 +407,7 @@ public final class BlockItemPacketRewriter1_17 extends BackwardsItemRewriter<Cli
map(Types.VAR_INT);
handler(wrapper -> {
int y = wrapper.passthrough(Types.BLOCK_POSITION1_14).y();
if (y < 0 || y > 255) {
if (y < 0 || y > 255 || (ViaBackwards.getConfig().bedrockAtY0() && y == 0)) {
wrapper.cancel();
}
});
@@ -22,10 +22,10 @@ import com.viaversion.viabackwards.api.rewriters.EntityRewriter;
import com.viaversion.viabackwards.protocol.v1_17to1_16_4.Protocol1_17To1_16_4;
import com.viaversion.viaversion.api.minecraft.Particle;
import com.viaversion.viaversion.api.minecraft.entities.EntityType;
import com.viaversion.viaversion.api.minecraft.entities.EntityTypes1_16_2;
import com.viaversion.viaversion.api.minecraft.entities.EntityTypes1_17;
import com.viaversion.viaversion.api.minecraft.entitydata.EntityDataType;
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.version.Types1_16;
import com.viaversion.viaversion.api.type.types.version.Types1_17;
@@ -36,7 +36,7 @@ import com.viaversion.viaversion.util.TagUtil;
public final class EntityPacketRewriter1_17 extends EntityRewriter<ClientboundPackets1_17, Protocol1_17To1_16_4> {
private boolean warned;
private boolean warned = ViaBackwards.getConfig().bedrockAtY0() || ViaBackwards.getConfig().suppressEmulationWarnings();
public EntityPacketRewriter1_17(Protocol1_17To1_16_4 protocol) {
super(protocol);
@@ -51,6 +51,29 @@ public final class EntityPacketRewriter1_17 extends EntityRewriter<ClientboundPa
registerTracker(ClientboundPackets1_17.ADD_PLAYER, EntityTypes1_17.PLAYER);
registerSetEntityData(ClientboundPackets1_17.SET_ENTITY_DATA, Types1_17.ENTITY_DATA_LIST, Types1_16.ENTITY_DATA_LIST);
protocol.appendClientbound(ClientboundPackets1_17.ADD_ENTITY, wrapper -> {
final int entityType = wrapper.get(Types.VAR_INT, 1);
if (entityType != EntityTypes1_16_2.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 data = wrapper.get(Types.INT, 0);
float pitch = 0F;
float yaw = 0F;
switch (Math.abs(data % 6)) {
case 0 /* down */ -> pitch = 90F;
case 1 /* up */ -> pitch = -90F;
case 2 /* north */ -> yaw = 180F;
case 4 /* west */ -> yaw = 90F;
case 5 /* east */ -> yaw = 270;
}
wrapper.set(Types.BYTE, 0, (byte) (pitch * 256F / 360F));
wrapper.set(Types.BYTE, 1, (byte) (yaw * 256F / 360F));
});
protocol.registerClientbound(ClientboundPackets1_17.REMOVE_ENTITY, ClientboundPackets1_16_2.REMOVE_ENTITIES, wrapper -> {
int entityId = wrapper.read(Types.VAR_INT);
tracker(wrapper.user()).removeEntity(entityId);
@@ -77,7 +100,7 @@ public final class EntityPacketRewriter1_17 extends EntityRewriter<ClientboundPa
wrapper.set(Types.BYTE, 1, (byte) 0);
}
});
handler(getTrackerHandler(EntityTypes1_17.PLAYER, Types.INT));
handler(getPlayerTrackerHandler());
handler(worldDataTrackerHandler(1));
handler(wrapper -> {
CompoundTag registry = wrapper.get(Types.NAMED_COMPOUND_TAG, 0);
@@ -133,20 +156,25 @@ public final class EntityPacketRewriter1_17 extends EntityRewriter<ClientboundPa
}
});
// TODO translatables
protocol.mergePacket(ClientboundPackets1_17.PLAYER_COMBAT_ENTER, ClientboundPackets1_16_2.PLAYER_COMBAT, 0);
protocol.mergePacket(ClientboundPackets1_17.PLAYER_COMBAT_END, ClientboundPackets1_16_2.PLAYER_COMBAT, 1);
protocol.mergePacket(ClientboundPackets1_17.PLAYER_COMBAT_KILL, ClientboundPackets1_16_2.PLAYER_COMBAT, 2);
protocol.registerClientbound(ClientboundPackets1_17.PLAYER_COMBAT_KILL, ClientboundPackets1_16_2.PLAYER_COMBAT, wrapper -> {
wrapper.write(Types.VAR_INT, 2);
wrapper.passthrough(Types.VAR_INT); // Duration/Player id
wrapper.passthrough(Types.INT); // Killer id
protocol.getComponentRewriter().processText(wrapper.user(), wrapper.passthrough(Types.COMPONENT));
});
}
@Override
protected void registerRewrites() {
filter().handler((event, meta) -> {
meta.setDataType(Types1_16.ENTITY_DATA_TYPES.byId(meta.dataType().typeId()));
filter().handler((event, data) -> {
data.setDataType(Types1_16.ENTITY_DATA_TYPES.byId(data.dataType().typeId()));
EntityDataType type = meta.dataType();
EntityDataType type = data.dataType();
if (type == Types1_16.ENTITY_DATA_TYPES.particleType) {
Particle particle = (Particle) meta.getValue();
Particle particle = (Particle) data.getValue();
if (particle.id() == 16) { // Dust / Dust Transition
// Remove transition target color values 4-6
particle.getArguments().subList(4, 7).clear();
@@ -160,17 +188,17 @@ public final class EntityPacketRewriter1_17 extends EntityRewriter<ClientboundPa
rewriteParticle(event.user(), particle);
} else if (type == Types1_16.ENTITY_DATA_TYPES.poseType) {
// Goat LONG_JUMP added at 6
int pose = meta.value();
int pose = data.value();
if (pose == 6) {
meta.setValue(1); // FALL_FLYING
data.setValue(1); // FALL_FLYING
} else if (pose > 6) {
meta.setValue(pose - 1);
data.setValue(pose - 1);
}
}
});
// Particles have already been handled
registerMetaTypeHandler(Types1_16.ENTITY_DATA_TYPES.itemType, null, Types1_16.ENTITY_DATA_TYPES.optionalBlockStateType, null,
registerEntityDataTypeHandler(Types1_16.ENTITY_DATA_TYPES.itemType, null, Types1_16.ENTITY_DATA_TYPES.optionalBlockStateType, null,
Types1_16.ENTITY_DATA_TYPES.componentType, Types1_16.ENTITY_DATA_TYPES.optionalComponentType);
filter().type(EntityTypes1_17.AXOLOTL).cancel(17);
@@ -206,8 +234,8 @@ public final class EntityPacketRewriter1_17 extends EntityRewriter<ClientboundPa
NumberTag height = tag.getNumberTag("height");
NumberTag logicalHeight = tag.getNumberTag("logical_height");
if (minY.asInt() != 0 || height.asInt() > 256 || logicalHeight.asInt() > 256) {
if (warn && !warned && !ViaBackwards.getConfig().suppressEmulationWarnings()) {
protocol.getLogger().warning("Increased world height is NOT SUPPORTED for 1.16 players and below. They will see a void below y 0 and above 256");
if (warn && !warned) {
protocol.getLogger().warning("Increased world height is NOT SUPPORTED for 1.16 players and below. They will see a void below y 0 and above 256. You can enable the `bedrock-at-y-0` config option to replace the air with a bedrock layer.");
warned = true;
}
@@ -24,7 +24,6 @@ import com.viaversion.viaversion.api.minecraft.entities.EntityType;
import com.viaversion.viaversion.api.minecraft.entities.EntityTypes1_17;
import com.viaversion.viaversion.api.minecraft.entitydata.EntityDataType;
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.version.Types1_17;
import com.viaversion.viaversion.api.type.types.version.Types1_18;
@@ -32,7 +31,6 @@ import com.viaversion.viaversion.protocols.v1_17_1to1_18.packet.ClientboundPacke
import com.viaversion.nbt.tag.CompoundTag;
import com.viaversion.nbt.tag.ListTag;
import com.viaversion.nbt.tag.StringTag;
import com.viaversion.nbt.tag.Tag;
import com.viaversion.viaversion.util.TagUtil;
public final class EntityPacketRewriter1_18 extends EntityRewriter<ClientboundPackets1_18, Protocol1_18To1_17_1> {
@@ -94,15 +92,15 @@ public final class EntityPacketRewriter1_18 extends EntityRewriter<ClientboundPa
@Override
protected void registerRewrites() {
filter().handler((event, meta) -> {
meta.setDataType(Types1_17.ENTITY_DATA_TYPES.byId(meta.dataType().typeId()));
filter().handler((event, data) -> {
data.setDataType(Types1_17.ENTITY_DATA_TYPES.byId(data.dataType().typeId()));
EntityDataType type = meta.dataType();
EntityDataType type = data.dataType();
if (type == Types1_17.ENTITY_DATA_TYPES.particleType) {
Particle particle = meta.value();
Particle particle = data.value();
if (particle.id() == 3) { // Block marker
Particle.ParticleData<?> data = particle.getArguments().remove(0);
int blockState = (int) data.getValue();
Particle.ParticleData<?> value = particle.getArguments().remove(0);
int blockState = (int) value.getValue();
if (blockState == 7786) { // Light block
particle.setId(3);
} else {
@@ -117,7 +115,7 @@ public final class EntityPacketRewriter1_18 extends EntityRewriter<ClientboundPa
});
// Particles have already been handled
registerMetaTypeHandler(Types1_17.ENTITY_DATA_TYPES.itemType, null, null, null,
registerEntityDataTypeHandler(Types1_17.ENTITY_DATA_TYPES.itemType, null, null, null,
Types1_17.ENTITY_DATA_TYPES.componentType, Types1_17.ENTITY_DATA_TYPES.optionalComponentType);
}
@@ -297,7 +297,7 @@ public final class Protocol1_19_1To1_19 extends BackwardsProtocol<ClientboundPac
}
});
registerServerbound(State.LOGIN, ServerboundLoginPackets.HELLO.getId(), ServerboundLoginPackets.HELLO.getId(), new PacketHandlers() {
registerServerbound(State.LOGIN, ServerboundLoginPackets.HELLO, new PacketHandlers() {
@Override
public void register() {
map(Types.STRING); // Name
@@ -315,7 +315,7 @@ public final class Protocol1_19_1To1_19 extends BackwardsProtocol<ClientboundPac
}
});
registerClientbound(State.LOGIN, ClientboundLoginPackets.HELLO.getId(), ClientboundLoginPackets.HELLO.getId(), new PacketHandlers() {
registerClientbound(State.LOGIN, ClientboundLoginPackets.HELLO, new PacketHandlers() {
@Override
public void register() {
map(Types.STRING); // Server id
@@ -331,7 +331,7 @@ public final class Protocol1_19_1To1_19 extends BackwardsProtocol<ClientboundPac
}
});
registerServerbound(State.LOGIN, ServerboundLoginPackets.ENCRYPTION_KEY.getId(), ServerboundLoginPackets.ENCRYPTION_KEY.getId(), new PacketHandlers() {
registerServerbound(State.LOGIN, ServerboundLoginPackets.ENCRYPTION_KEY, new PacketHandlers() {
@Override
public void register() {
map(Types.BYTE_ARRAY_PRIMITIVE); // Key
@@ -352,7 +352,7 @@ public final class Protocol1_19_1To1_19 extends BackwardsProtocol<ClientboundPac
}
});
registerClientbound(State.LOGIN, ClientboundLoginPackets.CUSTOM_QUERY.getId(), ClientboundLoginPackets.CUSTOM_QUERY.getId(), new PacketHandlers() {
registerClientbound(State.LOGIN, ClientboundLoginPackets.CUSTOM_QUERY, new PacketHandlers() {
@Override
public void register() {
map(Types.VAR_INT);
@@ -171,7 +171,7 @@ public final class Protocol1_19_3To1_19_1 extends BackwardsProtocol<ClientboundP
});
// Remove the key once again
registerServerbound(State.LOGIN, ServerboundLoginPackets.HELLO.getId(), ServerboundLoginPackets.HELLO.getId(), new PacketHandlers() {
registerServerbound(State.LOGIN, ServerboundLoginPackets.HELLO, new PacketHandlers() {
@Override
public void register() {
map(Types.STRING); // Name
@@ -183,7 +183,7 @@ public final class Protocol1_19_3To1_19_1 extends BackwardsProtocol<ClientboundP
});
}
});
registerClientbound(State.LOGIN, ClientboundLoginPackets.HELLO.getId(), ClientboundLoginPackets.HELLO.getId(), new PacketHandlers() {
registerClientbound(State.LOGIN, ClientboundLoginPackets.HELLO, new PacketHandlers() {
@Override
public void register() {
map(Types.STRING); // Server id
@@ -198,7 +198,7 @@ public final class Protocol1_19_3To1_19_1 extends BackwardsProtocol<ClientboundP
});
}
});
registerServerbound(State.LOGIN, ServerboundLoginPackets.ENCRYPTION_KEY.getId(), ServerboundLoginPackets.ENCRYPTION_KEY.getId(), new PacketHandlers() {
registerServerbound(State.LOGIN, ServerboundLoginPackets.ENCRYPTION_KEY, new PacketHandlers() {
@Override
public void register() {
map(Types.BYTE_ARRAY_PRIMITIVE); // Keys
@@ -21,7 +21,6 @@ import com.viaversion.viabackwards.api.rewriters.BackwardsItemRewriter;
import com.viaversion.viabackwards.protocol.v1_19_3to1_19_1.Protocol1_19_3To1_19_1;
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.packet.ClientboundPackets1_19_3;
@@ -73,7 +72,7 @@ public final class BlockItemPacketRewriter1_19_3 extends BackwardsItemRewriter<C
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.read(Types.VAR_INT); // Crafting book category
final int ingredients = wrapper.passthrough(Types.VAR_INT);
@@ -84,9 +83,8 @@ public final class BlockItemPacketRewriter1_19_3 extends BackwardsItemRewriter<C
}
}
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.read(Types.VAR_INT); // Crafting book category
@@ -97,12 +95,8 @@ public final class BlockItemPacketRewriter1_19_3 extends BackwardsItemRewriter<C
}
}
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.read(Types.VAR_INT); // Crafting book category
final Item[] items = wrapper.passthrough(Types.ITEM1_13_2_ARRAY); // Ingredients
@@ -112,25 +106,13 @@ public final class BlockItemPacketRewriter1_19_3 extends BackwardsItemRewriter<C
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.read(Types.VAR_INT); // 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.read(Types.VAR_INT); // Crafting book category
default -> recipeRewriter.handleRecipeType(wrapper, type);
}
}
});
@@ -27,7 +27,6 @@ import com.viaversion.viaversion.api.minecraft.entities.EntityTypes1_19_3;
import com.viaversion.viaversion.api.minecraft.signature.storage.ChatSession1_19_3;
import com.viaversion.viaversion.api.protocol.packet.PacketWrapper;
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.BitSetType;
import com.viaversion.viaversion.api.type.types.version.Types1_19;
@@ -230,25 +229,25 @@ public final class EntityPacketRewriter1_19_3 extends EntityRewriter<Clientbound
@Override
public void registerRewrites() {
filter().handler((event, meta) -> {
final int id = meta.dataType().typeId();
filter().handler((event, data) -> {
final int id = data.dataType().typeId();
if (id > 2) {
meta.setDataType(Types1_19.ENTITY_DATA_TYPES.byId(id - 1)); // long added
data.setDataType(Types1_19.ENTITY_DATA_TYPES.byId(id - 1)); // long added
} else if (id != 2) {
meta.setDataType(Types1_19.ENTITY_DATA_TYPES.byId(id));
data.setDataType(Types1_19.ENTITY_DATA_TYPES.byId(id));
}
});
registerMetaTypeHandler(Types1_19.ENTITY_DATA_TYPES.itemType, null, Types1_19.ENTITY_DATA_TYPES.optionalBlockStateType, Types1_19.ENTITY_DATA_TYPES.particleType,
registerEntityDataTypeHandler(Types1_19.ENTITY_DATA_TYPES.itemType, null, Types1_19.ENTITY_DATA_TYPES.optionalBlockStateType, Types1_19.ENTITY_DATA_TYPES.particleType,
Types1_19.ENTITY_DATA_TYPES.componentType, Types1_19.ENTITY_DATA_TYPES.optionalComponentType);
registerBlockStateHandler(EntityTypes1_19_3.ABSTRACT_MINECART, 11);
filter().dataType(Types1_19.ENTITY_DATA_TYPES.poseType).handler((event, meta) -> {
filter().dataType(Types1_19.ENTITY_DATA_TYPES.poseType).handler((event, data) -> {
// Sitting pose added
final int pose = meta.value();
final int pose = data.value();
if (pose == 10) {
meta.setValue(0); // Standing
data.setValue(0); // Standing
} else if (pose > 10) {
meta.setValue(pose - 1);
data.setValue(pose - 1);
}
});
@@ -78,21 +78,14 @@ public final class Protocol1_19_4To1_19_3 extends BackwardsProtocol<ClientboundP
@Override
public void handleArgument(final PacketWrapper wrapper, final String argumentType) {
switch (argumentType) {
case "minecraft:heightmap":
wrapper.write(Types.VAR_INT, 0);
break;
case "minecraft:time":
wrapper.read(Types.INT); // Minimum
break;
case "minecraft:resource":
case "minecraft:resource_or_tag":
case "minecraft:heightmap" -> wrapper.write(Types.VAR_INT, 0);
case "minecraft:time" -> wrapper.read(Types.INT); // Minimum
case "minecraft:resource", "minecraft:resource_or_tag" -> {
final String resource = wrapper.read(Types.STRING);
// Replace damage types with... something
wrapper.write(Types.STRING, resource.equals("minecraft:damage_type") ? "minecraft:mob_effect" : resource);
break;
default:
super.handleArgument(wrapper, argumentType);
break;
}
default -> super.handleArgument(wrapper, argumentType);
}
}
}.registerDeclareCommands1_19(ClientboundPackets1_19_4.COMMANDS);
@@ -17,6 +17,9 @@
*/
package com.viaversion.viabackwards.protocol.v1_19_4to1_19_3.rewriter;
import com.viaversion.nbt.tag.CompoundTag;
import com.viaversion.nbt.tag.ListTag;
import com.viaversion.nbt.tag.NumberTag;
import com.viaversion.viabackwards.api.entities.storage.EntityReplacement;
import com.viaversion.viabackwards.api.rewriters.EntityRewriter;
import com.viaversion.viabackwards.protocol.v1_19_4to1_19_3.Protocol1_19_4To1_19_3;
@@ -30,9 +33,6 @@ import com.viaversion.viaversion.api.type.types.version.Types1_19_4;
import com.viaversion.viaversion.libs.gson.JsonElement;
import com.viaversion.viaversion.protocols.v1_19_1to1_19_3.packet.ClientboundPackets1_19_3;
import com.viaversion.viaversion.protocols.v1_19_3to1_19_4.packet.ClientboundPackets1_19_4;
import com.viaversion.nbt.tag.CompoundTag;
import com.viaversion.nbt.tag.ListTag;
import com.viaversion.nbt.tag.NumberTag;
import com.viaversion.viaversion.util.TagUtil;
public final class EntityPacketRewriter1_19_4 extends EntityRewriter<ClientboundPackets1_19_4, Protocol1_19_4To1_19_3> {
@@ -127,43 +127,50 @@ public final class EntityPacketRewriter1_19_4 extends EntityRewriter<Clientbound
handler(worldDataTrackerHandlerByKey());
}
});
protocol.registerClientbound(ClientboundPackets1_19_4.UPDATE_MOB_EFFECT, wrapper -> {
wrapper.passthrough(Types.VAR_INT); // Entity id
wrapper.passthrough(Types.VAR_INT); // Effect id
wrapper.passthrough(Types.BYTE); // Amplifier
// Handle inifinite duration. Use a value the client still accepts without bugging out the display while still being practically infinite
final int duration = wrapper.read(Types.VAR_INT);
wrapper.write(Types.VAR_INT, duration == -1 ? 999999 : duration);
});
}
@Override
public void registerRewrites() {
filter().handler((event, meta) -> {
int id = meta.dataType().typeId();
filter().handler((event, data) -> {
int id = data.dataType().typeId();
if (id >= 25) { // Sniffer state, Vector3f, Quaternion types
return;
} else if (id >= 15) { // Optional block state - just map down to block state
id--;
}
meta.setDataType(Types1_19_3.ENTITY_DATA_TYPES.byId(id));
data.setDataType(Types1_19_3.ENTITY_DATA_TYPES.byId(id));
});
registerMetaTypeHandler(Types1_19_3.ENTITY_DATA_TYPES.itemType, null, Types1_19_3.ENTITY_DATA_TYPES.optionalBlockStateType, Types1_19_3.ENTITY_DATA_TYPES.particleType,
registerEntityDataTypeHandler(Types1_19_3.ENTITY_DATA_TYPES.itemType, null, Types1_19_3.ENTITY_DATA_TYPES.optionalBlockStateType, Types1_19_3.ENTITY_DATA_TYPES.particleType,
Types1_19_3.ENTITY_DATA_TYPES.componentType, Types1_19_3.ENTITY_DATA_TYPES.optionalComponentType);
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
meta.setValue(boatType - 1);
data.setValue(boatType - 1);
}
});
filter().type(EntityTypes1_19_4.TEXT_DISPLAY).index(22).handler(((event, meta) -> {
filter().type(EntityTypes1_19_4.TEXT_DISPLAY).index(22).handler(((event, data) -> {
// Send as custom display name
event.setIndex(2);
meta.setDataType(Types1_19_3.ENTITY_DATA_TYPES.optionalComponentType);
data.setDataType(Types1_19_3.ENTITY_DATA_TYPES.optionalComponentType);
event.createExtraData(new EntityData(3, Types1_19_3.ENTITY_DATA_TYPES.booleanType, true)); // Show custom name
final JsonElement element = meta.value();
protocol.getComponentRewriter().processText(event.user(), element);
}));
filter().type(EntityTypes1_19_4.DISPLAY).handler((event, meta) -> {
filter().type(EntityTypes1_19_4.DISPLAY).handler((event, data) -> {
// TODO Maybe spawn an extra entity to ride the armor stand for blocks and items
// Remove a large heap of display metadata
// Remove a large heap of display entity data
if (event.index() > 7) {
event.cancel();
}
@@ -183,16 +190,16 @@ public final class EntityPacketRewriter1_19_4 extends EntityRewriter<Clientbound
public void onMappingDataLoaded() {
mapTypes();
final EntityReplacement.MetaCreator displayMetaCreator = storage -> {
final EntityReplacement.EntityDataCreator displayDataCreator = storage -> {
storage.add(new EntityData(0, Types1_19_3.ENTITY_DATA_TYPES.byteType, (byte) 0x20)); // Invisible
storage.add(new EntityData(5, Types1_19_3.ENTITY_DATA_TYPES.booleanType, true)); // No gravity
storage.add(new EntityData(15, Types1_19_3.ENTITY_DATA_TYPES.byteType, (byte) (0x01 | 0x10))); // Small marker
};
mapEntityTypeWithData(EntityTypes1_19_4.TEXT_DISPLAY, EntityTypes1_19_4.ARMOR_STAND).spawnMetadata(displayMetaCreator);
mapEntityTypeWithData(EntityTypes1_19_4.ITEM_DISPLAY, EntityTypes1_19_4.ARMOR_STAND).spawnMetadata(displayMetaCreator);
mapEntityTypeWithData(EntityTypes1_19_4.BLOCK_DISPLAY, EntityTypes1_19_4.ARMOR_STAND).spawnMetadata(displayMetaCreator);
mapEntityTypeWithData(EntityTypes1_19_4.TEXT_DISPLAY, EntityTypes1_19_4.ARMOR_STAND).spawnEntityData(displayDataCreator);
mapEntityTypeWithData(EntityTypes1_19_4.ITEM_DISPLAY, EntityTypes1_19_4.ARMOR_STAND).spawnEntityData(displayDataCreator);
mapEntityTypeWithData(EntityTypes1_19_4.BLOCK_DISPLAY, EntityTypes1_19_4.ARMOR_STAND).spawnEntityData(displayDataCreator);
mapEntityTypeWithData(EntityTypes1_19_4.INTERACTION, EntityTypes1_19_4.ARMOR_STAND).spawnMetadata(displayMetaCreator); // Not much we can do about this one
mapEntityTypeWithData(EntityTypes1_19_4.INTERACTION, EntityTypes1_19_4.ARMOR_STAND).spawnEntityData(displayDataCreator); // Not much we can do about this one
mapEntityTypeWithData(EntityTypes1_19_4.SNIFFER, EntityTypes1_19_4.RAVAGER).jsonName();
}
@@ -291,7 +291,7 @@ public final class Protocol1_19To1_18_2 extends BackwardsProtocol<ClientboundPac
});
// Login changes
registerClientbound(State.LOGIN, ClientboundLoginPackets.GAME_PROFILE.getId(), ClientboundLoginPackets.GAME_PROFILE.getId(), new PacketHandlers() {
registerClientbound(State.LOGIN, ClientboundLoginPackets.GAME_PROFILE, new PacketHandlers() {
@Override
public void register() {
map(Types.UUID); // UUID
@@ -307,7 +307,7 @@ public final class Protocol1_19To1_18_2 extends BackwardsProtocol<ClientboundPac
}
});
registerClientbound(State.LOGIN, ClientboundLoginPackets.HELLO.getId(), ClientboundLoginPackets.HELLO.getId(), new PacketHandlers() {
registerClientbound(State.LOGIN, ClientboundLoginPackets.HELLO, new PacketHandlers() {
@Override
public void register() {
map(Types.STRING); // Server id
@@ -319,7 +319,7 @@ public final class Protocol1_19To1_18_2 extends BackwardsProtocol<ClientboundPac
});
}
});
registerServerbound(State.LOGIN, ServerboundLoginPackets.HELLO.getId(), ServerboundLoginPackets.HELLO.getId(), new PacketHandlers() {
registerServerbound(State.LOGIN, ServerboundLoginPackets.HELLO, new PacketHandlers() {
@Override
public void register() {
map(Types.STRING); // Name
@@ -330,7 +330,7 @@ public final class Protocol1_19To1_18_2 extends BackwardsProtocol<ClientboundPac
}
});
registerServerbound(State.LOGIN, ServerboundLoginPackets.ENCRYPTION_KEY.getId(), ServerboundLoginPackets.ENCRYPTION_KEY.getId(), new PacketHandlers() {
registerServerbound(State.LOGIN, ServerboundLoginPackets.ENCRYPTION_KEY, new PacketHandlers() {
@Override
public void register() {
map(Types.BYTE_ARRAY_PRIMITIVE); // Public key
@@ -17,6 +17,7 @@
*/
package com.viaversion.viabackwards.protocol.v1_19to1_18_2.data;
import com.viaversion.viabackwards.ViaBackwards;
import com.viaversion.viabackwards.api.data.BackwardsMappingData;
import com.viaversion.viabackwards.api.data.BackwardsMappingDataLoader;
import com.viaversion.viaversion.libs.fastutil.ints.Int2ObjectMap;
@@ -29,6 +30,8 @@ import org.checkerframework.checker.nullness.qual.Nullable;
public final class BackwardsMappingData1_19 extends BackwardsMappingData {
private final boolean sculkShriekerToCryingObsidian = ViaBackwards.getConfig().sculkShriekerToCryingObsidian();
private final Int2ObjectMap<CompoundTag> defaultChatTypes = new Int2ObjectOpenHashMap<>();
public BackwardsMappingData1_19() {
@@ -39,6 +42,13 @@ public final class BackwardsMappingData1_19 extends BackwardsMappingData {
protected void loadExtras(final CompoundTag data) {
super.loadExtras(data);
if (sculkShriekerToCryingObsidian) {
blockMappings.setNewId(850, 750);
for (int i = 18900; i <= 18907; i++) {
blockStateMappings.setNewId(i, 16082);
}
}
final ListTag<CompoundTag> chatTypes = BackwardsMappingDataLoader.INSTANCE.loadNBT("chat-types-1.19.1.nbt").getListTag("values", CompoundTag.class);
for (final CompoundTag chatType : chatTypes) {
final NumberTag idTag = chatType.getNumberTag("id");
@@ -46,6 +56,14 @@ public final class BackwardsMappingData1_19 extends BackwardsMappingData {
}
}
@Override
public int getNewItemId(final int id) {
if (sculkShriekerToCryingObsidian && id == 329) {
return 1065;
}
return super.getNewItemId(id);
}
public @Nullable CompoundTag chatType(final int id) {
return defaultChatTypes.get(id);
}
@@ -19,6 +19,7 @@ package com.viaversion.viabackwards.protocol.v1_19to1_18_2.rewriter;
import com.viaversion.nbt.tag.CompoundTag;
import com.viaversion.viabackwards.api.rewriters.BackwardsItemRewriter;
import com.viaversion.viabackwards.api.rewriters.EnchantmentRewriter;
import com.viaversion.viabackwards.protocol.v1_19to1_18_2.Protocol1_19To1_18_2;
import com.viaversion.viabackwards.protocol.v1_19to1_18_2.storage.LastDeathPosition;
import com.viaversion.viaversion.api.connection.UserConnection;
@@ -42,6 +43,8 @@ import com.viaversion.viaversion.util.MathUtil;
public final class BlockItemPacketRewriter1_19 extends BackwardsItemRewriter<ClientboundPackets1_19, ServerboundPackets1_17, Protocol1_19To1_18_2> {
private final EnchantmentRewriter enchantmentRewriter = new EnchantmentRewriter(this);
public BlockItemPacketRewriter1_19(final Protocol1_19To1_18_2 protocol) {
super(protocol, Types.ITEM1_13_2, Types.ITEM1_13_2_ARRAY);
}
@@ -208,6 +211,11 @@ public final class BlockItemPacketRewriter1_19 extends BackwardsItemRewriter<Cli
});
}
@Override
protected void registerRewrites() {
enchantmentRewriter.registerEnchantment("minecraft:swift_sneak", "§7Swift Sneak");
}
@Override
public Item handleItemToClient(final UserConnection connection, final Item item) {
if (item == null) return null;
@@ -232,6 +240,8 @@ public final class BlockItemPacketRewriter1_19 extends BackwardsItemRewriter<Cli
lodestonePosTag.putInt("X", position.x());
lodestonePosTag.putInt("Y", position.y());
lodestonePosTag.putInt("Z", position.z());
enchantmentRewriter.handleToClient(item);
return item;
}
@@ -252,6 +262,8 @@ public final class BlockItemPacketRewriter1_19 extends BackwardsItemRewriter<Cli
item.setTag(null);
}
}
enchantmentRewriter.handleToServer(item);
return item;
}
}
@@ -84,7 +84,7 @@ public final class EntityPacketRewriter1_19 extends EntityRewriter<ClientboundPa
return;
} else if (entityType == EntityTypes1_19.PAINTING) {
wrapper.cancel();
// The entity has been tracked, now we wait for the metadata packet
// The entity has been tracked, now we wait for the entity data packet
final int entityId = wrapper.get(Types.VAR_INT, 0);
final StoredEntityData entityData = tracker(wrapper.user()).entityData(entityId);
final BlockPosition position = new BlockPosition(wrapper.get(Types.DOUBLE, 0).intValue(), wrapper.get(Types.DOUBLE, 1).intValue(), wrapper.get(Types.DOUBLE, 2).intValue());
@@ -202,7 +202,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
handler(wrapper -> {
final GlobalBlockPosition lastDeathPosition = wrapper.read(Types.OPTIONAL_GLOBAL_POSITION);
if (lastDeathPosition != null) {
@@ -247,14 +247,14 @@ public final class EntityPacketRewriter1_19 extends EntityRewriter<ClientboundPa
@Override
protected void registerRewrites() {
filter().handler((event, meta) -> {
if (meta.dataType().typeId() <= Types1_18.ENTITY_DATA_TYPES.poseType.typeId()) {
meta.setDataType(Types1_18.ENTITY_DATA_TYPES.byId(meta.dataType().typeId()));
filter().handler((event, data) -> {
if (data.dataType().typeId() <= Types1_18.ENTITY_DATA_TYPES.poseType.typeId()) {
data.setDataType(Types1_18.ENTITY_DATA_TYPES.byId(data.dataType().typeId()));
}
final EntityDataType type = meta.dataType();
final EntityDataType type = data.dataType();
if (type == Types1_18.ENTITY_DATA_TYPES.particleType) {
final Particle particle = (Particle) meta.getValue();
final Particle particle = (Particle) data.getValue();
final ParticleMappings particleMappings = protocol.getMappingData().getParticleMappings();
if (particle.id() == particleMappings.id("sculk_charge")) {
//TODO
@@ -272,19 +272,19 @@ public final class EntityPacketRewriter1_19 extends EntityRewriter<ClientboundPa
rewriteParticle(event.user(), particle);
} else if (type == Types1_18.ENTITY_DATA_TYPES.poseType) {
final int pose = meta.value();
final int pose = data.value();
if (pose >= 8) {
// Croaking, using_tongue, roaring, sniffing, emerging, digging -> standing -> standing
meta.setValue(0);
data.setValue(0);
}
}
});
registerMetaTypeHandler(Types1_18.ENTITY_DATA_TYPES.itemType, null, Types1_18.ENTITY_DATA_TYPES.optionalBlockStateType, null,
registerEntityDataTypeHandler(Types1_18.ENTITY_DATA_TYPES.itemType, null, Types1_18.ENTITY_DATA_TYPES.optionalBlockStateType, null,
Types1_18.ENTITY_DATA_TYPES.componentType, Types1_18.ENTITY_DATA_TYPES.optionalComponentType);
registerBlockStateHandler(EntityTypes1_19.ABSTRACT_MINECART, 11);
filter().type(EntityTypes1_19.PAINTING).index(8).handler((event, meta) -> {
filter().type(EntityTypes1_19.PAINTING).index(8).handler((event, data) -> {
event.cancel();
final StoredEntityData entityData = tracker(event.user()).entityDataIfPresent(event.entityId());
@@ -293,7 +293,7 @@ public final class EntityPacketRewriter1_19 extends EntityRewriter<ClientboundPa
final PacketWrapper packet = PacketWrapper.create(ClientboundPackets1_18.ADD_PAINTING, event.user());
packet.write(Types.VAR_INT, storedPainting.entityId());
packet.write(Types.UUID, storedPainting.uuid());
packet.write(Types.VAR_INT, meta.value());
packet.write(Types.VAR_INT, data.value());
packet.write(Types.BLOCK_POSITION1_14, storedPainting.position());
packet.write(Types.BYTE, storedPainting.direction());
try {
@@ -305,7 +305,7 @@ public final class EntityPacketRewriter1_19 extends EntityRewriter<ClientboundPa
}
});
filter().type(EntityTypes1_19.CAT).index(19).handler((event, meta) -> meta.setDataType(Types1_18.ENTITY_DATA_TYPES.varIntType));
filter().type(EntityTypes1_19.CAT).index(19).handler((event, data) -> data.setDataType(Types1_18.ENTITY_DATA_TYPES.varIntType));
filter().type(EntityTypes1_19.FROG).cancel(16); // Age
filter().type(EntityTypes1_19.FROG).cancel(17); // Variant
@@ -76,7 +76,7 @@ public final class Protocol1_20_2To1_20 extends BackwardsProtocol<ClientboundPac
wrapper.write(Types.BYTE, (byte) slot);
});
registerClientbound(State.LOGIN, ClientboundLoginPackets.GAME_PROFILE.getId(), ClientboundLoginPackets.GAME_PROFILE.getId(), wrapper -> {
registerClientbound(State.LOGIN, ClientboundLoginPackets.GAME_PROFILE, wrapper -> {
// We can't set the internal state to configuration here as protocols down the line will expect the state to be play
// Add this *before* sending the ack since the server might immediately answer
wrapper.user().put(new ConfigurationPacketStorage());
@@ -88,7 +88,7 @@ public final class Protocol1_20_2To1_20 extends BackwardsProtocol<ClientboundPac
wrapper.create(ServerboundLoginPackets.LOGIN_ACKNOWLEDGED).scheduleSendToServer(Protocol1_20_2To1_20.class);
});
registerClientbound(State.CONFIGURATION, ClientboundConfigurationPackets1_20_2.FINISH_CONFIGURATION.getId(), ClientboundConfigurationPackets1_20_2.FINISH_CONFIGURATION.getId(), wrapper -> {
registerClientbound(State.CONFIGURATION, ClientboundConfigurationPackets1_20_2.FINISH_CONFIGURATION, wrapper -> {
wrapper.cancel();
wrapper.user().getProtocolInfo().setServerState(State.PLAY);
wrapper.user().get(ConfigurationPacketStorage.class).setFinished(true);
@@ -97,7 +97,7 @@ public final class Protocol1_20_2To1_20 extends BackwardsProtocol<ClientboundPac
wrapper.user().getProtocolInfo().setClientState(State.PLAY);
});
registerServerbound(State.LOGIN, ServerboundLoginPackets.HELLO.getId(), ServerboundLoginPackets.HELLO.getId(), wrapper -> {
registerServerbound(State.LOGIN, ServerboundLoginPackets.HELLO, wrapper -> {
wrapper.passthrough(Types.STRING); // Name
// TODO Bad
@@ -155,7 +155,7 @@ public final class Protocol1_20_2To1_20 extends BackwardsProtocol<ClientboundPac
wrapper.cancel();
});
registerClientbound(State.CONFIGURATION, ClientboundConfigurationPackets1_20_2.UPDATE_TAGS.getId(), -1, wrapper -> {
tagRewriter.getGenericHandler().handle(wrapper);
tagRewriter.handleGeneric(wrapper);
wrapper.user().get(ConfigurationPacketStorage.class).addRawPacket(wrapper, ClientboundPackets1_19_4.UPDATE_TAGS);
wrapper.cancel();
});
@@ -229,4 +229,4 @@ public final class Protocol1_20_2To1_20 extends BackwardsProtocol<ClientboundPac
public TagRewriter<ClientboundPackets1_20_2> getTagRewriter() {
return tagRewriter;
}
}
}
@@ -21,7 +21,7 @@ import com.viaversion.viaversion.api.platform.providers.Provider;
public class AdvancementCriteriaProvider implements Provider {
public String[] getCriteria(final String advacementKey) {
public String[] getCriteria(final String advancementKey) {
return new String[0];
}
}
@@ -26,7 +26,6 @@ import com.viaversion.viabackwards.protocol.v1_20_2to1_20.Protocol1_20_2To1_20;
import com.viaversion.viabackwards.protocol.v1_20_2to1_20.provider.AdvancementCriteriaProvider;
import com.viaversion.viaversion.api.Via;
import com.viaversion.viaversion.api.connection.UserConnection;
import com.viaversion.viaversion.api.data.ParticleMappings;
import com.viaversion.viaversion.api.data.entity.EntityTracker;
import com.viaversion.viaversion.api.minecraft.ChunkPosition;
import com.viaversion.viaversion.api.minecraft.blockentity.BlockEntity;
@@ -54,7 +53,7 @@ import org.checkerframework.checker.nullness.qual.Nullable;
public final class BlockItemPacketRewriter1_20_2 extends BackwardsItemRewriter<ClientboundPackets1_20_2, ServerboundPackets1_19_4, Protocol1_20_2To1_20> {
public BlockItemPacketRewriter1_20_2(final Protocol1_20_2To1_20 protocol) {
super(protocol, Types.ITEM1_20_2, Types.ITEM1_20_2_ARRAY);
super(protocol, Types.ITEM1_20_2, Types.ITEM1_20_2_ARRAY, Types.ITEM1_13_2, Types.ITEM1_13_2_ARRAY);
}
@Override
@@ -65,6 +64,13 @@ public final class BlockItemPacketRewriter1_20_2 extends BackwardsItemRewriter<C
blockRewriter.registerSectionBlocksUpdate1_20(ClientboundPackets1_20_2.SECTION_BLOCKS_UPDATE);
blockRewriter.registerLevelEvent(ClientboundPackets1_20_2.LEVEL_EVENT, 1010, 2001);
registerSetContent1_17_1(ClientboundPackets1_20_2.CONTAINER_SET_CONTENT);
registerSetSlot1_17_1(ClientboundPackets1_20_2.CONTAINER_SET_SLOT);
registerContainerClick1_17_1(ServerboundPackets1_19_4.CONTAINER_CLICK);
registerMerchantOffers1_19(ClientboundPackets1_20_2.MERCHANT_OFFERS);
registerSetCreativeModeSlot(ServerboundPackets1_19_4.SET_CREATIVE_MODE_SLOT);
registerLevelParticles1_19(ClientboundPackets1_20_2.LEVEL_PARTICLES);
protocol.cancelClientbound(ClientboundPackets1_20_2.CHUNK_BATCH_START);
protocol.registerClientbound(ClientboundPackets1_20_2.CHUNK_BATCH_FINISHED, null, wrapper -> {
wrapper.cancel();
@@ -145,32 +151,6 @@ public final class BlockItemPacketRewriter1_20_2 extends BackwardsItemRewriter<C
}
});
// Replace the NBT type everywhere
protocol.registerClientbound(ClientboundPackets1_20_2.CONTAINER_SET_CONTENT, new PacketHandlers() {
@Override
public void register() {
map(Types.UNSIGNED_BYTE); // Window id
map(Types.VAR_INT); // State id
handler(wrapper -> {
final Item[] items = wrapper.read(Types.ITEM1_20_2_ARRAY);
for (final Item item : items) {
handleItemToClient(wrapper.user(), item);
}
wrapper.write(Types.ITEM1_13_2_ARRAY, items);
wrapper.write(Types.ITEM1_13_2, handleItemToClient(wrapper.user(), wrapper.read(Types.ITEM1_20_2))); // Carried item
});
}
});
protocol.registerClientbound(ClientboundPackets1_20_2.CONTAINER_SET_SLOT, new PacketHandlers() {
@Override
public void register() {
map(Types.UNSIGNED_BYTE); // Window id
map(Types.VAR_INT); // State id
map(Types.SHORT); // Slot id
handler(wrapper -> wrapper.write(Types.ITEM1_13_2, handleItemToClient(wrapper.user(), wrapper.read(Types.ITEM1_20_2))));
}
});
protocol.registerClientbound(ClientboundPackets1_20_2.UPDATE_ADVANCEMENTS, wrapper -> {
wrapper.passthrough(Types.BOOLEAN); // Reset/clear
final int size = wrapper.passthrough(Types.VAR_INT);
@@ -216,159 +196,18 @@ public final class BlockItemPacketRewriter1_20_2 extends BackwardsItemRewriter<C
});
}
});
protocol.registerServerbound(ServerboundPackets1_19_4.CONTAINER_CLICK, new PacketHandlers() {
@Override
public void register() {
map(Types.UNSIGNED_BYTE); // Window Id
map(Types.VAR_INT); // State id
map(Types.SHORT); // Slot
map(Types.BYTE); // Button
map(Types.VAR_INT); // Mode
handler(wrapper -> {
// Affected items
final int length = wrapper.passthrough(Types.VAR_INT);
for (int i = 0; i < length; i++) {
wrapper.passthrough(Types.SHORT); // Slot
wrapper.write(Types.ITEM1_20_2, handleItemToServer(wrapper.user(), wrapper.read(Types.ITEM1_13_2)));
}
// Carried item
wrapper.write(Types.ITEM1_20_2, handleItemToServer(wrapper.user(), wrapper.read(Types.ITEM1_13_2)));
});
}
});
protocol.registerClientbound(ClientboundPackets1_20_2.MERCHANT_OFFERS, wrapper -> {
wrapper.passthrough(Types.VAR_INT); // Container id
final int size = wrapper.passthrough(Types.VAR_INT);
for (int i = 0; i < size; i++) {
wrapper.write(Types.ITEM1_13_2, handleItemToClient(wrapper.user(), wrapper.read(Types.ITEM1_20_2))); // Input
wrapper.write(Types.ITEM1_13_2, handleItemToClient(wrapper.user(), wrapper.read(Types.ITEM1_20_2))); // Output
wrapper.write(Types.ITEM1_13_2, handleItemToClient(wrapper.user(), wrapper.read(Types.ITEM1_20_2))); // Second Item
wrapper.passthrough(Types.BOOLEAN); // Trade disabled
wrapper.passthrough(Types.INT); // Number of tools uses
wrapper.passthrough(Types.INT); // Maximum number of trade uses
wrapper.passthrough(Types.INT); // XP
wrapper.passthrough(Types.INT); // Special price
wrapper.passthrough(Types.FLOAT); // Price multiplier
wrapper.passthrough(Types.INT); // Demand
}
});
protocol.registerServerbound(ServerboundPackets1_19_4.SET_CREATIVE_MODE_SLOT, new PacketHandlers() {
@Override
public void register() {
map(Types.SHORT); // 0 - Slot
handler(wrapper -> wrapper.write(Types.ITEM1_20_2, handleItemToServer(wrapper.user(), wrapper.read(Types.ITEM1_13_2)))); // 1 - Clicked Item
}
});
protocol.registerClientbound(ClientboundPackets1_20_2.LEVEL_PARTICLES, new PacketHandlers() {
@Override
public void register() {
map(Types.VAR_INT); // 0 - Particle ID
map(Types.BOOLEAN); // 1 - Long Distance
map(Types.DOUBLE); // 2 - X
map(Types.DOUBLE); // 3 - Y
map(Types.DOUBLE); // 4 - Z
map(Types.FLOAT); // 5 - Offset X
map(Types.FLOAT); // 6 - Offset Y
map(Types.FLOAT); // 7 - Offset Z
map(Types.FLOAT); // 8 - Particle Data
map(Types.INT); // 9 - Particle Count
handler(wrapper -> {
final int id = wrapper.get(Types.VAR_INT, 0);
final ParticleMappings mappings = Protocol1_20_2To1_20.MAPPINGS.getParticleMappings();
if (mappings.isBlockParticle(id)) {
final int data = wrapper.read(Types.VAR_INT);
wrapper.write(Types.VAR_INT, protocol.getMappingData().getNewBlockStateId(data));
} else if (mappings.isItemParticle(id)) {
wrapper.write(Types.ITEM1_13_2, handleItemToClient(wrapper.user(), wrapper.read(Types.ITEM1_20_2)));
}
});
}
});
new RecipeRewriter1_20_2<>(protocol) {
@Override
public void handleCraftingShapeless(final PacketWrapper wrapper) {
wrapper.passthrough(Types.STRING); // Group
wrapper.passthrough(Types.VAR_INT); // Crafting book category
handleIngredients(wrapper);
final Item result = wrapper.read(itemType());
rewrite(wrapper.user(), result);
wrapper.write(Types.ITEM1_13_2, result);
protected Type<Item> mappedItemType() {
return BlockItemPacketRewriter1_20_2.this.mappedItemType();
}
@Override
public void handleSmelting(final PacketWrapper wrapper) {
wrapper.passthrough(Types.STRING); // Group
wrapper.passthrough(Types.VAR_INT); // Crafting book category
handleIngredient(wrapper);
final Item result = wrapper.read(itemType());
rewrite(wrapper.user(), result);
wrapper.write(Types.ITEM1_13_2, result);
wrapper.passthrough(Types.FLOAT); // EXP
wrapper.passthrough(Types.VAR_INT); // Cooking time
protected Type<Item[]> mappedItemArrayType() {
return BlockItemPacketRewriter1_20_2.this.mappedItemArrayType();
}
@Override
public void handleCraftingShaped(final PacketWrapper wrapper) {
final int ingredients = wrapper.passthrough(Types.VAR_INT) * wrapper.passthrough(Types.VAR_INT);
wrapper.passthrough(Types.STRING); // Group
wrapper.passthrough(Types.VAR_INT); // Crafting book category
for (int i = 0; i < ingredients; i++) {
handleIngredient(wrapper);
}
final Item result = wrapper.read(itemType());
rewrite(wrapper.user(), result);
wrapper.write(Types.ITEM1_13_2, result);
wrapper.passthrough(Types.BOOLEAN); // Show notification
}
@Override
public void handleStonecutting(final PacketWrapper wrapper) {
wrapper.passthrough(Types.STRING); // Group
handleIngredient(wrapper);
final Item result = wrapper.read(itemType());
rewrite(wrapper.user(), result);
wrapper.write(Types.ITEM1_13_2, result);
}
@Override
public void handleSmithing(final PacketWrapper wrapper) {
handleIngredient(wrapper); // Base
handleIngredient(wrapper); // Addition
final Item result = wrapper.read(itemType());
rewrite(wrapper.user(), result);
wrapper.write(Types.ITEM1_13_2, result);
}
@Override
public void handleSmithingTransform(final PacketWrapper wrapper) {
handleIngredient(wrapper); // Template
handleIngredient(wrapper); // Base
handleIngredient(wrapper); // Additions
final Item result = wrapper.read(itemType());
rewrite(wrapper.user(), result);
wrapper.write(Types.ITEM1_13_2, result);
}
@Override
protected void handleIngredient(final PacketWrapper wrapper) {
final Item[] items = wrapper.read(itemArrayType());
wrapper.write(Types.ITEM1_13_2_ARRAY, items);
for (final Item item : items) {
rewrite(wrapper.user(), item);
}
}
}.register(ClientboundPackets1_20_2.UPDATE_RECIPES);
}
@@ -108,7 +108,7 @@ public final class EntityPacketRewriter1_20_2 extends EntityRewriter<Clientbound
@Override
public void register() {
handler(wrapper -> {
final ConfigurationPacketStorage configurationPacketStorage = wrapper.user().remove(ConfigurationPacketStorage.class);
final ConfigurationPacketStorage configurationPacketStorage = wrapper.user().get(ConfigurationPacketStorage.class);
wrapper.passthrough(Types.INT); // Entity id
wrapper.passthrough(Types.BOOLEAN); // Hardcore
@@ -198,8 +198,8 @@ public final class EntityPacketRewriter1_20_2 extends EntityRewriter<Clientbound
@Override
protected void registerRewrites() {
filter().handler((event, meta) -> meta.setDataType(Types1_20.ENTITY_DATA_TYPES.byId(meta.dataType().typeId())));
registerMetaTypeHandler(Types1_20.ENTITY_DATA_TYPES.itemType, Types1_20.ENTITY_DATA_TYPES.blockStateType, Types1_20.ENTITY_DATA_TYPES.optionalBlockStateType, Types1_20.ENTITY_DATA_TYPES.particleType, null, null);
filter().handler((event, data) -> data.setDataType(Types1_20.ENTITY_DATA_TYPES.byId(data.dataType().typeId())));
registerEntityDataTypeHandler(Types1_20.ENTITY_DATA_TYPES.itemType, Types1_20.ENTITY_DATA_TYPES.blockStateType, Types1_20.ENTITY_DATA_TYPES.optionalBlockStateType, Types1_20.ENTITY_DATA_TYPES.particleType, null, null);
registerBlockStateHandler(EntityTypes1_19_4.ABSTRACT_MINECART, 11);
filter().type(EntityTypes1_19_4.DISPLAY).removeIndex(10);
@@ -18,13 +18,13 @@
package com.viaversion.viabackwards.protocol.v1_20_2to1_20.storage;
import com.google.common.base.Preconditions;
import com.viaversion.nbt.tag.CompoundTag;
import com.viaversion.viabackwards.protocol.v1_20_2to1_20.Protocol1_20_2To1_20;
import com.viaversion.viaversion.api.connection.StorableObject;
import com.viaversion.viaversion.api.connection.UserConnection;
import com.viaversion.viaversion.api.protocol.packet.PacketType;
import com.viaversion.viaversion.api.protocol.packet.PacketWrapper;
import com.viaversion.viaversion.protocols.v1_19_3to1_19_4.packet.ClientboundPackets1_19_4;
import com.viaversion.nbt.tag.CompoundTag;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import java.util.ArrayList;
@@ -77,17 +77,21 @@ public final class ConfigurationPacketStorage implements StorableObject {
public void sendQueuedPackets(final UserConnection connection) {
// Send resource pack at the end
List<QueuedPacket> packets = rawPackets;
if (resourcePack != null) {
rawPackets.add(resourcePack);
packets = new ArrayList<>(rawPackets);
packets.add(resourcePack);
resourcePack = null;
}
for (final QueuedPacket queuedPacket : rawPackets) {
for (final QueuedPacket queuedPacket : packets) {
// Don't clear the list or use the original buffer, we might need them later if a server skips subsequent config phases
final ByteBuf buf = queuedPacket.buf().copy();
try {
final PacketWrapper packet = PacketWrapper.create(queuedPacket.packetType(), queuedPacket.buf(), connection);
final PacketWrapper packet = PacketWrapper.create(queuedPacket.packetType(), buf, connection);
packet.send(Protocol1_20_2To1_20.class);
} finally {
queuedPacket.buf().release();
buf.release();
}
}
}
@@ -27,7 +27,6 @@ import com.viaversion.viaversion.api.minecraft.entities.EntityTypes1_20_3;
import com.viaversion.viaversion.api.minecraft.entitydata.EntityDataType;
import com.viaversion.viaversion.api.protocol.remapper.PacketHandler;
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.version.Types1_20_2;
import com.viaversion.viaversion.api.type.types.version.Types1_20_3;
@@ -44,9 +43,9 @@ public final class EntityPacketRewriter1_20_3 extends EntityRewriter<Clientbound
@Override
public void registerPackets() {
registerSpawnTracker(ClientboundPackets1_20_3.ADD_ENTITY);
registerSetEntityData(ClientboundPackets1_20_3.SET_ENTITY_DATA, Types1_20_3.ENTITY_DATA_LIST, Types1_20_2.ENTITY_DATA_LIST);
registerRemoveEntities(ClientboundPackets1_20_3.REMOVE_ENTITIES);
registerTrackerWithData1_19(ClientboundPackets1_20_3.ADD_ENTITY, EntityTypes1_20_3.FALLING_BLOCK);
protocol.registerClientbound(ClientboundConfigurationPackets1_20_3.REGISTRY_DATA, new PacketHandlers() {
@Override
@@ -97,16 +96,16 @@ 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_3.ENTITY_DATA_TYPES.componentType) {
meta.setTypeAndValue(Types1_20_2.ENTITY_DATA_TYPES.componentType, ComponentUtil.tagToJson(meta.value()));
data.setTypeAndValue(Types1_20_2.ENTITY_DATA_TYPES.componentType, ComponentUtil.tagToJson(data.value()));
return;
} else if (type == Types1_20_3.ENTITY_DATA_TYPES.optionalComponentType) {
meta.setTypeAndValue(Types1_20_2.ENTITY_DATA_TYPES.optionalComponentType, ComponentUtil.tagToJson(meta.value()));
data.setTypeAndValue(Types1_20_2.ENTITY_DATA_TYPES.optionalComponentType, ComponentUtil.tagToJson(data.value()));
return;
} else if (type == Types1_20_3.ENTITY_DATA_TYPES.particleType) {
final Particle particle = (Particle) meta.getValue();
final Particle particle = (Particle) data.getValue();
final ParticleMappings particleMappings = protocol.getMappingData().getParticleMappings();
if (particle.id() == particleMappings.id("vibration")) {
// Change the type of the position source type argument
@@ -118,16 +117,16 @@ public final class EntityPacketRewriter1_20_3 extends EntityRewriter<Clientbound
}
}
} else if (type == Types1_20_3.ENTITY_DATA_TYPES.poseType) {
final int pose = meta.value();
final int pose = data.value();
if (pose >= 15) {
event.cancel();
}
}
meta.setDataType(Types1_20_2.ENTITY_DATA_TYPES.byId(type.typeId()));
data.setDataType(Types1_20_2.ENTITY_DATA_TYPES.byId(type.typeId()));
});
registerMetaTypeHandler(
registerEntityDataTypeHandler(
Types1_20_2.ENTITY_DATA_TYPES.itemType,
Types1_20_2.ENTITY_DATA_TYPES.blockStateType,
Types1_20_2.ENTITY_DATA_TYPES.optionalBlockStateType,
@@ -145,11 +144,11 @@ public final class EntityPacketRewriter1_20_3 extends EntityRewriter<Clientbound
mapTypes();
mapEntityTypeWithData(EntityTypes1_20_3.BREEZE, EntityTypes1_20_3.BLAZE).jsonName();
mapEntityTypeWithData(EntityTypes1_20_3.WIND_CHARGE, EntityTypes1_20_3.LLAMA_SPIT).jsonName();
mapEntityTypeWithData(EntityTypes1_20_3.WIND_CHARGE, EntityTypes1_20_3.SHULKER_BULLET).jsonName();
}
@Override
public EntityType typeFromId(final int type) {
return EntityTypes1_20_3.getTypeFromId(type);
}
}
}
@@ -29,6 +29,7 @@ import com.viaversion.viabackwards.protocol.v1_20_5to1_20_3.storage.RegistryData
import com.viaversion.viabackwards.protocol.v1_20_5to1_20_3.storage.SecureChatStorage;
import com.viaversion.viaversion.api.Via;
import com.viaversion.viaversion.api.connection.UserConnection;
import com.viaversion.viaversion.api.minecraft.RegistryType;
import com.viaversion.viaversion.api.minecraft.entities.EntityTypes1_20_5;
import com.viaversion.viaversion.api.platform.providers.ViaProviders;
import com.viaversion.viaversion.api.protocol.packet.PacketWrapper;
@@ -53,6 +54,7 @@ import com.viaversion.viaversion.protocols.v1_20_3to1_20_5.packet.ClientboundPac
import com.viaversion.viaversion.protocols.v1_20_3to1_20_5.packet.ServerboundConfigurationPackets1_20_5;
import com.viaversion.viaversion.protocols.v1_20_3to1_20_5.packet.ServerboundPacket1_20_5;
import com.viaversion.viaversion.protocols.v1_20_3to1_20_5.packet.ServerboundPackets1_20_5;
import com.viaversion.viaversion.protocols.v1_20_3to1_20_5.storage.ArmorTrimStorage;
import com.viaversion.viaversion.protocols.v1_20_3to1_20_5.storage.BannerPatternStorage;
import com.viaversion.viaversion.protocols.v1_20to1_20_2.packet.ServerboundConfigurationPackets1_20_2;
import com.viaversion.viaversion.rewriter.ComponentRewriter.ReadType;
@@ -77,11 +79,12 @@ public final class Protocol1_20_5To1_20_3 extends BackwardsProtocol<ClientboundP
protected void registerPackets() {
super.registerPackets();
tagRewriter.addEmptyTag(RegistryType.ITEM, "minecraft:axolotl_tempt_items");
tagRewriter.registerGeneric(ClientboundPackets1_20_5.UPDATE_TAGS);
registerClientbound(ClientboundConfigurationPackets1_20_5.UPDATE_TAGS, wrapper -> {
// Send off registry data first, needed for tags
sendRegistryData(wrapper.user());
tagRewriter.getGenericHandler().handle(wrapper);
tagRewriter.handleGeneric(wrapper);
});
registerClientbound(ClientboundConfigurationPackets1_20_5.FINISH_CONFIGURATION, wrapper -> {
@@ -121,19 +124,8 @@ public final class Protocol1_20_5To1_20_3 extends BackwardsProtocol<ClientboundP
wrapper.write(Types.BOOLEAN, wrapper.user().get(SecureChatStorage.class).enforcesSecureChat());
});
registerServerbound(ServerboundPackets1_20_3.CHAT_COMMAND, ServerboundPackets1_20_5.CHAT_COMMAND_SIGNED, wrapper -> {
final String command = wrapper.passthrough(Types.STRING); // Command
wrapper.passthrough(Types.LONG); // Timestamp
wrapper.passthrough(Types.LONG); // Salt
final int signatures = wrapper.passthrough(Types.VAR_INT); // Signatures
if (signatures == 0) {
wrapper.cancel();
final PacketWrapper chatCommand = wrapper.create(ServerboundPackets1_20_5.CHAT_COMMAND);
chatCommand.write(Types.STRING, command);
chatCommand.sendToServer(Protocol1_20_5To1_20_3.class);
}
});
// Always write as signed, even if there is 0 signatures attached, else the validation chain gets broken
registerServerbound(ServerboundPackets1_20_3.CHAT_COMMAND, ServerboundPackets1_20_5.CHAT_COMMAND_SIGNED);
registerClientbound(State.LOGIN, ClientboundLoginPackets.COOKIE_REQUEST.getId(), -1, wrapper -> handleCookieRequest(wrapper, ServerboundLoginPackets.COOKIE_RESPONSE));
cancelClientbound(ClientboundConfigurationPackets1_20_5.RESET_CHAT); // Old clients already reset chat when entering the configuration phase
@@ -231,6 +223,7 @@ public final class Protocol1_20_5To1_20_3 extends BackwardsProtocol<ClientboundP
user.put(new CookieStorage());
user.put(new RegistryDataStorage());
user.put(new BannerPatternStorage());
user.put(new ArmorTrimStorage());
}
@Override
@@ -272,4 +265,4 @@ public final class Protocol1_20_5To1_20_3 extends BackwardsProtocol<ClientboundP
packetTypeMap(unmappedServerboundPacketType, ServerboundPackets1_20_3.class, ServerboundConfigurationPackets1_20_2.class)
);
}
}
}
@@ -40,7 +40,6 @@ 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;
import com.viaversion.viaversion.api.type.types.version.Types1_20_5;
import com.viaversion.viaversion.libs.fastutil.ints.Int2IntFunction;
import com.viaversion.viaversion.protocols.v1_20_2to1_20_3.packet.ServerboundPacket1_20_3;
import com.viaversion.viaversion.protocols.v1_20_2to1_20_3.packet.ServerboundPackets1_20_3;
import com.viaversion.viaversion.protocols.v1_20_2to1_20_3.rewriter.RecipeRewriter1_20_3;
@@ -142,8 +141,10 @@ public final class BlockItemPacketRewriter1_20_5 extends BackwardsStructuredItem
wrapper.passthrough(Types.FLOAT); // Knockback Z
wrapper.passthrough(Types.VAR_INT); // Block interaction type
protocol.getEntityRewriter().rewriteParticle(wrapper, Types1_20_5.PARTICLE, Types1_20_3.PARTICLE); // Small explosion particle
protocol.getEntityRewriter().rewriteParticle(wrapper, Types1_20_5.PARTICLE, Types1_20_3.PARTICLE); // Large explosion particle
final Particle smallExplosionParticle = wrapper.passthroughAndMap(Types1_20_5.PARTICLE, Types1_20_3.PARTICLE);
final Particle largeExplosionParticle = wrapper.passthroughAndMap(Types1_20_5.PARTICLE, Types1_20_3.PARTICLE);
rewriteParticle(wrapper.user(), smallExplosionParticle);
rewriteParticle(wrapper.user(), largeExplosionParticle);
final Holder<SoundEvent> soundEventHolder = wrapper.read(Types.SOUND_EVENT);
if (soundEventHolder.isDirect()) {
@@ -186,6 +187,23 @@ public final class BlockItemPacketRewriter1_20_5 extends BackwardsStructuredItem
}
});
protocol.registerClientbound(ClientboundPackets1_20_5.MAP_ITEM_DATA, wrapper -> {
wrapper.passthrough(Types.VAR_INT); // Map id
wrapper.passthrough(Types.BYTE); // Scale
wrapper.passthrough(Types.BOOLEAN); // Locked
if (wrapper.passthrough(Types.BOOLEAN)) {
final int icons = wrapper.passthrough(Types.VAR_INT);
for (int i = 0; i < icons; i++) {
final int decorationType = wrapper.read(Types.VAR_INT);
wrapper.write(Types.VAR_INT, decorationType == 34 ? 32 : decorationType); // Trial champer to jungle temple
wrapper.passthrough(Types.BYTE); // X
wrapper.passthrough(Types.BYTE); // Y
wrapper.passthrough(Types.BYTE); // Rotation
wrapper.passthrough(Types.OPTIONAL_TAG); // Display name
}
}
});
final RecipeRewriter1_20_3<ClientboundPacket1_20_5> recipeRewriter = new RecipeRewriter1_20_3<>(protocol);
protocol.registerClientbound(ClientboundPackets1_20_5.UPDATE_RECIPES, wrapper -> {
final int size = wrapper.passthrough(Types.VAR_INT);
@@ -335,18 +353,36 @@ public final class BlockItemPacketRewriter1_20_5 extends BackwardsStructuredItem
return null;
}
final StructuredDataContainer data = item.dataContainer();
item.dataContainer().setIdLookup(protocol, true);
enchantmentRewriter.handleToClient(item);
super.handleItemToClient(connection, item);
// Text components since we skip the usual rewrite method
updateComponent(connection, item, StructuredDataKey.ITEM_NAME, "item_name");
updateComponent(connection, item, StructuredDataKey.CUSTOM_NAME, "custom_name");
final Tag[] lore = data.get(StructuredDataKey.LORE);
if (lore != null) {
for (final Tag tag : lore) {
protocol.getComponentRewriter().processTag(connection, tag);
}
}
// In 1.20.6, some items have default values which are not written into the components
final StructuredDataContainer data = item.dataContainer();
if (item.identifier() == 1105 && !data.contains(StructuredDataKey.FIREWORKS)) {
if (item.identifier() == 1105 && !data.has(StructuredDataKey.FIREWORKS)) {
data.set(StructuredDataKey.FIREWORKS, new Fireworks(1, new FireworkExplosion[0]));
}
final CompoundTag customData = data.get(StructuredDataKey.CUSTOM_DATA);
final Item oldItem = vvProtocol.getItemRewriter().toOldItem(connection, item, DATA_CONVERTER);
if (customData != null) {
// We later don't know which tags are custom data and which are not because the VV conversion
// keeps converted data, so we backup the original custom data and restore it later
oldItem.tag().put(nbtTagName(), customData.copy());
}
if (oldItem.tag() != null && oldItem.tag().isEmpty()) {
// Improve item equality checks by removing empty tags
oldItem.setTag(null);
@@ -355,7 +391,7 @@ public final class BlockItemPacketRewriter1_20_5 extends BackwardsStructuredItem
}
@Override
protected void updateItemComponents(final UserConnection connection, final StructuredDataContainer container, final ItemHandler itemHandler, @Nullable final Int2IntFunction idRewriter, @Nullable final Int2IntFunction blockIdRewriter) {
protected void updateItemDataComponents(final UserConnection connection, final Item item, final boolean clientbound) {
// Items and data within components are handled in this protocol
}
@@ -369,9 +405,14 @@ public final class BlockItemPacketRewriter1_20_5 extends BackwardsStructuredItem
// Convert to structured item first
final Item structuredItem = vvProtocol.getItemRewriter().toStructuredItem(connection, item);
if (item.tag() != null && item.tag().get(nbtTagName()) instanceof final CompoundTag tag) {
// Set original custom data from backup
structuredItem.dataContainer().set(StructuredDataKey.CUSTOM_DATA, tag);
}
structuredItem.dataContainer().setIdLookup(protocol, false);
enchantmentRewriter.handleToServer(structuredItem);
return super.handleItemToServer(connection, structuredItem);
}
}
}
@@ -30,7 +30,6 @@ import com.viaversion.viabackwards.protocol.v1_20_5to1_20_3.storage.RegistryData
import com.viaversion.viabackwards.protocol.v1_20_5to1_20_3.storage.SecureChatStorage;
import com.viaversion.viaversion.api.connection.UserConnection;
import com.viaversion.viaversion.api.data.entity.DimensionData;
import com.viaversion.viaversion.api.data.entity.EntityTracker;
import com.viaversion.viaversion.api.minecraft.Particle;
import com.viaversion.viaversion.api.minecraft.RegistryEntry;
import com.viaversion.viaversion.api.minecraft.entities.EntityType;
@@ -49,6 +48,7 @@ import com.viaversion.viaversion.protocols.v1_20_3to1_20_5.data.Attributes1_20_5
import com.viaversion.viaversion.protocols.v1_20_3to1_20_5.packet.ClientboundConfigurationPackets1_20_5;
import com.viaversion.viaversion.protocols.v1_20_3to1_20_5.packet.ClientboundPacket1_20_5;
import com.viaversion.viaversion.protocols.v1_20_3to1_20_5.packet.ClientboundPackets1_20_5;
import com.viaversion.viaversion.protocols.v1_20_3to1_20_5.storage.ArmorTrimStorage;
import com.viaversion.viaversion.protocols.v1_20_3to1_20_5.storage.BannerPatternStorage;
import com.viaversion.viaversion.util.Key;
import com.viaversion.viaversion.util.KeyMappings;
@@ -72,15 +72,17 @@ public final class EntityPacketRewriter1_20_5 extends EntityRewriter<Clientbound
protocol.registerClientbound(ClientboundPackets1_20_5.SET_EQUIPMENT, wrapper -> {
final int entityId = wrapper.passthrough(Types.VAR_INT); // Entity id
final EntityType type = tracker(wrapper.user()).entityType(entityId);
byte slot;
do {
slot = wrapper.read(Types.BYTE);
final Item item = protocol.getItemRewriter().handleItemToClient(wrapper.user(), wrapper.read(Types1_20_5.ITEM));
final int rawSlot = slot & 0x7F;
if (rawSlot == 6) {
final boolean lastSlot = (slot & 0xFFFFFF80) == 0;
slot = (byte) (lastSlot ? 4 : 4 | 0xFFFFFF80); // Map body slot index to chest slot index for horses, also wolves
if (slot == 6) {
final EntityTracker tracker = wrapper.user().getEntityTracker(Protocol1_20_5To1_20_3.class);
slot = 4; // Map body slot index to chest slot index for horses
final EntityType type = tracker.entityType(entityId);
if (type != null && type.isOrHasParent(EntityTypes1_20_5.LLAMA)) {
// Cancel equipment and set correct entity data instead
wrapper.cancel();
@@ -90,7 +92,7 @@ public final class EntityPacketRewriter1_20_5 extends EntityRewriter<Clientbound
wrapper.write(Types.BYTE, slot);
wrapper.write(Types.ITEM1_20_2, item);
} while (slot < 0);
} while ((slot & 0xFFFFFF80) != 0);
});
protocol.registerClientbound(ClientboundPackets1_20_5.HORSE_SCREEN_OPEN, wrapper -> {
@@ -112,16 +114,21 @@ public final class EntityPacketRewriter1_20_5 extends EntityRewriter<Clientbound
final RegistryDataStorage registryDataStorage = wrapper.user().get(RegistryDataStorage.class);
final RegistryEntry[] entries = wrapper.read(Types.REGISTRY_ENTRY_ARRAY);
// Track trim patterns and armor trims for conversion in items
if (registryKey.equals("banner_pattern")) {
// Track banner pattern and material ids for conversion in items
final String[] keys = new String[entries.length];
for (int i = 0; i < entries.length; i++) {
keys[i] = Key.stripMinecraftNamespace(entries[i].key());
}
wrapper.user().get(BannerPatternStorage.class).setBannerPatterns(new KeyMappings(keys));
// Don't send it
wrapper.user().get(BannerPatternStorage.class).setBannerPatterns(toMappings(entries));
return;
}
final boolean isTrimPattern = registryKey.equals("trim_pattern");
if (isTrimPattern) {
wrapper.user().get(ArmorTrimStorage.class).setTrimPatterns(toMappings(entries));
} else if (registryKey.equals("trim_material")) {
wrapper.user().get(ArmorTrimStorage.class).setTrimMaterials(toMappings(entries));
}
// Track biome and dimension data
if (registryKey.equals("worldgen/biome")) {
tracker(wrapper.user()).setBiomesSent(entries.length);
@@ -158,7 +165,6 @@ public final class EntityPacketRewriter1_20_5 extends EntityRewriter<Clientbound
}
// Write to old format
final boolean isTrimPattern = registryKey.equals("trim_pattern");
final CompoundTag registryTag = new CompoundTag();
final ListTag<CompoundTag> entriesTag = new ListTag<>(CompoundTag.class);
registryTag.putString("type", registryKey);
@@ -293,6 +299,14 @@ public final class EntityPacketRewriter1_20_5 extends EntityRewriter<Clientbound
});
}
private KeyMappings toMappings(final RegistryEntry[] entries) {
final String[] keys = new String[entries.length];
for (int i = 0; i < entries.length; i++) {
keys[i] = Key.stripMinecraftNamespace(entries[i].key());
}
return new KeyMappings(keys);
}
private void updateParticleFormat(final CompoundTag options, final String particleType) {
if ("block".equals(particleType) || "block_marker".equals(particleType) || "falling_dust".equals(particleType) || "dust_pillar".equals(particleType)) {
Tag blockState = options.remove("block_state");
@@ -372,34 +386,43 @@ public final class EntityPacketRewriter1_20_5 extends EntityRewriter<Clientbound
color = item.identifier() - 445;
}
}
final List<EntityData> metadataList = new ArrayList<>();
metadataList.add(new EntityData(20, Types1_20_3.ENTITY_DATA_TYPES.varIntType, color));
setEntityData.write(Types1_20_3.ENTITY_DATA_LIST, metadataList);
final List<EntityData> entityDataList = new ArrayList<>();
entityDataList.add(new EntityData(20, Types1_20_3.ENTITY_DATA_TYPES.varIntType, color));
setEntityData.write(Types1_20_3.ENTITY_DATA_LIST, entityDataList);
setEntityData.send(Protocol1_20_5To1_20_3.class);
}
@Override
protected void registerRewrites() {
filter().mapDataType(typeId -> {
filter().handler((event, data) -> {
final int typeId = data.dataType().typeId();
if (typeId == Types1_20_5.ENTITY_DATA_TYPES.particlesType.typeId()) {
// Handled with living entity
return Types1_20_5.ENTITY_DATA_TYPES.particlesType;
final Particle[] particles = data.value();
int color = 0;
for (final Particle particle : particles) {
if (particle.id() == protocol.getMappingData().getParticleMappings().id("entity_effect")) {
// Remove color argument, use one of them for the ambient particle color
color = particle.<Integer>removeArgument(0).getValue();
}
}
data.setTypeAndValue(Types1_20_3.ENTITY_DATA_TYPES.varIntType, removeAlpha(color));
return;
}
int id = typeId;
if (typeId >= Types1_20_5.ENTITY_DATA_TYPES.wolfVariantType.typeId()) {
if (typeId >= Types1_20_5.ENTITY_DATA_TYPES.armadilloState.typeId()) {
id--;
}
if (typeId >= Types1_20_5.ENTITY_DATA_TYPES.armadilloState.typeId()) {
if (typeId >= Types1_20_5.ENTITY_DATA_TYPES.wolfVariantType.typeId()) {
id--;
}
if (typeId >= Types1_20_5.ENTITY_DATA_TYPES.particlesType.typeId()) {
id--;
}
return Types1_20_3.ENTITY_DATA_TYPES.byId(id);
data.setDataType(Types1_20_3.ENTITY_DATA_TYPES.byId(id));
});
registerMetaTypeHandler1_20_3(
registerEntityDataTypeHandler1_20_3(
Types1_20_3.ENTITY_DATA_TYPES.itemType,
Types1_20_3.ENTITY_DATA_TYPES.blockStateType,
Types1_20_3.ENTITY_DATA_TYPES.optionalBlockStateType,
@@ -410,23 +433,11 @@ public final class EntityPacketRewriter1_20_5 extends EntityRewriter<Clientbound
);
registerBlockStateHandler(EntityTypes1_20_5.ABSTRACT_MINECART, 11);
filter().type(EntityTypes1_20_5.LIVING_ENTITY).index(10).handler((event, meta) -> {
final Particle[] particles = meta.value();
int color = 0;
for (final Particle particle : particles) {
if (particle.id() == protocol.getMappingData().getParticleMappings().id("entity_effect")) {
// Remove color argument, use one of them for the ambient particle color
color = particle.<Integer>removeArgument(0).getValue();
}
}
meta.setTypeAndValue(Types1_20_3.ENTITY_DATA_TYPES.varIntType, removeAlpha(color));
});
filter().type(EntityTypes1_20_5.AREA_EFFECT_CLOUD).addIndex(9); // Color
filter().type(EntityTypes1_20_5.AREA_EFFECT_CLOUD).index(11).handler((event, meta) -> {
final Particle particle = meta.value();
filter().type(EntityTypes1_20_5.AREA_EFFECT_CLOUD).index(11).handler((event, data) -> {
final Particle particle = data.value();
if (particle.id() == protocol.getMappingData().getParticleMappings().mappedId("entity_effect")) {
// Move color to its own metadata
// Move color to its own entity data
final int color = particle.<Integer>removeArgument(0).getValue();
event.createExtraData(new EntityData(9, Types1_20_3.ENTITY_DATA_TYPES.varIntType, removeAlpha(color)));
}
@@ -452,4 +463,4 @@ public final class EntityPacketRewriter1_20_5 extends EntityRewriter<Clientbound
public EntityType typeFromId(final int type) {
return EntityTypes1_20_5.getTypeFromId(type);
}
}
}
@@ -34,7 +34,7 @@ import com.viaversion.viaversion.protocols.v1_19_3to1_19_4.packet.ServerboundPac
import com.viaversion.viaversion.rewriter.ComponentRewriter;
import com.viaversion.viaversion.rewriter.StatisticsRewriter;
import com.viaversion.viaversion.rewriter.TagRewriter;
import java.util.Arrays;
import com.viaversion.viaversion.util.ArrayUtil;
public final class Protocol1_20To1_19_4 extends BackwardsProtocol<ClientboundPackets1_19_4, ClientboundPackets1_19_4, ServerboundPackets1_19_4, ServerboundPackets1_19_4> {
@@ -62,7 +62,6 @@ public final class Protocol1_20To1_19_4 extends BackwardsProtocol<ClientboundPac
new StatisticsRewriter<>(this).register(ClientboundPackets1_19_4.AWARD_STATS);
//TODO open window
translatableRewriter.registerComponentPacket(ClientboundPackets1_19_4.SET_ACTION_BAR_TEXT);
translatableRewriter.registerComponentPacket(ClientboundPackets1_19_4.SET_TITLE_TEXT);
translatableRewriter.registerComponentPacket(ClientboundPackets1_19_4.SET_SUBTITLE_TEXT);
@@ -75,10 +74,7 @@ public final class Protocol1_20To1_19_4 extends BackwardsProtocol<ClientboundPac
registerClientbound(ClientboundPackets1_19_4.UPDATE_ENABLED_FEATURES, wrapper -> {
String[] enabledFeatures = wrapper.read(Types.STRING_ARRAY);
final int length = enabledFeatures.length;
enabledFeatures = Arrays.copyOf(enabledFeatures, length + 1);
enabledFeatures[length] = "minecraft:update_1_20";
wrapper.write(Types.STRING_ARRAY, enabledFeatures);
wrapper.write(Types.STRING_ARRAY, ArrayUtil.add(enabledFeatures, "minecraft:update_1_20"));
});
registerClientbound(ClientboundPackets1_19_4.PLAYER_COMBAT_END, wrapper -> {
@@ -86,7 +82,7 @@ public final class Protocol1_20To1_19_4 extends BackwardsProtocol<ClientboundPac
wrapper.write(Types.INT, -1); // Killer ID - unused (who knows for how long?)
});
registerClientbound(ClientboundPackets1_19_4.PLAYER_COMBAT_KILL, wrapper -> {
wrapper.passthrough(Types.VAR_INT); // Duration
wrapper.passthrough(Types.VAR_INT); // Player ID
wrapper.write(Types.INT, -1); // Killer ID - unused (who knows for how long?)
translatableRewriter.processText(wrapper.user(), wrapper.passthrough(Types.COMPONENT));
});
@@ -26,7 +26,6 @@ import com.viaversion.viaversion.api.minecraft.BlockPosition;
import com.viaversion.viaversion.api.minecraft.blockentity.BlockEntity;
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.nbt.tag.CompoundTag;
@@ -86,7 +85,13 @@ public final class BlockItemPacketRewriter1_20 extends BackwardsItemRewriter<Cli
}
});
registerOpenScreen(ClientboundPackets1_19_4.OPEN_SCREEN);
protocol.registerClientbound(ClientboundPackets1_19_4.OPEN_SCREEN, wrapper -> {
wrapper.passthrough(Types.VAR_INT); // Container id
handleMenuType(wrapper);
protocol.getComponentRewriter().passthroughAndProcess(wrapper);
});
registerCooldown(ClientboundPackets1_19_4.COOLDOWN);
registerSetContent1_17_1(ClientboundPackets1_19_4.CONTAINER_SET_CONTENT);
registerSetSlot1_17_1(ClientboundPackets1_19_4.CONTAINER_SET_SLOT);
@@ -25,7 +25,6 @@ import com.viaversion.viaversion.api.minecraft.entities.EntityType;
import com.viaversion.viaversion.api.minecraft.entities.EntityTypes1_19_4;
import com.viaversion.viaversion.api.minecraft.entitydata.EntityData;
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.version.Types1_19_4;
import com.viaversion.viaversion.api.type.types.version.Types1_20;
@@ -33,7 +32,6 @@ import com.viaversion.viaversion.protocols.v1_19_3to1_19_4.packet.ClientboundPac
import com.viaversion.nbt.tag.CompoundTag;
import com.viaversion.nbt.tag.ListTag;
import com.viaversion.nbt.tag.StringTag;
import com.viaversion.nbt.tag.Tag;
import com.viaversion.viaversion.util.Key;
import java.util.Set;
@@ -124,13 +122,13 @@ public final class EntityPacketRewriter1_20 extends EntityRewriter<ClientboundPa
@Override
protected void registerRewrites() {
filter().handler((event, meta) -> meta.setDataType(Types1_19_4.ENTITY_DATA_TYPES.byId(meta.dataType().typeId())));
registerMetaTypeHandler(Types1_19_4.ENTITY_DATA_TYPES.itemType, Types1_19_4.ENTITY_DATA_TYPES.blockStateType, Types1_19_4.ENTITY_DATA_TYPES.optionalBlockStateType,
filter().handler((event, data) -> data.setDataType(Types1_19_4.ENTITY_DATA_TYPES.byId(data.dataType().typeId())));
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, Types1_19_4.ENTITY_DATA_TYPES.componentType, Types1_19_4.ENTITY_DATA_TYPES.optionalComponentType);
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;
}
@@ -139,9 +137,9 @@ public final class EntityPacketRewriter1_20 extends EntityRewriter<ClientboundPa
event.createExtraData(new EntityData(12, Types1_19_4.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));
});
}
@@ -25,6 +25,8 @@ import com.viaversion.viabackwards.protocol.v1_21to1_20_5.rewriter.BlockItemPack
import com.viaversion.viabackwards.protocol.v1_21to1_20_5.rewriter.ComponentRewriter1_21;
import com.viaversion.viabackwards.protocol.v1_21to1_20_5.rewriter.EntityPacketRewriter1_21;
import com.viaversion.viabackwards.protocol.v1_21to1_20_5.storage.EnchantmentsPaintingsStorage;
import com.viaversion.viabackwards.protocol.v1_21to1_20_5.storage.OpenScreenStorage;
import com.viaversion.viabackwards.protocol.v1_21to1_20_5.storage.PlayerRotationStorage;
import com.viaversion.viaversion.api.connection.UserConnection;
import com.viaversion.viaversion.api.minecraft.Holder;
import com.viaversion.viaversion.api.minecraft.entities.EntityTypes1_20_5;
@@ -45,6 +47,7 @@ import com.viaversion.viaversion.protocols.v1_20_5to1_21.packet.ClientboundPacke
import com.viaversion.viaversion.protocols.v1_20_5to1_21.packet.ClientboundPackets1_21;
import com.viaversion.viaversion.rewriter.StatisticsRewriter;
import com.viaversion.viaversion.rewriter.TagRewriter;
import com.viaversion.viaversion.util.ArrayUtil;
import static com.viaversion.viaversion.util.ProtocolUtil.packetTypeMap;
@@ -74,7 +77,6 @@ public final class Protocol1_21To1_20_5 extends BackwardsProtocol<ClientboundPac
new StatisticsRewriter<>(this).register(ClientboundPackets1_21.AWARD_STATS);
translatableRewriter.registerOpenScreen(ClientboundPackets1_21.OPEN_SCREEN);
translatableRewriter.registerComponentPacket(ClientboundPackets1_21.SET_ACTION_BAR_TEXT);
translatableRewriter.registerComponentPacket(ClientboundPackets1_21.SET_TITLE_TEXT);
translatableRewriter.registerComponentPacket(ClientboundPackets1_21.SET_SUBTITLE_TEXT);
@@ -174,12 +176,19 @@ public final class Protocol1_21To1_20_5 extends BackwardsProtocol<ClientboundPac
wrapper.set(Types.VAR_INT, 1, newSize);
}
});
registerClientbound(ClientboundConfigurationPackets1_21.UPDATE_ENABLED_FEATURES, wrapper -> {
final String[] enabledFeatures = wrapper.read(Types.STRING_ARRAY);
wrapper.write(Types.STRING_ARRAY, ArrayUtil.add(enabledFeatures, "minecraft:update_1_21"));
});
}
@Override
public void init(final UserConnection user) {
addEntityTracker(user, new EntityTrackerBase(user, EntityTypes1_20_5.PLAYER));
user.put(new EnchantmentsPaintingsStorage());
user.put(new OpenScreenStorage());
user.put(new PlayerRotationStorage());
}
@Override
@@ -216,4 +225,4 @@ public final class Protocol1_21To1_20_5 extends BackwardsProtocol<ClientboundPac
packetTypeMap(unmappedServerboundPacketType, ServerboundPackets1_20_5.class, ServerboundConfigurationPackets1_20_5.class)
);
}
}
}
@@ -17,8 +17,7 @@
*/
package com.viaversion.viabackwards.protocol.v1_21to1_20_5.rewriter;
import com.viaversion.nbt.tag.CompoundTag;
import com.viaversion.nbt.tag.ListTag;
import com.viaversion.nbt.tag.ByteTag;
import com.viaversion.nbt.tag.StringTag;
import com.viaversion.nbt.tag.Tag;
import com.viaversion.viabackwards.api.rewriters.BackwardsStructuredItemRewriter;
@@ -26,8 +25,9 @@ import com.viaversion.viabackwards.api.rewriters.EnchantmentRewriter;
import com.viaversion.viabackwards.api.rewriters.StructuredEnchantmentRewriter;
import com.viaversion.viabackwards.protocol.v1_21to1_20_5.Protocol1_21To1_20_5;
import com.viaversion.viabackwards.protocol.v1_21to1_20_5.storage.EnchantmentsPaintingsStorage;
import com.viaversion.viabackwards.protocol.v1_21to1_20_5.storage.OpenScreenStorage;
import com.viaversion.viabackwards.protocol.v1_21to1_20_5.storage.PlayerRotationStorage;
import com.viaversion.viaversion.api.connection.UserConnection;
import com.viaversion.viaversion.api.minecraft.data.StructuredData;
import com.viaversion.viaversion.api.minecraft.data.StructuredDataContainer;
import com.viaversion.viaversion.api.minecraft.data.StructuredDataKey;
import com.viaversion.viaversion.api.minecraft.item.Item;
@@ -37,6 +37,9 @@ import com.viaversion.viaversion.api.type.types.chunk.ChunkType1_20_2;
import com.viaversion.viaversion.api.type.types.version.Types1_20_5;
import com.viaversion.viaversion.api.type.types.version.Types1_21;
import com.viaversion.viaversion.libs.fastutil.ints.Int2IntMap;
import com.viaversion.viaversion.libs.mcstructs.core.TextFormatting;
import com.viaversion.viaversion.libs.mcstructs.text.components.StringComponent;
import com.viaversion.viaversion.libs.mcstructs.text.components.TranslationComponent;
import com.viaversion.viaversion.protocols.v1_20_2to1_20_3.rewriter.RecipeRewriter1_20_3;
import com.viaversion.viaversion.protocols.v1_20_3to1_20_5.data.Enchantments1_20_5;
import com.viaversion.viaversion.protocols.v1_20_3to1_20_5.packet.ServerboundPacket1_20_5;
@@ -45,10 +48,12 @@ import com.viaversion.viaversion.protocols.v1_20_5to1_21.packet.ClientboundPacke
import com.viaversion.viaversion.protocols.v1_20_5to1_21.packet.ClientboundPackets1_21;
import com.viaversion.viaversion.rewriter.BlockRewriter;
import com.viaversion.viaversion.rewriter.IdRewriteFunction;
import com.viaversion.viaversion.util.SerializerVersion;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import static com.viaversion.viaversion.protocols.v1_20_5to1_21.rewriter.BlockItemPacketRewriter1_21.downgradeItemData;
import static com.viaversion.viaversion.protocols.v1_20_5to1_21.rewriter.BlockItemPacketRewriter1_21.resetRarityValues;
import static com.viaversion.viaversion.protocols.v1_20_5to1_21.rewriter.BlockItemPacketRewriter1_21.updateItemData;
public final class BlockItemPacketRewriter1_21 extends BackwardsStructuredItemRewriter<ClientboundPacket1_21, ServerboundPacket1_20_5, Protocol1_21To1_20_5> {
@@ -56,7 +61,11 @@ public final class BlockItemPacketRewriter1_21 extends BackwardsStructuredItemRe
private final StructuredEnchantmentRewriter enchantmentRewriter = new StructuredEnchantmentRewriter(this);
public BlockItemPacketRewriter1_21(final Protocol1_21To1_20_5 protocol) {
super(protocol, Types1_21.ITEM, Types1_21.ITEM_ARRAY, Types1_20_5.ITEM, Types1_20_5.ITEM_ARRAY);
super(protocol,
Types1_21.ITEM, Types1_21.ITEM_ARRAY, Types1_20_5.ITEM, Types1_20_5.ITEM_ARRAY,
Types1_21.ITEM_COST, Types1_21.OPTIONAL_ITEM_COST, Types1_20_5.ITEM_COST, Types1_20_5.OPTIONAL_ITEM_COST,
Types1_21.PARTICLE, Types1_20_5.PARTICLE
);
}
@Override
@@ -74,11 +83,37 @@ public final class BlockItemPacketRewriter1_21 extends BackwardsStructuredItemRe
registerAdvancements1_20_3(ClientboundPackets1_21.UPDATE_ADVANCEMENTS);
registerSetEquipment(ClientboundPackets1_21.SET_EQUIPMENT);
registerContainerClick1_17_1(ServerboundPackets1_20_5.CONTAINER_CLICK);
registerMerchantOffers1_20_5(ClientboundPackets1_21.MERCHANT_OFFERS, Types1_21.ITEM_COST, Types1_20_5.ITEM_COST, Types1_21.OPTIONAL_ITEM_COST, Types1_20_5.OPTIONAL_ITEM_COST);
registerMerchantOffers1_20_5(ClientboundPackets1_21.MERCHANT_OFFERS);
registerSetCreativeModeSlot(ServerboundPackets1_20_5.SET_CREATIVE_MODE_SLOT);
registerContainerSetData(ClientboundPackets1_21.CONTAINER_SET_DATA);
registerLevelParticles1_20_5(ClientboundPackets1_21.LEVEL_PARTICLES, Types1_21.PARTICLE, Types1_20_5.PARTICLE);
registerExplosion(ClientboundPackets1_21.EXPLODE, Types1_21.PARTICLE, Types1_20_5.PARTICLE);
registerLevelParticles1_20_5(ClientboundPackets1_21.LEVEL_PARTICLES);
registerExplosion(ClientboundPackets1_21.EXPLODE);
protocol.registerClientbound(ClientboundPackets1_21.OPEN_SCREEN, wrapper -> {
wrapper.passthrough(Types.VAR_INT); // Id
// Tracking the type actually matters now with crafters also using container data above index 3
final int menuType = wrapper.passthrough(Types.VAR_INT);
wrapper.user().get(OpenScreenStorage.class).setMenuType(menuType);
protocol.getComponentRewriter().passthroughAndProcess(wrapper);
});
protocol.registerClientbound(ClientboundPackets1_21.CONTAINER_SET_DATA, wrapper -> {
wrapper.passthrough(Types.UNSIGNED_BYTE); // Container id
final short property = wrapper.passthrough(Types.SHORT);
if (property >= 4 && property <= 6) { // Enchantment hints
final OpenScreenStorage openScreenStorage = wrapper.user().get(OpenScreenStorage.class);
if (openScreenStorage.menuType() != 13) { // Enchantment table
return;
}
final short enchantmentId = wrapper.read(Types.SHORT);
final EnchantmentsPaintingsStorage storage = wrapper.user().get(EnchantmentsPaintingsStorage.class);
final String key = storage.enchantments().idToKey(enchantmentId);
final int mappedId = key != null ? Enchantments1_20_5.keyToId(key) : -1;
wrapper.write(Types.SHORT, (short) mappedId);
}
});
protocol.registerClientbound(ClientboundPackets1_21.HORSE_SCREEN_OPEN, wrapper -> {
wrapper.passthrough(Types.UNSIGNED_BYTE); // Container id
@@ -111,8 +146,10 @@ public final class BlockItemPacketRewriter1_21 extends BackwardsStructuredItemRe
protocol.registerServerbound(ServerboundPackets1_20_5.USE_ITEM, wrapper -> {
wrapper.passthrough(Types.VAR_INT); // Hand
wrapper.passthrough(Types.VAR_INT); // Sequence
wrapper.write(Types.FLOAT, 0f); // Y rotation
wrapper.write(Types.FLOAT, 0f); // X rotation
final PlayerRotationStorage rotation = wrapper.user().get(PlayerRotationStorage.class);
wrapper.write(Types.FLOAT, rotation.yaw());
wrapper.write(Types.FLOAT, rotation.pitch());
});
new RecipeRewriter1_20_3<>(protocol).register1_20_5(ClientboundPackets1_21.UPDATE_RECIPES);
@@ -139,17 +176,34 @@ public final class BlockItemPacketRewriter1_21 extends BackwardsStructuredItemRe
return new StringTag("Unknown enchantment");
}
final CompoundTag fullDescription = new CompoundTag();
fullDescription.putString("translate", "%s " + EnchantmentRewriter.getRomanNumber(level));
fullDescription.put("with", new ListTag<>(Arrays.asList(description)));
return fullDescription;
final var component = SerializerVersion.V1_20_5.toComponent(description);
component.getStyle().setItalic(false);
component.getStyle().setFormatting(TextFormatting.GRAY);
component.getSiblings().add(new StringComponent(" "));
component.getSiblings().add(new TranslationComponent(EnchantmentRewriter.ENCHANTMENT_LEVEL_TRANSLATION.formatted(level)));
return SerializerVersion.V1_20_5.toTag(component);
};
enchantmentRewriter.rewriteEnchantmentsToClient(data, StructuredDataKey.ENCHANTMENTS, idRewriteFunction, descriptionSupplier, false);
enchantmentRewriter.rewriteEnchantmentsToClient(data, StructuredDataKey.STORED_ENCHANTMENTS, idRewriteFunction, descriptionSupplier, true);
final int identifier = item.identifier();
// Order is important
super.handleItemToClient(connection, item);
downgradeItemData(item);
final StructuredDataContainer dataContainer = item.dataContainer();
if (dataContainer.has(StructuredDataKey.RARITY)) {
return item;
}
// Change rarity of trident and piglin banner pattern
final boolean trident = identifier == 1188;
if (trident || identifier == 1200) {
dataContainer.set(StructuredDataKey.RARITY, trident ? 3 : 1); // Epic or Uncommon
saveTag(createCustomTag(item), new ByteTag(true), "rarity");
}
return item;
}
@@ -173,17 +227,18 @@ public final class BlockItemPacketRewriter1_21 extends BackwardsStructuredItemRe
// Order is important
super.handleItemToServer(connection, item);
updateItemData(item);
resetRarityValues(item, nbtTagName("rarity"));
return item;
}
private void rewriteEnchantmentToServer(final EnchantmentsPaintingsStorage storage, final Item item, final StructuredDataKey<Enchantments> key) {
final StructuredData<Enchantments> enchantmentsData = item.dataContainer().getNonEmpty(key);
if (enchantmentsData == null) {
final Enchantments enchantments = item.dataContainer().get(key);
if (enchantments == null) {
return;
}
final Enchantments enchantments = enchantmentsData.value();
for (final Int2IntMap.Entry entry : new ArrayList<>(enchantments.enchantments().int2IntEntrySet())) {
final List<PendingIdChange> updatedIds = new ArrayList<>();
for (final Int2IntMap.Entry entry : enchantments.enchantments().int2IntEntrySet()) {
final int id = entry.getIntKey();
final String enchantmentKey = Enchantments1_20_5.idToKey(id);
if (enchantmentKey == null) {
@@ -192,9 +247,20 @@ public final class BlockItemPacketRewriter1_21 extends BackwardsStructuredItemRe
final int mappedId = storage.enchantments().keyToId(enchantmentKey);
if (id != mappedId) {
enchantments.enchantments().remove(id);
enchantments.enchantments().put(mappedId, entry.getIntValue());
final int level = entry.getIntValue();
updatedIds.add(new PendingIdChange(id, mappedId, level));
}
}
// Remove first, then add updated entries
for (final PendingIdChange change : updatedIds) {
enchantments.remove(change.id);
}
for (final PendingIdChange change : updatedIds) {
enchantments.add(change.mappedId, change.level);
}
}
}
private record PendingIdChange(int id, int mappedId, int level) {
}
}
@@ -23,9 +23,11 @@ import com.viaversion.nbt.tag.ListTag;
import com.viaversion.viabackwards.api.rewriters.TranslatableRewriter;
import com.viaversion.viabackwards.protocol.v1_21to1_20_5.Protocol1_21To1_20_5;
import com.viaversion.viaversion.api.connection.UserConnection;
import com.viaversion.viaversion.protocols.v1_20_3to1_20_5.data.Attributes1_20_5;
import com.viaversion.viaversion.protocols.v1_20_5to1_21.Protocol1_20_5To1_21;
import com.viaversion.viaversion.protocols.v1_20_5to1_21.data.AttributeModifierMappings1_21;
import com.viaversion.viaversion.protocols.v1_20_5to1_21.packet.ClientboundPacket1_21;
import com.viaversion.viaversion.util.Key;
import com.viaversion.viaversion.util.SerializerVersion;
import com.viaversion.viaversion.util.TagUtil;
import com.viaversion.viaversion.util.UUIDUtil;
@@ -37,21 +39,38 @@ public final class ComponentRewriter1_21 extends TranslatableRewriter<Clientboun
super(protocol, ReadType.NBT);
}
@Override
protected void handleShowItem(final UserConnection connection, final CompoundTag componentsTag) {
final CompoundTag attributeModifiers = TagUtil.getNamespacedCompoundTag(componentsTag, "attribute_modifiers");
if (attributeModifiers != null) {
final ListTag<CompoundTag> modifiers = attributeModifiers.getListTag("modifiers", CompoundTag.class);
for (final CompoundTag modifier : modifiers) {
final String id = modifier.getString("id");
final UUID uuid = Protocol1_20_5To1_21.mapAttributeId(id);
final String name = AttributeModifierMappings1_21.idToName(id);
modifier.put("uuid", new IntArrayTag(UUIDUtil.toIntArray(uuid)));
modifier.putString("name", name != null ? name : id);
}
private void convertAttributeModifiersComponent(final CompoundTag tag) {
final CompoundTag attributeModifiers = TagUtil.getNamespacedCompoundTag(tag, "attribute_modifiers");
if (attributeModifiers == null) {
return;
}
final ListTag<CompoundTag> modifiers = attributeModifiers.getListTag("modifiers", CompoundTag.class);
int size = modifiers.size();
for (int i = 0; i < size; i++) {
final CompoundTag modifier = modifiers.get(i);
final String type = Key.stripMinecraftNamespace(modifier.getString("type"));
if (Attributes1_20_5.keyToId(type) == -1) {
// Ignore new attributes
modifiers.remove(i--);
size--;
continue;
}
TagUtil.removeNamespaced(componentsTag, "jukebox_playable");
final String id = modifier.getString("id");
final UUID uuid = Protocol1_20_5To1_21.mapAttributeId(id);
final String name = AttributeModifierMappings1_21.idToName(id);
modifier.put("uuid", new IntArrayTag(UUIDUtil.toIntArray(uuid)));
modifier.putString("name", name != null ? name : id);
}
}
@Override
protected void handleShowItem(final UserConnection connection, final CompoundTag itemTag, final CompoundTag componentsTag) {
super.handleShowItem(connection, itemTag, componentsTag);
if (componentsTag != null) {
TagUtil.removeNamespaced(componentsTag, "jukebox_playable");
convertAttributeModifiersComponent(componentsTag);
}
}
@Override
@@ -22,6 +22,7 @@ import com.viaversion.nbt.tag.Tag;
import com.viaversion.viabackwards.api.rewriters.EntityRewriter;
import com.viaversion.viabackwards.protocol.v1_21to1_20_5.Protocol1_21To1_20_5;
import com.viaversion.viabackwards.protocol.v1_21to1_20_5.storage.EnchantmentsPaintingsStorage;
import com.viaversion.viabackwards.protocol.v1_21to1_20_5.storage.PlayerRotationStorage;
import com.viaversion.viaversion.api.minecraft.Holder;
import com.viaversion.viaversion.api.minecraft.PaintingVariant;
import com.viaversion.viaversion.api.minecraft.RegistryEntry;
@@ -29,10 +30,12 @@ import com.viaversion.viaversion.api.minecraft.WolfVariant;
import com.viaversion.viaversion.api.minecraft.entities.EntityType;
import com.viaversion.viaversion.api.minecraft.entities.EntityTypes1_20_5;
import com.viaversion.viaversion.api.minecraft.entitydata.EntityDataType;
import com.viaversion.viaversion.api.protocol.packet.PacketWrapper;
import com.viaversion.viaversion.api.protocol.remapper.PacketHandlers;
import com.viaversion.viaversion.api.type.Types;
import com.viaversion.viaversion.api.type.types.version.Types1_20_5;
import com.viaversion.viaversion.api.type.types.version.Types1_21;
import com.viaversion.viaversion.protocols.v1_20_3to1_20_5.packet.ServerboundPackets1_20_5;
import com.viaversion.viaversion.protocols.v1_20_5to1_21.data.Paintings1_20_5;
import com.viaversion.viaversion.protocols.v1_20_5to1_21.packet.ClientboundConfigurationPackets1_21;
import com.viaversion.viaversion.protocols.v1_20_5to1_21.packet.ClientboundPacket1_21;
@@ -123,6 +126,23 @@ public final class EntityPacketRewriter1_21 extends EntityRewriter<ClientboundPa
final String world = wrapper.passthrough(Types.STRING);
trackWorldDataByKey1_20_5(wrapper.user(), dimensionId, world); // Tracks world height and name for chunk data and entity (un)tracking
});
protocol.registerServerbound(ServerboundPackets1_20_5.MOVE_PLAYER_POS_ROT, wrapper -> {
wrapper.passthrough(Types.DOUBLE); // X
wrapper.passthrough(Types.DOUBLE); // Y
wrapper.passthrough(Types.DOUBLE); // Z
storePlayerRotation(wrapper);
});
protocol.registerServerbound(ServerboundPackets1_20_5.MOVE_PLAYER_ROT, this::storePlayerRotation);
}
private void storePlayerRotation(final PacketWrapper wrapper) {
final float yaw = wrapper.passthrough(Types.FLOAT);
final float pitch = wrapper.passthrough(Types.FLOAT);
wrapper.user().get(PlayerRotationStorage.class).setRotation(yaw, pitch);
}
private int[] paintingMappingsForEntries(final RegistryEntry[] entries) {
@@ -176,7 +196,7 @@ public final class EntityPacketRewriter1_21 extends EntityRewriter<ClientboundPa
data.setDataType(Types1_20_5.ENTITY_DATA_TYPES.byId(type.typeId()));
}
});
registerMetaTypeHandler1_20_3(
registerEntityDataTypeHandler1_20_3(
Types1_20_5.ENTITY_DATA_TYPES.itemType,
Types1_20_5.ENTITY_DATA_TYPES.blockStateType,
Types1_20_5.ENTITY_DATA_TYPES.optionalBlockStateType,
@@ -15,20 +15,19 @@
* 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.viabackwards.protocol.v1_17to1_16_4.storage;
package com.viaversion.viabackwards.protocol.v1_21to1_20_5.storage;
import com.viaversion.viaversion.api.connection.StorableObject;
import com.viaversion.viaversion.libs.fastutil.ints.IntOpenHashSet;
import com.viaversion.viaversion.libs.fastutil.ints.IntSet;
public final class PingRequests implements StorableObject {
private final IntSet ids = new IntOpenHashSet();
public final class OpenScreenStorage implements StorableObject {
public void addId(short id) {
ids.add(id);
private int menuType = -1;
public int menuType() {
return menuType;
}
public boolean removeId(short id) {
return ids.remove(id);
public void setMenuType(final int menuType) {
this.menuType = menuType;
}
}
@@ -0,0 +1,38 @@
/*
* This file is part of ViaBackwards - https://github.com/ViaVersion/ViaBackwards
* 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.viabackwards.protocol.v1_21to1_20_5.storage;
import com.viaversion.viaversion.api.connection.StorableObject;
public final class PlayerRotationStorage implements StorableObject {
private float yaw, pitch;
public void setRotation(final float yaw, final float pitch) {
this.yaw = yaw;
this.pitch = pitch;
}
public float yaw() {
return yaw;
}
public float pitch() {
return pitch;
}
}
@@ -24,7 +24,6 @@ import com.viaversion.viaversion.api.connection.UserConnection;
import com.viaversion.viaversion.api.minecraft.ClientWorld;
import com.viaversion.viaversion.api.minecraft.BlockPosition;
import com.viaversion.viaversion.api.minecraft.chunks.Chunk;
import com.viaversion.viaversion.api.protocol.AbstractProtocol;
import com.viaversion.viaversion.api.protocol.remapper.PacketHandlers;
import com.viaversion.viaversion.api.type.Types;
import com.viaversion.viaversion.api.type.types.chunk.ChunkType1_9_1;
@@ -60,9 +59,9 @@ public class Protocol1_9_3To1_9_1 extends BackwardsProtocol<ClientboundPackets1_
wrapper.setPacketType(ClientboundPackets1_9.UPDATE_SIGN);
wrapper.write(Types.BLOCK_POSITION1_8, position); // Position
for (int i = 1; i < 5; i++) {
for (int i = 0; i < 4; i++) {
// Should technically be written as COMPONENT, but left as String for simplification/to remove redundant wrapping for VR
StringTag textTag = tag.getStringTag("Text" + i);
StringTag textTag = tag.getStringTag("Text" + (i + 1));
String line = textTag != null ? textTag.getValue() : "";
wrapper.write(Types.STRING, line); // Sign line
}
@@ -72,7 +71,7 @@ public class Protocol1_9_3To1_9_1 extends BackwardsProtocol<ClientboundPackets1_
});
registerClientbound(ClientboundPackets1_9_3.LEVEL_CHUNK, wrapper -> {
ClientWorld clientWorld = wrapper.user().get(ClientWorld.class);
ClientWorld clientWorld = wrapper.user().getClientWorld(Protocol1_9_3To1_9_1.class);
ChunkType1_9_3 newType = ChunkType1_9_3.forEnvironment(clientWorld.getEnvironment());
ChunkType1_9_1 oldType = ChunkType1_9_1.forEnvironment(clientWorld.getEnvironment()); // Get the old type to not write Block Entities
@@ -90,10 +89,10 @@ public class Protocol1_9_3To1_9_1 extends BackwardsProtocol<ClientboundPackets1_
map(Types.INT); // 2 - Dimension
handler(wrapper -> {
ClientWorld clientChunks = wrapper.user().get(ClientWorld.class);
ClientWorld clientWorld = wrapper.user().getClientWorld(Protocol1_9_3To1_9_1.class);
int dimensionId = wrapper.get(Types.INT, 1);
clientChunks.setEnvironment(dimensionId);
clientWorld.setEnvironment(dimensionId);
});
}
});
@@ -104,7 +103,7 @@ public class Protocol1_9_3To1_9_1 extends BackwardsProtocol<ClientboundPackets1_
map(Types.INT); // 0 - Dimension ID
handler(wrapper -> {
ClientWorld clientWorld = wrapper.user().get(ClientWorld.class);
ClientWorld clientWorld = wrapper.user().getClientWorld(Protocol1_9_3To1_9_1.class);
int dimensionId = wrapper.get(Types.INT, 0);
clientWorld.setEnvironment(dimensionId);
@@ -118,8 +117,6 @@ public class Protocol1_9_3To1_9_1 extends BackwardsProtocol<ClientboundPackets1_
@Override
public void init(UserConnection userConnection) {
if (!userConnection.has(ClientWorld.class)) {
userConnection.put(new ClientWorld());
}
userConnection.addClientWorld(this.getClass(), new ClientWorld());
}
}
}
@@ -17,9 +17,15 @@
*/
package com.viaversion.viabackwards.utils;
import com.viaversion.viaversion.libs.mcstructs.text.ATextComponent;
import com.viaversion.viaversion.libs.mcstructs.text.Style;
import com.viaversion.viaversion.libs.mcstructs.text.components.TranslationComponent;
import com.viaversion.viaversion.libs.mcstructs.text.serializer.LegacyStringDeserializer;
import com.viaversion.viaversion.util.SerializerVersion;
import java.util.HashSet;
import java.util.Objects;
import java.util.Set;
import java.util.function.Consumer;
import java.util.regex.Pattern;
public final class ChatUtil {
@@ -30,6 +36,23 @@ public final class ChatUtil {
return removeUnusedColor(legacy, defaultColor, false);
}
public static String legacyToJsonString(String legacy, String translation, boolean itemData) {
return legacyToJsonString(legacy, text -> {
text.append(" ");
text.append(new TranslationComponent(translation));
}, itemData);
}
public static String legacyToJsonString(String legacy, Consumer<ATextComponent> consumer, boolean itemData) {
final ATextComponent component = LegacyStringDeserializer.parse(legacy, true);
consumer.accept(component);
if (itemData) {
component.setParentStyle((new Style()).setItalic(false));
}
return SerializerVersion.V1_12.toString(component);
}
private static class ChatFormattingState {
private final Set<Character> formatting;
private final char defaultColor;
@@ -21,5 +21,12 @@ fix-formatted-inventory-titles: true
# This only takes effect for ids in the short range. Useful for anticheat compatibility.
handle-pings-as-inv-acknowledgements: false
#
# Adds bedrock blocks at y=0 for sub 1.17 clients. This may allow for weird interactions due to sending fake blocks.
bedrock-at-y-0: false
#
# Shows sculk shriekers as crying obsidian for 1.18.2 clients on 1.19+ servers. This fixes collision and block breaking issues.
# If disabled, the client will see them as end portal frames.
sculk-shriekers-to-crying-obsidian: true
#
# Suppresses warnings of missing emulations for certain features that are not supported (e.g. world height in 1.17+).
suppress-emulation-warnings: false
@@ -11,41 +11,30 @@
"attribute.name.player.submerged_mining_speed": "Submerged Mining Speed",
"attribute.name.player.sweeping_damage_ratio": "Sweeping Damage Ratio",
"gamerule.entitiesWithPassengersCanUsePortals": "Entities with passengers can use portals",
"gamerule.entitiesWithPassengersCanUsePortals.description": "Allow entities with passengers to teleport through nether portals, end portals and end gateways.",
"gamerule.entitiesWithPassengersCanUsePortals.description": "Allow entities with passengers to teleport through Nether Portals, End Portals, and End Gateways.",
"gui.abuseReport.attestation": "By submitting this report, you confirm that the information you have provided is accurate and complete to the best of your knowledge.",
"gui.abuseReport.send.not_attested": "Please read the text above and tick the checkbox to be able to send the report",
"gui.fileDropFailure.detail": "Rejected %d files",
"gui.fileDropFailure.title": "Failed to add files",
"gui.open_report_dir": "Open Report Directory",
"gui.report_to_server": "Report To Server",
"item.minecraft.music_disc_creator": "Music Disc",
"item.minecraft.music_disc_creator_music_box": "Music Disc",
"item.minecraft.music_disc_creator_music_box.desc": "Lena Raine - Creator (Music Box)",
"item.minecraft.music_disc_creator.desc": "Lena Raine - Creator",
"item.minecraft.music_disc_precipice": "Music Disc",
"item.minecraft.music_disc_precipice.desc": "Aaron Cherof - Precipice",
"item.modifiers.any": "When equipped:",
"item.modifiers.armor": "When worn:",
"item.modifiers.hand": "When held:",
"jukebox_song.minecraft.5": "Samuel �berg - 5",
"jukebox_song.minecraft.11": "C418 - 11",
"jukebox_song.minecraft.13": "C418 - 13",
"jukebox_song.minecraft.blocks": "C418 - blocks",
"jukebox_song.minecraft.cat": "C418 - cat",
"jukebox_song.minecraft.chirp": "C418 - chirp",
"jukebox_song.minecraft.creator": "Lena Raine - Creator",
"jukebox_song.minecraft.creator_music_box": "Lena Raine - Creator (Music Box)",
"jukebox_song.minecraft.far": "C418 - far",
"jukebox_song.minecraft.mall": "C418 - mall",
"jukebox_song.minecraft.mellohi": "C418 - mellohi",
"jukebox_song.minecraft.otherside": "Lena Raine - otherside",
"jukebox_song.minecraft.pigstep": "Lena Raine - Pigstep",
"jukebox_song.minecraft.precipice": "Aaron Cherof - Precipice",
"jukebox_song.minecraft.relic": "Aaron Cherof - Relic",
"jukebox_song.minecraft.stal": "C418 - stal",
"jukebox_song.minecraft.strad": "C418 - strad",
"jukebox_song.minecraft.wait": "C418 - wait",
"jukebox_song.minecraft.ward": "C418 - ward",
"known_server_link.announcements": "Announcements",
"known_server_link.community": "Community",
"known_server_link.community_guidelines": "Community Guidelines",
"known_server_link.feedback": "Feedback",
"known_server_link.forums": "Forums",
"known_server_link.news": "News",
"known_server_link.report_bug": "Report Server Bug",
"mco.compatibility.incompatible.popup.title": "Incompatible version",
"known_server_link.support": "Support",
"known_server_link.website": "Website",
"mco.compatibility.incompatible.releaseType.popup.message": "The world you are trying to join is incompatible with the version you are on.",
"mco.compatibility.incompatible.series.popup.message": "This world was last played in version %s; you are on version %s.\n\nThese series are not compatible with each other. A new world is needed to play on this version.",
"mco.compatibility.upgrade.friend.description": "This world was last played in version %s; you are on version %s.\n\nA backup of the world will be saved under \"World Backups\".\n\nThe owner of the Realm can restore the world if needed.",
@@ -57,53 +46,38 @@
"menu.server_links": "Server Links...",
"menu.server_links.title": "Server Links",
"options.realmsNotifications.tooltip": "Fetches Realms news and invites in the title screen and displays their respective icon on the Realms button.",
"painting.minecraft.backyard.author": "Kristoffer Zetterstrand",
"painting.minecraft.backyard.title": "Backyard",
"painting.minecraft.baroque.author": "Sarah Boeving",
"painting.minecraft.baroque.title": "Baroque",
"painting.minecraft.bouquet.author": "Kristoffer Zetterstrand",
"painting.minecraft.bouquet.title": "Bouquet",
"painting.minecraft.cavebird.author": "Kristoffer Zetterstrand",
"painting.minecraft.cavebird.title": "Cavebird",
"painting.minecraft.changing.author": "Kristoffer Zetterstrand",
"painting.minecraft.changing.title": "Changing",
"painting.minecraft.cotan.author": "Kristoffer Zetterstrand",
"painting.minecraft.cotan.title": "Cot�n",
"painting.minecraft.endboss.author": "Kristoffer Zetterstrand",
"painting.minecraft.endboss.title": "Endboss",
"painting.minecraft.fern.author": "Kristoffer Zetterstrand",
"painting.minecraft.fern.title": "Fern",
"painting.minecraft.finding.author": "Kristoffer Zetterstrand",
"painting.minecraft.finding.title": "Finding",
"painting.minecraft.humble.author": "Sarah Boeving",
"painting.minecraft.humble.title": "Humble",
"painting.minecraft.lowmist.author": "Kristoffer Zetterstrand",
"painting.minecraft.lowmist.title": "Lowmist",
"painting.minecraft.meditative.author": "Sarah Boeving",
"painting.minecraft.meditative.title": "Meditative",
"painting.minecraft.orb.author": "Kristoffer Zetterstrand",
"painting.minecraft.orb.title": "Orb",
"painting.minecraft.owlemons.author": "Kristoffer Zetterstrand",
"painting.minecraft.owlemons.title": "Owlemons",
"painting.minecraft.passage.author": "Kristoffer Zetterstrand",
"painting.minecraft.passage.title": "Passage",
"painting.minecraft.pond.author": "Kristoffer Zetterstrand",
"painting.minecraft.pond.title": "Pond",
"painting.minecraft.prairie_ride.author": "Sarah Boeving",
"painting.minecraft.prairie_ride.title": "Prairie Ride",
"painting.minecraft.sunflowers.author": "Kristoffer Zetterstrand",
"painting.minecraft.sunflowers.title": "Sunflowers",
"painting.minecraft.tides.author": "Kristoffer Zetterstrand",
"painting.minecraft.tides.title": "Tides",
"painting.minecraft.unpacked.author": "Sarah Boeving",
"painting.minecraft.unpacked.title": "Unpacked",
"subtitles.block.trial_spawner.ambient_ominous": "Ominous crackling",
"subtitles.block.trial_spawner.ominous_activate": "Omen engulfs Trial Spawner",
"subtitles.block.vault.reject_rewarded_player": "Vault rejects already rewarded player"
"subtitles.block.vault.reject_rewarded_player": "Vault rejects player"
},
"1.20.5": {
"advancements.adventure.blowback.description": "Kill a Breeze with a deflected Breeze-shot Wind Charge",
"advancements.adventure.blowback.title": "Blowback",
"advancements.adventure.brush_armadillo.description": "Get Armadillo Scutes from an Armadillo using a Brush",
"advancements.adventure.brush_armadillo.title": "Isn't It Scute?",
"advancements.adventure.crafters_crafting_crafters.description": "Be near a Crafter when it crafts a Crafter",
"advancements.adventure.crafters_crafting_crafters.title": "Crafters Crafting Crafters",
"advancements.adventure.lighten_up.description": "Scrape a Copper Bulb with an Axe to make it brighter",
@@ -112,18 +86,28 @@
"advancements.adventure.minecraft_trials_edition.title": "Minecraft: Trial(s) Edition",
"advancements.adventure.overoverkill.description": "Deal 50 hearts of damage in a single hit using the Mace",
"advancements.adventure.overoverkill.title": "Over-Overkill",
"advancements.adventure.revaulting.description": "Unlock an Ominous Vault with an Ominous Trial Key",
"advancements.adventure.revaulting.title": "Revaulting",
"advancements.adventure.under_lock_and_key.description": "Unlock a Vault with a Trial Key",
"advancements.adventure.under_lock_and_key.title": "Under Lock and Key",
"advancements.adventure.who_needs_rockets.description": "Use a Wind Charge to launch yourself upward 8 blocks",
"advancements.adventure.who_needs_rockets.title": "Who Needs Rockets?",
"advancements.husbandry.remove_wolf_armor.description": "Remove Wolf Armor from a Wolf using Shears",
"advancements.husbandry.remove_wolf_armor.title": "Shear Brilliance",
"advancements.husbandry.repair_wolf_armor.description": "Repair a damaged Wolf Armor using Armadillo Scutes",
"advancements.husbandry.repair_wolf_armor.title": "Good as New",
"advancements.husbandry.whole_pack.description": "Tame one of each Wolf variant",
"advancements.husbandry.whole_pack.title": "The Whole Pack",
"argument.message.too_long": "Chat message was too long (%s > maximum %s characters)",
"argument.resource_or_id.failed_to_parse": "Failed to parse structure: %s",
"argument.resource_or_id.invalid": "Invalid id or tag",
"arguments.item.component.expected": "Expected item component",
"arguments.item.component.malformed": "Malformed '%s' component: '%s'",
"arguments.item.component.repeated": "Item component '%s' was repeated, but only one value can be specified",
"arguments.item.component.unknown": "Unknown item component '%s'",
"arguments.item.malformed": "Malformed item: '%s'",
"arguments.item.predicate.malformed": "Malformed '%s' predicate: '%s'",
"arguments.item.predicate.unknown": "Unknown item predicate '%s''",
"arguments.item.predicate.unknown": "Unknown item predicate '%s'",
"attribute.name.generic.block_interaction_range": "Block Interaction Range",
"attribute.name.generic.entity_interaction_range": "Entity Interaction Range",
"attribute.name.generic.fall_damage_multiplier": "Fall Damage Multiplier",
@@ -135,6 +119,38 @@
"attribute.name.player.block_break_speed": "Block Break Speed",
"attribute.name.player.block_interaction_range": "Block Interaction Range",
"attribute.name.player.entity_interaction_range": "Entity Interaction Range",
"block.minecraft.banner.flow.black": "Black Flow",
"block.minecraft.banner.flow.blue": "Blue Flow",
"block.minecraft.banner.flow.brown": "Brown Flow",
"block.minecraft.banner.flow.cyan": "Cyan Flow",
"block.minecraft.banner.flow.gray": "Gray Flow",
"block.minecraft.banner.flow.green": "Green Flow",
"block.minecraft.banner.flow.light_blue": "Light Blue Flow",
"block.minecraft.banner.flow.light_gray": "Light Gray Flow",
"block.minecraft.banner.flow.lime": "Lime Flow",
"block.minecraft.banner.flow.magenta": "Magenta Flow",
"block.minecraft.banner.flow.orange": "Orange Flow",
"block.minecraft.banner.flow.pink": "Pink Flow",
"block.minecraft.banner.flow.purple": "Purple Flow",
"block.minecraft.banner.flow.red": "Red Flow",
"block.minecraft.banner.flow.white": "White Flow",
"block.minecraft.banner.flow.yellow": "Yellow Flow",
"block.minecraft.banner.guster.black": "Black Guster",
"block.minecraft.banner.guster.blue": "Blue Guster",
"block.minecraft.banner.guster.brown": "Brown Guster",
"block.minecraft.banner.guster.cyan": "Cyan Guster",
"block.minecraft.banner.guster.gray": "Gray Guster",
"block.minecraft.banner.guster.green": "Green Guster",
"block.minecraft.banner.guster.light_blue": "Light Blue Guster",
"block.minecraft.banner.guster.light_gray": "Light Gray Guster",
"block.minecraft.banner.guster.lime": "Lime Guster",
"block.minecraft.banner.guster.magenta": "Magenta Guster",
"block.minecraft.banner.guster.orange": "Orange Guster",
"block.minecraft.banner.guster.pink": "Pink Guster",
"block.minecraft.banner.guster.purple": "Purple Guster",
"block.minecraft.banner.guster.red": "Red Guster",
"block.minecraft.banner.guster.white": "White Guster",
"block.minecraft.banner.guster.yellow": "Yellow Guster",
"block.minecraft.heavy_core": "Heavy Core",
"block.minecraft.vault": "Vault",
"chat.disabled.invalid_command_signature": "Command had unexpected or missing command argument signatures.",
@@ -152,6 +168,7 @@
"commands.transfer.success.single": "Transferring %s to %s:%s",
"connect.failed.transfer": "Connection failed while transferring to the server",
"connect.transferring": "Transferring to new server...",
"disconnect.packetError": "Network Protocol Error",
"disconnect.transfer": "Transferred to another server",
"effect.minecraft.infested": "Infested",
"effect.minecraft.oozing": "Oozing",
@@ -161,28 +178,21 @@
"effect.minecraft.wind_charged": "Wind Charged",
"enchantment.minecraft.breach": "Breach",
"enchantment.minecraft.density": "Density",
"enchantment.minecraft.sweeping_edge": "Sweeping Edge",
"enchantment.minecraft.wind_burst": "Wind Burst",
"entity.minecraft.armadillo": "Armadillo",
"entity.minecraft.bogged": "Bogged",
"entity.minecraft.breeze_wind_charge": "Wind Charge",
"entity.minecraft.ominous_item_spawner": "Ominous Item Spawner",
"filled_map.trial_chambers": "Trial Chambers Map",
"gamerule.spawnChunkRadius": "Spawn chunk radius",
"gamerule.spawnChunkRadius.description": "Amount of chunks that stay loaded around the overworld spawn position.",
"gamerule.spawnRadius.description": "Controls the size of the area around the spawn point that players can spawn in.",
"item.canUse.unknown": "Unknown",
"item.components": "%s component(s)",
"item.minecraft.armadillo_scute": "Armadillo Scute",
"item.minecraft.armadillo_spawn_egg": "Armadillo Spawn Egg",
"item.minecraft.bogged_spawn_egg": "Bogged Spawn Egg",
"item.minecraft.bolt_armor_trim_smithing_template": "Smithing Template",
"item.minecraft.breeze_rod": "Breeze Rod",
"item.minecraft.flow_armor_trim_smithing_template": "Smithing Template",
"item.minecraft.flow_banner_pattern": "Banner Pattern",
"item.minecraft.flow_banner_pattern.desc": "Flow",
"item.minecraft.flow_pottery_sherd": "Flow Pottery Sherd",
"item.minecraft.guster_banner_pattern": "Banner Pattern",
"item.minecraft.guster_banner_pattern.desc": "Guster",
"item.minecraft.guster_pottery_sherd": "Guster Pottery Sherd",
"item.minecraft.lingering_potion.effect.infested": "Lingering Potion of Infestation",
@@ -206,19 +216,16 @@
"item.minecraft.tipped_arrow.effect.weaving": "Arrow of Weaving",
"item.minecraft.tipped_arrow.effect.wind_charged": "Arrow of Wind Charging",
"item.minecraft.turtle_scute": "Turtle Scute",
"item.minecraft.wind_charge": "Wind Charge",
"item.minecraft.wolf_armor": "Wolf Armor",
"item.modifiers.body": "When equipped:",
"mco.backup.narration": "Backup from %s",
"mco.client.outdated.stable.version": "Your client version (%s) is not compatible with Realms.\n\nPlease use the most recent version of Minecraft.",
"mco.client.unsupported.snapshot.version": "Your client version (%s) is not compatible with Realms.\n\nRealms is not available for this snapshot version.",
"mco.invited.player.narration": "Invited player %s",
"mco.upload.entry.commands": "%1$s, %2$s",
"multiplayer.disconnect.transfers_disabled": "Server does not accept transfers",
"optimizeWorld.stage.finished.chunks": "Finishing up upgrading chunks...",
"optimizeWorld.stage.finished.entities": "Finishing up upgrading entities...",
"optimizeWorld.stage.finished.poi": "Finishing up upgrading points of interest...",
"optimizeWorld.stage.upgrading.chunks": "Upgrading all chunks...",
"optimizeWorld.stage.upgrading.entities": "Upgrading all entities...",
"optimizeWorld.stage.upgrading.poi": "Upgrading all points of interest...",
"options.accessibility.menu_background_blurriness": "Menu Background Blur",
@@ -228,6 +235,7 @@
"options.japaneseGlyphVariants": "Japanese Glyph Variants",
"options.japaneseGlyphVariants.tooltip": "Uses Japanese variants of CJK characters in the default font",
"options.telemetry.disabled": "Telemetry is disabled.",
"particle.invalidOptions": "Can't parse particle options: %s",
"selectWorld.allowCommands.new": "Allow Commands",
"selectWorld.commands": "Commands",
"selectWorld.warning.lowDiskSpace.description": "There is not much space left on your device.\nRunning out of disk space while in game can lead to your world being damaged.",
@@ -266,12 +274,9 @@
"subtitles.entity.breeze.charge": "Breeze charges",
"subtitles.entity.breeze.deflect": "Breeze deflects",
"subtitles.entity.breeze.whirl": "Breeze whirls",
"subtitles.entity.breeze.wind_burst": "Wind Charge bursts",
"subtitles.entity.donkey.jump": "Donkey jumps",
"subtitles.entity.mule.jump": "Mule jumps",
"subtitles.entity.parrot.imitate.bogged": "Parrot rattles",
"subtitles.entity.wind_charge.throw": "Wind Charge flies",
"subtitles.entity.wind_charge.wind_burst": "Wind Charge bursts",
"subtitles.event.mob_effect.bad_omen": "Omen takes hold",
"subtitles.event.mob_effect.raid_omen": "Raid looms nearby",
"subtitles.event.mob_effect.trial_omen": "Ominous trial looms nearby",
@@ -4107,6 +4112,9 @@
"realms.missing.snapshot.error.text": "Realms is currently not supported in snapshots"
},
"1.12": {
"potion.potency.3": "enchantment.level.4",
"potion.potency.4": "enchantment.level.5",
"potion.potency.5": "enchantment.level.6",
"gui.recipebook.moreRecipes": "Right Click for more",
"gui.recipebook.toggleRecipes.all": "Showing all",
"gui.recipebook.toggleRecipes.craftable": "Showing craftable",
+1 -5
View File
@@ -26,11 +26,7 @@
]
},
"depends": {
"fabricloader": ">=0.14.0",
"viafabric": ">=0.4.10"
},
"recommends": {
"viarewind": "*"
"viafabric": ">=0.4.14"
},
"custom": {
"modmenu:api": true,
+3 -4
View File
@@ -1,7 +1,6 @@
projectVersion=5.0.0
projectVersion=5.0.4
# Smile emoji
mcVersions=1.21,1.20.6,1.20.5,1.20.4, 1.20.3, 1.20.2, 1.20.1, 1.20, 1.19.4, 1.19.3, 1.19.2, 1.19.1, 1.19, 1.18.2, 1.18.1, 1.18, 1.17.1, 1.17, 1.16.5, 1.16.4, 1.16.3, 1.16.2, 1.16.1, 1.16, 1.15.2, 1.15.1, 1.15, 1.14.4, 1.14.3, 1.14.2, 1.14.1, 1.14, 1.13.2, 1.13.1, 1.13, 1.12.2, 1.12.1, 1.12, 1.11.2, 1.11.1, 1.11, 1.10.2, 1.10.1, 1.10
mcVersionRange=1.10-1.21
waterfallVersion=1.20
mcVersions=1.21.1,1.21,1.20.6,1.20.5,1.20.4, 1.20.3, 1.20.2, 1.20.1, 1.20, 1.19.4, 1.19.3, 1.19.2, 1.19.1, 1.19, 1.18.2, 1.18.1, 1.18, 1.17.1, 1.17, 1.16.5, 1.16.4, 1.16.3, 1.16.2, 1.16.1, 1.16, 1.15.2, 1.15.1, 1.15, 1.14.4, 1.14.3, 1.14.2, 1.14.1, 1.14, 1.13.2, 1.13.1, 1.13, 1.12.2, 1.12.1, 1.12, 1.11.2, 1.11.1, 1.11, 1.10.2, 1.10.1, 1.10
mcVersionRange=1.10-1.21.1
velocityVersion=3.3
+1 -1
View File
@@ -3,7 +3,7 @@ metadata.format.version = "1.1"
[versions]
# ViaVersion
viaver = "5.0.0"
viaver = "5.0.4-SNAPSHOT"
# Common provided
netty = "4.0.20.Final"
Loaded 100 of 109 files, more files were not shown because too many files have changed in this diff. Show more