Compare commits

...
47 Commits
Author SHA1 Message Date
Nassim Jahnke 76b98eb396 5.7.0 Release 2025-12-29 12:48:01 +01:00
Nassim Jahnke b33221b95c Don't throw on bad entity data in 1.14->1.13 2025-12-28 10:33:03 +01:00
Nassim Jahnke 8ce26b1353 Bump to 5.7.0-SNAPSHOT and update VV usage 2025-12-26 21:57:06 +01:00
9a79f9e217 Delay mannequin spawning for proper skin application (#1158)
Co-authored-by: FlorianMichael <git@florianmichael.de>
Co-authored-by: Nassim Jahnke <nassim@njahnke.dev>
2025-12-26 21:50:10 +01:00
Nassim Jahnke 44476f2468 Replace toIntExact with clamp
Fixes #1159
2025-12-25 09:10:09 +01:00
David Lüdtke 54655e34e7 Fix world border lerp size set in ticks instead of millis (#1156) 2025-12-23 09:55:03 +01:00
Nassim Jahnke 863258df4e Correct overworld fog color 2025-12-21 16:55:01 +01:00
Nassim Jahnke 8a5fce2d2e Put set_objective and set_score packets through component rewriter
Fixes #1155
2025-12-21 15:53:03 +01:00
Nassim Jahnke 5374c3b626 Fix avatar arm handling in 1.21.11->1.21.9 2025-12-20 22:53:24 +01:00
FlorianMichael 96e0d85bc0 Map pale oak shelf to pale oak planks in 1.21.9->1.21.7 (#1154) 2025-12-20 16:38:29 +01:00
Kichura 84576d1d95 [ci skip] Set CI timeout to 30 mins (#1153) 2025-12-20 15:46:05 +01:00
Nassim Jahnke c6f0717ad5 Convert compact sound list to single entry in registry data 2025-12-20 12:00:16 +01:00
Nassim Jahnke 395bebac62 Remove tamable entity data from nautilus
Fixes #1152
2025-12-14 09:25:07 +01:00
FlorianMichael 6d19ad3b81 [ci skip] Include the newest ViaProxy version from 3.0.0 to 4.0.0 (#1151) 2025-12-13 19:59:23 +01:00
Nassim Jahnke 38080fc5cc Remove 1.21.11 registries 2025-12-13 12:04:12 +01:00
FlorianMichael 285dcdd81f Add ViaBackwardsPlatform#init with config instance (#1149) 2025-12-13 11:30:04 +01:00
Nassim Jahnke 1f5fd88fef 5.6.0 Release 2025-12-12 16:00:57 +01:00
Nassim Jahnke 531f7d078e Remove nautilus variant in 1.21.11 component rewriter 2025-12-12 16:00:57 +01:00
Nassim Jahnke 2806671813 Add translatables 2025-12-12 16:00:56 +01:00
Nassim Jahnke 7634a7ec7a Add fog effects to dimensions and biomes 2025-12-12 16:00:56 +01:00
Nassim Jahnke 8cd5bd3368 1.21.11-pre4 2025-12-12 16:00:56 +01:00
Nassim Jahnke 0735e4afb5 Handle biome color type changes 2025-12-12 16:00:56 +01:00
Nassim Jahnke 3568eee8f2 Back up new item data 2025-12-12 16:00:55 +01:00
Nassim Jahnke e694b3532a 1.21.11-pre1 2025-12-12 16:00:55 +01:00
Nassim Jahnke 2bcf79c501 25w46a 2025-12-12 16:00:55 +01:00
Nassim Jahnke 7ded34c55e 25w45a 2025-12-12 16:00:55 +01:00
Nassim Jahnke 3bdeed8a9f 25w43a 2025-12-12 16:00:54 +01:00
Nassim Jahnke 30df707369 WIP 25w42a 2025-12-12 16:00:54 +01:00
github-actions[bot]andgradle-update-robot cf8058016c Update Gradle Wrapper from 9.2.0 to 9.2.1 (#1141)
Signed-off-by: gradle-update-robot <gradle-update-robot@regolo.cc>
Co-authored-by: gradle-update-robot <gradle-update-robot@regolo.cc>
2025-12-12 15:58:35 +01:00
Kichura 3468b0a785 Update workflow configs (#1144) 2025-12-06 20:34:00 +01:00
tmpod d273b06e05 Fix text components in signs not being rewritten in 1.21.9→1.21.7 (#1147) 2025-12-06 20:14:36 +01:00
dependabot[bot] 4f561ba4a7 Bump actions/checkout from 5 to 6 (#1142)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-11-24 21:58:08 +01:00
Nanashi.andFlorianMichael 0a5035d209 More dialog emulation fixes (#1131)
Co-authored-by: FlorianMichael <florian.michael07@gmail.com>
2025-11-24 21:57:46 +01:00
Nassim Jahnke 609b657c68 Handle set_player_team text component changes 2025-11-23 19:47:05 +01:00
Nassim Jahnke 5885074fcd [ci skip] Update issue template 2025-11-18 19:50:03 +01:00
Nassim Jahnke d499918e4b Don't cancel full equipment containing saddle in 1.21.5->1.21.4
Plugins manually sending equipment packets may include saddles for entities that shouldn't have saddle equipment, though the client will ignore them
Closes #1140
2025-11-18 19:33:34 +01:00
FlorianMichael 17d7b4873f Set accepted = true in 1.12->1.11.1 shift click fix (#1139) 2025-11-16 19:04:17 +01:00
FlorianMichael 38243bad78 [ci skip] Update ViaFabricPlus jars path (#1133) 2025-11-12 16:58:40 +01:00
Nassim Jahnke 50577abbb5 Fix jukebox_playable backup
Fixes #1130
2025-11-08 10:45:51 +01:00
github-actions[bot]andgradle-update-robot 277de42948 Update Gradle Wrapper from 9.1.0 to 9.2.0 (#1129)
Signed-off-by: gradle-update-robot <gradle-update-robot@regolo.cc>
Co-authored-by: gradle-update-robot <gradle-update-robot@regolo.cc>
2025-11-03 16:52:13 +01:00
FlorianMichael 4c26915fdf Fix text display y offset in 1.19.4->1.19.3 (#1128) 2025-11-01 15:07:36 +01:00
FlorianMichael 7c98b75543 Cancel sign editor open packet for invalid positions in 1.21.2->1.21 (#1099) 2025-11-01 14:59:13 +01:00
Nassim Jahnke 7d39bcc365 Fix regression in cancelling new 1.21.5 registries 2025-10-28 21:11:26 +01:00
Nassim Jahnke 85688beba8 Go through normal registry handling for removed registries in 1.21.5->1.21.4 2025-10-20 14:28:26 +02:00
FlorianMichael fd16c4469c Add option to disable dialog handling in 1.21.6->1.21.5 (#1116) 2025-10-18 18:34:23 +02:00
Nassim Jahnke a37605e920 Update VV usage 2025-10-14 17:59:53 +02:00
FlorianMichael 1d4e41f867 Fix custom action button in notice dialogs not added in 1.21.6->1.21.5 (#1117) 2025-10-13 20:30:47 +02:00
72 changed files with 1969 additions and 307 deletions

No files matched your search

+2 -11
View File
@@ -48,21 +48,12 @@ body:
label: Steps to Reproduce
description: |
List the steps on how we can reproduce the issue. Make sure we can easily understand what you mean with each step.
**Please always include the client version(s) with which the issue happens. Ideally also try to find out from what specific version downward/in what version range the issue happens.**
placeholder: |
Example:
1. Login with a 1.16.5 client
2. Place a sign
3. The sign text is displayed wrong
validations:
required: true
- type: textarea
attributes:
label: Expected Behavior
description: |
Describe what exactly you expected to happen.
placeholder: |
Example: "Placed sign text should not disappear."
3. The sign text disappears
validations:
required: true
+3 -1
View File
@@ -1,6 +1,8 @@
version: 2
updates:
- package-ecosystem: "github-actions"
cooldown:
default-days: 7
directory: "/"
schedule:
interval: "weekly"
interval: "monthly"
+9 -8
View File
@@ -1,22 +1,23 @@
name: Java CI with Gradle
on: [push, pull_request]
name: Build
on: [pull_request, push, workflow_dispatch]
permissions:
contents: read
jobs:
build:
# Only run on PRs if the source branch is on a different repo. We do not need to run everything twice.
if: ${{ github.event_name != 'pull_request' || github.repository != github.event.pull_request.head.repo.full_name }}
runs-on: ubuntu-24.04
timeout-minutes: 30
steps:
- name: Checkout Repository
uses: actions/checkout@v5
uses: actions/checkout@1af3b93b6815bc44a9784bd300feb67ff0d1eeb3 # 6.0.0
with:
persist-credentials: false
- name: Set up Gradle
uses: gradle/actions/setup-gradle@v5
uses: gradle/actions/setup-gradle@4d9f0ba0025fe599b4ebab900eb7f3a1d93ef4c2 # 5.0.0
- name: Set up JDK 17
uses: actions/setup-java@v5
uses: actions/setup-java@dded0888837ed1f317902acf8a20df0ad188d165 # 5.0.0
with:
distribution: 'temurin'
java-version: 17
+8 -4
View File
@@ -6,24 +6,28 @@ on:
- dev
workflow_dispatch:
permissions:
contents: read
jobs:
publish:
if: github.repository_owner == 'ViaVersion'
runs-on: ubuntu-24.04
timeout-minutes: 30
steps:
- name: Checkout Repository
uses: actions/checkout@v5
uses: actions/checkout@1af3b93b6815bc44a9784bd300feb67ff0d1eeb3 # 6.0.0
with:
persist-credentials: false
- name: Set up Gradle
uses: gradle/actions/setup-gradle@v5
uses: gradle/actions/setup-gradle@4d9f0ba0025fe599b4ebab900eb7f3a1d93ef4c2 # 5.0.0
- name: Set up JDK 17
uses: actions/setup-java@v5
uses: actions/setup-java@dded0888837ed1f317902acf8a20df0ad188d165 # 5.0.0
with:
distribution: 'temurin'
java-version: 17
check-latest: true
- name: Build
- name: Build with Gradle
run: ./gradlew build --refresh-dependencies
- name: Publish to Hangar
env:
+8 -2
View File
@@ -4,13 +4,19 @@ on:
schedule:
- cron: "0 0 * * 0"
permissions:
contents: write
pull-requests: write
jobs:
update-gradle-wrapper:
runs-on: ubuntu-24.04
timeout-minutes: 30
steps:
- name: Checkout Repository
uses: actions/checkout@v5
uses: actions/checkout@1af3b93b6815bc44a9784bd300feb67ff0d1eeb3 # 6.0.0
with:
fetch-depth: 0
persist-credentials: false
- name: Update Gradle Wrapper
uses: gradle-update/update-gradle-wrapper-action@v2
uses: gradle-update/update-gradle-wrapper-action@512b1875f3b6270828abfe77b247d5895a2da1e5 # 2.1.0
+1 -1
View File
@@ -12,7 +12,7 @@ Supported Versions
-
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
- in **ViaFabricPlus**, put ViaBackwards into the `config/viafabriclus/jars` folder
See [HERE](https://viaversion.com) for an overview of the different Via* projects.
@@ -44,6 +44,7 @@ public class ViaBackwardsConfig extends Config implements com.viaversion.viaback
private boolean mapCustomModelData;
private boolean mapDisplayEntities;
private boolean suppressEmulationWarnings;
private boolean dialogsViaChests;
private DialogStyleConfig dialogStyleConfig;
public ViaBackwardsConfig(File configFile, Logger logger) {
@@ -70,6 +71,7 @@ public class ViaBackwardsConfig extends Config implements com.viaversion.viaback
mapCustomModelData = getBoolean("map-custom-model-data", true);
mapDisplayEntities = getBoolean("map-display-entities", true);
suppressEmulationWarnings = getBoolean("suppress-emulation-warnings", false);
dialogsViaChests = getBoolean("dialogs-via-chests", true);
dialogStyleConfig = loadDialogStyleConfig(getSection("dialog-style"));
}
@@ -160,6 +162,11 @@ public class ViaBackwardsConfig extends Config implements com.viaversion.viaback
return suppressEmulationWarnings;
}
@Override
public boolean dialogsViaChests() {
return dialogsViaChests;
}
@Override
public DialogStyleConfig dialogStyleConfig() {
return dialogStyleConfig;
@@ -113,6 +113,13 @@ public interface ViaBackwardsConfig extends Config {
*/
boolean suppressEmulationWarnings();
/**
* If enabled, dialogs will be shown via chest inventories for 1.21.5 clients on 1.21.6+ servers.
*
* @return true if enabled
*/
boolean dialogsViaChests();
/**
* Returns the dialog style configuration.
*
@@ -55,6 +55,7 @@ import com.viaversion.viabackwards.protocol.v1_20_2to1_20.Protocol1_20_2To1_20;
import com.viaversion.viabackwards.protocol.v1_20_3to1_20_2.Protocol1_20_3To1_20_2;
import com.viaversion.viabackwards.protocol.v1_20_5to1_20_3.Protocol1_20_5To1_20_3;
import com.viaversion.viabackwards.protocol.v1_20to1_19_4.Protocol1_20To1_19_4;
import com.viaversion.viabackwards.protocol.v1_21_11to1_21_9.Protocol1_21_11To1_21_9;
import com.viaversion.viabackwards.protocol.v1_21_2to1_21.Protocol1_21_2To1_21;
import com.viaversion.viabackwards.protocol.v1_21_2to1_21.task.PlayerPacketsTickTask;
import com.viaversion.viabackwards.protocol.v1_21_4to1_21_2.Protocol1_21_4To1_21_2;
@@ -77,13 +78,16 @@ import java.util.logging.Logger;
public interface ViaBackwardsPlatform {
String MINIMUM_VV_VERSION = "5.5.1";
String MINIMUM_VV_VERSION = "5.7.0";
default void init(final File configFile) {
init(new ViaBackwardsConfig(configFile, getLogger()));
}
/**
* Initialize ViaBackwards.
*/
default void init(final File configFile) {
ViaBackwardsConfig config = new ViaBackwardsConfig(configFile, getLogger());
default void init(final ViaBackwardsConfig config) {
config.reload();
Via.getManager().getConfigurationProvider().register(config);
@@ -156,6 +160,7 @@ public interface ViaBackwardsPlatform {
protocolManager.registerProtocol(new Protocol1_21_6To1_21_5(), ProtocolVersion.v1_21_5, ProtocolVersion.v1_21_6);
protocolManager.registerProtocol(new Protocol1_21_7To1_21_6(), ProtocolVersion.v1_21_6, ProtocolVersion.v1_21_7);
protocolManager.registerProtocol(new Protocol1_21_9To1_21_7(), ProtocolVersion.v1_21_7, ProtocolVersion.v1_21_9);
protocolManager.registerProtocol(new Protocol1_21_11To1_21_9(), ProtocolVersion.v1_21_9, ProtocolVersion.v1_21_11);
}
default void enable() {
@@ -300,7 +300,11 @@ public class BackwardsStructuredItemRewriter<C extends ClientboundPacketType, S
}
protected Holder<SoundEvent> restoreSoundEventHolder(final CompoundTag tag) {
return restoreHolder(tag, "sound_event", soundEventTag -> {
return restoreSoundEventHolder(tag, "sound_event");
}
protected Holder<SoundEvent> restoreSoundEventHolder(final CompoundTag tag, final String key) {
return restoreHolder(tag, key, soundEventTag -> {
final String identifier = soundEventTag.getString("identifier");
final FloatTag fixedRange = soundEventTag.getFloatTag("fixed_range");
return new SoundEvent(identifier, fixedRange != null ? fixedRange.asFloat() : null);
@@ -17,16 +17,13 @@
*/
package com.viaversion.viabackwards.protocol.template;
import com.viaversion.viabackwards.api.rewriters.BackwardsRegistryRewriter;
import com.viaversion.viabackwards.api.rewriters.EntityRewriter;
import com.viaversion.viaversion.api.minecraft.entities.EntityType;
import com.viaversion.viaversion.api.minecraft.entities.EntityTypes1_21_4;
import com.viaversion.viaversion.api.minecraft.entitydata.types.EntityDataTypes1_21_2;
import com.viaversion.viaversion.api.type.types.version.VersionedTypes;
import com.viaversion.viaversion.protocols.v1_20_5to1_21.packet.ClientboundConfigurationPackets1_21;
import com.viaversion.viaversion.protocols.v1_21to1_21_2.packet.ClientboundPacket1_21_2;
import com.viaversion.viaversion.protocols.v1_21to1_21_2.packet.ClientboundPackets1_21_2;
import com.viaversion.viaversion.rewriter.RegistryDataRewriter;
// Replace if needed
// VersionedTypes
@@ -45,9 +42,6 @@ final class EntityPacketRewriter1_99 extends EntityRewriter<ClientboundPacket1_2
registerGameEvent(ClientboundPackets1_21_2.GAME_EVENT);
registerLogin1_20_5(ClientboundPackets1_21_2.LOGIN);
registerRespawn1_20_5(ClientboundPackets1_21_2.RESPAWN);
final RegistryDataRewriter registryDataRewriter = new BackwardsRegistryRewriter(protocol);
protocol.registerClientbound(ClientboundConfigurationPackets1_21.REGISTRY_DATA, registryDataRewriter::handle);
}
@Override
@@ -19,6 +19,7 @@ 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.BackwardsRegistryRewriter;
import com.viaversion.viabackwards.api.rewriters.SoundRewriter;
import com.viaversion.viabackwards.api.rewriters.text.NBTComponentRewriter;
import com.viaversion.viaversion.api.connection.UserConnection;
@@ -37,9 +38,9 @@ import com.viaversion.viaversion.protocols.v1_21_2to1_21_4.packet.ServerboundPac
import com.viaversion.viaversion.protocols.v1_21to1_21_2.packet.ClientboundPacket1_21_2;
import com.viaversion.viaversion.protocols.v1_21to1_21_2.packet.ClientboundPackets1_21_2;
import com.viaversion.viaversion.rewriter.ParticleRewriter;
import com.viaversion.viaversion.rewriter.RegistryDataRewriter;
import com.viaversion.viaversion.rewriter.StatisticsRewriter;
import com.viaversion.viaversion.rewriter.TagRewriter;
import com.viaversion.viaversion.util.SerializerVersion;
import static com.viaversion.viaversion.util.ProtocolUtil.packetTypeMap;
@@ -62,6 +63,7 @@ final class Protocol1_99To1_98 extends BackwardsProtocol<ClientboundPacket1_21_2
private final ParticleRewriter<ClientboundPacket1_21_2> particleRewriter = new ParticleRewriter<>(this);
private final NBTComponentRewriter<ClientboundPacket1_21_2> translatableRewriter = new ComponentRewriter1_99(this);
private final TagRewriter<ClientboundPacket1_21_2> tagRewriter = new TagRewriter<>(this);
private final RegistryDataRewriter registryDataRewriter = new BackwardsRegistryRewriter(this);
public Protocol1_99To1_98() {
super(ClientboundPacket1_21_2.class, ClientboundPacket1_21_2.class, ServerboundPacket1_21_4.class, ServerboundPacket1_21_4.class);
@@ -71,6 +73,8 @@ final class Protocol1_99To1_98 extends BackwardsProtocol<ClientboundPacket1_21_2
protected void registerPackets() {
super.registerPackets();
registerClientbound(ClientboundConfigurationPackets1_21.REGISTRY_DATA, registryDataRewriter::handle);
tagRewriter.registerGeneric(ClientboundPackets1_21_2.UPDATE_TAGS);
tagRewriter.registerGeneric(ClientboundConfigurationPackets1_21.UPDATE_TAGS);
@@ -89,12 +93,16 @@ final class Protocol1_99To1_98 extends BackwardsProtocol<ClientboundPacket1_21_2
translatableRewriter.registerComponentPacket(ClientboundPackets1_21_2.SET_SUBTITLE_TEXT);
translatableRewriter.registerBossEvent(ClientboundPackets1_21_2.BOSS_EVENT);
translatableRewriter.registerComponentPacket(ClientboundPackets1_21_2.DISCONNECT);
translatableRewriter.registerComponentPacket(ClientboundConfigurationPackets1_21.DISCONNECT);
translatableRewriter.registerTabList(ClientboundPackets1_21_2.TAB_LIST);
translatableRewriter.registerSetPlayerTeam1_21_5(ClientboundPackets1_21_2.SET_PLAYER_TEAM);
translatableRewriter.registerPlayerCombatKill1_20(ClientboundPackets1_21_2.PLAYER_COMBAT_KILL);
translatableRewriter.registerPlayerInfoUpdate1_21_4(ClientboundPackets1_21_2.PLAYER_INFO_UPDATE);
translatableRewriter.registerComponentPacket(ClientboundPackets1_21_2.SYSTEM_CHAT);
translatableRewriter.registerDisguisedChat(ClientboundPackets1_21_2.DISGUISED_CHAT);
translatableRewriter.registerPlayerChat1_21_5(ClientboundPackets1_21_2.PLAYER_CHAT);
translatableRewriter.registerSetObjective(ClientboundPackets1_21_2.SET_OBJECTIVE);
translatableRewriter.registerSetScore1_20_3(ClientboundPackets1_21_2.SET_SCORE);
translatableRewriter.registerPing();
// If needed for any particle, item, or block changes. Extend ParticleRewriter for particle serializer changes
@@ -123,6 +131,11 @@ final class Protocol1_99To1_98 extends BackwardsProtocol<ClientboundPacket1_21_2
return itemRewriter;
}
@Override
public RegistryDataRewriter getRegistryDataRewriter() {
return registryDataRewriter;
}
@Override
public ParticleRewriter<ClientboundPacket1_21_2> getParticleRewriter() {
return particleRewriter;
@@ -114,7 +114,7 @@ public class BlockItemPacketRewriter1_12 extends LegacyBlockItemRewriter<Clientb
PacketWrapper confirm = wrapper.create(ServerboundPackets1_12.CONTAINER_ACK);
confirm.write(Types.BYTE, wrapper.get(Types.BYTE, 0));
confirm.write(Types.SHORT, wrapper.get(Types.SHORT, 1));
confirm.write(Types.BOOLEAN, false); // Success - not used
confirm.write(Types.BOOLEAN, true); // Success - not used
wrapper.sendToServer(Protocol1_12To1_11_1.class);
wrapper.cancel();
@@ -69,7 +69,9 @@ public class Protocol1_13_1To1_13 extends BackwardsProtocol<ClientboundPackets1_
translatableRewriter.registerPlayerCombat(ClientboundPackets1_13.PLAYER_COMBAT);
translatableRewriter.registerComponentPacket(ClientboundPackets1_13.DISCONNECT);
translatableRewriter.registerTabList(ClientboundPackets1_13.TAB_LIST);
translatableRewriter.registerSetPlayerTeam1_13(ClientboundPackets1_13.SET_PLAYER_TEAM);
translatableRewriter.registerTitle(ClientboundPackets1_13.SET_TITLES);
translatableRewriter.registerSetObjective(ClientboundPackets1_13.SET_OBJECTIVE);
translatableRewriter.registerPing();
new CommandRewriter1_13_1(this).registerDeclareCommands(ClientboundPackets1_13.COMMANDS);
@@ -508,7 +508,7 @@ public class BlockItemPacketRewriter1_13 extends BackwardsItemRewriter<Clientbou
if (originalId == 362) { // base/colorless shulker box
rawId = 0xe50000; // purple shulker box
} else {
if (!Via.getConfig().isSuppressConversionWarnings()) {
if (Via.getConfig().logOtherConversionWarnings()) {
protocol.getLogger().warning("Failed to get new item for " + originalId);
}
@@ -818,7 +818,7 @@ public class BlockItemPacketRewriter1_13 extends BackwardsItemRewriter<Clientbou
} else if (protocol.getMappingData().getItemMappings().inverse().getNewId(rawId & ~0xF) != -1) {
rawId &= ~0xF; // Remove data
} else {
if (!Via.getConfig().isSuppressConversionWarnings()) {
if (Via.getConfig().logOtherConversionWarnings()) {
protocol.getLogger().warning("Failed to get old item for " + item.identifier());
}
rawId = 16; // Stone
@@ -81,7 +81,7 @@ public class PlayerPacketRewriter1_13 extends RewriterBase<Protocol1_13To1_12_2>
} else {
String oldChannel = ItemPacketRewriter1_13.getOldPluginChannelId(channel);
if (oldChannel == null) {
if (!Via.getConfig().isSuppressConversionWarnings()) {
if (Via.getConfig().logOtherConversionWarnings()) {
protocol.getLogger().warning("Ignoring clientbound plugin message with channel: " + channel);
}
wrapper.cancel();
@@ -96,7 +96,7 @@ public class PlayerPacketRewriter1_13 extends RewriterBase<Protocol1_13To1_12_2>
String rewritten = ItemPacketRewriter1_13.getOldPluginChannelId(s);
if (rewritten != null) {
rewrittenChannels.add(rewritten);
} else if (!Via.getConfig().isSuppressConversionWarnings()) {
} else if (Via.getConfig().logOtherConversionWarnings()) {
protocol.getLogger().warning("Ignoring plugin channel in clientbound " + oldChannel + ": " + s);
}
}
@@ -367,7 +367,7 @@ public class PlayerPacketRewriter1_13 extends RewriterBase<Protocol1_13To1_12_2>
//Maybe older versions used this and we need to implement this? The issue is that we would have to save the command block types
wrapper.setPacketType(ServerboundPackets1_13.SET_COMMAND_BLOCK);
wrapper.cancel();
if (!Via.getConfig().isSuppressConversionWarnings()) {
if (Via.getConfig().logOtherConversionWarnings()) {
protocol.getLogger().warning("Client send MC|AdvCmd custom payload to update command block, weird!");
}
} else if (type == 1) {
@@ -457,7 +457,7 @@ public class PlayerPacketRewriter1_13 extends RewriterBase<Protocol1_13To1_12_2>
default -> {
String newChannel = ItemPacketRewriter1_13.getNewPluginChannelId(channel);
if (newChannel == null) {
if (!Via.getConfig().isSuppressConversionWarnings()) {
if (Via.getConfig().logOtherConversionWarnings()) {
protocol.getLogger().warning("Ignoring serverbound plugin message with channel: " + channel);
}
wrapper.cancel();
@@ -472,7 +472,7 @@ public class PlayerPacketRewriter1_13 extends RewriterBase<Protocol1_13To1_12_2>
String rewritten = ItemPacketRewriter1_13.getNewPluginChannelId(s);
if (rewritten != null) {
rewrittenChannels.add(rewritten);
} else if (!Via.getConfig().isSuppressConversionWarnings()) {
} else if (Via.getConfig().logOtherConversionWarnings()) {
protocol.getLogger().warning("Ignoring plugin channel in serverbound " + Key.stripMinecraftNamespace(newChannel).toUpperCase(Locale.ROOT) + ": " + s);
}
}
@@ -62,7 +62,9 @@ public class Protocol1_14To1_13_2 extends BackwardsProtocol<ClientboundPackets1_
translatableRewriter.registerPlayerCombat(ClientboundPackets1_14.PLAYER_COMBAT);
translatableRewriter.registerComponentPacket(ClientboundPackets1_14.DISCONNECT);
translatableRewriter.registerTabList(ClientboundPackets1_14.TAB_LIST);
translatableRewriter.registerSetPlayerTeam1_13(ClientboundPackets1_14.SET_PLAYER_TEAM);
translatableRewriter.registerTitle(ClientboundPackets1_14.SET_TITLES);
translatableRewriter.registerSetObjective(ClientboundPackets1_14.SET_OBJECTIVE);
translatableRewriter.registerPing();
particleRewriter.registerLevelParticles1_13(ClientboundPackets1_14.LEVEL_PARTICLES, Types.FLOAT);
@@ -487,7 +487,7 @@ public class EntityPacketRewriter1_14 extends LegacyEntityRewriter<ClientboundPa
filter().handler((event, data) -> {
if (data.dataType().typeId() > 15) {
throw new IllegalArgumentException("Unhandled entity data: " + data);
event.cancel(); // Cancel bad data (generally from plugins sending data for despawned entities)
}
});
}
@@ -64,7 +64,9 @@ public class Protocol1_15To1_14_4 extends BackwardsProtocol<ClientboundPackets1_
translatableRewriter.registerComponentPacket(ClientboundPackets1_15.DISCONNECT);
translatableRewriter.registerOpenScreen1_14(ClientboundPackets1_15.OPEN_SCREEN);
translatableRewriter.registerTabList(ClientboundPackets1_15.TAB_LIST);
translatableRewriter.registerSetPlayerTeam1_13(ClientboundPackets1_15.SET_PLAYER_TEAM);
translatableRewriter.registerTitle(ClientboundPackets1_15.SET_TITLES);
translatableRewriter.registerSetObjective(ClientboundPackets1_15.SET_OBJECTIVE);
translatableRewriter.registerPing();
SoundRewriter<ClientboundPackets1_15> soundRewriter = new SoundRewriter<>(this);
@@ -67,7 +67,9 @@ public class Protocol1_16_2To1_16_1 extends BackwardsProtocol<ClientboundPackets
translatableRewriter.registerComponentPacket(ClientboundPackets1_16_2.DISCONNECT);
translatableRewriter.registerTabList(ClientboundPackets1_16_2.TAB_LIST);
translatableRewriter.registerTitle(ClientboundPackets1_16_2.SET_TITLES);
translatableRewriter.registerSetPlayerTeam1_13(ClientboundPackets1_16_2.SET_PLAYER_TEAM);
translatableRewriter.registerOpenScreen1_14(ClientboundPackets1_16_2.OPEN_SCREEN);
translatableRewriter.registerSetObjective(ClientboundPackets1_16_2.SET_OBJECTIVE);
translatableRewriter.registerPing();
particleRewriter.registerLevelParticles1_13(ClientboundPackets1_16_2.LEVEL_PARTICLES, Types.DOUBLE);
@@ -136,7 +136,7 @@ public final class BiomeMappings1_16_1 {
public static int toLegacyBiome(String biome) {
final int legacyBiome = MODERN_TO_LEGACY_ID.getInt(Key.stripMinecraftNamespace(biome));
if (legacyBiome == -1) {
if (!Via.getConfig().isSuppressConversionWarnings()) {
if (Via.getConfig().logOtherConversionWarnings()) {
Protocol1_16_2To1_16_1.LOGGER.warning("Biome with id " + biome + " has no legacy biome mapping (custom datapack?)");
}
return 1; // Plains
@@ -70,7 +70,9 @@ public class Protocol1_16To1_15_2 extends BackwardsProtocol<ClientboundPackets1_
translatableRewriter.registerPlayerCombat(ClientboundPackets1_16.PLAYER_COMBAT);
translatableRewriter.registerComponentPacket(ClientboundPackets1_16.DISCONNECT);
translatableRewriter.registerTabList(ClientboundPackets1_16.TAB_LIST);
translatableRewriter.registerSetPlayerTeam1_13(ClientboundPackets1_16.SET_PLAYER_TEAM);
translatableRewriter.registerTitle(ClientboundPackets1_16.SET_TITLES);
translatableRewriter.registerSetObjective(ClientboundPackets1_16.SET_OBJECTIVE);
translatableRewriter.registerPing();
particleRewriter.registerLevelParticles1_13(ClientboundPackets1_16.LEVEL_PARTICLES, Types.DOUBLE);
@@ -74,7 +74,9 @@ public final class Protocol1_17To1_16_4 extends BackwardsProtocol<ClientboundPac
translatableRewriter.registerBossEvent(ClientboundPackets1_17.BOSS_EVENT);
translatableRewriter.registerComponentPacket(ClientboundPackets1_17.DISCONNECT);
translatableRewriter.registerTabList(ClientboundPackets1_17.TAB_LIST);
translatableRewriter.registerSetPlayerTeam1_13(ClientboundPackets1_17.SET_PLAYER_TEAM);
translatableRewriter.registerOpenScreen1_14(ClientboundPackets1_17.OPEN_SCREEN);
translatableRewriter.registerSetObjective(ClientboundPackets1_17.SET_OBJECTIVE);
translatableRewriter.registerPing();
SoundRewriter<ClientboundPackets1_17> soundRewriter = new SoundRewriter<>(this);
@@ -102,7 +104,7 @@ public final class Protocol1_17To1_16_4 extends BackwardsProtocol<ClientboundPac
// Put them into the hardcoded order of Vanilla tags (and only those), rewrite ids
for (RegistryType type : TAG_REGISTRY_TYPES) {
List<TagData> tagList = tags.get(type.resourceLocation());
List<TagData> tagList = tags.get(type.identifier());
if (tagList == null) {
// Higher versions may not send the otherwise expected tags
wrapper.write(Types.VAR_INT, 0);
@@ -43,7 +43,7 @@ public final class Protocol1_18_2To1_18 extends BackwardsProtocol<ClientboundPac
final PacketHandler entityEffectIdHandler = wrapper -> {
final int id = wrapper.read(Types.VAR_INT);
if ((byte) id != id) {
if (!Via.getConfig().isSuppressConversionWarnings()) {
if (Via.getConfig().logOtherConversionWarnings()) {
getLogger().warning("Cannot send entity effect id " + id + " to old client");
}
wrapper.cancel();
@@ -82,8 +82,10 @@ public final class Protocol1_19_1To1_19 extends BackwardsProtocol<ClientboundPac
translatableRewriter.registerBossEvent(ClientboundPackets1_19_1.BOSS_EVENT);
translatableRewriter.registerComponentPacket(ClientboundPackets1_19_1.DISCONNECT);
translatableRewriter.registerTabList(ClientboundPackets1_19_1.TAB_LIST);
translatableRewriter.registerSetPlayerTeam1_13(ClientboundPackets1_19_1.SET_PLAYER_TEAM);
translatableRewriter.registerOpenScreen1_14(ClientboundPackets1_19_1.OPEN_SCREEN);
translatableRewriter.registerPlayerCombatKill(ClientboundPackets1_19_1.PLAYER_COMBAT_KILL);
translatableRewriter.registerSetObjective(ClientboundPackets1_19_1.SET_OBJECTIVE);
translatableRewriter.registerPing();
entityRewriter.register();
@@ -93,8 +93,10 @@ public final class Protocol1_19_3To1_19_1 extends BackwardsProtocol<ClientboundP
translatableRewriter.registerBossEvent(ClientboundPackets1_19_3.BOSS_EVENT);
translatableRewriter.registerComponentPacket(ClientboundPackets1_19_3.DISCONNECT);
translatableRewriter.registerTabList(ClientboundPackets1_19_3.TAB_LIST);
translatableRewriter.registerSetPlayerTeam1_13(ClientboundPackets1_19_3.SET_PLAYER_TEAM);
translatableRewriter.registerOpenScreen1_14(ClientboundPackets1_19_3.OPEN_SCREEN);
translatableRewriter.registerPlayerCombatKill(ClientboundPackets1_19_3.PLAYER_COMBAT_KILL);
translatableRewriter.registerSetObjective(ClientboundPackets1_19_3.SET_OBJECTIVE);
translatableRewriter.registerPing();
particleRewriter.registerLevelParticles1_19(ClientboundPackets1_19_3.LEVEL_PARTICLES);
@@ -71,8 +71,10 @@ public final class Protocol1_19_4To1_19_3 extends BackwardsProtocol<ClientboundP
translatableRewriter.registerComponentPacket(ClientboundPackets1_19_4.DISCONNECT);
translatableRewriter.registerTabList(ClientboundPackets1_19_4.TAB_LIST);
translatableRewriter.registerPlayerCombatKill(ClientboundPackets1_19_4.PLAYER_COMBAT_KILL);
translatableRewriter.registerSetPlayerTeam1_13(ClientboundPackets1_19_4.SET_PLAYER_TEAM);
translatableRewriter.registerComponentPacket(ClientboundPackets1_19_4.SYSTEM_CHAT);
translatableRewriter.registerComponentPacket(ClientboundPackets1_19_4.DISGUISED_CHAT);
translatableRewriter.registerSetObjective(ClientboundPackets1_19_4.SET_OBJECTIVE);
translatableRewriter.registerPing();
particleRewriter.registerLevelParticles1_19(ClientboundPackets1_19_4.LEVEL_PARTICLES);
@@ -45,6 +45,8 @@ import com.viaversion.viaversion.util.TagUtil;
public final class EntityPacketRewriter1_19_4 extends EntityRewriter<ClientboundPackets1_19_4, Protocol1_19_4To1_19_3> {
private static final double TEXT_DISPLAY_Y_OFFSET = -0.25; // Move emulated armor stands down to match text display height offsets
public EntityPacketRewriter1_19_4(final Protocol1_19_4To1_19_3 protocol) {
super(protocol, Types1_19_3.ENTITY_DATA_TYPES.optionalComponentType, Types1_19_3.ENTITY_DATA_TYPES.booleanType);
}
@@ -78,6 +80,11 @@ public final class EntityPacketRewriter1_19_4 extends EntityRewriter<Clientbound
}
}
final double y = wrapper.get(Types.DOUBLE, 1);
if (entityType == EntityTypes1_19_4.TEXT_DISPLAY.getId()) {
wrapper.set(Types.DOUBLE, 1, y + TEXT_DISPLAY_Y_OFFSET);
}
// First track (and remap) entity, then put storage for block display entity
getSpawnTrackerWithDataHandler1_19(EntityTypes1_19_4.FALLING_BLOCK).handle(wrapper);
if (entityType != EntityTypes1_19_4.BLOCK_DISPLAY.getId()) {
@@ -88,7 +95,6 @@ public final class EntityPacketRewriter1_19_4 extends EntityRewriter<Clientbound
if (data != null) {
final LinkedEntityStorage storage = new LinkedEntityStorage();
final double x = wrapper.get(Types.DOUBLE, 0);
final double y = wrapper.get(Types.DOUBLE, 1);
final double z = wrapper.get(Types.DOUBLE, 2);
storage.setPosition(x, y, z);
data.put(storage);
@@ -183,7 +189,7 @@ public final class EntityPacketRewriter1_19_4 extends EntityRewriter<Clientbound
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
// Handle infinite 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);
});
@@ -198,11 +204,14 @@ public final class EntityPacketRewriter1_19_4 extends EntityRewriter<Clientbound
final double z = wrapper.passthrough(Types.DOUBLE);
final EntityTracker1_19_4 tracker = tracker(wrapper.user());
final LinkedEntityStorage storage = tracker.linkedEntityStorage(entityId);
if (storage == null) {
return;
if (tracker.entityType(entityId) == EntityTypes1_19_4.TEXT_DISPLAY) {
wrapper.set(Types.DOUBLE, 1, y + TEXT_DISPLAY_Y_OFFSET);
}
final LinkedEntityStorage storage = tracker.linkedEntityStorage(entityId);
if (storage != null) {
storage.setPosition(x, y, z);
}
storage.setPosition(x, y, z);
});
final PacketHandler entityPositionHandler = wrapper -> {
@@ -213,10 +222,9 @@ public final class EntityPacketRewriter1_19_4 extends EntityRewriter<Clientbound
final EntityTracker1_19_4 tracker = tracker(wrapper.user());
final LinkedEntityStorage storage = tracker.linkedEntityStorage(entityId);
if (storage == null) {
return;
if (storage != null) {
storage.addRelativePosition(x, y, z);
}
storage.addRelativePosition(x, y, z);
};
protocol.registerClientbound(ClientboundPackets1_19_4.MOVE_ENTITY_POS, entityPositionHandler);
@@ -86,8 +86,10 @@ public final class Protocol1_19To1_18_2 extends BackwardsProtocol<ClientboundPac
translatableRewriter.registerBossEvent(ClientboundPackets1_19.BOSS_EVENT);
translatableRewriter.registerComponentPacket(ClientboundPackets1_19.DISCONNECT);
translatableRewriter.registerTabList(ClientboundPackets1_19.TAB_LIST);
translatableRewriter.registerSetPlayerTeam1_13(ClientboundPackets1_19.SET_PLAYER_TEAM);
translatableRewriter.registerOpenScreen1_14(ClientboundPackets1_19.OPEN_SCREEN);
translatableRewriter.registerPlayerCombatKill(ClientboundPackets1_19.PLAYER_COMBAT_KILL);
translatableRewriter.registerSetObjective(ClientboundPackets1_19.SET_OBJECTIVE);
translatableRewriter.registerPing();
final SoundRewriter<ClientboundPackets1_19> soundRewriter = new SoundRewriter<>(this);
@@ -110,12 +110,16 @@ public final class Protocol1_20_5To1_20_3 extends BackwardsProtocol<ClientboundP
translatableRewriter.registerComponentPacket(ClientboundPackets1_20_5.SET_SUBTITLE_TEXT);
translatableRewriter.registerBossEvent(ClientboundPackets1_20_5.BOSS_EVENT);
translatableRewriter.registerComponentPacket(ClientboundPackets1_20_5.DISCONNECT);
translatableRewriter.registerComponentPacket(ClientboundConfigurationPackets1_20_5.DISCONNECT);
translatableRewriter.registerTabList(ClientboundPackets1_20_5.TAB_LIST);
translatableRewriter.registerSetPlayerTeam1_13(ClientboundPackets1_20_5.SET_PLAYER_TEAM);
translatableRewriter.registerPlayerCombatKill1_20(ClientboundPackets1_20_5.PLAYER_COMBAT_KILL);
translatableRewriter.registerComponentPacket(ClientboundPackets1_20_5.SYSTEM_CHAT);
translatableRewriter.registerComponentPacket(ClientboundPackets1_20_5.DISGUISED_CHAT);
translatableRewriter.registerPlayerChat(ClientboundPackets1_20_5.PLAYER_CHAT, Types.VAR_INT);
translatableRewriter.registerPlayerInfoUpdate1_20_3(ClientboundPackets1_20_5.PLAYER_INFO_UPDATE);
translatableRewriter.registerSetObjective(ClientboundPackets1_20_5.SET_OBJECTIVE);
translatableRewriter.registerSetScore1_20_3(ClientboundPackets1_20_5.SET_SCORE);
translatableRewriter.registerPing();
registerClientbound(State.LOGIN, ClientboundLoginPackets.HELLO, wrapper -> {
@@ -71,8 +71,10 @@ public final class Protocol1_20To1_19_4 extends BackwardsProtocol<ClientboundPac
translatableRewriter.registerBossEvent(ClientboundPackets1_19_4.BOSS_EVENT);
translatableRewriter.registerComponentPacket(ClientboundPackets1_19_4.DISCONNECT);
translatableRewriter.registerTabList(ClientboundPackets1_19_4.TAB_LIST);
translatableRewriter.registerSetPlayerTeam1_13(ClientboundPackets1_19_4.SET_PLAYER_TEAM);
translatableRewriter.registerComponentPacket(ClientboundPackets1_19_4.SYSTEM_CHAT);
translatableRewriter.registerComponentPacket(ClientboundPackets1_19_4.DISGUISED_CHAT);
translatableRewriter.registerSetObjective(ClientboundPackets1_19_4.SET_OBJECTIVE);
translatableRewriter.registerPing();
registerClientbound(ClientboundPackets1_19_4.UPDATE_ENABLED_FEATURES, wrapper -> {
@@ -0,0 +1,273 @@
/*
* This file is part of ViaBackwards - https://github.com/ViaVersion/ViaBackwards
* Copyright (C) 2016-2025 ViaVersion and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.viaversion.viabackwards.protocol.v1_21_11to1_21_9;
import com.viaversion.nbt.tag.ByteTag;
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.StringTag;
import com.viaversion.nbt.tag.Tag;
import com.viaversion.viabackwards.api.BackwardsProtocol;
import com.viaversion.viabackwards.api.data.BackwardsMappingData;
import com.viaversion.viabackwards.api.rewriters.BackwardsRegistryRewriter;
import com.viaversion.viabackwards.api.rewriters.SoundRewriter;
import com.viaversion.viabackwards.api.rewriters.text.NBTComponentRewriter;
import com.viaversion.viabackwards.protocol.v1_21_11to1_21_9.rewriter.BlockItemPacketRewriter1_21_11;
import com.viaversion.viabackwards.protocol.v1_21_11to1_21_9.rewriter.ComponentRewriter1_21_11;
import com.viaversion.viabackwards.protocol.v1_21_11to1_21_9.rewriter.EntityPacketRewriter1_21_11;
import com.viaversion.viabackwards.protocol.v1_21_11to1_21_9.storage.GameTimeStorage;
import com.viaversion.viaversion.api.connection.UserConnection;
import com.viaversion.viaversion.api.data.FullMappings;
import com.viaversion.viaversion.api.minecraft.entities.EntityTypes1_21_11;
import com.viaversion.viaversion.api.protocol.packet.provider.PacketTypesProvider;
import com.viaversion.viaversion.api.protocol.packet.provider.SimplePacketTypesProvider;
import com.viaversion.viaversion.api.type.types.version.VersionedTypes;
import com.viaversion.viaversion.api.type.types.version.VersionedTypesHolder;
import com.viaversion.viaversion.data.entity.EntityTrackerBase;
import com.viaversion.viaversion.data.item.ItemHasherBase;
import com.viaversion.viaversion.protocols.v1_21_5to1_21_6.packet.ServerboundPackets1_21_6;
import com.viaversion.viaversion.protocols.v1_21_7to1_21_9.packet.ClientboundConfigurationPackets1_21_9;
import com.viaversion.viaversion.protocols.v1_21_7to1_21_9.packet.ClientboundPacket1_21_9;
import com.viaversion.viaversion.protocols.v1_21_7to1_21_9.packet.ClientboundPackets1_21_9;
import com.viaversion.viaversion.protocols.v1_21_7to1_21_9.packet.ServerboundConfigurationPackets1_21_9;
import com.viaversion.viaversion.protocols.v1_21_7to1_21_9.packet.ServerboundPacket1_21_9;
import com.viaversion.viaversion.protocols.v1_21_9to1_21_11.Protocol1_21_9To1_21_11;
import com.viaversion.viaversion.protocols.v1_21_9to1_21_11.packet.ClientboundPacket1_21_11;
import com.viaversion.viaversion.protocols.v1_21_9to1_21_11.packet.ClientboundPackets1_21_11;
import com.viaversion.viaversion.rewriter.AttributeRewriter;
import com.viaversion.viaversion.rewriter.ParticleRewriter;
import com.viaversion.viaversion.rewriter.RegistryDataRewriter;
import com.viaversion.viaversion.rewriter.StatisticsRewriter;
import com.viaversion.viaversion.rewriter.TagRewriter;
import com.viaversion.viaversion.util.Key;
import com.viaversion.viaversion.util.TagUtil;
import java.util.function.Function;
import org.checkerframework.checker.nullness.qual.Nullable;
import static com.viaversion.viaversion.util.ProtocolUtil.packetTypeMap;
import static com.viaversion.viaversion.util.TagUtil.getNamespacedTag;
public final class Protocol1_21_11To1_21_9 extends BackwardsProtocol<ClientboundPacket1_21_11, ClientboundPacket1_21_9, ServerboundPacket1_21_9, ServerboundPacket1_21_9> {
public static final BackwardsMappingData MAPPINGS = new BackwardsMappingData("1.21.11", "1.21.9", Protocol1_21_9To1_21_11.class);
private static final int END_FOG_COLOR = 10518688;
private static final int OVERWORLD_FOG_COLOR = -4138753;
private final EntityPacketRewriter1_21_11 entityRewriter = new EntityPacketRewriter1_21_11(this);
private final BlockItemPacketRewriter1_21_11 itemRewriter = new BlockItemPacketRewriter1_21_11(this);
private final ParticleRewriter<ClientboundPacket1_21_11> particleRewriter = new ParticleRewriter<>(this);
private final NBTComponentRewriter<ClientboundPacket1_21_11> translatableRewriter = new ComponentRewriter1_21_11(this);
private final TagRewriter<ClientboundPacket1_21_11> tagRewriter = new TagRewriter<>(this);
private final RegistryDataRewriter registryDataRewriter = new BackwardsRegistryRewriter(this) {
@Override
protected void updateType(final CompoundTag tag, final String key, final FullMappings mappings) {
super.updateType(tag, key, mappings);
if (key.equals("sound") && tag.get(key) instanceof ListTag<?> listTag) {
// From a compact list to a single value
final Tag first;
if (listTag.isEmpty()) {
first = new StringTag(mappings.mappedIdentifier(0)); // Dummy
} else {
first = listTag.get(0);
}
tag.put(key, first);
}
}
};
public Protocol1_21_11To1_21_9() {
super(ClientboundPacket1_21_11.class, ClientboundPacket1_21_9.class, ServerboundPacket1_21_9.class, ServerboundPacket1_21_9.class);
}
private void moveAttribute(final CompoundTag baseTag, @Nullable final CompoundTag attributes, final String key, final String mappedKey, final Function<Tag, Tag> tagMapper, @Nullable final Tag defaultTag) {
final Tag attributeTag;
if (attributes != null && (attributeTag = getNamespacedTag(attributes, key)) != null) {
baseTag.put(mappedKey, tagMapper.apply(attributeTag));
} else if (defaultTag != null) {
baseTag.put(mappedKey, defaultTag);
}
}
private int floatsToARGB(final float r, final float g, final float b) {
return 255 << 24 | (int) (r * 255) << 16 | (int) (g * 255) << 8 | (int) (b * 255);
}
@Override
protected void registerPackets() {
super.registerPackets();
// Add back mandatory fields from attributes, though most don't have any use in the client
registryDataRewriter.addHandler("dimension_type", (key, tag) -> {
if (Key.equals(key, "the_nether")) {
tag.putString("effects", "minecraft:the_nether");
tag.putBoolean("natural", false);
} else if (Key.equals(key, "the_end")) {
tag.putString("effects", "minecraft:the_end");
tag.putBoolean("natural", false);
} else {
tag.putString("effects", "minecraft:overworld");
tag.putBoolean("natural", true);
}
final ByteTag trueTag = new ByteTag((byte) 1);
final CompoundTag attributes = tag.getCompoundTag("attributes");
moveAttribute(tag, attributes, "visual/cloud_height", "cloud_height", Function.identity(), null);
moveAttribute(tag, attributes, "gameplay/can_start_raid", "has_raids", Function.identity(), trueTag);
moveAttribute(tag, attributes, "gameplay/can_start_raid", "has_raids", Function.identity(), trueTag);
moveAttribute(tag, attributes, "gameplay/piglins_zombify", "piglin_safe", attributeTag -> ((NumberTag) attributeTag).asBoolean() ? ByteTag.ZERO : trueTag, ByteTag.ZERO);
moveAttribute(tag, attributes, "gameplay/respawn_anchor_works", "respawn_anchor_works", Function.identity(), trueTag);
moveAttribute(tag, attributes, "gameplay/bed_rule", "bed_works", attributeTag -> {
final CompoundTag bedRule = (CompoundTag) attributeTag;
return bedRule.getBoolean("can_sleep") || bedRule.getBoolean("can_set_spawn") ? trueTag : ByteTag.ZERO;
}, trueTag);
// Many different functions back into one, all have different effects on the client, so pick the most important one...
moveAttribute(tag, attributes, "gameplay/fast_lava", "ultrawarm", Function.identity(), ByteTag.ZERO);
});
registryDataRewriter.addHandler("worldgen/biome", (key, tag) -> {
final CompoundTag effects = tag.getCompoundTag("effects");
final CompoundTag attributes = tag.removeUnchecked("attributes");
moveAttribute(effects, attributes, "visual/sky_color", "sky_color", this::mapColor, new IntTag(0));
moveAttribute(effects, attributes, "visual/water_fog_color", "water_fog_color", this::mapColor, new IntTag(-16448205));
moveAttribute(effects, attributes, "visual/fog_color", "fog_color", this::mapColor, new IntTag(Key.equals(key, "the_end") ? END_FOG_COLOR : OVERWORLD_FOG_COLOR)); // overworld fog color as default
moveAttribute(effects, effects, "water_color", "water_color", this::mapColor, new IntTag(4159204));
moveAttribute(effects, effects, "foliage_color", "foliage_color", this::mapColor, null);
moveAttribute(effects, effects, "dry_foliage_color", "dry_foliage_color", this::mapColor, null);
moveAttribute(effects, effects, "grass_color", "grass_color", this::mapColor, null);
});
registryDataRewriter.addHandler("enchantment", (key, tag) -> {
final CompoundTag effects = tag.getCompoundTag("effects");
if (effects != null) {
TagUtil.removeNamespaced(effects, "post_piercing_attack");
}
});
registryDataRewriter.remove("zombie_nautilus_variant");
registryDataRewriter.remove("timeline");
registerClientbound(ClientboundConfigurationPackets1_21_9.REGISTRY_DATA, registryDataRewriter::handle);
tagRewriter.removeTags("timeline");
tagRewriter.registerGeneric(ClientboundPackets1_21_11.UPDATE_TAGS);
tagRewriter.registerGeneric(ClientboundConfigurationPackets1_21_9.UPDATE_TAGS);
final SoundRewriter<ClientboundPacket1_21_11> soundRewriter = new SoundRewriter<>(this);
soundRewriter.registerSound1_19_3(ClientboundPackets1_21_11.SOUND);
soundRewriter.registerSound1_19_3(ClientboundPackets1_21_11.SOUND_ENTITY);
soundRewriter.registerStopSound(ClientboundPackets1_21_11.STOP_SOUND);
new StatisticsRewriter<>(this).register(ClientboundPackets1_21_11.AWARD_STATS);
new AttributeRewriter<>(this).register1_21(ClientboundPackets1_21_11.UPDATE_ATTRIBUTES);
translatableRewriter.registerOpenScreen1_14(ClientboundPackets1_21_11.OPEN_SCREEN);
translatableRewriter.registerComponentPacket(ClientboundPackets1_21_11.SET_ACTION_BAR_TEXT);
translatableRewriter.registerComponentPacket(ClientboundPackets1_21_11.SET_TITLE_TEXT);
translatableRewriter.registerComponentPacket(ClientboundPackets1_21_11.SET_SUBTITLE_TEXT);
translatableRewriter.registerBossEvent(ClientboundPackets1_21_11.BOSS_EVENT);
translatableRewriter.registerComponentPacket(ClientboundPackets1_21_11.DISCONNECT);
translatableRewriter.registerComponentPacket(ClientboundConfigurationPackets1_21_9.DISCONNECT);
translatableRewriter.registerTabList(ClientboundPackets1_21_11.TAB_LIST);
translatableRewriter.registerPlayerCombatKill1_20(ClientboundPackets1_21_11.PLAYER_COMBAT_KILL);
translatableRewriter.registerPlayerInfoUpdate1_21_4(ClientboundPackets1_21_11.PLAYER_INFO_UPDATE);
translatableRewriter.registerComponentPacket(ClientboundPackets1_21_11.SYSTEM_CHAT);
translatableRewriter.registerDisguisedChat(ClientboundPackets1_21_11.DISGUISED_CHAT);
translatableRewriter.registerPlayerChat1_21_5(ClientboundPackets1_21_11.PLAYER_CHAT);
translatableRewriter.registerSetObjective(ClientboundPackets1_21_11.SET_OBJECTIVE);
translatableRewriter.registerSetScore1_20_3(ClientboundPackets1_21_11.SET_SCORE);
translatableRewriter.registerPing();
particleRewriter.registerLevelParticles1_21_4(ClientboundPackets1_21_11.LEVEL_PARTICLES);
particleRewriter.registerExplode1_21_9(ClientboundPackets1_21_11.EXPLODE);
}
@Override
public void init(final UserConnection connection) {
addEntityTracker(connection, new EntityTrackerBase(connection, EntityTypes1_21_11.PLAYER));
addItemHasher(connection, new ItemHasherBase(this, connection));
connection.put(new GameTimeStorage());
}
@Override
public BackwardsMappingData getMappingData() {
return MAPPINGS;
}
@Override
public EntityPacketRewriter1_21_11 getEntityRewriter() {
return entityRewriter;
}
@Override
public BlockItemPacketRewriter1_21_11 getItemRewriter() {
return itemRewriter;
}
@Override
public RegistryDataRewriter getRegistryDataRewriter() {
return registryDataRewriter;
}
@Override
public ParticleRewriter<ClientboundPacket1_21_11> getParticleRewriter() {
return particleRewriter;
}
@Override
public NBTComponentRewriter<ClientboundPacket1_21_11> getComponentRewriter() {
return translatableRewriter;
}
@Override
public TagRewriter<ClientboundPacket1_21_11> getTagRewriter() {
return tagRewriter;
}
@Override
public VersionedTypesHolder types() {
return VersionedTypes.V1_21_11;
}
@Override
public VersionedTypesHolder mappedTypes() {
return VersionedTypes.V1_21_9;
}
@Override
protected PacketTypesProvider<ClientboundPacket1_21_11, ClientboundPacket1_21_9, ServerboundPacket1_21_9, ServerboundPacket1_21_9> createPacketTypesProvider() {
return new SimplePacketTypesProvider<>(
packetTypeMap(unmappedClientboundPacketType, ClientboundPackets1_21_11.class, ClientboundConfigurationPackets1_21_9.class),
packetTypeMap(mappedClientboundPacketType, ClientboundPackets1_21_9.class, ClientboundConfigurationPackets1_21_9.class),
packetTypeMap(mappedServerboundPacketType, ServerboundPackets1_21_6.class, ServerboundConfigurationPackets1_21_9.class),
packetTypeMap(unmappedServerboundPacketType, ServerboundPackets1_21_6.class, ServerboundConfigurationPackets1_21_9.class)
);
}
private Tag mapColor(final Tag attributeTag) {
if (attributeTag instanceof ListTag<?> listTag) {
final NumberTag r = ((NumberTag) listTag.get(0));
final NumberTag g = ((NumberTag) listTag.get(1));
final NumberTag b = ((NumberTag) listTag.get(2));
return new IntTag(floatsToARGB(r.asFloat(), g.asFloat(), b.asFloat()));
} else if (attributeTag instanceof StringTag stringTag) {
// Remove '#' and parse hex string
return new IntTag(Integer.parseInt(stringTag.getValue().substring(1), 16));
}
return attributeTag;
}
}
@@ -0,0 +1,307 @@
/*
* This file is part of ViaBackwards - https://github.com/ViaVersion/ViaBackwards
* Copyright (C) 2016-2025 ViaVersion and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.viaversion.viabackwards.protocol.v1_21_11to1_21_9.rewriter;
import com.viaversion.nbt.tag.CompoundTag;
import com.viaversion.nbt.tag.IntTag;
import com.viaversion.nbt.tag.StringTag;
import com.viaversion.nbt.tag.Tag;
import com.viaversion.viabackwards.api.rewriters.BackwardsStructuredItemRewriter;
import com.viaversion.viabackwards.protocol.v1_21_11to1_21_9.Protocol1_21_11To1_21_9;
import com.viaversion.viabackwards.protocol.v1_21_11to1_21_9.storage.GameTimeStorage;
import com.viaversion.viaversion.api.connection.UserConnection;
import com.viaversion.viaversion.api.minecraft.Holder;
import com.viaversion.viaversion.api.minecraft.SoundEvent;
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.AttackRange;
import com.viaversion.viaversion.api.minecraft.item.data.DamageType;
import com.viaversion.viaversion.api.minecraft.item.data.KineticWeapon;
import com.viaversion.viaversion.api.minecraft.item.data.PiercingWeapon;
import com.viaversion.viaversion.api.minecraft.item.data.SwingAnimation;
import com.viaversion.viaversion.api.minecraft.item.data.UseEffects;
import com.viaversion.viaversion.api.type.Types;
import com.viaversion.viaversion.api.type.types.chunk.ChunkType1_21_5;
import com.viaversion.viaversion.protocols.v1_21_4to1_21_5.rewriter.RecipeDisplayRewriter1_21_5;
import com.viaversion.viaversion.protocols.v1_21_5to1_21_6.packet.ServerboundPackets1_21_6;
import com.viaversion.viaversion.protocols.v1_21_7to1_21_9.packet.ServerboundPacket1_21_9;
import com.viaversion.viaversion.protocols.v1_21_9to1_21_11.packet.ClientboundPacket1_21_11;
import com.viaversion.viaversion.protocols.v1_21_9to1_21_11.packet.ClientboundPackets1_21_11;
import com.viaversion.viaversion.rewriter.BlockRewriter;
import com.viaversion.viaversion.rewriter.RecipeDisplayRewriter;
import com.viaversion.viaversion.util.Either;
import org.checkerframework.checker.nullness.qual.Nullable;
import static com.viaversion.viaversion.protocols.v1_21_9to1_21_11.rewriter.BlockItemPacketRewriter1_21_11.downgradeData;
import static com.viaversion.viaversion.protocols.v1_21_9to1_21_11.rewriter.BlockItemPacketRewriter1_21_11.upgradeData;
public final class BlockItemPacketRewriter1_21_11 extends BackwardsStructuredItemRewriter<ClientboundPacket1_21_11, ServerboundPacket1_21_9, Protocol1_21_11To1_21_9> {
public BlockItemPacketRewriter1_21_11(final Protocol1_21_11To1_21_9 protocol) {
super(protocol);
}
@Override
public void registerPackets() {
final BlockRewriter<ClientboundPacket1_21_11> blockRewriter = BlockRewriter.for1_20_2(protocol);
blockRewriter.registerBlockEvent(ClientboundPackets1_21_11.BLOCK_EVENT);
blockRewriter.registerBlockUpdate(ClientboundPackets1_21_11.BLOCK_UPDATE);
blockRewriter.registerSectionBlocksUpdate1_20(ClientboundPackets1_21_11.SECTION_BLOCKS_UPDATE);
blockRewriter.registerLevelEvent1_21(ClientboundPackets1_21_11.LEVEL_EVENT, 2001);
blockRewriter.registerLevelChunk1_19(ClientboundPackets1_21_11.LEVEL_CHUNK_WITH_LIGHT, ChunkType1_21_5::new);
blockRewriter.registerBlockEntityData(ClientboundPackets1_21_11.BLOCK_ENTITY_DATA);
registerSetCursorItem(ClientboundPackets1_21_11.SET_CURSOR_ITEM);
registerSetPlayerInventory(ClientboundPackets1_21_11.SET_PLAYER_INVENTORY);
registerCooldown1_21_2(ClientboundPackets1_21_11.COOLDOWN);
registerSetContent1_21_2(ClientboundPackets1_21_11.CONTAINER_SET_CONTENT);
registerSetSlot1_21_2(ClientboundPackets1_21_11.CONTAINER_SET_SLOT);
registerAdvancements1_20_3(ClientboundPackets1_21_11.UPDATE_ADVANCEMENTS);
registerSetEquipment(ClientboundPackets1_21_11.SET_EQUIPMENT);
registerMerchantOffers1_20_5(ClientboundPackets1_21_11.MERCHANT_OFFERS);
registerContainerClick1_21_5(ServerboundPackets1_21_6.CONTAINER_CLICK);
registerSetCreativeModeSlot1_21_5(ServerboundPackets1_21_6.SET_CREATIVE_MODE_SLOT);
final RecipeDisplayRewriter<ClientboundPacket1_21_11> recipeRewriter = new RecipeDisplayRewriter1_21_5<>(protocol);
recipeRewriter.registerUpdateRecipes(ClientboundPackets1_21_11.UPDATE_RECIPES);
recipeRewriter.registerRecipeBookAdd(ClientboundPackets1_21_11.RECIPE_BOOK_ADD);
recipeRewriter.registerPlaceGhostRecipe(ClientboundPackets1_21_11.PLACE_GHOST_RECIPE);
protocol.registerClientbound(ClientboundPackets1_21_11.SET_BORDER_LERP_SIZE, wrapper -> {
wrapper.passthrough(Types.DOUBLE); // oldSize
wrapper.passthrough(Types.DOUBLE); // newSize
wrapper.write(Types.VAR_LONG, wrapper.read(Types.VAR_LONG) * 50); // lerpTime
});
protocol.registerClientbound(ClientboundPackets1_21_11.INITIALIZE_BORDER, wrapper -> {
wrapper.passthrough(Types.DOUBLE); // newCenterX
wrapper.passthrough(Types.DOUBLE); // newCenterZ
wrapper.passthrough(Types.DOUBLE); // oldSize
wrapper.passthrough(Types.DOUBLE); // newSize
wrapper.write(Types.VAR_LONG, wrapper.read(Types.VAR_LONG) * 50); // lerpTime
});
protocol.registerClientbound(ClientboundPackets1_21_11.SET_TIME, wrapper -> {
final long gameTime = wrapper.passthrough(Types.LONG);
wrapper.user().get(GameTimeStorage.class).setGameTime(gameTime);
});
protocol.registerServerbound(ServerboundPackets1_21_6.CLIENT_TICK_END, wrapper -> {
wrapper.user().get(GameTimeStorage.class).incrementGameTime();
});
}
@Override
protected void handleItemDataComponentsToClient(final UserConnection connection, final Item item, final StructuredDataContainer container) {
super.handleItemDataComponentsToClient(connection, item, container);
downgradeData(item, container);
}
@Override
protected void handleItemDataComponentsToServer(final UserConnection connection, final Item item, final StructuredDataContainer container) {
super.handleItemDataComponentsToServer(connection, item, container);
upgradeData(item, container);
}
@Override
protected void restoreBackupData(final Item item, final StructuredDataContainer container, final CompoundTag customData) {
super.restoreBackupData(item, container, customData);
if (!(customData.remove(nbtTagName("backup")) instanceof final CompoundTag backupTag)) {
return;
}
final CompoundTag swingTag = backupTag.getCompoundTag("swing_animation");
if (swingTag != null) {
final int type = swingTag.getInt("type");
final int duration = swingTag.getInt("duration");
container.set(StructuredDataKey.SWING_ANIMATION, new SwingAnimation(type, duration));
}
final CompoundTag kineticTag = backupTag.getCompoundTag("kinetic_weapon");
if (kineticTag != null) {
final int contactCooldownTicks = kineticTag.getInt("contact_cooldown_ticks");
final int delayTicks = kineticTag.getInt("delay_ticks");
final KineticWeapon.Condition damageConditions = loadDamageCondition(kineticTag, "damage_conditions");
final KineticWeapon.Condition dismountConditions = loadDamageCondition(kineticTag, "dismount_conditions");
final KineticWeapon.Condition knockbackConditions = loadDamageCondition(kineticTag, "knockback_conditions");
final float forwardMovement = kineticTag.getFloat("forward_movement");
final float damageMultiplier = kineticTag.getFloat("damage_multiplier");
final Holder<SoundEvent> sound = kineticTag.contains("sound") ? restoreSoundEventHolder(kineticTag, "sound") : null;
final Holder<SoundEvent> hitSound = kineticTag.contains("hit_sound") ? restoreSoundEventHolder(kineticTag, "hit_sound") : null;
container.set(StructuredDataKey.KINETIC_WEAPON, new KineticWeapon(contactCooldownTicks, delayTicks, damageConditions, dismountConditions, knockbackConditions, forwardMovement, damageMultiplier, sound, hitSound));
}
final CompoundTag piercingTag = backupTag.getCompoundTag("piercing_weapon");
if (piercingTag != null) {
final boolean dealsKnockback = piercingTag.getBoolean("deals_knockback");
final boolean dismounts = piercingTag.getBoolean("dismounts");
final Holder<SoundEvent> sound = piercingTag.contains("sound") ? restoreSoundEventHolder(piercingTag, "sound") : null;
final Holder<SoundEvent> hitSound = piercingTag.contains("hit_sound") ? restoreSoundEventHolder(piercingTag, "hit_sound") : null;
container.set(StructuredDataKey.PIERCING_WEAPON, new PiercingWeapon(dealsKnockback, dismounts, sound, hitSound));
}
final Tag damageTypeId = backupTag.get("damage_type_id");
if (damageTypeId != null) {
if (damageTypeId instanceof StringTag stringTag) {
container.set(StructuredDataKey.DAMAGE_TYPE, new DamageType(Either.right(stringTag.getValue())));
} else if (damageTypeId instanceof IntTag intTag) {
container.set(StructuredDataKey.DAMAGE_TYPE, new DamageType(Either.left(intTag.asInt())));
}
}
final CompoundTag useEffectsTag = backupTag.getCompoundTag("use_effects");
if (useEffectsTag != null) {
final boolean canSprint = useEffectsTag.getBoolean("can_sprint");
final boolean interactVibrations = useEffectsTag.getBoolean("interact_vibrations");
final float speedMultiplier = useEffectsTag.getFloat("speed_multiplier");
container.set(StructuredDataKey.USE_EFFECTS, new UseEffects(canSprint, interactVibrations, speedMultiplier));
}
final CompoundTag attackRangeTag = backupTag.getCompoundTag("attack_range");
if (attackRangeTag != null) {
final float minRange = attackRangeTag.getFloat("min_range");
final float maxRange = attackRangeTag.getFloat("max_range");
final float minCreativeRange = attackRangeTag.getFloat("min_creative_reach");
final float maxCreativeRange = attackRangeTag.getFloat("max_creative_reach");
final float hitboxMargin = attackRangeTag.getFloat("hitbox_margin");
final float mobFactor = attackRangeTag.getFloat("mob_factor");
container.set(StructuredDataKey.ATTACK_RANGE, new AttackRange(minRange, maxRange, minCreativeRange, maxCreativeRange, hitboxMargin, mobFactor));
}
final Tag zombieNautilusVariantTag = backupTag.get("zombie_nautilus_variant");
if (zombieNautilusVariantTag != null) {
if (zombieNautilusVariantTag instanceof StringTag stringTag) {
container.set(StructuredDataKey.ZOMBIE_NAUTILUS_VARIANT, Either.right(stringTag.getValue()));
} else if (zombieNautilusVariantTag instanceof IntTag intTag) {
container.set(StructuredDataKey.ZOMBIE_NAUTILUS_VARIANT, Either.left(intTag.asInt()));
}
}
restoreFloatData(StructuredDataKey.MINIMUM_ATTACK_CHARGE, container, backupTag);
}
private KineticWeapon.Condition loadDamageCondition(final CompoundTag tag, final String key) {
final CompoundTag conditionTag = tag.getCompoundTag(key);
if (conditionTag == null) {
return null;
}
final int maxDurationTicks = conditionTag.getInt("max_duration_ticks");
final float minSpeed = conditionTag.getFloat("min_speed");
final float minRelativeSpeed = conditionTag.getFloat("min_relative_speed");
return new KineticWeapon.Condition(maxDurationTicks, minSpeed, minRelativeSpeed);
}
@Override
protected void backupInconvertibleData(final UserConnection connection, final Item item, final StructuredDataContainer dataContainer, final CompoundTag backupTag) {
super.backupInconvertibleData(connection, item, dataContainer, backupTag);
final SwingAnimation swingAnimation = dataContainer.get(StructuredDataKey.SWING_ANIMATION);
if (swingAnimation != null) {
final CompoundTag swingTag = new CompoundTag();
swingTag.putInt("type", swingAnimation.type());
swingTag.putInt("duration", swingAnimation.duration());
backupTag.put("swing_animation", swingTag);
}
final KineticWeapon kineticWeapon = dataContainer.get(StructuredDataKey.KINETIC_WEAPON);
if (kineticWeapon != null) {
final CompoundTag kineticTag = new CompoundTag();
kineticTag.putInt("contact_cooldown_ticks", kineticWeapon.contactCooldownTicks());
kineticTag.putInt("delay_ticks", kineticWeapon.delayTicks());
saveDamageCondition(kineticTag, "damage_conditions", kineticWeapon.damageConditions());
saveDamageCondition(kineticTag, "dismount_conditions", kineticWeapon.dismountConditions());
saveDamageCondition(kineticTag, "knockback_conditions", kineticWeapon.knockbackConditions());
kineticTag.putFloat("forward_movement", kineticWeapon.forwardMovement());
kineticTag.putFloat("damage_multiplier", kineticWeapon.damageMultiplier());
if (kineticWeapon.sound() != null) {
kineticTag.put("sound", holderToTag(kineticWeapon.sound(), this::saveSoundEvent));
}
if (kineticWeapon.hitSound() != null) {
kineticTag.put("hit_sound", holderToTag(kineticWeapon.hitSound(), this::saveSoundEvent));
}
backupTag.put("kinetic_weapon", kineticTag);
}
final PiercingWeapon piercingWeapon = dataContainer.get(StructuredDataKey.PIERCING_WEAPON);
if (piercingWeapon != null) {
final CompoundTag piercingTag = new CompoundTag();
piercingTag.putBoolean("deals_knockback", piercingWeapon.dealsKnockback());
piercingTag.putBoolean("dismounts", piercingWeapon.dismounts());
if (piercingWeapon.sound() != null) {
piercingTag.put("sound", holderToTag(piercingWeapon.sound(), this::saveSoundEvent));
}
if (piercingWeapon.hitSound() != null) {
piercingTag.put("hit_sound", holderToTag(piercingWeapon.hitSound(), this::saveSoundEvent));
}
backupTag.put("piercing_weapon", piercingTag);
}
final DamageType damageType = dataContainer.get(StructuredDataKey.DAMAGE_TYPE);
if (damageType != null) {
if (damageType.id().isLeft()) {
backupTag.putInt("damage_type_id", damageType.id().left());
} else {
backupTag.putString("damage_type_id", damageType.id().right());
}
}
final UseEffects useEffects = dataContainer.get(StructuredDataKey.USE_EFFECTS);
if (useEffects != null) {
final CompoundTag useEffectsTag = new CompoundTag();
useEffectsTag.putBoolean("can_sprint", useEffects.canSprint());
useEffectsTag.putBoolean("interact_vibrations", useEffects.interactVibrations());
useEffectsTag.putFloat("speed_multiplier", useEffects.speedMultiplier());
backupTag.put("use_effects", useEffectsTag);
}
final AttackRange attackRange = dataContainer.get(StructuredDataKey.ATTACK_RANGE);
if (attackRange != null) {
final CompoundTag attackRangeTag = new CompoundTag();
attackRangeTag.putFloat("min_range", attackRange.minRange());
attackRangeTag.putFloat("max_range", attackRange.maxRange());
attackRangeTag.putFloat("min_creative_reach", attackRange.minCreativeRange());
attackRangeTag.putFloat("max_creative_reach", attackRange.maxCreativeRange());
attackRangeTag.putFloat("hitbox_margin", attackRange.hitboxMargin());
attackRangeTag.putFloat("mob_factor", attackRange.mobFactor());
backupTag.put("attack_range", attackRangeTag);
}
final Either<Integer, String> zombieNautilusVariant = dataContainer.get(StructuredDataKey.ZOMBIE_NAUTILUS_VARIANT);
if (zombieNautilusVariant != null) {
if (zombieNautilusVariant.isLeft()) {
backupTag.putInt("zombie_nautilus_variant", zombieNautilusVariant.left());
} else {
backupTag.putString("zombie_nautilus_variant", zombieNautilusVariant.right());
}
}
saveFloatData(StructuredDataKey.MINIMUM_ATTACK_CHARGE, dataContainer, backupTag);
}
private void saveDamageCondition(final CompoundTag tag, final String key, final KineticWeapon.@Nullable Condition condition) {
if (condition == null) {
return;
}
final CompoundTag conditionTag = new CompoundTag();
conditionTag.putInt("max_duration_ticks", condition.maxDurationTicks());
conditionTag.putFloat("min_speed", condition.minSpeed());
conditionTag.putFloat("min_relative_speed", condition.minRelativeSpeed());
tag.put(key, conditionTag);
}
}
@@ -0,0 +1,43 @@
/*
* This file is part of ViaBackwards - https://github.com/ViaVersion/ViaBackwards
* Copyright (C) 2016-2025 ViaVersion and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.viaversion.viabackwards.protocol.v1_21_11to1_21_9.rewriter;
import com.viaversion.nbt.tag.CompoundTag;
import com.viaversion.viabackwards.api.BackwardsProtocol;
import com.viaversion.viabackwards.api.rewriters.text.NBTComponentRewriter;
import com.viaversion.viaversion.api.connection.UserConnection;
import com.viaversion.viaversion.api.minecraft.data.StructuredDataKey;
import com.viaversion.viaversion.protocols.v1_21_9to1_21_11.packet.ClientboundPacket1_21_11;
public final class ComponentRewriter1_21_11 extends NBTComponentRewriter<ClientboundPacket1_21_11> {
public ComponentRewriter1_21_11(final BackwardsProtocol<ClientboundPacket1_21_11, ?, ?, ?> protocol) {
super(protocol);
}
@Override
protected void handleShowItem(final UserConnection connection, final CompoundTag itemTag, final CompoundTag componentsTag) {
super.handleShowItem(connection, itemTag, componentsTag);
if (componentsTag == null) {
return;
}
removeDataComponents(componentsTag, StructuredDataKey.SWING_ANIMATION, StructuredDataKey.KINETIC_WEAPON, StructuredDataKey.PIERCING_WEAPON,
StructuredDataKey.DAMAGE_TYPE, StructuredDataKey.MINIMUM_ATTACK_CHARGE, StructuredDataKey.USE_EFFECTS, StructuredDataKey.ZOMBIE_NAUTILUS_VARIANT, StructuredDataKey.ATTACK_RANGE);
}
}
@@ -0,0 +1,114 @@
/*
* This file is part of ViaBackwards - https://github.com/ViaVersion/ViaBackwards
* Copyright (C) 2016-2025 ViaVersion and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.viaversion.viabackwards.protocol.v1_21_11to1_21_9.rewriter;
import com.viaversion.viabackwards.api.rewriters.EntityRewriter;
import com.viaversion.viabackwards.protocol.v1_21_11to1_21_9.Protocol1_21_11To1_21_9;
import com.viaversion.viabackwards.protocol.v1_21_11to1_21_9.storage.GameTimeStorage;
import com.viaversion.viaversion.api.minecraft.entities.EntityType;
import com.viaversion.viaversion.api.minecraft.entities.EntityTypes1_21_11;
import com.viaversion.viaversion.api.minecraft.entitydata.EntityData;
import com.viaversion.viaversion.api.minecraft.entitydata.types.EntityDataTypes1_21_11;
import com.viaversion.viaversion.api.minecraft.entitydata.types.EntityDataTypes1_21_9;
import com.viaversion.viaversion.api.type.types.version.VersionedTypes;
import com.viaversion.viaversion.protocols.v1_21_7to1_21_9.packet.ClientboundPackets1_21_9;
import com.viaversion.viaversion.protocols.v1_21_9to1_21_11.packet.ClientboundPacket1_21_11;
import com.viaversion.viaversion.protocols.v1_21_9to1_21_11.packet.ClientboundPackets1_21_11;
import com.viaversion.viaversion.rewriter.entitydata.EntityDataHandlerEvent;
import com.viaversion.viaversion.util.MathUtil;
public final class EntityPacketRewriter1_21_11 extends EntityRewriter<ClientboundPacket1_21_11, Protocol1_21_11To1_21_9> {
public EntityPacketRewriter1_21_11(final Protocol1_21_11To1_21_9 protocol) {
super(protocol, VersionedTypes.V1_21_9.entityDataTypes.optionalComponentType, VersionedTypes.V1_21_9.entityDataTypes.booleanType);
}
@Override
public void registerPackets() {
registerTrackerWithData1_21_9(ClientboundPackets1_21_11.ADD_ENTITY, EntityTypes1_21_11.FALLING_BLOCK);
registerSetEntityData(ClientboundPackets1_21_11.SET_ENTITY_DATA);
registerRemoveEntities(ClientboundPackets1_21_11.REMOVE_ENTITIES);
registerPlayerAbilities(ClientboundPackets1_21_11.PLAYER_ABILITIES);
registerGameEvent(ClientboundPackets1_21_11.GAME_EVENT);
registerLogin1_20_5(ClientboundPackets1_21_11.LOGIN);
registerRespawn1_20_5(ClientboundPackets1_21_11.RESPAWN);
protocol.registerClientbound(ClientboundPackets1_21_11.MOUNT_SCREEN_OPEN, ClientboundPackets1_21_9.HORSE_SCREEN_OPEN);
}
@Override
protected void registerRewrites() {
final EntityDataTypes1_21_11 unmappedDataTypes = VersionedTypes.V1_21_11.entityDataTypes;
final EntityDataTypes1_21_9 entityDataTypes = VersionedTypes.V1_21_9.entityDataTypes;
filter().handler((event, data) -> {
if (data.dataType() == unmappedDataTypes.humanoidArmType) {
final int arm = data.value();
data.setTypeAndValue(entityDataTypes.byteType, (byte) arm);
return;
} else if (data.dataType() == unmappedDataTypes.zombieNautilusVariantType) {
event.cancel();
return;
}
int id = data.dataType().typeId();
if (id > unmappedDataTypes.zombieNautilusVariantType.typeId()) {
id--;
}
data.setDataType(entityDataTypes.byId(id));
});
registerEntityDataTypeHandler1_20_3(
entityDataTypes.itemType,
entityDataTypes.blockStateType,
entityDataTypes.optionalBlockStateType,
entityDataTypes.particleType,
entityDataTypes.particlesType,
entityDataTypes.componentType,
entityDataTypes.optionalComponentType
);
filter().type(EntityTypes1_21_11.WOLF).index(21).handler(this::absoluteToRelativeTicks);
filter().type(EntityTypes1_21_11.BEE).index(18).handler(this::absoluteToRelativeTicks);
filter().type(EntityTypes1_21_11.ABSTRACT_NAUTILUS).cancel(17); // Tamable flags
filter().type(EntityTypes1_21_11.ABSTRACT_NAUTILUS).cancel(18); // Owner UUID
filter().type(EntityTypes1_21_11.ABSTRACT_NAUTILUS).cancel(19); // Dashing
filter().type(EntityTypes1_21_11.ZOMBIE_NAUTILUS).cancel(20); // Variant
}
private void absoluteToRelativeTicks(final EntityDataHandlerEvent event, final EntityData data) {
final long currentGameTime = event.user().get(GameTimeStorage.class).gameTime();
final long angerEndTime = data.value();
final int angerEndIn = (int) MathUtil.clamp(angerEndTime - currentGameTime, Integer.MIN_VALUE, Integer.MAX_VALUE);
data.setTypeAndValue(VersionedTypes.V1_21_9.entityDataTypes.varIntType, Math.max(angerEndIn, 0));
}
@Override
public void onMappingDataLoaded() {
mapTypes();
mapEntityTypeWithData(EntityTypes1_21_11.NAUTILUS, EntityTypes1_21_11.SQUID).tagName();
mapEntityTypeWithData(EntityTypes1_21_11.ZOMBIE_NAUTILUS, EntityTypes1_21_11.GLOW_SQUID).tagName();
mapEntityTypeWithData(EntityTypes1_21_11.CAMEL_HUSK, EntityTypes1_21_11.CAMEL).tagName();
mapEntityTypeWithData(EntityTypes1_21_11.PARCHED, EntityTypes1_21_11.SKELETON).tagName();
}
@Override
public EntityType typeFromId(final int type) {
return EntityTypes1_21_11.getTypeFromId(type);
}
}
@@ -0,0 +1,37 @@
/*
* This file is part of ViaVersion - https://github.com/ViaVersion/ViaVersion
* Copyright (C) 2016-2025 ViaVersion and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.viaversion.viabackwards.protocol.v1_21_11to1_21_9.storage;
import com.viaversion.viaversion.api.connection.StorableObject;
public final class GameTimeStorage implements StorableObject {
private long gameTime;
public long gameTime() {
return gameTime;
}
public void setGameTime(final long gameTime) {
this.gameTime = gameTime;
}
public void incrementGameTime() {
gameTime++;
}
}
@@ -29,6 +29,7 @@ import com.viaversion.viabackwards.protocol.v1_21_2to1_21.storage.InventoryState
import com.viaversion.viabackwards.protocol.v1_21_2to1_21.storage.ItemTagStorage;
import com.viaversion.viabackwards.protocol.v1_21_2to1_21.storage.PlayerStorage;
import com.viaversion.viabackwards.protocol.v1_21_2to1_21.storage.RecipeStorage;
import com.viaversion.viabackwards.protocol.v1_21_2to1_21.storage.SignStorage;
import com.viaversion.viaversion.api.connection.UserConnection;
import com.viaversion.viaversion.api.minecraft.entities.EntityTypes1_20_5;
import com.viaversion.viaversion.api.minecraft.item.data.ChatType;
@@ -94,11 +95,15 @@ public final class Protocol1_21_2To1_21 extends BackwardsProtocol<ClientboundPac
translatableRewriter.registerComponentPacket(ClientboundPackets1_21_2.SET_SUBTITLE_TEXT);
translatableRewriter.registerBossEvent(ClientboundPackets1_21_2.BOSS_EVENT);
translatableRewriter.registerComponentPacket(ClientboundPackets1_21_2.DISCONNECT);
translatableRewriter.registerComponentPacket(ClientboundConfigurationPackets1_21.DISCONNECT);
translatableRewriter.registerTabList(ClientboundPackets1_21_2.TAB_LIST);
translatableRewriter.registerSetPlayerTeam1_13(ClientboundPackets1_21_2.SET_PLAYER_TEAM);
translatableRewriter.registerPlayerCombatKill1_20(ClientboundPackets1_21_2.PLAYER_COMBAT_KILL);
translatableRewriter.registerComponentPacket(ClientboundPackets1_21_2.SYSTEM_CHAT);
translatableRewriter.registerDisguisedChat(ClientboundPackets1_21_2.DISGUISED_CHAT);
translatableRewriter.registerPlayerChat(ClientboundPackets1_21_2.PLAYER_CHAT, ChatType.TYPE);
translatableRewriter.registerSetObjective(ClientboundPackets1_21_2.SET_OBJECTIVE);
translatableRewriter.registerSetScore1_20_3(ClientboundPackets1_21_2.SET_SCORE);
translatableRewriter.registerPing();
registerServerbound(ServerboundPackets1_20_5.CLIENT_INFORMATION, this::clientInformation);
@@ -159,6 +164,7 @@ public final class Protocol1_21_2To1_21 extends BackwardsProtocol<ClientboundPac
user.put(new ItemTagStorage());
user.put(new RecipeStorage(this));
user.put(new PlayerStorage());
user.put(new SignStorage());
}
@Override
@@ -26,12 +26,20 @@ import com.viaversion.viabackwards.api.rewriters.BackwardsStructuredItemRewriter
import com.viaversion.viabackwards.protocol.v1_21_2to1_21.Protocol1_21_2To1_21;
import com.viaversion.viabackwards.protocol.v1_21_2to1_21.storage.InventoryStateIdStorage;
import com.viaversion.viabackwards.protocol.v1_21_2to1_21.storage.RecipeStorage;
import com.viaversion.viabackwards.protocol.v1_21_2to1_21.storage.SignStorage;
import com.viaversion.viaversion.api.connection.UserConnection;
import com.viaversion.viaversion.api.data.MappingData;
import com.viaversion.viaversion.api.data.entity.EntityTracker;
import com.viaversion.viaversion.api.minecraft.BlockChangeRecord;
import com.viaversion.viaversion.api.minecraft.BlockPosition;
import com.viaversion.viaversion.api.minecraft.Holder;
import com.viaversion.viaversion.api.minecraft.HolderSet;
import com.viaversion.viaversion.api.minecraft.Particle;
import com.viaversion.viaversion.api.minecraft.SoundEvent;
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.data.StructuredDataContainer;
import com.viaversion.viaversion.api.minecraft.data.StructuredDataKey;
import com.viaversion.viaversion.api.minecraft.item.Item;
@@ -48,6 +56,7 @@ import com.viaversion.viaversion.api.minecraft.item.data.PotionEffectData;
import com.viaversion.viaversion.api.minecraft.item.data.Repairable;
import com.viaversion.viaversion.api.minecraft.item.data.UseCooldown;
import com.viaversion.viaversion.api.protocol.packet.PacketWrapper;
import com.viaversion.viaversion.api.protocol.version.ProtocolVersion;
import com.viaversion.viaversion.api.type.Types;
import com.viaversion.viaversion.api.type.types.chunk.ChunkType1_20_2;
import com.viaversion.viaversion.api.type.types.version.VersionedTypes;
@@ -75,10 +84,7 @@ public final class BlockItemPacketRewriter1_21_2 extends BackwardsStructuredItem
public void registerPackets() {
final BlockRewriter<ClientboundPacket1_21_2> blockRewriter = BlockRewriter.for1_20_2(protocol);
blockRewriter.registerBlockEvent(ClientboundPackets1_21_2.BLOCK_EVENT);
blockRewriter.registerBlockUpdate(ClientboundPackets1_21_2.BLOCK_UPDATE);
blockRewriter.registerSectionBlocksUpdate1_20(ClientboundPackets1_21_2.SECTION_BLOCKS_UPDATE);
blockRewriter.registerLevelEvent1_21(ClientboundPackets1_21_2.LEVEL_EVENT, 2001);
blockRewriter.registerLevelChunk1_19(ClientboundPackets1_21_2.LEVEL_CHUNK_WITH_LIGHT, ChunkType1_20_2::new);
blockRewriter.registerBlockEntityData(ClientboundPackets1_21_2.BLOCK_ENTITY_DATA);
registerAdvancements1_20_3(ClientboundPackets1_21_2.UPDATE_ADVANCEMENTS);
@@ -86,6 +92,109 @@ public final class BlockItemPacketRewriter1_21_2 extends BackwardsStructuredItem
registerMerchantOffers1_20_5(ClientboundPackets1_21_2.MERCHANT_OFFERS);
registerSetCreativeModeSlot(ServerboundPackets1_20_5.SET_CREATIVE_MODE_SLOT);
protocol.registerClientbound(ClientboundPackets1_21_2.LEVEL_CHUNK_WITH_LIGHT, wrapper -> {
final Chunk chunk = blockRewriter.handleChunk1_19(wrapper, ChunkType1_20_2::new);
blockRewriter.handleBlockEntities(null, chunk, wrapper.user());
if (!wrapper.user().getProtocolInfo().protocolVersion().equalTo(ProtocolVersion.v1_21)) {
return;
}
final EntityTracker tracker = wrapper.user().getEntityTracker(Protocol1_21_2To1_21.class);
final SignStorage storage = wrapper.user().get(SignStorage.class);
storage.removeSigns(chunk.getX(), chunk.getZ());
for (int i = 0; i < chunk.getSections().length; i++) {
final ChunkSection section = chunk.getSections()[i];
final DataPalette blockPalette = section.palette(PaletteType.BLOCKS);
boolean containsSign = false;
for (int idx = 0; idx < blockPalette.size(); idx++) {
if (signBlockState(blockPalette.idByIndex(idx))) {
containsSign = true;
break;
}
}
if (!containsSign) {
continue;
}
for (int idx = 0; idx < ChunkSection.SIZE; idx++) {
if (!signBlockState(blockPalette.idAt(idx))) {
continue;
}
storage.addSign(new BlockPosition(
ChunkSection.xFromIndex(idx) + (chunk.getX() << 4),
ChunkSection.yFromIndex(idx) + tracker.currentMinY() + (i << 4),
ChunkSection.zFromIndex(idx) + (chunk.getZ() << 4)
));
}
}
});
protocol.registerClientbound(ClientboundPackets1_21_2.BLOCK_UPDATE, wrapper -> {
final BlockPosition position = wrapper.passthrough(Types.BLOCK_POSITION1_14);
final int blockId = wrapper.read(Types.VAR_INT);
final int mappedBlockId = protocol.getMappingData().getNewBlockStateId(blockId);
wrapper.write(Types.VAR_INT, mappedBlockId);
if (!wrapper.user().getProtocolInfo().protocolVersion().equalTo(ProtocolVersion.v1_21)) {
return;
}
final SignStorage storage = wrapper.user().get(SignStorage.class);
storage.removeSign(position);
if (signBlockState(mappedBlockId)) {
storage.addSign(position);
}
});
protocol.registerClientbound(ClientboundPackets1_21_2.SECTION_BLOCKS_UPDATE, wrapper -> {
final long position = wrapper.passthrough(Types.LONG);
final int chunkX = (int) (position >> 42);
final int chunkY = (int) (position << 44 >> 44);
final int chunkZ = (int) (position << 22 >> 42);
final SignStorage signStorage = wrapper.user().get(SignStorage.class);
final boolean equalToV1_21 = wrapper.user().getProtocolInfo().protocolVersion().equalTo(ProtocolVersion.v1_21);
for (final BlockChangeRecord record : wrapper.passthrough(Types.VAR_LONG_BLOCK_CHANGE_ARRAY)) {
record.setBlockId(protocol.getMappingData().getNewBlockStateId(record.getBlockId()));
if (!equalToV1_21) {
continue;
}
final int x = record.getSectionX() + (chunkX << 4);
final int y = record.getSectionY() + (chunkY << 4);
final int z = record.getSectionZ() + (chunkZ << 4);
final BlockPosition pos = new BlockPosition(x, y, z);
if (signBlockState(record.getBlockId())) {
signStorage.addSign(pos);
} else {
signStorage.removeSign(pos);
}
}
});
protocol.registerClientbound(ClientboundPackets1_21_2.OPEN_SIGN_EDITOR, wrapper -> {
if (!wrapper.user().getProtocolInfo().protocolVersion().equalTo(ProtocolVersion.v1_21)) {
return;
}
final BlockPosition position = wrapper.passthrough(Types.BLOCK_POSITION1_14);
if (!wrapper.user().get(SignStorage.class).isSign(position)) {
wrapper.cancel();
}
});
protocol.registerClientbound(ClientboundPackets1_21_2.COOLDOWN, wrapper -> {
final MappingData mappingData = protocol.getMappingData();
final String itemIdentifier = wrapper.read(Types.STRING);
@@ -297,6 +406,10 @@ public final class BlockItemPacketRewriter1_21_2 extends BackwardsStructuredItem
wrapper.write(Types.VAR_INT, (int) containerId);
}
private boolean signBlockState(final int blockStateId) {
return (blockStateId >= 4302 && blockStateId <= 4589) || (blockStateId >= 4762 && blockStateId <= 5625);
}
@Override
public Item handleItemToClient(final UserConnection connection, Item item) {
backupInconvertibleData(item);
@@ -27,6 +27,8 @@ import com.viaversion.viabackwards.api.rewriters.BackwardsRegistryRewriter;
import com.viaversion.viabackwards.api.rewriters.EntityRewriter;
import com.viaversion.viabackwards.protocol.v1_21_2to1_21.Protocol1_21_2To1_21;
import com.viaversion.viabackwards.protocol.v1_21_2to1_21.storage.PlayerStorage;
import com.viaversion.viabackwards.protocol.v1_21_2to1_21.storage.SignStorage;
import com.viaversion.viaversion.api.data.entity.EntityTracker;
import com.viaversion.viaversion.api.minecraft.Holder;
import com.viaversion.viaversion.api.minecraft.Particle;
import com.viaversion.viaversion.api.minecraft.RegistryEntry;
@@ -173,6 +175,11 @@ public final class EntityPacketRewriter1_21_2 extends EntityRewriter<Clientbound
wrapper.passthrough(Types.VAR_INT); // Portal cooldown
wrapper.read(Types.VAR_INT); // Sea level
final EntityTracker tracker = tracker(wrapper.user());
if (tracker.currentWorld() != null && !tracker.currentWorld().equals(world)) {
wrapper.user().put(new SignStorage());
}
trackWorldDataByKey1_20_5(wrapper.user(), dimensionId, world);
});
@@ -0,0 +1,45 @@
/*
* This file is part of ViaBackwards - https://github.com/ViaVersion/ViaBackwards
* Copyright (C) 2016-2025 ViaVersion and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.viaversion.viabackwards.protocol.v1_21_2to1_21.storage;
import com.viaversion.viaversion.api.connection.StorableObject;
import com.viaversion.viaversion.api.minecraft.BlockPosition;
import java.util.HashSet;
import java.util.Set;
public final class SignStorage implements StorableObject {
private final Set<BlockPosition> signs = new HashSet<>();
public void addSign(final BlockPosition position) {
signs.add(position);
}
public boolean isSign(final BlockPosition position) {
return signs.contains(position);
}
public void removeSign(final BlockPosition position) {
signs.remove(position);
}
public void removeSigns(final int chunkX, final int chunkZ) {
signs.removeIf(pos -> pos.x() >> 4 == chunkX && pos.z() >> 4 == chunkZ);
}
}
@@ -88,11 +88,15 @@ public final class Protocol1_21_4To1_21_2 extends BackwardsProtocol<ClientboundP
translatableRewriter.registerComponentPacket(ClientboundPackets1_21_2.SET_SUBTITLE_TEXT);
translatableRewriter.registerBossEvent(ClientboundPackets1_21_2.BOSS_EVENT);
translatableRewriter.registerComponentPacket(ClientboundPackets1_21_2.DISCONNECT);
translatableRewriter.registerComponentPacket(ClientboundConfigurationPackets1_21.DISCONNECT);
translatableRewriter.registerTabList(ClientboundPackets1_21_2.TAB_LIST);
translatableRewriter.registerSetPlayerTeam1_13(ClientboundPackets1_21_2.SET_PLAYER_TEAM);
translatableRewriter.registerPlayerCombatKill1_20(ClientboundPackets1_21_2.PLAYER_COMBAT_KILL);
translatableRewriter.registerComponentPacket(ClientboundPackets1_21_2.SYSTEM_CHAT);
translatableRewriter.registerDisguisedChat(ClientboundPackets1_21_2.DISGUISED_CHAT);
translatableRewriter.registerPlayerChat(ClientboundPackets1_21_2.PLAYER_CHAT, ChatType.TYPE);
translatableRewriter.registerSetObjective(ClientboundPackets1_21_2.SET_OBJECTIVE);
translatableRewriter.registerSetScore1_20_3(ClientboundPackets1_21_2.SET_SCORE);
translatableRewriter.registerPing();
particleRewriter.registerExplode1_21_2(ClientboundPackets1_21_2.EXPLODE);
@@ -23,6 +23,7 @@ import com.viaversion.viabackwards.api.rewriters.SoundRewriter;
import com.viaversion.viabackwards.protocol.v1_21_5to1_21_4.rewriter.BlockItemPacketRewriter1_21_5;
import com.viaversion.viabackwards.protocol.v1_21_5to1_21_4.rewriter.ComponentRewriter1_21_5;
import com.viaversion.viabackwards.protocol.v1_21_5to1_21_4.rewriter.EntityPacketRewriter1_21_5;
import com.viaversion.viabackwards.protocol.v1_21_5to1_21_4.rewriter.RegistryDataRewriter1_21_5;
import com.viaversion.viabackwards.protocol.v1_21_5to1_21_4.storage.HashedItemConverterStorage;
import com.viaversion.viaversion.api.connection.UserConnection;
import com.viaversion.viaversion.api.minecraft.Particle;
@@ -52,6 +53,7 @@ import com.viaversion.viaversion.protocols.v1_21_4to1_21_5.packet.ServerboundPac
import com.viaversion.viaversion.protocols.v1_21to1_21_2.packet.ClientboundPacket1_21_2;
import com.viaversion.viaversion.protocols.v1_21to1_21_2.packet.ClientboundPackets1_21_2;
import com.viaversion.viaversion.rewriter.ParticleRewriter;
import com.viaversion.viaversion.rewriter.RegistryDataRewriter;
import com.viaversion.viaversion.rewriter.StatisticsRewriter;
import com.viaversion.viaversion.rewriter.TagRewriter;
import com.viaversion.viaversion.util.Key;
@@ -75,6 +77,7 @@ public final class Protocol1_21_5To1_21_4 extends BackwardsProtocol<ClientboundP
};
private final ComponentRewriter1_21_5 translatableRewriter = new ComponentRewriter1_21_5(this);
private final TagRewriter<ClientboundPacket1_21_5> tagRewriter = new TagRewriter<>(this);
private final RegistryDataRewriter registryDataRewriter = new RegistryDataRewriter1_21_5(this);
public Protocol1_21_5To1_21_4() {
super(ClientboundPacket1_21_5.class, ClientboundPacket1_21_2.class, ServerboundPacket1_21_5.class, ServerboundPacket1_21_4.class);
@@ -84,6 +87,8 @@ public final class Protocol1_21_5To1_21_4 extends BackwardsProtocol<ClientboundP
protected void registerPackets() {
super.registerPackets();
registerClientbound(ClientboundConfigurationPackets1_21.REGISTRY_DATA, registryDataRewriter::handle);
tagRewriter.registerGeneric(ClientboundPackets1_21_5.UPDATE_TAGS);
tagRewriter.registerGeneric(ClientboundConfigurationPackets1_21.UPDATE_TAGS);
@@ -100,11 +105,14 @@ public final class Protocol1_21_5To1_21_4 extends BackwardsProtocol<ClientboundP
translatableRewriter.registerComponentPacket(ClientboundPackets1_21_5.SET_SUBTITLE_TEXT);
translatableRewriter.registerBossEvent(ClientboundPackets1_21_5.BOSS_EVENT);
translatableRewriter.registerComponentPacket(ClientboundPackets1_21_5.DISCONNECT);
translatableRewriter.registerComponentPacket(ClientboundConfigurationPackets1_21.DISCONNECT);
translatableRewriter.registerTabList(ClientboundPackets1_21_5.TAB_LIST);
translatableRewriter.registerPlayerCombatKill1_20(ClientboundPackets1_21_5.PLAYER_COMBAT_KILL);
translatableRewriter.registerComponentPacket(ClientboundPackets1_21_5.SYSTEM_CHAT);
translatableRewriter.registerDisguisedChat(ClientboundPackets1_21_5.DISGUISED_CHAT);
translatableRewriter.registerPlayerInfoUpdate1_21_4(ClientboundPackets1_21_5.PLAYER_INFO_UPDATE);
translatableRewriter.registerSetObjective(ClientboundPackets1_21_5.SET_OBJECTIVE);
translatableRewriter.registerSetScore1_20_3(ClientboundPackets1_21_5.SET_SCORE);
translatableRewriter.registerPing();
particleRewriter.registerLevelParticles1_21_4(ClientboundPackets1_21_5.LEVEL_PARTICLES);
@@ -204,6 +212,11 @@ public final class Protocol1_21_5To1_21_4 extends BackwardsProtocol<ClientboundP
return itemRewriter;
}
@Override
public RegistryDataRewriter getRegistryDataRewriter() {
return registryDataRewriter;
}
@Override
public ParticleRewriter<ClientboundPacket1_21_5> getParticleRewriter() {
return particleRewriter;
@@ -67,7 +67,9 @@ import com.viaversion.viaversion.api.type.types.chunk.ChunkType1_20_2;
import com.viaversion.viaversion.api.type.types.chunk.ChunkType1_21_5;
import com.viaversion.viaversion.api.type.types.version.VersionedTypes;
import com.viaversion.viaversion.data.item.ItemHasherBase;
import com.viaversion.viaversion.libs.fastutil.ints.IntArrayList;
import com.viaversion.viaversion.libs.fastutil.ints.IntLinkedOpenHashSet;
import com.viaversion.viaversion.libs.fastutil.ints.IntList;
import com.viaversion.viaversion.protocols.v1_21_2to1_21_4.packet.ServerboundPacket1_21_4;
import com.viaversion.viaversion.protocols.v1_21_2to1_21_4.packet.ServerboundPackets1_21_4;
import com.viaversion.viaversion.protocols.v1_21_4to1_21_5.packet.ClientboundPacket1_21_5;
@@ -78,7 +80,6 @@ import com.viaversion.viaversion.rewriter.RecipeDisplayRewriter;
import com.viaversion.viaversion.util.Either;
import com.viaversion.viaversion.util.Key;
import com.viaversion.viaversion.util.Limit;
import com.viaversion.viaversion.util.SerializerVersion;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
@@ -182,20 +183,37 @@ public final class BlockItemPacketRewriter1_21_5 extends BackwardsStructuredItem
protocol.registerClientbound(ClientboundPackets1_21_5.SET_EQUIPMENT, wrapper -> {
final int entityId = wrapper.passthrough(Types.VAR_INT);
final TrackedEntity trackedEntity = protocol.getEntityRewriter().tracker(wrapper.user()).entity(entityId);
// Remove saddle equipment, keep the rest
final IntList keptSlots = new IntArrayList();
final List<Item> keptItems = new ArrayList<>();
byte value;
do {
value = wrapper.passthrough(Types.BYTE);
value = wrapper.read(Types.BYTE);
final int equipmentSlot = value & 0x7F;
final Item item = wrapper.read(itemType());
if (equipmentSlot == SADDLE_EQUIPMENT_SLOT) {
// Send saddle entity data for horses
if (trackedEntity != null && trackedEntity.entityType().isOrHasParent(EntityTypes1_21_5.ABSTRACT_HORSE)) {
final Item item = wrapper.read(itemType());
sendSaddledEntityData(wrapper.user(), trackedEntity, entityId, item.identifier() == 800);
}
wrapper.cancel();
return;
} else {
keptSlots.add(equipmentSlot);
keptItems.add(handleItemToClient(wrapper.user(), item));
}
passthroughClientboundItem(wrapper);
} while (value < 0);
if (keptSlots.isEmpty()) {
wrapper.cancel();
return;
}
for (int i = 0; i < keptSlots.size(); i++) {
final int slot = keptSlots.getInt(i);
final boolean more = i < keptSlots.size() - 1;
wrapper.write(Types.BYTE, (byte) (more ? (slot | -128) : slot));
wrapper.write(mappedItemType(), keptItems.get(i));
}
});
protocol.registerClientbound(ClientboundPackets1_21_5.UPDATE_ADVANCEMENTS, wrapper -> {
@@ -17,18 +17,11 @@
*/
package com.viaversion.viabackwards.protocol.v1_21_5to1_21_4.rewriter;
import com.viaversion.nbt.tag.CompoundTag;
import com.viaversion.nbt.tag.ListTag;
import com.viaversion.nbt.tag.StringTag;
import com.viaversion.viabackwards.api.rewriters.BackwardsRegistryRewriter;
import com.viaversion.viabackwards.api.rewriters.EntityRewriter;
import com.viaversion.viabackwards.protocol.v1_21_5to1_21_4.Protocol1_21_5To1_21_4;
import com.viaversion.viabackwards.protocol.v1_21_5to1_21_4.storage.HashedItemConverterStorage;
import com.viaversion.viabackwards.protocol.v1_21_5to1_21_4.storage.HorseDataStorage;
import com.viaversion.viaversion.api.connection.UserConnection;
import com.viaversion.viaversion.api.data.entity.TrackedEntity;
import com.viaversion.viaversion.api.minecraft.Holder;
import com.viaversion.viaversion.api.minecraft.RegistryEntry;
import com.viaversion.viaversion.api.minecraft.WolfVariant;
import com.viaversion.viaversion.api.minecraft.entities.EntityType;
import com.viaversion.viaversion.api.minecraft.entities.EntityTypes1_21_5;
@@ -38,22 +31,13 @@ import com.viaversion.viaversion.api.minecraft.entitydata.types.EntityDataTypes1
import com.viaversion.viaversion.api.protocol.packet.PacketWrapper;
import com.viaversion.viaversion.api.type.Types;
import com.viaversion.viaversion.api.type.types.version.VersionedTypes;
import com.viaversion.viaversion.protocols.v1_20_5to1_21.packet.ClientboundConfigurationPackets1_21;
import com.viaversion.viaversion.protocols.v1_21_4to1_21_5.packet.ClientboundPacket1_21_5;
import com.viaversion.viaversion.protocols.v1_21_4to1_21_5.packet.ClientboundPackets1_21_5;
import com.viaversion.viaversion.protocols.v1_21to1_21_2.packet.ClientboundPackets1_21_2;
import com.viaversion.viaversion.rewriter.RegistryDataRewriter;
import com.viaversion.viaversion.util.Key;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;
import java.util.UUID;
public final class EntityPacketRewriter1_21_5 extends EntityRewriter<ClientboundPacket1_21_5, Protocol1_21_5To1_21_4> {
private static final Set<String> NEW_REGISTRIES = Set.of("pig_variant", "cow_variant", "frog_variant", "cat_variant",
"chicken_variant", "test_environment", "test_instance", "wolf_sound_variant");
public EntityPacketRewriter1_21_5(final Protocol1_21_5To1_21_4 protocol) {
super(protocol, protocol.mappedTypes().entityDataTypes().optionalComponentType, protocol.mappedTypes().entityDataTypes().booleanType);
}
@@ -112,69 +96,6 @@ public final class EntityPacketRewriter1_21_5 extends EntityRewriter<Clientbound
}
});
final RegistryDataRewriter registryDataRewriter = new BackwardsRegistryRewriter(protocol) {
@Override
public RegistryEntry[] handle(final UserConnection connection, final String key, final RegistryEntry[] entries) {
final boolean trimPatternRegistry = key.equals("trim_pattern");
if (trimPatternRegistry || key.equals("trim_material")) {
updateTrim(entries, trimPatternRegistry ? "template_item" : "ingredient");
return super.handle(connection, key, entries);
}
if (key.equals("enchantment")) {
updateEnchantment(entries);
return super.handle(connection, key, entries);
}
if (!key.equals("wolf_variant")) {
return super.handle(connection, key, entries);
}
for (final RegistryEntry entry : entries) {
if (entry.tag() == null) {
continue;
}
final CompoundTag variant = (CompoundTag) entry.tag();
final CompoundTag assets = (CompoundTag) variant.remove("assets");
variant.put("wild_texture", assets.get("wild"));
variant.put("tame_texture", assets.get("tame"));
variant.put("angry_texture", assets.get("angry"));
variant.put("biomes", new ListTag<>(StringTag.class));
}
return entries;
}
private void updateTrim(final RegistryEntry[] entries, final String itemKey) {
for (final RegistryEntry entry : entries) {
if (entry.tag() == null) {
continue;
}
final CompoundTag tag = (CompoundTag) entry.tag();
tag.putString(itemKey, "stone"); // dummy ingredient
}
}
};
protocol.registerClientbound(ClientboundConfigurationPackets1_21.REGISTRY_DATA, wrapper -> {
final String registryKey = Key.stripMinecraftNamespace(wrapper.passthrough(Types.STRING));
if (NEW_REGISTRIES.contains(registryKey)) {
wrapper.cancel();
return;
}
final RegistryEntry[] entries = wrapper.read(Types.REGISTRY_ENTRY_ARRAY);
if (registryKey.equals("enchantment")) {
final List<String> identifiers = new ArrayList<>(entries.length);
for (final RegistryEntry entry : entries) {
identifiers.add(entry.key());
}
wrapper.user().get(HashedItemConverterStorage.class).setEnchantments(identifiers);
}
wrapper.write(Types.REGISTRY_ENTRY_ARRAY, registryDataRewriter.handle(wrapper.user(), registryKey, entries));
});
protocol.registerClientbound(ClientboundPackets1_21_5.LOGIN, wrapper -> {
final int entityId = wrapper.passthrough(Types.INT); // Entity id
wrapper.passthrough(Types.BOOLEAN); // Hardcore
@@ -201,7 +122,7 @@ public final class EntityPacketRewriter1_21_5 extends EntityRewriter<Clientbound
wrapper.passthrough(Types.STRING); // Team Name
final byte action = wrapper.passthrough(Types.BYTE); // Mode
if (action == 0 || action == 2) {
wrapper.passthrough(Types.TAG); // Display Name
protocol.getComponentRewriter().passthroughAndProcess(wrapper); // Display name
wrapper.passthrough(Types.BYTE); // Flags
final int nametagVisibility = wrapper.read(Types.VAR_INT);
@@ -210,26 +131,12 @@ public final class EntityPacketRewriter1_21_5 extends EntityRewriter<Clientbound
wrapper.write(Types.STRING, collision(collisionRule));
wrapper.passthrough(Types.VAR_INT); // Color
wrapper.passthrough(Types.TAG); // Prefix
wrapper.passthrough(Types.TAG); // Suffix
protocol.getComponentRewriter().passthroughAndProcess(wrapper); // Prefix
protocol.getComponentRewriter().passthroughAndProcess(wrapper); // Suffix
}
});
}
private void updateEnchantment(final RegistryEntry[] entries) {
for (final RegistryEntry entry : entries) {
if (entry.tag() == null) {
continue;
}
final CompoundTag enchantment = (CompoundTag) entry.tag();
final ListTag<StringTag> slots = enchantment.getListTag("slots", StringTag.class);
if (slots != null) {
slots.getValue().removeIf(tag -> tag.getValue().equals("saddle")); // Remove saddle slot
}
}
}
private String visibility(final int id) {
return switch (id) {
case 0 -> "always";
@@ -0,0 +1,97 @@
/*
* This file is part of ViaBackwards - https://github.com/ViaVersion/ViaBackwards
* Copyright (C) 2016-2025 ViaVersion and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.viaversion.viabackwards.protocol.v1_21_5to1_21_4.rewriter;
import com.viaversion.nbt.tag.CompoundTag;
import com.viaversion.nbt.tag.ListTag;
import com.viaversion.nbt.tag.StringTag;
import com.viaversion.viabackwards.api.BackwardsProtocol;
import com.viaversion.viabackwards.api.rewriters.BackwardsRegistryRewriter;
import com.viaversion.viaversion.api.connection.UserConnection;
import com.viaversion.viaversion.api.minecraft.RegistryEntry;
import java.util.List;
public final class RegistryDataRewriter1_21_5 extends BackwardsRegistryRewriter {
public RegistryDataRewriter1_21_5(final BackwardsProtocol<?, ?, ?, ?> protocol) {
super(protocol);
final List<String> newRegistries = List.of("pig_variant", "cow_variant", "frog_variant", "cat_variant",
"chicken_variant", "test_environment", "test_instance", "wolf_sound_variant");
for (final String registry : newRegistries) {
remove(registry);
}
}
@Override
public RegistryEntry[] handle(final UserConnection connection, final String key, final RegistryEntry[] entries) {
final boolean trimPatternRegistry = key.equals("trim_pattern");
if (trimPatternRegistry || key.equals("trim_material")) {
updateTrim(entries, trimPatternRegistry ? "template_item" : "ingredient");
return super.handle(connection, key, entries);
}
if (key.equals("enchantment")) {
updateEnchantment(entries);
return super.handle(connection, key, entries);
}
if (!key.equals("wolf_variant")) {
return super.handle(connection, key, entries);
}
for (final RegistryEntry entry : entries) {
if (entry.tag() == null) {
continue;
}
final CompoundTag variant = (CompoundTag) entry.tag();
final CompoundTag assets = (CompoundTag) variant.remove("assets");
variant.put("wild_texture", assets.get("wild"));
variant.put("tame_texture", assets.get("tame"));
variant.put("angry_texture", assets.get("angry"));
variant.put("biomes", new ListTag<>(StringTag.class));
}
return entries;
}
private void updateTrim(final RegistryEntry[] entries, final String itemKey) {
for (final RegistryEntry entry : entries) {
if (entry.tag() == null) {
continue;
}
final CompoundTag tag = (CompoundTag) entry.tag();
tag.putString(itemKey, "stone"); // dummy ingredient
}
}
private void updateEnchantment(final RegistryEntry[] entries) {
for (final RegistryEntry entry : entries) {
if (entry.tag() == null) {
continue;
}
final CompoundTag enchantment = (CompoundTag) entry.tag();
final ListTag<StringTag> slots = enchantment.getListTag("slots", StringTag.class);
if (slots != null) {
slots.getValue().removeIf(tag -> tag.getValue().equals("saddle")); // Remove saddle slot
}
}
}
}
@@ -25,25 +25,17 @@ import com.viaversion.viaversion.api.protocol.Protocol;
import com.viaversion.viaversion.codec.CodecRegistryContext;
import com.viaversion.viaversion.codec.hash.HashFunction;
import com.viaversion.viaversion.codec.hash.HashOps;
import java.util.ArrayList;
import java.util.List;
public class HashedItemConverterStorage implements StorableObject {
private final List<String> enchantments = new ArrayList<>();
private final Hasher hasher;
public HashedItemConverterStorage(final Protocol<?, ?, ?, ?> protocol) {
final RegistryAccess registryAccess = RegistryAccess.of(this.enchantments, protocol.getMappingData());
final RegistryAccess registryAccess = RegistryAccess.of(protocol);
final CodecContext context = new CodecRegistryContext(protocol, registryAccess, false);
this.hasher = new HashOps(context, HashFunction.CRC32C);
}
public void setEnchantments(final List<String> enchantments) {
this.enchantments.clear();
this.enchantments.addAll(enchantments);
}
public Hasher hasher() {
return hasher; // reusable
}
@@ -19,6 +19,7 @@ package com.viaversion.viabackwards.protocol.v1_21_6to1_21_5;
import com.viaversion.nbt.tag.CompoundTag;
import com.viaversion.nbt.tag.Tag;
import com.viaversion.viabackwards.ViaBackwards;
import com.viaversion.viabackwards.api.BackwardsProtocol;
import com.viaversion.viabackwards.api.data.BackwardsMappingData;
import com.viaversion.viabackwards.api.rewriters.SoundRewriter;
@@ -29,6 +30,7 @@ import com.viaversion.viabackwards.protocol.v1_21_6to1_21_5.provider.DialogViewP
import com.viaversion.viabackwards.protocol.v1_21_6to1_21_5.rewriter.BlockItemPacketRewriter1_21_6;
import com.viaversion.viabackwards.protocol.v1_21_6to1_21_5.rewriter.ComponentRewriter1_21_6;
import com.viaversion.viabackwards.protocol.v1_21_6to1_21_5.rewriter.EntityPacketRewriter1_21_6;
import com.viaversion.viabackwards.protocol.v1_21_6to1_21_5.rewriter.RegistryDataRewriter1_21_6;
import com.viaversion.viabackwards.protocol.v1_21_6to1_21_5.storage.ChestDialogStorage;
import com.viaversion.viabackwards.protocol.v1_21_6to1_21_5.storage.ClickEvents;
import com.viaversion.viabackwards.protocol.v1_21_6to1_21_5.storage.RegistryAndTags;
@@ -61,6 +63,7 @@ import com.viaversion.viaversion.protocols.v1_21_5to1_21_6.packet.ServerboundPac
import com.viaversion.viaversion.protocols.v1_21_5to1_21_6.packet.ServerboundPackets1_21_6;
import com.viaversion.viaversion.rewriter.AttributeRewriter;
import com.viaversion.viaversion.rewriter.ParticleRewriter;
import com.viaversion.viaversion.rewriter.RegistryDataRewriter;
import com.viaversion.viaversion.rewriter.StatisticsRewriter;
import com.viaversion.viaversion.rewriter.TagRewriter;
import com.viaversion.viaversion.util.Key;
@@ -75,6 +78,7 @@ public final class Protocol1_21_6To1_21_5 extends BackwardsProtocol<ClientboundP
private final ParticleRewriter<ClientboundPacket1_21_6> particleRewriter = new ParticleRewriter<>(this);
private final NBTComponentRewriter<ClientboundPacket1_21_6> translatableRewriter = new ComponentRewriter1_21_6(this);
private final TagRewriter<ClientboundPacket1_21_6> tagRewriter = new TagRewriter<>(this);
private final RegistryDataRewriter registryDataRewriter = new RegistryDataRewriter1_21_6(this);
public Protocol1_21_6To1_21_5() {
super(ClientboundPacket1_21_6.class, ClientboundPacket1_21_5.class, ServerboundPacket1_21_6.class, ServerboundPacket1_21_5.class);
@@ -84,6 +88,8 @@ public final class Protocol1_21_6To1_21_5 extends BackwardsProtocol<ClientboundP
protected void registerPackets() {
super.registerPackets();
registerClientbound(ClientboundConfigurationPackets1_21_6.REGISTRY_DATA, registryDataRewriter::handle);
registerClientbound(ClientboundPackets1_21_6.UPDATE_TAGS, this::updateTags);
registerClientbound(ClientboundConfigurationPackets1_21_6.UPDATE_TAGS, this::updateTags);
@@ -125,12 +131,16 @@ public final class Protocol1_21_6To1_21_5 extends BackwardsProtocol<ClientboundP
translatableRewriter.registerComponentPacket(ClientboundPackets1_21_6.SET_SUBTITLE_TEXT);
translatableRewriter.registerBossEvent(ClientboundPackets1_21_6.BOSS_EVENT);
translatableRewriter.registerComponentPacket(ClientboundPackets1_21_6.DISCONNECT);
translatableRewriter.registerComponentPacket(ClientboundConfigurationPackets1_21_6.DISCONNECT);
translatableRewriter.registerTabList(ClientboundPackets1_21_6.TAB_LIST);
translatableRewriter.registerSetPlayerTeam1_21_5(ClientboundPackets1_21_6.SET_PLAYER_TEAM);
translatableRewriter.registerPlayerCombatKill1_20(ClientboundPackets1_21_6.PLAYER_COMBAT_KILL);
translatableRewriter.registerPlayerInfoUpdate1_21_4(ClientboundPackets1_21_6.PLAYER_INFO_UPDATE);
translatableRewriter.registerComponentPacket(ClientboundPackets1_21_6.SYSTEM_CHAT);
translatableRewriter.registerDisguisedChat(ClientboundPackets1_21_6.DISGUISED_CHAT);
translatableRewriter.registerPlayerChat1_21_5(ClientboundPackets1_21_6.PLAYER_CHAT);
translatableRewriter.registerSetObjective(ClientboundPackets1_21_6.SET_OBJECTIVE);
translatableRewriter.registerSetScore1_20_3(ClientboundPackets1_21_6.SET_SCORE);
translatableRewriter.registerPing();
particleRewriter.registerLevelParticles1_21_4(ClientboundPackets1_21_6.LEVEL_PARTICLES);
@@ -144,10 +154,15 @@ public final class Protocol1_21_6To1_21_5 extends BackwardsProtocol<ClientboundP
final short difficulty = wrapper.read(Types.UNSIGNED_BYTE);
wrapper.write(Types.VAR_INT, (int) difficulty);
});
registerServerbound(ServerboundPackets1_21_5.CHAT_COMMAND, this::handleClickEvents);
registerServerbound(ServerboundPackets1_21_5.CHAT_COMMAND_SIGNED, this::handleClickEvents);
// Are you sure you want to see this? This is your last chance to turn back.
registerClientbound(ClientboundPackets1_21_6.SHOW_DIALOG, null, wrapper -> {
wrapper.cancel();
if (!ViaBackwards.getConfig().dialogsViaChests()) {
return;
}
final RegistryAndTags registryAndTags = wrapper.user().get(RegistryAndTags.class);
final ServerLinks serverLinks = wrapper.user().get(ServerLinks.class);
@@ -164,6 +179,9 @@ public final class Protocol1_21_6To1_21_5 extends BackwardsProtocol<ClientboundP
});
registerClientbound(ClientboundConfigurationPackets1_21_6.SHOW_DIALOG, null, wrapper -> {
wrapper.cancel();
if (!ViaBackwards.getConfig().dialogsViaChests()) {
return;
}
final RegistryAndTags registryAndTags = wrapper.user().get(RegistryAndTags.class);
final ServerLinks serverLinks = wrapper.user().get(ServerLinks.class);
@@ -178,9 +196,6 @@ public final class Protocol1_21_6To1_21_5 extends BackwardsProtocol<ClientboundP
registerClientbound(ClientboundPackets1_21_6.SERVER_LINKS, this::storeServerLinks);
registerClientbound(ClientboundConfigurationPackets1_21_6.SERVER_LINKS, this::storeServerLinks);
registerServerbound(ServerboundPackets1_21_5.CHAT_COMMAND, this::handleClickEvents);
registerServerbound(ServerboundPackets1_21_5.CHAT_COMMAND_SIGNED, this::handleClickEvents);
// The ones below are specific to the chest dialog view provider
registerServerbound(ServerboundPackets1_21_5.CONTAINER_CLOSE, wrapper -> {
final ChestDialogStorage storage = wrapper.user().get(ChestDialogStorage.class);
@@ -285,6 +300,10 @@ public final class Protocol1_21_6To1_21_5 extends BackwardsProtocol<ClientboundP
private void clearDialog(final PacketWrapper wrapper) {
wrapper.cancel();
if (!ViaBackwards.getConfig().dialogsViaChests()) {
return;
}
final DialogViewProvider provider = Via.getManager().getProviders().get(DialogViewProvider.class);
provider.closeDialog(wrapper.user());
}
@@ -343,6 +362,11 @@ public final class Protocol1_21_6To1_21_5 extends BackwardsProtocol<ClientboundP
return itemRewriter;
}
@Override
public RegistryDataRewriter getRegistryDataRewriter() {
return registryDataRewriter;
}
@Override
public ParticleRewriter<ClientboundPacket1_21_6> getParticleRewriter() {
return particleRewriter;
@@ -74,7 +74,7 @@ public class Button implements Widget {
for (final String event : CLICK_EVENTS) {
if (Key.stripMinecraftNamespace(type).equals(event)) {
clickEvent = actionTag;
clickEvent = actionTag.copy();
clickEvent.put("action", clickEvent.remove("type"));
return;
}
@@ -132,7 +132,7 @@ public final class Dialog implements Widget {
private void fillNoticeDialog(final CompoundTag tag) {
final CompoundTag actionTag = tag.getCompoundTag("action");
actionButton = actionTag == null ? Button.DEFAULT : actionButton;
actionButton = actionTag == null ? Button.DEFAULT : new Button(this, actionTag);
}
private void fillServerLinksDialog(final ServerLinks serverLinks, final CompoundTag tag) {
@@ -150,7 +150,7 @@ public final class Dialog implements Widget {
}
private void fillDialogList(final RegistryAndTags registryAndTags, final ServerLinks serverLinks, final CompoundTag tag) {
// Hold them as either a list of inlined, a singleton inlined, a registry entry or a tag.
// Hold them as either a list of inlined / singleton inlined, a list of registry entries / singleton entry or a tag.
ListTag<CompoundTag> dialogsTag = tag.getListTag("dialogs", CompoundTag.class);
if (dialogsTag == null) {
CompoundTag dialogTag = tag.getCompoundTag("dialogs");
@@ -159,16 +159,23 @@ public final class Dialog implements Widget {
dialogsTag.add(dialogTag);
}
ListTag<StringTag> registryDialogsTag = tag.getListTag("dialogs", StringTag.class);
StringTag registryDialogTag = tag.getStringTag("dialogs");
if (registryDialogTag != null) {
registryDialogsTag = new ListTag<>(StringTag.class);
registryDialogsTag.add(registryDialogTag);
}
if (registryDialogsTag != null) {
dialogsTag = new ListTag<>(CompoundTag.class);
final String key = registryDialogTag.getValue();
if (key.startsWith("#")) {
for (final CompoundTag entry : registryAndTags.fromRegistryKey(key.substring(1))) {
dialogsTag.add(entry);
for (final StringTag nameTag : registryDialogsTag) {
final String key = nameTag.getValue();
if (key.startsWith("#")) {
for (final CompoundTag entry : registryAndTags.fromRegistryKey(key.substring(1))) {
dialogsTag.add(entry);
}
} else {
dialogsTag.add(registryAndTags.fromRegistry(key));
}
} else {
dialogsTag.add(registryAndTags.fromRegistry(key));
}
}
}
@@ -85,11 +85,18 @@ public class ChestDialogViewProvider implements DialogViewProvider {
texts.add(textWidget.label());
dialog.widgets().remove(textWidget);
} else if (!texts.isEmpty()) {
// Flush collected texts before adding the non-text widget
dialog.widgets().add(dialog.widgets().indexOf(widget), new MultiTextWidget(texts.toArray(Tag[]::new)));
texts.clear();
}
}
// Flush remaining texts if any
if (!texts.isEmpty()) {
dialog.widgets().add(new MultiTextWidget(texts.toArray(Tag[]::new)));
texts.clear();
}
final ChestDialogStorage previousStorage = connection.get(ChestDialogStorage.class);
final ChestDialogStorage storage = new ChestDialogStorage(this, dialog);
if (previousStorage != null) {
@@ -210,8 +217,9 @@ public class ChestDialogViewProvider implements DialogViewProvider {
}
}
// Resync inventory view if the actions above didn't close the dialog.
if (connection.has(ChestDialogStorage.class) && storage.phase() == ChestDialogStorage.Phase.DIALOG_VIEW) {
// Resync inventory view if the actions above didn't close the dialog nor opened another one.
final ChestDialogStorage currentStorage = connection.get(ChestDialogStorage.class);
if (currentStorage == storage && connection.has(ChestDialogStorage.class) && storage.phase() == ChestDialogStorage.Phase.DIALOG_VIEW) {
updateDialog(connection, storage.dialog());
}
return true;
@@ -274,17 +282,19 @@ public class ChestDialogViewProvider implements DialogViewProvider {
}
protected Item getMultiTextWidget(final UserConnection connection, final MultiTextWidget multiTextWidget) {
final Tag name = handleTag(connection, multiTextWidget.labels()[0]);
final int length = multiTextWidget.labels().length;
if (length == 1) {
return createItem("minecraft:paper", name);
final List<Tag> lines = new ArrayList<>();
for (final Tag label : multiTextWidget.labels()) {
final Tag[] split = ChatUtil.split(fixStyle(label), "\n");
for (final Tag line : split) {
lines.add(handleTag(connection, line));
}
}
final Tag[] lore = new Tag[length - 1];
for (int i = 1; i < length; i++) {
lore[i - 1] = handleTag(connection, fixStyle(multiTextWidget.labels()[i]));
final Tag[] lore = new Tag[lines.size() - 1];
for (int i = 1; i < lines.size(); i++) {
lore[i - 1] = lines.get(i);
}
return createItem("minecraft:paper", name, lore);
return createItem("minecraft:paper", lines.get(0), lore);
}
protected Item getBooleanInput(final UserConnection connection, final BooleanInput booleanInput) {
@@ -17,29 +17,18 @@
*/
package com.viaversion.viabackwards.protocol.v1_21_6to1_21_5.rewriter;
import com.viaversion.nbt.tag.CompoundTag;
import com.viaversion.viabackwards.api.rewriters.BackwardsRegistryRewriter;
import com.viaversion.viabackwards.api.rewriters.EntityRewriter;
import com.viaversion.viabackwards.protocol.v1_21_6to1_21_5.Protocol1_21_6To1_21_5;
import com.viaversion.viabackwards.protocol.v1_21_6to1_21_5.storage.RegistryAndTags;
import com.viaversion.viaversion.api.connection.UserConnection;
import com.viaversion.viaversion.api.minecraft.RegistryEntry;
import com.viaversion.viaversion.api.minecraft.entities.EntityType;
import com.viaversion.viaversion.api.minecraft.entities.EntityTypes1_21_6;
import com.viaversion.viaversion.api.minecraft.entitydata.types.EntityDataTypes1_21_5;
import com.viaversion.viaversion.api.protocol.packet.PacketWrapper;
import com.viaversion.viaversion.api.type.Types;
import com.viaversion.viaversion.api.type.types.version.VersionedTypes;
import com.viaversion.viaversion.libs.fastutil.objects.Object2ObjectArrayMap;
import com.viaversion.viaversion.libs.fastutil.objects.Object2ObjectMap;
import com.viaversion.viaversion.protocols.v1_21_4to1_21_5.packet.ClientboundPackets1_21_5;
import com.viaversion.viaversion.protocols.v1_21_4to1_21_5.packet.ServerboundPackets1_21_5;
import com.viaversion.viaversion.protocols.v1_21_5to1_21_6.packet.ClientboundConfigurationPackets1_21_6;
import com.viaversion.viaversion.protocols.v1_21_5to1_21_6.packet.ClientboundPacket1_21_6;
import com.viaversion.viaversion.protocols.v1_21_5to1_21_6.packet.ClientboundPackets1_21_6;
import com.viaversion.viaversion.rewriter.RegistryDataRewriter;
import com.viaversion.viaversion.util.Key;
import com.viaversion.viaversion.util.KeyMappings;
public final class EntityPacketRewriter1_21_6 extends EntityRewriter<ClientboundPacket1_21_6, Protocol1_21_6To1_21_5> {
@@ -86,31 +75,6 @@ public final class EntityPacketRewriter1_21_6 extends EntityRewriter<Clientbound
}
});
final RegistryDataRewriter registryDataRewriter = new BackwardsRegistryRewriter(protocol) {
@Override
public RegistryEntry[] handle(final UserConnection connection, final String key, final RegistryEntry[] entries) {
if (Key.stripMinecraftNamespace(key).equals("dialog")) {
final String[] keys = new String[entries.length];
for (int i = 0; i < entries.length; i++) {
keys[i] = Key.stripMinecraftNamespace(entries[i].key());
}
final Object2ObjectMap<String, CompoundTag> dialogs = new Object2ObjectArrayMap<>();
for (final RegistryEntry entry : entries) {
if (entry.tag() instanceof final CompoundTag tag) {
dialogs.put(Key.stripMinecraftNamespace(entry.key()), tag);
}
}
final RegistryAndTags registryAndTags = connection.get(RegistryAndTags.class);
registryAndTags.storeRegistry(new KeyMappings(keys), dialogs);
}
return super.handle(connection, key, entries);
}
};
registryDataRewriter.remove("dialog"); // Tracked and now removed
protocol.registerClientbound(ClientboundConfigurationPackets1_21_6.REGISTRY_DATA, registryDataRewriter::handle);
protocol.registerServerbound(ServerboundPackets1_21_5.PLAYER_COMMAND, wrapper -> {
wrapper.passthrough(Types.VAR_INT); // Entity ID
@@ -0,0 +1,59 @@
/*
* This file is part of ViaBackwards - https://github.com/ViaVersion/ViaBackwards
* Copyright (C) 2016-2025 ViaVersion and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.viaversion.viabackwards.protocol.v1_21_6to1_21_5.rewriter;
import com.viaversion.nbt.tag.CompoundTag;
import com.viaversion.viabackwards.api.BackwardsProtocol;
import com.viaversion.viabackwards.api.rewriters.BackwardsRegistryRewriter;
import com.viaversion.viabackwards.protocol.v1_21_6to1_21_5.storage.RegistryAndTags;
import com.viaversion.viaversion.api.connection.UserConnection;
import com.viaversion.viaversion.api.minecraft.RegistryEntry;
import com.viaversion.viaversion.libs.fastutil.objects.Object2ObjectArrayMap;
import com.viaversion.viaversion.libs.fastutil.objects.Object2ObjectMap;
import com.viaversion.viaversion.util.Key;
import com.viaversion.viaversion.util.KeyMappings;
public final class RegistryDataRewriter1_21_6 extends BackwardsRegistryRewriter {
public RegistryDataRewriter1_21_6(final BackwardsProtocol<?, ?, ?, ?> protocol) {
super(protocol);
remove("dialog"); // Tracked and now removed
}
@Override
public RegistryEntry[] handle(final UserConnection connection, final String key, final RegistryEntry[] entries) {
if (Key.stripMinecraftNamespace(key).equals("dialog")) {
final String[] keys = new String[entries.length];
for (int i = 0; i < entries.length; i++) {
keys[i] = Key.stripMinecraftNamespace(entries[i].key());
}
final Object2ObjectMap<String, CompoundTag> dialogs = new Object2ObjectArrayMap<>();
for (final RegistryEntry entry : entries) {
if (entry.tag() instanceof final CompoundTag tag) {
dialogs.put(Key.stripMinecraftNamespace(entry.key()), tag);
}
}
final RegistryAndTags registryAndTags = connection.get(RegistryAndTags.class);
registryAndTags.storeRegistry(new KeyMappings(keys), dialogs);
}
return super.handle(connection, key, entries);
}
}
@@ -19,6 +19,7 @@ package com.viaversion.viabackwards.protocol.v1_21_6to1_21_5.storage;
import com.viaversion.nbt.tag.CompoundTag;
import com.viaversion.nbt.tag.StringTag;
import com.viaversion.viabackwards.ViaBackwards;
import com.viaversion.viabackwards.protocol.v1_21_6to1_21_5.Protocol1_21_6To1_21_5;
import com.viaversion.viabackwards.protocol.v1_21_6to1_21_5.data.Dialog;
import com.viaversion.viabackwards.protocol.v1_21_6to1_21_5.provider.DialogViewProvider;
@@ -59,6 +60,10 @@ public final class ClickEvents implements StorableObject {
public static void handleClickEvent(final UserConnection connection, final CompoundTag clickEvent) {
final String action = Key.stripMinecraftNamespace(clickEvent.getString("action"));
if ("show_dialog".equals(action)) {
if (!ViaBackwards.getConfig().dialogsViaChests()) {
return;
}
final RegistryAndTags registryAndTags = connection.get(RegistryAndTags.class);
final ServerLinks serverLinks = connection.get(ServerLinks.class);
@@ -19,6 +19,7 @@ package com.viaversion.viabackwards.protocol.v1_21_7to1_21_6;
import com.viaversion.viabackwards.api.BackwardsProtocol;
import com.viaversion.viabackwards.api.data.BackwardsMappingData;
import com.viaversion.viabackwards.api.rewriters.BackwardsRegistryRewriter;
import com.viaversion.viabackwards.api.rewriters.SoundRewriter;
import com.viaversion.viabackwards.api.rewriters.text.NBTComponentRewriter;
import com.viaversion.viabackwards.api.rewriters.text.TranslatableRewriter;
@@ -42,6 +43,7 @@ import com.viaversion.viaversion.protocols.v1_21_5to1_21_6.packet.ServerboundPac
import com.viaversion.viaversion.protocols.v1_21_5to1_21_6.packet.ServerboundPackets1_21_6;
import com.viaversion.viaversion.protocols.v1_21_6to1_21_7.Protocol1_21_6To1_21_7;
import com.viaversion.viaversion.rewriter.ParticleRewriter;
import com.viaversion.viaversion.rewriter.RegistryDataRewriter;
import com.viaversion.viaversion.rewriter.StatisticsRewriter;
import com.viaversion.viaversion.rewriter.TagRewriter;
@@ -55,6 +57,7 @@ public final class Protocol1_21_7To1_21_6 extends BackwardsProtocol<ClientboundP
private final ParticleRewriter<ClientboundPacket1_21_6> particleRewriter = new ParticleRewriter<>(this);
private final NBTComponentRewriter<ClientboundPacket1_21_6> translatableRewriter = new NBTComponentRewriter<>(this);
private final TagRewriter<ClientboundPacket1_21_6> tagRewriter = new TagRewriter<>(this);
private final RegistryDataRewriter registryDataRewriter = new BackwardsRegistryRewriter(this);
public Protocol1_21_7To1_21_6() {
super(ClientboundPacket1_21_6.class, ClientboundPacket1_21_6.class, ServerboundPacket1_21_6.class, ServerboundPacket1_21_6.class);
@@ -64,6 +67,8 @@ public final class Protocol1_21_7To1_21_6 extends BackwardsProtocol<ClientboundP
protected void registerPackets() {
super.registerPackets();
registerClientbound(ClientboundConfigurationPackets1_21_6.REGISTRY_DATA, registryDataRewriter::handle);
tagRewriter.registerGeneric(ClientboundPackets1_21_6.UPDATE_TAGS);
tagRewriter.registerGeneric(ClientboundConfigurationPackets1_21_6.UPDATE_TAGS);
@@ -79,12 +84,16 @@ public final class Protocol1_21_7To1_21_6 extends BackwardsProtocol<ClientboundP
translatableRewriter.registerComponentPacket(ClientboundPackets1_21_6.SET_SUBTITLE_TEXT);
translatableRewriter.registerBossEvent(ClientboundPackets1_21_6.BOSS_EVENT);
translatableRewriter.registerComponentPacket(ClientboundPackets1_21_6.DISCONNECT);
translatableRewriter.registerComponentPacket(ClientboundConfigurationPackets1_21_6.DISCONNECT);
translatableRewriter.registerTabList(ClientboundPackets1_21_6.TAB_LIST);
translatableRewriter.registerSetPlayerTeam1_21_5(ClientboundPackets1_21_6.SET_PLAYER_TEAM);
translatableRewriter.registerPlayerCombatKill1_20(ClientboundPackets1_21_6.PLAYER_COMBAT_KILL);
translatableRewriter.registerPlayerInfoUpdate1_21_4(ClientboundPackets1_21_6.PLAYER_INFO_UPDATE);
translatableRewriter.registerComponentPacket(ClientboundPackets1_21_6.SYSTEM_CHAT);
translatableRewriter.registerDisguisedChat(ClientboundPackets1_21_6.DISGUISED_CHAT);
translatableRewriter.registerPlayerChat1_21_5(ClientboundPackets1_21_6.PLAYER_CHAT);
translatableRewriter.registerSetObjective(ClientboundPackets1_21_6.SET_OBJECTIVE);
translatableRewriter.registerSetScore1_20_3(ClientboundPackets1_21_6.SET_SCORE);
translatableRewriter.registerPing();
particleRewriter.registerLevelParticles1_21_4(ClientboundPackets1_21_6.LEVEL_PARTICLES);
@@ -127,6 +136,11 @@ public final class Protocol1_21_7To1_21_6 extends BackwardsProtocol<ClientboundP
return itemRewriter;
}
@Override
public RegistryDataRewriter getRegistryDataRewriter() {
return registryDataRewriter;
}
@Override
public ParticleRewriter<ClientboundPacket1_21_6> getParticleRewriter() {
return particleRewriter;
@@ -17,7 +17,6 @@
*/
package com.viaversion.viabackwards.protocol.v1_21_7to1_21_6.rewriter;
import com.viaversion.viabackwards.api.rewriters.BackwardsRegistryRewriter;
import com.viaversion.viabackwards.api.rewriters.EntityRewriter;
import com.viaversion.viabackwards.protocol.v1_21_7to1_21_6.Protocol1_21_7To1_21_6;
import com.viaversion.viaversion.api.minecraft.entities.EntityType;
@@ -25,10 +24,8 @@ import com.viaversion.viaversion.api.minecraft.entities.EntityTypes1_21_4;
import com.viaversion.viaversion.api.minecraft.entities.EntityTypes1_21_6;
import com.viaversion.viaversion.api.minecraft.entitydata.types.EntityDataTypes1_21_5;
import com.viaversion.viaversion.api.type.types.version.VersionedTypes;
import com.viaversion.viaversion.protocols.v1_21_5to1_21_6.packet.ClientboundConfigurationPackets1_21_6;
import com.viaversion.viaversion.protocols.v1_21_5to1_21_6.packet.ClientboundPacket1_21_6;
import com.viaversion.viaversion.protocols.v1_21_5to1_21_6.packet.ClientboundPackets1_21_6;
import com.viaversion.viaversion.rewriter.RegistryDataRewriter;
public final class EntityPacketRewriter1_21_7 extends EntityRewriter<ClientboundPacket1_21_6, Protocol1_21_7To1_21_6> {
@@ -45,9 +42,6 @@ public final class EntityPacketRewriter1_21_7 extends EntityRewriter<Clientbound
registerGameEvent(ClientboundPackets1_21_6.GAME_EVENT);
registerLogin1_20_5(ClientboundPackets1_21_6.LOGIN);
registerRespawn1_20_5(ClientboundPackets1_21_6.RESPAWN);
final RegistryDataRewriter registryDataRewriter = new BackwardsRegistryRewriter(protocol);
protocol.registerClientbound(ClientboundConfigurationPackets1_21_6.REGISTRY_DATA, registryDataRewriter::handle);
}
@Override
@@ -26,6 +26,7 @@ import com.viaversion.viabackwards.protocol.v1_21_9to1_21_7.rewriter.BlockItemPa
import com.viaversion.viabackwards.protocol.v1_21_9to1_21_7.rewriter.ComponentRewriter1_21_9;
import com.viaversion.viabackwards.protocol.v1_21_9to1_21_7.rewriter.EntityPacketRewriter1_21_9;
import com.viaversion.viabackwards.protocol.v1_21_9to1_21_7.rewriter.ParticleRewriter1_21_9;
import com.viaversion.viabackwards.protocol.v1_21_9to1_21_7.rewriter.RegistryDataRewriter1_21_9;
import com.viaversion.viabackwards.protocol.v1_21_9to1_21_7.storage.DimensionScaleStorage;
import com.viaversion.viabackwards.protocol.v1_21_9to1_21_7.storage.PlayerRotationStorage;
import com.viaversion.viabackwards.protocol.v1_21_9to1_21_7.tracker.EntityTracker1_21_9;
@@ -54,7 +55,9 @@ import com.viaversion.viaversion.protocols.v1_21_7to1_21_9.packet.ClientboundPac
import com.viaversion.viaversion.protocols.v1_21_7to1_21_9.packet.ClientboundPackets1_21_9;
import com.viaversion.viaversion.protocols.v1_21_7to1_21_9.packet.ServerboundConfigurationPackets1_21_9;
import com.viaversion.viaversion.protocols.v1_21_7to1_21_9.packet.ServerboundPacket1_21_9;
import com.viaversion.viaversion.protocols.v1_21to1_21_2.storage.BundleStateTracker;
import com.viaversion.viaversion.rewriter.ParticleRewriter;
import com.viaversion.viaversion.rewriter.RegistryDataRewriter;
import com.viaversion.viaversion.rewriter.StatisticsRewriter;
import com.viaversion.viaversion.rewriter.TagRewriter;
@@ -68,6 +71,7 @@ public final class Protocol1_21_9To1_21_7 extends BackwardsProtocol<ClientboundP
private final ParticleRewriter<ClientboundPacket1_21_9> particleRewriter = new ParticleRewriter1_21_9(this);
private final NBTComponentRewriter<ClientboundPacket1_21_9> translatableRewriter = new ComponentRewriter1_21_9(this);
private final TagRewriter<ClientboundPacket1_21_9> tagRewriter = new TagRewriter<>(this);
private final RegistryDataRewriter registryDataRewriter = new RegistryDataRewriter1_21_9(this);
public Protocol1_21_9To1_21_7() {
super(ClientboundPacket1_21_9.class, ClientboundPacket1_21_6.class, ServerboundPacket1_21_9.class, ServerboundPacket1_21_6.class);
@@ -77,6 +81,8 @@ public final class Protocol1_21_9To1_21_7 extends BackwardsProtocol<ClientboundP
protected void registerPackets() {
super.registerPackets();
registerClientbound(ClientboundConfigurationPackets1_21_9.REGISTRY_DATA, registryDataRewriter::handle);
tagRewriter.registerGeneric(ClientboundPackets1_21_9.UPDATE_TAGS);
tagRewriter.registerGeneric(ClientboundConfigurationPackets1_21_9.UPDATE_TAGS);
@@ -93,12 +99,16 @@ public final class Protocol1_21_9To1_21_7 extends BackwardsProtocol<ClientboundP
translatableRewriter.registerComponentPacket(ClientboundPackets1_21_9.SET_SUBTITLE_TEXT);
translatableRewriter.registerBossEvent(ClientboundPackets1_21_9.BOSS_EVENT);
translatableRewriter.registerComponentPacket(ClientboundPackets1_21_9.DISCONNECT);
translatableRewriter.registerComponentPacket(ClientboundConfigurationPackets1_21_9.DISCONNECT);
translatableRewriter.registerTabList(ClientboundPackets1_21_9.TAB_LIST);
translatableRewriter.registerSetPlayerTeam1_21_5(ClientboundPackets1_21_9.SET_PLAYER_TEAM);
translatableRewriter.registerPlayerCombatKill1_20(ClientboundPackets1_21_9.PLAYER_COMBAT_KILL);
translatableRewriter.registerPlayerInfoUpdate1_21_4(ClientboundPackets1_21_9.PLAYER_INFO_UPDATE);
translatableRewriter.registerComponentPacket(ClientboundPackets1_21_9.SYSTEM_CHAT);
translatableRewriter.registerDisguisedChat(ClientboundPackets1_21_9.DISGUISED_CHAT);
translatableRewriter.registerPlayerChat1_21_5(ClientboundPackets1_21_9.PLAYER_CHAT);
translatableRewriter.registerSetObjective(ClientboundPackets1_21_9.SET_OBJECTIVE);
translatableRewriter.registerSetScore1_20_3(ClientboundPackets1_21_9.SET_SCORE);
translatableRewriter.registerPing();
particleRewriter.registerLevelParticles1_21_4(ClientboundPackets1_21_9.LEVEL_PARTICLES);
@@ -193,6 +203,7 @@ public final class Protocol1_21_9To1_21_7 extends BackwardsProtocol<ClientboundP
wrapper.write(Types.VAR_INT, 0); // Subscription registry id (DEDICATED_SERVER_TICK_TIME)
}
});
registerClientbound(ClientboundPackets1_21_9.BUNDLE_DELIMITER, wrapper -> wrapper.user().get(BundleStateTracker.class).toggleBundling());
cancelClientbound(ClientboundPackets1_21_9.DEBUG_BLOCK_VALUE);
cancelClientbound(ClientboundPackets1_21_9.DEBUG_CHUNK_VALUE);
@@ -207,6 +218,7 @@ public final class Protocol1_21_9To1_21_7 extends BackwardsProtocol<ClientboundP
addItemHasher(connection, new ItemHasherBase(this, connection));
connection.put(new PlayerRotationStorage());
connection.put(new DimensionScaleStorage());
connection.put(new BundleStateTracker());
}
@Override
@@ -224,6 +236,11 @@ public final class Protocol1_21_9To1_21_7 extends BackwardsProtocol<ClientboundP
return itemRewriter;
}
@Override
public RegistryDataRewriter getRegistryDataRewriter() {
return registryDataRewriter;
}
@Override
public ParticleRewriter<ClientboundPacket1_21_9> getParticleRewriter() {
return particleRewriter;
@@ -18,12 +18,15 @@
package com.viaversion.viabackwards.protocol.v1_21_9to1_21_7.rewriter;
import com.viaversion.nbt.tag.CompoundTag;
import com.viaversion.nbt.tag.ListTag;
import com.viaversion.viabackwards.api.rewriters.BackwardsStructuredItemRewriter;
import com.viaversion.viabackwards.protocol.v1_21_9to1_21_7.Protocol1_21_9To1_21_7;
import com.viaversion.viabackwards.protocol.v1_21_9to1_21_7.storage.DimensionScaleStorage;
import com.viaversion.viaversion.api.connection.UserConnection;
import com.viaversion.viaversion.api.data.entity.EntityTracker;
import com.viaversion.viaversion.api.minecraft.ResolvableProfile;
import com.viaversion.viaversion.api.minecraft.blockentity.BlockEntity;
import com.viaversion.viaversion.api.minecraft.chunks.Chunk;
import com.viaversion.viaversion.api.minecraft.data.StructuredDataContainer;
import com.viaversion.viaversion.api.minecraft.data.StructuredDataKey;
import com.viaversion.viaversion.api.minecraft.item.Item;
@@ -42,6 +45,8 @@ import static com.viaversion.viaversion.protocols.v1_21_7to1_21_9.rewriter.Block
import static com.viaversion.viaversion.protocols.v1_21_7to1_21_9.rewriter.BlockItemPacketRewriter1_21_9.upgradeData;
public final class BlockItemPacketRewriter1_21_9 extends BackwardsStructuredItemRewriter<ClientboundPacket1_21_9, ServerboundPacket1_21_6, Protocol1_21_9To1_21_7> {
private static final int SIGN_BOCK_ENTITY_ID = 7;
private static final int HANGING_SIGN_BOCK_ENTITY_ID = 8;
public BlockItemPacketRewriter1_21_9(final Protocol1_21_9To1_21_7 protocol) {
super(protocol);
@@ -54,8 +59,8 @@ public final class BlockItemPacketRewriter1_21_9 extends BackwardsStructuredItem
blockRewriter.registerBlockUpdate(ClientboundPackets1_21_9.BLOCK_UPDATE);
blockRewriter.registerSectionBlocksUpdate1_20(ClientboundPackets1_21_9.SECTION_BLOCKS_UPDATE);
blockRewriter.registerLevelEvent1_21(ClientboundPackets1_21_9.LEVEL_EVENT, 2001);
blockRewriter.registerLevelChunk1_19(ClientboundPackets1_21_9.LEVEL_CHUNK_WITH_LIGHT, ChunkType1_21_5::new);
blockRewriter.registerBlockEntityData(ClientboundPackets1_21_9.BLOCK_ENTITY_DATA);
blockRewriter.registerLevelChunk1_19(ClientboundPackets1_21_9.LEVEL_CHUNK_WITH_LIGHT, ChunkType1_21_5::new, this::handleBlockEntity);
blockRewriter.registerBlockEntityData(ClientboundPackets1_21_9.BLOCK_ENTITY_DATA, this::handleBlockEntity);
registerSetCursorItem(ClientboundPackets1_21_9.SET_CURSOR_ITEM);
registerSetPlayerInventory(ClientboundPackets1_21_9.SET_PLAYER_INVENTORY);
@@ -63,7 +68,6 @@ public final class BlockItemPacketRewriter1_21_9 extends BackwardsStructuredItem
registerSetContent1_21_2(ClientboundPackets1_21_9.CONTAINER_SET_CONTENT);
registerSetSlot1_21_2(ClientboundPackets1_21_9.CONTAINER_SET_SLOT);
registerAdvancements1_20_3(ClientboundPackets1_21_9.UPDATE_ADVANCEMENTS);
registerSetEquipment(ClientboundPackets1_21_9.SET_EQUIPMENT);
registerMerchantOffers1_20_5(ClientboundPackets1_21_9.MERCHANT_OFFERS);
registerContainerClick1_21_5(ServerboundPackets1_21_6.CONTAINER_CLICK);
registerSetCreativeModeSlot1_21_5(ServerboundPackets1_21_6.SET_CREATIVE_MODE_SLOT);
@@ -131,6 +135,31 @@ public final class BlockItemPacketRewriter1_21_9 extends BackwardsStructuredItem
}
}
private void handleBlockEntity(final UserConnection connection, final BlockEntity blockEntity) {
final CompoundTag tag = blockEntity.tag();
if (tag == null) {
return;
}
if (blockEntity.typeId() == SIGN_BOCK_ENTITY_ID || blockEntity.typeId() == HANGING_SIGN_BOCK_ENTITY_ID) {
updateSignMessages(connection, tag.getCompoundTag("front_text"));
updateSignMessages(connection, tag.getCompoundTag("back_text"));
}
}
private void updateSignMessages(final UserConnection connection, final CompoundTag tag) {
if (tag == null) {
return;
}
final ListTag<?> messages = tag.getListTag("messages");
protocol.getComponentRewriter().processTag(connection, messages);
final ListTag<?> filteredMessages = tag.getListTag("filtered_messages");
if (filteredMessages != null) {
protocol.getComponentRewriter().processTag(connection, filteredMessages);
}
}
private void updateBorderCenter(final PacketWrapper wrapper) {
double centerX = wrapper.read(Types.DOUBLE);
double centerZ = wrapper.read(Types.DOUBLE);
@@ -20,35 +20,38 @@ package com.viaversion.viabackwards.protocol.v1_21_9to1_21_7.rewriter;
import com.viaversion.nbt.tag.CompoundTag;
import com.viaversion.nbt.tag.StringTag;
import com.viaversion.nbt.tag.Tag;
import com.viaversion.viabackwards.api.rewriters.BackwardsRegistryRewriter;
import com.viaversion.viabackwards.api.rewriters.EntityRewriter;
import com.viaversion.viabackwards.protocol.v1_21_9to1_21_7.Protocol1_21_9To1_21_7;
import com.viaversion.viabackwards.protocol.v1_21_9to1_21_7.storage.DimensionScaleStorage;
import com.viaversion.viabackwards.protocol.v1_21_9to1_21_7.storage.MannequinData;
import com.viaversion.viabackwards.protocol.v1_21_9to1_21_7.storage.PlayerRotationStorage;
import com.viaversion.viabackwards.protocol.v1_21_9to1_21_7.tracker.EntityTracker1_21_9;
import com.viaversion.viaversion.api.connection.UserConnection;
import com.viaversion.viaversion.api.data.entity.TrackedEntity;
import com.viaversion.viaversion.api.minecraft.BlockPosition;
import com.viaversion.viaversion.api.minecraft.GameProfile;
import com.viaversion.viaversion.api.minecraft.GlobalBlockPosition;
import com.viaversion.viaversion.api.minecraft.RegistryEntry;
import com.viaversion.viaversion.api.minecraft.ResolvableProfile;
import com.viaversion.viaversion.api.minecraft.Vector3d;
import com.viaversion.viaversion.api.minecraft.entities.EntityType;
import com.viaversion.viaversion.api.minecraft.entities.EntityTypes1_21_6;
import com.viaversion.viaversion.api.minecraft.entities.EntityTypes1_21_9;
import com.viaversion.viaversion.api.minecraft.entitydata.EntityData;
import com.viaversion.viaversion.api.minecraft.entitydata.types.EntityDataTypes1_21_5;
import com.viaversion.viaversion.api.minecraft.item.Item;
import com.viaversion.viaversion.api.protocol.packet.PacketWrapper;
import com.viaversion.viaversion.api.type.Types;
import com.viaversion.viaversion.api.type.types.version.VersionedTypes;
import com.viaversion.viaversion.protocols.v1_21_5to1_21_6.packet.ClientboundPackets1_21_6;
import com.viaversion.viaversion.protocols.v1_21_5to1_21_6.packet.ServerboundPackets1_21_6;
import com.viaversion.viaversion.protocols.v1_21_7to1_21_9.packet.ClientboundConfigurationPackets1_21_9;
import com.viaversion.viaversion.protocols.v1_21_7to1_21_9.packet.ClientboundPacket1_21_9;
import com.viaversion.viaversion.protocols.v1_21_7to1_21_9.packet.ClientboundPackets1_21_9;
import com.viaversion.viaversion.rewriter.RegistryDataRewriter;
import com.viaversion.viaversion.protocols.v1_21to1_21_2.storage.BundleStateTracker;
import com.viaversion.viaversion.rewriter.entitydata.EntityDataHandler;
import com.viaversion.viaversion.util.ChatColorUtil;
import com.viaversion.viaversion.util.Copyable;
import java.util.BitSet;
import java.util.List;
import java.util.Map;
import java.util.UUID;
import java.util.concurrent.ThreadLocalRandom;
import org.checkerframework.checker.nullness.qual.Nullable;
@@ -73,15 +76,16 @@ public final class EntityPacketRewriter1_21_9 extends EntityRewriter<Clientbound
final UUID uuid = wrapper.passthrough(Types.UUID);
final int entityTypeId = wrapper.passthrough(Types.VAR_INT);
wrapper.passthrough(Types.DOUBLE); // X
wrapper.passthrough(Types.DOUBLE); // Y
wrapper.passthrough(Types.DOUBLE); // Z
final double x = wrapper.passthrough(Types.DOUBLE);
final double y = wrapper.passthrough(Types.DOUBLE);
final double z = wrapper.passthrough(Types.DOUBLE);
final Vector3d movement = wrapper.read(Types.MOVEMENT_VECTOR);
wrapper.passthrough(Types.BYTE); // Pitch
wrapper.passthrough(Types.BYTE); // Yaw
wrapper.passthrough(Types.BYTE); // Head yaw
final byte pitch = wrapper.passthrough(Types.BYTE);
final byte yaw = wrapper.passthrough(Types.BYTE);
final byte headYaw = wrapper.passthrough(Types.BYTE);
final int data = wrapper.passthrough(Types.VAR_INT);
final EntityType entityType = trackAndRewrite(wrapper, entityTypeId, entityId);
if (protocol.getMappingData() != null && entityType == EntityTypes1_21_9.FALLING_BLOCK) {
@@ -94,11 +98,72 @@ public final class EntityPacketRewriter1_21_9 extends EntityRewriter<Clientbound
if (EntityTypes1_21_9.getTypeFromId(entityTypeId) == EntityTypes1_21_9.MANNEQUIN) {
final String name = randomHackyEmptyName();
final MannequinData mannequinData = new MannequinData(uuid, name);
tracker(wrapper.user()).entity(entityId).data().put(mannequinData);
sendInitialPlayerInfoUpdate(wrapper, mannequinData);
final TrackedEntity trackedEntity = tracker(wrapper.user()).entity(entityId);
trackedEntity.data().put(mannequinData);
sendInitialPlayerInfoUpdate(wrapper.user(), mannequinData, null, new GameProfile.Property[0]);
mannequinData.setPosition(x, y, z);
mannequinData.setRotation(yaw, pitch);
mannequinData.setHeadYaw(headYaw);
}
});
// Track movement
protocol.registerClientbound(ClientboundPackets1_21_9.TELEPORT_ENTITY, this::trackMannequinTeleport);
protocol.registerClientbound(ClientboundPackets1_21_9.ENTITY_POSITION_SYNC, this::trackMannequinTeleport);
protocol.registerClientbound(ClientboundPackets1_21_9.MOVE_ENTITY_POS, wrapper -> storeMovementMannequinData(wrapper, true, false));
protocol.registerClientbound(ClientboundPackets1_21_9.MOVE_ENTITY_POS_ROT, wrapper -> storeMovementMannequinData(wrapper, true, true));
protocol.registerClientbound(ClientboundPackets1_21_9.MOVE_ENTITY_ROT, wrapper -> storeMovementMannequinData(wrapper, false, true));
protocol.registerClientbound(ClientboundPackets1_21_9.ROTATE_HEAD, wrapper -> {
final int vehicleId = wrapper.passthrough(Types.VAR_INT);
final byte headRotation = wrapper.passthrough(Types.BYTE);
final EntityTracker1_21_9 tracker = tracker(wrapper.user());
final TrackedEntity trackedEntity = tracker.entity(vehicleId);
if (trackedEntity != null && trackedEntity.hasData()) {
final MannequinData data = trackedEntity.data().get(MannequinData.class);
if (data != null) {
data.setHeadYaw(headRotation);
}
}
});
// Track passengers
protocol.registerClientbound(ClientboundPackets1_21_9.SET_PASSENGERS, wrapper -> {
final int vehicleId = wrapper.passthrough(Types.VAR_INT);
final int[] passengerIds = wrapper.passthrough(Types.VAR_INT_ARRAY_PRIMITIVE);
final EntityTracker1_21_9 tracker = tracker(wrapper.user());
final TrackedEntity trackedEntity = tracker.entity(vehicleId);
if (trackedEntity != null && trackedEntity.hasData()) {
final MannequinData data = trackedEntity.data().get(MannequinData.class);
if (data != null) {
data.setPassengers(passengerIds);
}
}
});
// Track items
protocol.registerClientbound(ClientboundPackets1_21_9.SET_EQUIPMENT, wrapper -> {
final int entityId = wrapper.passthrough(Types.VAR_INT);
final TrackedEntity trackedEntity = tracker(wrapper.user()).entity(entityId);
final MannequinData mannequinData = trackedEntity != null && trackedEntity.hasData() ? trackedEntity.data().get(MannequinData.class) : null;
byte slot;
do {
slot = wrapper.passthrough(Types.BYTE);
final Item item = protocol.getItemRewriter().handleItemToClient(wrapper.user(), wrapper.read(protocol.getItemRewriter().itemType()));
wrapper.write(protocol.getItemRewriter().mappedItemType(), item);
if (mannequinData != null) {
mannequinData.setEquipment((byte) (slot & 0x7F), item);
}
} while (slot < 0);
});
// Back to more non-mannequin things
protocol.registerClientbound(ClientboundPackets1_21_9.SET_ENTITY_MOTION, wrapper -> {
wrapper.passthrough(Types.VAR_INT); // Entity ID
writeMovementShorts(wrapper, wrapper.read(Types.MOVEMENT_VECTOR));
@@ -129,29 +194,6 @@ public final class EntityPacketRewriter1_21_9 extends EntityRewriter<Clientbound
wrapper.read(Types.FLOAT); // Pitch
});
final RegistryDataRewriter registryDataRewriter = new BackwardsRegistryRewriter(protocol) {
@Override
public void trackDimensionAndBiomes(final UserConnection connection, final String registryKey, final RegistryEntry[] entries) {
super.trackDimensionAndBiomes(connection, registryKey, entries);
if (!registryKey.equals("dimension_type")) {
return;
}
final DimensionScaleStorage dimensionScaleStorage = connection.get(DimensionScaleStorage.class);
for (int i = 0; i < entries.length; i++) {
final RegistryEntry entry = entries[i];
final CompoundTag dimension = (CompoundTag) entry.tag();
if (dimension == null) {
continue;
}
final double coordinateScale = dimension.getDouble("coordinate_scale", 1);
dimensionScaleStorage.setScale(i, coordinateScale);
}
}
};
protocol.registerClientbound(ClientboundConfigurationPackets1_21_9.REGISTRY_DATA, registryDataRewriter::handle);
protocol.registerServerbound(ServerboundPackets1_21_6.MOVE_PLAYER_POS_ROT, wrapper -> {
wrapper.passthrough(Types.DOUBLE); // X
wrapper.passthrough(Types.DOUBLE); // Y
@@ -163,8 +205,63 @@ public final class EntityPacketRewriter1_21_9 extends EntityRewriter<Clientbound
protocol.registerServerbound(ServerboundPackets1_21_6.MOVE_PLAYER_ROT, this::storePlayerRotation);
}
private void sendInitialPlayerInfoUpdate(final PacketWrapper wrapper, final MannequinData mannequinData) {
final PacketWrapper playerInfo = wrapper.create(ClientboundPackets1_21_6.PLAYER_INFO_UPDATE);
private void trackMannequinTeleport(final PacketWrapper wrapper) {
final int entityId = wrapper.passthrough(Types.VAR_INT);
final EntityTracker1_21_9 tracker = tracker(wrapper.user());
final TrackedEntity trackedEntity = tracker.entity(entityId);
if (trackedEntity == null || !trackedEntity.hasData()) {
return;
}
final MannequinData mannequinData = trackedEntity.data().get(MannequinData.class);
if (mannequinData == null) {
return;
}
final double x = wrapper.passthrough(Types.DOUBLE);
final double y = wrapper.passthrough(Types.DOUBLE);
final double z = wrapper.passthrough(Types.DOUBLE);
wrapper.passthrough(Types.DOUBLE); // Delta movement X
wrapper.passthrough(Types.DOUBLE); // Delta movement Y
wrapper.passthrough(Types.DOUBLE); // Delta movement Z
final byte yaw = (byte) Math.floor(wrapper.passthrough(Types.FLOAT) * 256F / 360F);
final byte pitch = (byte) Math.floor(wrapper.passthrough(Types.FLOAT) * 256F / 360F);
mannequinData.setPosition(x, y, z);
mannequinData.setRotation(yaw, pitch);
}
private void storeMovementMannequinData(final PacketWrapper wrapper, final boolean position, final boolean rotation) {
final int entityId = wrapper.passthrough(Types.VAR_INT);
final TrackedEntity trackedEntity = tracker(wrapper.user()).entity(entityId);
if (trackedEntity == null || !trackedEntity.hasData()) {
return;
}
final MannequinData mannequinData = trackedEntity.data().get(MannequinData.class);
if (mannequinData == null) {
return;
}
if (position) {
final double deltaX = wrapper.passthrough(Types.SHORT) / 4096.0;
final double deltaY = wrapper.passthrough(Types.SHORT) / 4096.0;
final double deltaZ = wrapper.passthrough(Types.SHORT) / 4096.0;
mannequinData.setPosition(mannequinData.x() + deltaX, mannequinData.y() + deltaY, mannequinData.z() + deltaZ);
}
if (rotation) {
final byte yaw = wrapper.passthrough(Types.BYTE);
final byte pitch = wrapper.passthrough(Types.BYTE);
mannequinData.setRotation(yaw, pitch);
}
}
private void sendInitialPlayerInfoUpdate(final UserConnection connection, final MannequinData mannequinData, final @Nullable String nameOverride, final GameProfile.Property[] properties) {
final PacketWrapper playerInfo = PacketWrapper.create(ClientboundPackets1_21_6.PLAYER_INFO_UPDATE, connection);
final BitSet actions = new BitSet(8);
for (int i = 0; i < 8; i++) {
@@ -173,8 +270,8 @@ public final class EntityPacketRewriter1_21_9 extends EntityRewriter<Clientbound
playerInfo.write(Types.PROFILE_ACTIONS_ENUM1_21_4, actions);
playerInfo.write(Types.VAR_INT, 1); // One entry
playerInfo.write(Types.UUID, mannequinData.uuid());
playerInfo.write(Types.STRING, mannequinData.name());
playerInfo.write(Types.PROFILE_PROPERTY_ARRAY, new GameProfile.Property[0]);
playerInfo.write(Types.STRING, nameOverride != null ? nameOverride : mannequinData.name());
playerInfo.write(Types.PROFILE_PROPERTY_ARRAY, properties);
playerInfo.write(Types.BOOLEAN, false); // Session info
playerInfo.write(Types.VAR_INT, 0); // Gamemode
playerInfo.write(Types.BOOLEAN, false); // Listed
@@ -184,7 +281,7 @@ public final class EntityPacketRewriter1_21_9 extends EntityRewriter<Clientbound
playerInfo.write(Types.BOOLEAN, true); // Show hat
playerInfo.send(Protocol1_21_9To1_21_7.class);
sendPlayerTeamDisplayName(wrapper.user(), mannequinData, null);
sendPlayerTeamDisplayName(connection, mannequinData, mannequinData.displayName());
}
private void sendPlayerInfoDisplayNameUpdate(final UserConnection connection, final MannequinData mannequinData, @Nullable final Tag displayName) {
@@ -219,18 +316,6 @@ public final class EntityPacketRewriter1_21_9 extends EntityRewriter<Clientbound
addTeam.send(Protocol1_21_9To1_21_7.class);
}
private void sendPlayerInfoProfileUpdate(final UserConnection connection, final UUID uuid, @Nullable final String name, final GameProfile.Property[] properties) {
final PacketWrapper playerInfo = PacketWrapper.create(ClientboundPackets1_21_6.PLAYER_INFO_UPDATE, connection);
final BitSet actions = new BitSet(8);
actions.set(0);
playerInfo.write(Types.PROFILE_ACTIONS_ENUM1_21_4, actions);
playerInfo.write(Types.VAR_INT, 1);
playerInfo.write(Types.UUID, uuid);
playerInfo.write(Types.STRING, name != null ? name : randomHackyEmptyName());
playerInfo.write(Types.PROFILE_PROPERTY_ARRAY, properties);
playerInfo.send(Protocol1_21_9To1_21_7.class);
}
private String randomHackyEmptyName() {
final StringBuilder builder = new StringBuilder();
// Player names cannot be updated after the initial add without fully respawning them;
@@ -311,15 +396,84 @@ public final class EntityPacketRewriter1_21_9 extends EntityRewriter<Clientbound
}
});
filter().type(EntityTypes1_21_9.MANNEQUIN).handler(((event, data) -> {
filter().type(EntityTypes1_21_9.MANNEQUIN).handler((event, data) -> {
if (event.index() == 2) { // Display name
final Tag displayName = data.value();
final MannequinData mannequinData = event.trackedEntity().data().get(MannequinData.class);
mannequinData.setDisplayName(displayName);
sendPlayerInfoDisplayNameUpdate(event.user(), mannequinData, displayName);
} else if (event.index() == 17) { // Profile
final boolean isBundling = event.user().get(BundleStateTracker.class).isBundling();
if (!isBundling) {
final PacketWrapper bundleStart = PacketWrapper.create(ClientboundPackets1_21_6.BUNDLE_DELIMITER, event.user());
bundleStart.send(Protocol1_21_9To1_21_7.class);
}
final ResolvableProfile profile = data.value();
final UUID uuid = event.trackedEntity().data().get(MannequinData.class).uuid();
sendPlayerInfoProfileUpdate(event.user(), uuid, profile.profile().name(), profile.profile().properties());
final MannequinData mannequinData = event.trackedEntity().data().get(MannequinData.class);
final UUID uuid = mannequinData.uuid();
// Remove the old entity
final PacketWrapper removeEntityPacket = PacketWrapper.create(ClientboundPackets1_21_6.REMOVE_ENTITIES, event.user());
removeEntityPacket.write(Types.VAR_INT_ARRAY_PRIMITIVE, new int[]{event.entityId()});
removeEntityPacket.send(Protocol1_21_9To1_21_7.class);
final PacketWrapper playerInfoRemove = PacketWrapper.create(ClientboundPackets1_21_6.PLAYER_INFO_REMOVE, event.user());
playerInfoRemove.write(Types.UUID_ARRAY, new UUID[]{uuid});
playerInfoRemove.send(Protocol1_21_9To1_21_7.class);
// Spawn new entity
sendInitialPlayerInfoUpdate(event.user(), mannequinData, profile.profile().name(), profile.profile().properties());
final PacketWrapper spawnEntityPacket = PacketWrapper.create(ClientboundPackets1_21_6.ADD_ENTITY, event.user());
spawnEntityPacket.write(Types.VAR_INT, event.entityId());
spawnEntityPacket.write(Types.UUID, mannequinData.uuid());
spawnEntityPacket.write(Types.VAR_INT, EntityTypes1_21_6.PLAYER.getId());
spawnEntityPacket.write(Types.DOUBLE, mannequinData.x());
spawnEntityPacket.write(Types.DOUBLE, mannequinData.y());
spawnEntityPacket.write(Types.DOUBLE, mannequinData.z());
spawnEntityPacket.write(Types.BYTE, mannequinData.pitch());
spawnEntityPacket.write(Types.BYTE, mannequinData.yaw());
spawnEntityPacket.write(Types.BYTE, mannequinData.headYaw());
spawnEntityPacket.write(Types.VAR_INT, 0); // Data
spawnEntityPacket.write(Types.SHORT, (short) 0); // Velocity X
spawnEntityPacket.write(Types.SHORT, (short) 0); // Velocity Y
spawnEntityPacket.write(Types.SHORT, (short) 0); // Velocity Z
spawnEntityPacket.send(Protocol1_21_9To1_21_7.class);
// Re-apply entity data previously set
final PacketWrapper setEntityDataPacket = PacketWrapper.create(ClientboundPackets1_21_6.SET_ENTITY_DATA, event.user());
setEntityDataPacket.write(Types.VAR_INT, event.entityId());
setEntityDataPacket.write(VersionedTypes.V1_21_6.entityDataList, mannequinData.entityData());
setEntityDataPacket.send(Protocol1_21_9To1_21_7.class);
// Re-attach all passengers
if (mannequinData.passengers() != null) {
final PacketWrapper setPassengersPacket = PacketWrapper.create(ClientboundPackets1_21_6.SET_PASSENGERS, event.user());
setPassengersPacket.write(Types.VAR_INT, event.entityId());
setPassengersPacket.write(Types.VAR_INT_ARRAY_PRIMITIVE, mannequinData.passengers());
setPassengersPacket.send(Protocol1_21_9To1_21_7.class);
}
// Put on items
if (!mannequinData.itemMap().isEmpty()) {
final PacketWrapper equipment = PacketWrapper.create(ClientboundPackets1_21_6.SET_EQUIPMENT, event.user());
equipment.write(Types.VAR_INT, event.entityId());
int i = 0;
for (final Map.Entry<Byte, Item> itemEntry : mannequinData.itemMap().entrySet()) {
final boolean more = i < mannequinData.itemMap().size() - 1;
equipment.write(Types.BYTE, more ? (byte) (itemEntry.getKey() | -128) : itemEntry.getKey());
equipment.write(protocol.getItemRewriter().mappedItemType(), itemEntry.getValue());
i++;
}
equipment.send(Protocol1_21_9To1_21_7.class);
}
if (!isBundling) {
final PacketWrapper bundleStart = PacketWrapper.create(ClientboundPackets1_21_6.BUNDLE_DELIMITER, event.user());
bundleStart.send(Protocol1_21_9To1_21_7.class);
}
event.cancel();
} else if (event.index() == 15) {
event.setIndex(18);
@@ -331,7 +485,30 @@ public final class EntityPacketRewriter1_21_9 extends EntityRewriter<Clientbound
} else if (event.index() == 19) {
event.cancel(); // Description
}
}));
});
}
@Override
public void handleEntityData(final int entityId, final List<EntityData> dataList, final UserConnection connection) {
super.handleEntityData(entityId, dataList, connection);
final EntityTracker1_21_9 tracker = tracker(connection);
final EntityType entityType = tracker.entityType(entityId);
if (entityType == null || !entityType.isOrHasParent(EntityTypes1_21_9.MANNEQUIN)) {
return;
}
final MannequinData mannequinData = tracker.entity(entityId).data().get(MannequinData.class);
if (mannequinData == null) {
return;
}
final List<EntityData> entityData = mannequinData.entityData();
entityData.removeIf(first -> dataList.stream().anyMatch(second -> first.id() == second.id()));
for (final EntityData data : dataList) {
final Object value = data.value();
entityData.add(new EntityData(data.id(), data.dataType(), Copyable.copy(value)));
}
}
@Override
@@ -0,0 +1,52 @@
/*
* This file is part of ViaBackwards - https://github.com/ViaVersion/ViaBackwards
* Copyright (C) 2016-2025 ViaVersion and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.viaversion.viabackwards.protocol.v1_21_9to1_21_7.rewriter;
import com.viaversion.nbt.tag.CompoundTag;
import com.viaversion.viabackwards.api.BackwardsProtocol;
import com.viaversion.viabackwards.api.rewriters.BackwardsRegistryRewriter;
import com.viaversion.viabackwards.protocol.v1_21_9to1_21_7.storage.DimensionScaleStorage;
import com.viaversion.viaversion.api.connection.UserConnection;
import com.viaversion.viaversion.api.minecraft.RegistryEntry;
public final class RegistryDataRewriter1_21_9 extends BackwardsRegistryRewriter {
public RegistryDataRewriter1_21_9(final BackwardsProtocol<?, ?, ?, ?> protocol) {
super(protocol);
}
@Override
public void trackDimensionAndBiomes(final UserConnection connection, final String registryKey, final RegistryEntry[] entries) {
super.trackDimensionAndBiomes(connection, registryKey, entries);
if (!registryKey.equals("dimension_type")) {
return;
}
final DimensionScaleStorage dimensionScaleStorage = connection.get(DimensionScaleStorage.class);
for (int i = 0; i < entries.length; i++) {
final RegistryEntry entry = entries[i];
final CompoundTag dimension = (CompoundTag) entry.tag();
if (dimension == null) {
continue;
}
final double coordinateScale = dimension.getDouble("coordinate_scale", 1);
dimensionScaleStorage.setScale(i, coordinateScale);
}
}
}
@@ -17,6 +17,14 @@
*/
package com.viaversion.viabackwards.protocol.v1_21_9to1_21_7.storage;
import com.viaversion.nbt.tag.Tag;
import com.viaversion.viaversion.api.minecraft.entitydata.EntityData;
import com.viaversion.viaversion.api.minecraft.item.Item;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.UUID;
public final class MannequinData {
@@ -24,6 +32,22 @@ public final class MannequinData {
private final String name;
private boolean hasTeam;
private double x;
private double y;
private double z;
// Packed values
private byte yaw;
private byte pitch;
private byte headYaw;
private int[] passengers;
private final List<EntityData> entityData = new ArrayList<>();
private final Map<Byte, Item> itemMap = new HashMap<>();
private Tag displayName;
public MannequinData(final UUID uuid, final String name) {
this.uuid = uuid;
this.name = name;
@@ -44,4 +68,71 @@ public final class MannequinData {
public String name() {
return name;
}
public void setPosition(final double x, final double y, final double z) {
this.x = x;
this.y = y;
this.z = z;
}
public void setRotation(final byte yaw, final byte pitch) {
this.yaw = yaw;
this.pitch = pitch;
}
public void setPassengers(final int[] passengers) {
this.passengers = passengers;
}
public double x() {
return x;
}
public double y() {
return y;
}
public double z() {
return z;
}
public byte yaw() {
return yaw;
}
public byte pitch() {
return pitch;
}
public List<EntityData> entityData() {
return entityData;
}
public int[] passengers() {
return passengers;
}
public void setDisplayName(Tag displayName) {
this.displayName = displayName;
}
public Tag displayName() {
return displayName;
}
public void setEquipment(byte slot, Item item) {
itemMap.put(slot, item);
}
public Map<Byte, Item> itemMap() {
return itemMap;
}
public byte headYaw() {
return headYaw;
}
public void setHeadYaw(byte headYaw) {
this.headYaw = headYaw;
}
}
@@ -92,9 +92,13 @@ public final class Protocol1_21To1_20_5 extends BackwardsProtocol<ClientboundPac
translatableRewriter.registerComponentPacket(ClientboundPackets1_21.SET_SUBTITLE_TEXT);
translatableRewriter.registerBossEvent(ClientboundPackets1_21.BOSS_EVENT);
translatableRewriter.registerComponentPacket(ClientboundPackets1_21.DISCONNECT);
translatableRewriter.registerComponentPacket(ClientboundConfigurationPackets1_21.DISCONNECT);
translatableRewriter.registerTabList(ClientboundPackets1_21.TAB_LIST);
translatableRewriter.registerSetPlayerTeam1_13(ClientboundPackets1_21.SET_PLAYER_TEAM);
translatableRewriter.registerPlayerCombatKill1_20(ClientboundPackets1_21.PLAYER_COMBAT_KILL);
translatableRewriter.registerComponentPacket(ClientboundPackets1_21.SYSTEM_CHAT);
translatableRewriter.registerSetObjective(ClientboundPackets1_21.SET_OBJECTIVE);
translatableRewriter.registerSetScore1_20_3(ClientboundPackets1_21.SET_SCORE);
translatableRewriter.registerPing();
// Format change we can't properly map - all this really results in is a desync one version earlier
@@ -324,7 +324,7 @@ public final class BlockItemPacketRewriter1_21 extends BackwardsStructuredItemRe
if (songIdentifier != null) {
song = EitherHolder.of(songIdentifier);
} else {
song = EitherHolder.of(restoreHolder(tag, "song", songTag -> {
song = EitherHolder.of(restoreHolder(jukeboxPlayableTag, "song", songTag -> {
final Holder<SoundEvent> soundEvent = restoreSoundEventHolder(songTag);
final Tag description = songTag.get("description");
final float lengthInSeconds = songTag.getFloat("length_in_seconds");
@@ -45,6 +45,9 @@ map-display-entities: true
# Suppresses warnings of missing emulations for certain features that are not supported (e.g. world height in 1.17+).
suppress-emulation-warnings: false
#
# If enabled, dialogs will be shown via chest inventories for 1.21.5 clients on 1.21.6+ servers.
dialogs-via-chests: true
#
# Dialog styling. You can also use translation keys here.
dialog-style:
page-navigation-title: "&9&lPage navigation"
@@ -1,4 +1,172 @@
{
"1.21.11": {
"advancements.adventure.spear_many_mobs.description": "Hit five mobs in the same Charge attack using the Spear",
"advancements.adventure.spear_many_mobs.title": "Mob Kabob",
"advMode.setCommand.disabled": "Command set: %s, but command blocks are still disabled",
"chat.queue.tooltip": "Click to display next message",
"commands.stopwatch.already_exists": "Stopwatch '%s' already exists",
"commands.stopwatch.create.success": "Created Stopwatch '%s'",
"commands.stopwatch.does_not_exist": "Stopwatch '%s' does not exist",
"commands.stopwatch.query": "Stopwatch '%s' has run for %ss",
"commands.stopwatch.remove.success": "Removed Stopwatch '%s'",
"commands.stopwatch.restart.success": "Restarted Stopwatch '%s'",
"death.attack.spear": "%1$s was speared by %2$s",
"death.attack.spear.item": "%1$s was speared by %2$s using %3$s",
"debug.crash.message.rebindable": "%s + %s is held down. This will crash the game unless released.",
"debug.entry.currently.inOverlay": "%s: Currently only in debug overlay",
"debug.entry.overlay": "In Overlay",
"debug.profiling.start.rebindable": "Profiling started for %s seconds. Use %s + %s to stop early",
"effect.minecraft.breath_of_the_nautilus": "Breath of the Nautilus",
"enchantment.minecraft.lunge": "Lunge",
"entity.minecraft.camel_husk": "Camel Husk",
"entity.minecraft.nautilus": "Nautilus",
"entity.minecraft.parched": "Parched",
"entity.minecraft.zombie_nautilus": "Zombie Nautilus",
"gamerule.minecraft.elytra_movement_check": "Do elytra movement check",
"gamerule.minecraft.fire_spread_radius_around_player": "Fire spread radius",
"gamerule.minecraft.fire_spread_radius_around_player.description": "The radius in blocks around a player in which fire can spread",
"gamerule.minecraft.player_movement_check": "Do player movement check",
"gamerule.minecraft.raids": "Do raids",
"item.intangible": "Intangible",
"item.minecraft.camel_husk_spawn_egg": "Camel Husk Spawn Egg",
"item.minecraft.copper_nautilus_armor": "Copper Nautilus Armor",
"item.minecraft.copper_spear": "Copper Spear",
"item.minecraft.diamond_nautilus_armor": "Diamond Nautilus Armor",
"item.minecraft.diamond_spear": "Diamond Spear",
"item.minecraft.golden_nautilus_armor": "Golden Nautilus Armor",
"item.minecraft.golden_spear": "Golden Spear",
"item.minecraft.iron_nautilus_armor": "Iron Nautilus Armor",
"item.minecraft.iron_spear": "Iron Spear",
"item.minecraft.nautilus_spawn_egg": "Nautilus Spawn Egg",
"item.minecraft.netherite_horse_armor": "Netherite Horse Armor",
"item.minecraft.netherite_nautilus_armor": "Netherite Nautilus Armor",
"item.minecraft.netherite_spear": "Netherite Spear",
"item.minecraft.parched_spawn_egg": "Parched Spawn Egg",
"item.minecraft.stone_spear": "Stone Spear",
"item.minecraft.wooden_spear": "Wooden Spear",
"item.minecraft.zombie_nautilus_spawn_egg": "Zombie Nautilus Spawn Egg",
"key.category.minecraft.debug": "Debug",
"key.debug.clearChat": "Clear Chat",
"key.debug.copyLocation": "Copy Location",
"key.debug.copyRecreateCommand": "Copy Data",
"key.debug.crash": "Debug Crash",
"key.debug.dumpDynamicTextures": "Dump Dynamic Textures",
"key.debug.dumpVersion": "Dump Version Info",
"key.debug.focusPause": "Toggle Lost Focus Pause",
"key.debug.fpsCharts": "FPS Charts",
"key.debug.modifier": "Debug Modifier Key",
"key.debug.networkCharts": "Network Charts",
"key.debug.overlay": "Toggle Overlay",
"key.debug.profiling": "Start/Stop Profiling",
"key.debug.profilingChart": "Profiling Chart",
"key.debug.reloadChunk": "Reload Chunks",
"key.debug.reloadResourcePacks": "Reload Resource Packs",
"key.debug.showAdvancedTooltips": "Show Advanced Tooltips",
"key.debug.showChunkBorders": "Show Chunk Boundaries",
"key.debug.showHitboxes": "Show Hitboxes",
"key.debug.spectate": "Cycle Spectator",
"key.debug.switchGameMode": "Game Mode Switcher",
"key.toggleGui": "Toggle GUI",
"key.toggleSpectatorShaderEffects": "Toggle Spectator Shader Effects",
"mco.backup.entry.worldType.adventureMap": "Adventure Map",
"mco.backup.entry.worldType.experience": "Experience",
"mco.configure.world.name.validation.whitespace": "Must not start or end with whitespace. It will be trimmed.",
"narration.checkbox.usage.focused.check": "Press Enter to check",
"narration.checkbox.usage.focused.uncheck": "Press Enter to uncheck",
"narration.checkbox.usage.hovered.check": "Left click to check",
"narration.checkbox.usage.hovered.uncheck": "Left click to uncheck",
"options.blocks": "%s Blocks",
"options.chunkFade": "Chunk Fade Time",
"options.chunkFade.none": "Chunk Fade: None",
"options.chunkFade.seconds": "Chunk Fade: %s second(s)",
"options.chunkFade.tooltip": "How long in seconds chunks should fade in when they're first rendered, if at all.",
"options.cutoutLeaves": "See-Through Leaves",
"options.cutoutLeaves.tooltip": "Allows you to see through gaps in leaves. Disabling improves performance.",
"options.graphics.preset": "Preset",
"options.graphics.preset.tooltip": "Sets \"Quality & Performance\" settings to reasonable defaults corresponding to the desired quality.",
"options.improvedTransparency": "Improved Transparency",
"options.improvedTransparency.tooltip": "An experimental approach that uses screen shaders for drawing weather, clouds, and particles behind translucent blocks and water.\nThis will impact GPU performance.",
"options.maxAnisotropy": "Anisotropic Filtering",
"options.maxAnisotropy.tooltip": "Each level significantly improves how smooth textures look, but impacts performance and significantly impacts video memory usage. Requires Texture Filtering to be set to Anisotropic.",
"options.musicToast": "Music Toast",
"options.musicToast.never.tooltip": "No music toast is shown.",
"options.musicToast.pauseMenu": "Pause Menu",
"options.musicToast.pauseMenu.tooltip": "A music toast is constantly displayed in the in-game pause menu while a song is playing.",
"options.musicToast.pauseMenuAndToast": "Pause Menu and Toast",
"options.musicToast.pauseMenuAndToast.tooltip": "Displays a toast when a song starts playing. The same toast is constantly displayed in the in-game pause menu while a song is playing.",
"options.textureFiltering": "Texture Filtering",
"options.textureFiltering.anisotropic": "Anisotropic",
"options.textureFiltering.anisotropic.tooltip": "A hardware based filtering method, but impacts performance and significantly impacts video memory usage. May not be supported on all hardware.",
"options.textureFiltering.none.tooltip": "Textures are displayed without any filtering. Blocks may look blurry when viewed at an angle.",
"options.textureFiltering.rgss": "RGSS",
"options.textureFiltering.rgss.tooltip": "(Rotated Grid Super Sampling)\nA shader based filtering method that improves texture quality with a moderate performance impact.",
"options.video.display.header": "Display",
"options.video.interface.header": "Interface",
"options.video.preferences.header": "Preferences",
"options.video.quality.header": "Quality & Performance",
"options.vignette": "Show Vignette",
"options.vignette.tooltip": "This is a subtle texture over the game screen used for reducing brightness towards the edges of the screen and warning about the world border.",
"options.weatherRadius": "Weather Effect Radius",
"options.weatherRadius.tooltip": "Radius of the area where rain and snow effects are visible. Very low performance impact.",
"stat.minecraft.nautilus_one_cm": "Distance by Nautilus",
"subtitles.entity.baby_nautilus.ambient": "Baby Nautilus chitters",
"subtitles.entity.baby_nautilus.ambient_land": "Baby Nautilus chitters",
"subtitles.entity.baby_nautilus.death": "Baby Nautilus dies",
"subtitles.entity.baby_nautilus.death_land": "Baby Nautilus dies",
"subtitles.entity.baby_nautilus.eat": "Baby Nautilus eats",
"subtitles.entity.baby_nautilus.hurt": "Baby Nautilus hurts",
"subtitles.entity.baby_nautilus.hurt_land": "Baby Nautilus hurts",
"subtitles.entity.baby_nautilus.swim": "Baby Nautilus swims",
"subtitles.entity.camel_husk.ambient": "Camel Husk grumphs",
"subtitles.entity.camel_husk.dash": "Camel Husk yeets",
"subtitles.entity.camel_husk.dash_ready": "Camel Husk recovers",
"subtitles.entity.camel_husk.death": "Camel Husk dies",
"subtitles.entity.camel_husk.eat": "Camel Husk eats",
"subtitles.entity.camel_husk.hurt": "Camel Husk hurts",
"subtitles.entity.camel_husk.sit": "Camel Husk sits down",
"subtitles.entity.camel_husk.stand": "Camel Husk stands up",
"subtitles.entity.nautilus.ambient": "Nautilus clacks",
"subtitles.entity.nautilus.ambient_land": "Nautilus clacks",
"subtitles.entity.nautilus.dash": "Nautilus jets",
"subtitles.entity.nautilus.dash_land": "Nautilus jets",
"subtitles.entity.nautilus.dash_ready": "Nautilus recovers",
"subtitles.entity.nautilus.dash_ready_land": "Nautilus recovers",
"subtitles.entity.nautilus.death": "Nautilus dies",
"subtitles.entity.nautilus.death_land": "Nautilus dies",
"subtitles.entity.nautilus.eat": "Nautilus eats",
"subtitles.entity.nautilus.hurt": "Nautilus hurts",
"subtitles.entity.nautilus.hurt_land": "Nautilus hurts",
"subtitles.entity.nautilus.swim": "Nautilus swims",
"subtitles.entity.parched.ambient": "Parched crackles",
"subtitles.entity.parched.death": "Parched dies",
"subtitles.entity.parched.hurt": "Parched hurts",
"subtitles.entity.parrot.imitate.camel_husk": "Parrot grumphs",
"subtitles.entity.parrot.imitate.parched": "Parrot crackles",
"subtitles.entity.parrot.imitate.zombie_nautilus": "Parrot gargles",
"subtitles.entity.zombie_horse.angry": "Zombie Horse neighs",
"subtitles.entity.zombie_horse.eat": "Zombie Horse eats",
"subtitles.entity.zombie_nautilus.ambient": "Zombie Nautilus burbles",
"subtitles.entity.zombie_nautilus.ambient_land": "Zombie Nautilus burbles",
"subtitles.entity.zombie_nautilus.dash": "Zombie Nautilus jets",
"subtitles.entity.zombie_nautilus.dash_land": "Zombie Nautilus jets",
"subtitles.entity.zombie_nautilus.dash_ready": "Zombie Nautilus recovers",
"subtitles.entity.zombie_nautilus.dash_ready_land": "Zombie Nautilus recovers",
"subtitles.entity.zombie_nautilus.death": "Zombie Nautilus dies",
"subtitles.entity.zombie_nautilus.death_land": "Zombie Nautilus dies",
"subtitles.entity.zombie_nautilus.eat": "Zombie Nautilus eats",
"subtitles.entity.zombie_nautilus.hurt": "Zombie Nautilus hurts",
"subtitles.entity.zombie_nautilus.hurt_land": "Zombie Nautilus hurts",
"subtitles.entity.zombie_nautilus.swim": "Zombie Nautilus swims",
"subtitles.item.armor.equip_nautilus": "Nautilus Armor equips",
"subtitles.item.armor.unequip_nautilus": "Nautilus Armor unequips",
"subtitles.item.spear_wood.attack": "Spear jabs",
"subtitles.item.spear_wood.hit": "Spear hits",
"subtitles.item.spear_wood.use": "Charges with Spear",
"subtitles.item.spear.attack": "Spear jabs",
"subtitles.item.spear.hit": "Spear hits",
"subtitles.item.spear.lunge": "Spear lunges",
"subtitles.item.spear.use": "Charges with Spear"
},
"1.21.9": {
"advMode.notEnabled.spawner": "Spawner blocks are not enabled",
"block.minecraft.acacia_shelf": "Acacia Shelf",
+3 -3
View File
@@ -1,8 +1,8 @@
projectVersion=5.5.1
projectVersion=5.7.0
# Smile emoji (note that modrinth may not have added the version on release yet)
mcVersions=1.21.10, 1.21.9, 1.21.8, 1.21.7, 1.21.6, 1.21.5, 1.21.4, 1.21.3, 1.21.2, 1.21.1, 1.21, 1.20.6, 1.20.5, 1.20.4, 1.20.3, 1.20.2, 1.20.1, 1.20, 1.19.4, 1.19.3, 1.19.2, 1.19.1, 1.19, 1.18.2, 1.18.1, 1.18, 1.17.1, 1.17, 1.16.5, 1.16.4, 1.16.3, 1.16.2, 1.16.1, 1.16, 1.15.2, 1.15.1, 1.15, 1.14.4, 1.14.3, 1.14.2, 1.14.1, 1.14, 1.13.2, 1.13.1, 1.13, 1.12.2, 1.12.1, 1.12, 1.11.2, 1.11.1, 1.11, 1.10.2, 1.10.1, 1.10
mcVersionRange=1.10-1.21.10
mcVersions=1.21.11, 1.21.10, 1.21.9, 1.21.8, 1.21.7, 1.21.6, 1.21.5, 1.21.4, 1.21.3, 1.21.2, 1.21.1, 1.21, 1.20.6, 1.20.5, 1.20.4, 1.20.3, 1.20.2, 1.20.1, 1.20, 1.19.4, 1.19.3, 1.19.2, 1.19.1, 1.19, 1.18.2, 1.18.1, 1.18, 1.17.1, 1.17, 1.16.5, 1.16.4, 1.16.3, 1.16.2, 1.16.1, 1.16, 1.15.2, 1.15.1, 1.15, 1.14.4, 1.14.3, 1.14.2, 1.14.1, 1.14, 1.13.2, 1.13.1, 1.13, 1.12.2, 1.12.1, 1.12, 1.11.2, 1.11.1, 1.11, 1.10.2, 1.10.1, 1.10
mcVersionRange=1.10-1.21.11
velocityVersion=3.4
org.gradle.configureondemand=true
+2 -2
View File
@@ -3,7 +3,7 @@ metadata.format.version = "1.1"
[versions]
# ViaVersion
viaver = "5.5.1-SNAPSHOT"
viaver = "5.7.0"
# Common provided
netty = "4.0.20.Final"
@@ -16,7 +16,7 @@ checkerQual = "3.51.0"
paper = "1.16.5-R0.1-SNAPSHOT"
velocity = "3.1.1"
fabricLoader = "0.11.6"
viaProxy = "3.4.6-SNAPSHOT"
viaProxy = "[3.0.0,4.0.0)"
[libraries]
Binary file not shown.
+2 -2
View File
@@ -1,7 +1,7 @@
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
distributionSha256Sum=a17ddd85a26b6a7f5ddb71ff8b05fc5104c0202c6e64782429790c933686c806
distributionUrl=https\://services.gradle.org/distributions/gradle-9.1.0-bin.zip
distributionSha256Sum=72f44c9f8ebcb1af43838f45ee5c4aa9c5444898b3468ab3f4af7b6076c5bc3f
distributionUrl=https\://services.gradle.org/distributions/gradle-9.2.1-bin.zip
networkTimeout=10000
validateDistributionUrl=true
zipStoreBase=GRADLE_USER_HOME
@@ -47,7 +47,7 @@
},
{
"id": "viaversion",
"version": "[5.5.1-SNAPSHOT,)"
"version": "[5.7.0-SNAPSHOT,)"
}
]
},
+1 -1
View File
@@ -1,5 +1,5 @@
plugins {
id("io.papermc.hangar-publish-plugin") version "0.1.3"
id("io.papermc.hangar-publish-plugin") version "0.1.4"
id("com.modrinth.minotaur") version "2.+"
// A nice no-conflict comment for patching in downgrading