Compare commits

...
72 Commits
Author SHA1 Message Date
Nassim Jahnke b67d7c076f Fix dust/dust_color_transition particles in biome data
Fixes #926
2024-12-05 17:16:57 +01:00
Nassim Jahnke 9d5cd04d4b Always update storage data 2024-11-27 21:50:46 +01:00
Nassim Jahnke 30499c8b30 Fix entity teleport for non-self in 1.21.2->1.21.1
Fixes #922
2024-11-27 21:47:40 +01:00
Nassim Jahnke fb328d4753 Fix recipe removal 2024-11-26 18:16:42 +01:00
Nassim Jahnke 5347820c28 Fix typo 2024-11-25 10:18:16 +01:00
Nassim Jahnke c4af653e42 Fix 1.21 client-sent food using_converts_to handling 2024-11-25 10:17:10 +01:00
github-actions[bot]andgradle-update-robot 5240487a35 Update Gradle Wrapper from 8.11 to 8.11.1 (#920)
Signed-off-by: gradle-update-robot <gradle-update-robot@regolo.cc>
Co-authored-by: gradle-update-robot <gradle-update-robot@regolo.cc>
2024-11-24 02:09:33 +01:00
EnZaXDandNassim Jahnke 276953f6cb Backup inconvertible item component data for creative clients in 1.21+ (#907)
Co-authored-by: Nassim Jahnke <nassim@njahnke.dev>
2024-11-22 10:36:42 +01:00
EnZaXD 1dfef5b97e Emulate block and item display entities in 1.19.4->1.19.3 (#871) 2024-11-18 14:38:20 +01:00
Nassim Jahnke 4a9c98aa1b Address Gradle deprecation warnings 2024-11-17 13:45:25 +01:00
github-actions[bot]andgradle-update-robot 07e2848e5b Update Gradle Wrapper from 8.10.2 to 8.11 (#917)
Signed-off-by: gradle-update-robot <gradle-update-robot@regolo.cc>
Co-authored-by: gradle-update-robot <gradle-update-robot@regolo.cc>
2024-11-17 12:23:33 +01:00
Gero 1db6824391 Fix remapping of 1.21.3 PLAYER_INFO_UPDATE list order (#915) 2024-11-11 17:01:35 +01:00
Nassim Jahnke 82a7c9bc3d Update VV usage 2024-11-11 15:00:34 +01:00
Nassim Jahnke 3a67be7fe5 Don't forget to rewrite item in set cursor and set player inventory 2024-11-08 17:25:40 +01:00
EnZaXD 8cb285db69 Change darkness->blindness in 1.19->1.18.2 (#908) 2024-11-07 09:18:33 +01:00
EnZaXD 04a692022a Move config option check for player face fix into packet handlers (#913) 2024-11-07 09:11:38 +01:00
Nassim Jahnke 498bec9065 Remove 'has recipe error' container data from smithing table
Fixes #909
2024-11-05 20:20:27 +01:00
Nassim Jahnke ab2a407742 Bump version to 5.1.2-SNAPSHOT 2024-11-05 20:18:30 +01:00
Nassim Jahnke cfad15a9b2 5.1.1 Release 2024-11-01 19:00:56 +01:00
EnZaXDandNassim Jahnke 2c3c62d246 Update VV API usage (#906)
Co-authored-by: Nassim Jahnke <nassim@njahnke.dev>
2024-11-01 18:58:44 +01:00
Nassim Jahnke d6c27add17 Add viaproxy jvm flags 2024-10-30 21:07:30 +01:00
RK_01 7b5ee01929 Fix SET_CURSOR_ITEM container id type (#905) 2024-10-30 17:05:57 +01:00
Nassim Jahnke c7a5de1176 Write inventory id as unsigned byte... 2024-10-30 16:52:52 +01:00
Nassim Jahnke 16aa6a51a2 Fix issues with creaking entity data
Fixes #904
2024-10-30 10:21:04 +01:00
EnZaXD 562651cd9d [ci skip] Add component rewriter to template (#903) 2024-10-30 10:20:24 +01:00
EnZaXD 3e8086e136 Add gradle task to quickly test/debug code changes (#902) 2024-10-29 15:00:34 +01:00
Nassim Jahnke 368f450e11 Remove lock item data in component rewriter 2024-10-29 13:38:01 +01:00
Nassim Jahnke 80b530a368 Fix trail particle handling 2024-10-29 13:33:16 +01:00
Nassim Jahnke d2d1d0014f Remove instrument registry
Some older clients don't like unknown registries
2024-10-29 12:45:56 +01:00
Nassim Jahnke 5a576d66b4 Update item type in area effect cloud particles in 1.13.2->1.13.1 2024-10-28 12:21:57 +01:00
EnZaXD a94d06716c Use new ParticleRewriter (#901) 2024-10-28 11:28:12 +01:00
Nassim Jahnke 8af8319839 Small cleanup 2024-10-27 23:25:00 +01:00
EnZaXD 927ffaf20a Correctly update action bits in PLAYER_INFO_UPDATE in 1.21.2->1.21 (#899) 2024-10-26 14:07:13 +02:00
Nassim Jahnke 31d5a98f26 5.1.0 Release 2024-10-25 18:15:16 +02:00
Nassim Jahnke b3c1266da7 Update ChunkSectionLightImpl call 2024-10-25 18:09:02 +02:00
Nassim Jahnke 0a6d143d92 Remove baby index via parent type 2024-10-24 16:56:54 +02:00
Nassim Jahnke b1f4a88050 Fix 1.20.5->1.20.3 darkness effect transition 2024-10-23 21:26:12 +02:00
FlorianMichael 4f119d26d7 Update version ranges in gradle.properties 2024-10-23 16:27:14 +02:00
Nassim Jahnke afb8384319 Enable bundle feature 2024-10-22 18:42:43 +02:00
Nassim Jahnke f27c977be2 Back to onenable tasks 2024-10-22 18:10:18 +02:00
RK_01 90878517db Fix CLIENT_INFORMATION skin flags data type (#4) 2024-10-22 10:26:05 +02:00
RK_01 a0f2a8595e Fix PLAYER_INFO_UPDATE display name data type (#5) 2024-10-22 10:25:43 +02:00
Nassim Jahnke 2ce11704ba Register tasks in the right place 2024-10-20 19:48:26 +02:00
Nassim Jahnke 0827b6f6bb Handle player info components in 1.20.5->1.20.3 2024-10-19 13:17:13 +02:00
Nassim Jahnke 1c7017a056 Pass position/rotation values directly, fix relative position and rotation handling 2024-10-19 13:10:54 +02:00
FlorianMichael 4d4f66a1a2 Emulate PLAYER_INPUT packet as well 2024-10-19 02:28:26 +02:00
FlorianMichael f274d643a5 Emulate CLIENT_TICK_END packet 2024-10-19 01:47:38 +02:00
FlorianMichael c7324b1b35 Use SET_ENTITY_MOTION and EXPLODE for delta movement translation 2024-10-19 01:19:22 +02:00
FlorianMichael c8ec145880 Always use correct PROFILE_ACTIONS_ENUM from VV types 2024-10-18 23:20:36 +02:00
FlorianMichael 30d3b0d02e Handle new relative arguments in PLAYER_POSITION and TELEPORT_ENTITY 2024-10-18 23:05:41 +02:00
FlorianMichael 545365786f Handle PLAYER_ROTATION packet using PLAYER_LOOK_AT 2024-10-18 21:57:06 +02:00
Nassim Jahnke 1b9d53af2a Create tag if needed 2024-10-17 19:44:37 +02:00
Nassim Jahnke fd85b67a92 Sort recipes 2024-10-17 17:06:56 +02:00
Nassim Jahnke 16eca5f6aa 1.21.2-pre3 2024-10-14 17:55:19 +02:00
Nassim Jahnke c57b238b86 Recipes mostly work now 2024-10-14 17:55:19 +02:00
Nassim Jahnke 5646d04ba9 1.21.2-pre1 2024-10-14 17:55:19 +02:00
Nassim Jahnke 4937ec4800 Start working on recipes 2024-10-14 17:55:19 +02:00
Nassim Jahnke d3be34adc9 Very WIP 24w40a 2024-10-14 17:55:19 +02:00
Nassim Jahnke 49febd1e63 Fix vehicle exiting 2024-10-14 17:55:18 +02:00
Nassim Jahnke 8737b2b51a 24w39a 2024-10-14 17:55:18 +02:00
Nassim Jahnke 1876b9bb95 Convert attributes in item hover event 2024-10-14 17:55:18 +02:00
Nassim Jahnke f2fcc9d02f 24w38a 2024-10-14 17:55:18 +02:00
Nassim Jahnke d0eeae92d3 24w37a 2024-10-14 17:55:18 +02:00
Nassim Jahnke be28d0c3e8 24w36a, mostly 2024-10-14 17:55:18 +02:00
Nassim Jahnke b0276eaa7d Handle item hover events 2024-10-14 17:55:17 +02:00
Nassim Jahnke 6b690a0218 Remove baby entity data from changed water animals 2024-10-14 17:55:17 +02:00
Nassim Jahnke 4bcc213f1b Handle item tags in recipe ingredients 2024-10-14 17:55:17 +02:00
Nassim Jahnke ff94019b08 Actually track inventory state id 2024-10-14 17:55:17 +02:00
Nassim Jahnke 681e8a2f07 Working 24w34a 2024-10-14 17:55:17 +02:00
Nassim Jahnke 5269a610d1 More work 2024-10-14 17:55:17 +02:00
Nassim Jahnke 5cd34e6fa8 WIP 24w33a 2024-10-14 17:55:16 +02:00
Nassim Jahnke 752c5fc48b Bump version to 5.1.0-SNAPSHOT 2024-10-14 17:55:14 +02:00
82 changed files with 3470 additions and 345 deletions

No files matched your search

+3
View File
@@ -107,3 +107,6 @@ nbdist/
nbactions.xml
nb-configuration.xml
.nb-gradle/
### Run Folder (ViaProxy) ###
common/run/
+11 -22
View File
@@ -1,33 +1,23 @@
import org.gradle.api.JavaVersion
import org.gradle.api.Project
import org.gradle.api.plugins.JavaPluginExtension
import java.io.ByteArrayOutputStream
import org.gradle.jvm.toolchain.JavaLanguageVersion
fun Project.latestCommitHash(): String {
val byteOut = ByteArrayOutputStream()
exec {
commandLine = listOf("git", "rev-parse", "--short", "HEAD")
standardOutput = byteOut
}
return byteOut.toString(Charsets.UTF_8.name()).trim()
return runGitCommand(listOf("rev-parse", "--short", "HEAD"))
}
fun Project.latestCommitMessage(): String {
val byteOut = ByteArrayOutputStream()
exec {
commandLine = listOf("git", "log", "-1", "--pretty=%B")
standardOutput = byteOut
}
return byteOut.toString(Charsets.UTF_8.name()).trim()
return runGitCommand(listOf("log", "-1", "--pretty=%B"))
}
fun Project.branchName(): String {
val byteOut = ByteArrayOutputStream()
exec {
commandLine = listOf("git", "rev-parse", "--abbrev-ref", "HEAD")
standardOutput = byteOut
}
return byteOut.toString(Charsets.UTF_8.name()).trim()
return runGitCommand(listOf("rev-parse", "--abbrev-ref", "HEAD"))
}
fun Project.runGitCommand(args: List<String>): String {
return providers.exec {
commandLine = listOf("git") + args
}.standardOutput.asBytes.get().toString(Charsets.UTF_8).trim()
}
fun Project.parseMinecraftSnapshotVersion(version: String): String? {
@@ -40,6 +30,5 @@ fun Project.parseMinecraftSnapshotVersion(version: String): String? {
}
fun JavaPluginExtension.javaTarget(version: Int) {
sourceCompatibility = JavaVersion.toVersion(version)
targetCompatibility = JavaVersion.toVersion(version)
toolchain.languageVersion.set(JavaLanguageVersion.of(version))
}
+2 -2
View File
@@ -16,10 +16,10 @@ val main = setOf(
projects.viabackwardsVelocity,
projects.viabackwardsSponge,
projects.viabackwardsFabric
).map { it.dependencyProject }
).map { it.path }
subprojects {
when (this) {
when (path) {
in main -> plugins.apply("vb.shadow-conventions")
else -> plugins.apply("vb.base-conventions")
}
@@ -48,7 +48,10 @@ public class BukkitPlugin extends JavaPlugin implements ViaBackwardsPlatform {
}
}
private void enable() {
@Override
public void enable() {
ViaBackwardsPlatform.super.enable();
final ProtocolVersion protocolVersion = Via.getAPI().getServerVersion().highestSupportedProtocolVersion();
if (protocolVersion.newerThanOrEqualTo(ProtocolVersion.v1_17)) {
new PlayerItemDropListener(this).register();
+29
View File
@@ -24,3 +24,32 @@ dependencies {
java {
withJavadocJar()
}
// Task to quickly test/debug code changes using https://github.com/ViaVersion/ViaProxy
// For further instructions see the ViaProxy repository README
tasks.register<JavaExec>("runViaProxy") {
dependsOn(tasks.shadowJar)
val viaProxyConfiguration = configurations.create("viaProxy")
viaProxyConfiguration.dependencies.add(dependencies.create(rootProject.libs.viaProxy.get().copy().setTransitive(false)))
mainClass.set("net.raphimc.viaproxy.ViaProxy")
classpath = viaProxyConfiguration
workingDir = file("run")
jvmArgs = listOf("-DskipUpdateCheck")
if (System.getProperty("viaproxy.gui.autoStart") != null) {
jvmArgs("-Dviaproxy.gui.autoStart")
}
doFirst {
val jarsDir = file("$workingDir/jars")
jarsDir.mkdirs()
file("$jarsDir/${project.name}.jar").writeBytes(tasks.shadowJar.get().archiveFile.get().asFile.readBytes())
}
doLast {
file("$workingDir/jars/${project.name}.jar").delete()
file("$workingDir/logs").deleteRecursively()
}
}
@@ -36,6 +36,7 @@ public class ViaBackwardsConfig extends Config implements com.viaversion.viaback
private boolean handlePingsAsInvAcknowledgements;
private boolean bedrockAtY0;
private boolean sculkShriekersToCryingObsidian;
private boolean mapDarknessEffect;
private boolean suppressEmulationWarnings;
public ViaBackwardsConfig(File configFile, Logger logger) {
@@ -57,6 +58,7 @@ public class ViaBackwardsConfig extends Config implements com.viaversion.viaback
handlePingsAsInvAcknowledgements = getBoolean("handle-pings-as-inv-acknowledgements", false);
bedrockAtY0 = getBoolean("bedrock-at-y-0", false);
sculkShriekersToCryingObsidian = getBoolean("sculk-shriekers-to-crying-obsidian", false);
mapDarknessEffect = getBoolean("map-darkness-effect", true);
suppressEmulationWarnings = getBoolean("suppress-emulation-warnings", false);
}
@@ -100,6 +102,11 @@ public class ViaBackwardsConfig extends Config implements com.viaversion.viaback
return sculkShriekersToCryingObsidian;
}
@Override
public boolean mapDarknessEffect() {
return mapDarknessEffect;
}
@Override
public boolean suppressEmulationWarnings() {
return suppressEmulationWarnings;
@@ -78,6 +78,13 @@ public interface ViaBackwardsConfig extends Config {
*/
boolean sculkShriekerToCryingObsidian();
/**
* Maps the darkness effect to blindness for 1.18.2 clients on 1.19+ servers.
*
* @return true if enabled
*/
boolean mapDarknessEffect();
/**
* Suppresses warnings of missing emulations for certain features that are not supported (e.g. world height in 1.17+).
*
@@ -54,6 +54,8 @@ import com.viaversion.viabackwards.protocol.v1_19_1to1_19.Protocol1_19_1To1_19;
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_20_2to1_20.Protocol1_20_2To1_20;
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_21to1_20_5.Protocol1_21To1_20_5;
import com.viaversion.viabackwards.protocol.v1_9_3to1_9_1.Protocol1_9_3To1_9_1;
import com.viaversion.viabackwards.protocol.v1_10to1_9_3.Protocol1_10To1_9_3;
@@ -69,7 +71,7 @@ import java.util.logging.Logger;
public interface ViaBackwardsPlatform {
String MINIMUM_VV_VERSION = "5.0.4";
String MINIMUM_VV_VERSION = "5.1.2";
/**
* Initialize ViaBackwards.
@@ -141,6 +143,14 @@ public interface ViaBackwardsPlatform {
protocolManager.registerProtocol(new Protocol1_20_5To1_20_3(), ProtocolVersion.v1_20_3, ProtocolVersion.v1_20_5);
protocolManager.registerProtocol(new Protocol1_21To1_20_5(), ProtocolVersion.v1_20_5, ProtocolVersion.v1_21);
protocolManager.registerProtocol(new Protocol1_21_2To1_21(), ProtocolVersion.v1_21, ProtocolVersion.v1_21_2);
}
default void enable() {
final ProtocolVersion protocolVersion = Via.getAPI().getServerVersion().highestSupportedProtocolVersion();
if (protocolVersion.newerThanOrEqualTo(ProtocolVersion.v1_21_2)) {
Via.getPlatform().runRepeatingSync(new PlayerPacketsTickTask(), 1L);
}
}
/**
@@ -75,7 +75,11 @@ public class EntityPositionHandler {
}
}
positionStorage.setCoordinates(x, y, z, relative);
if (relative) {
positionStorage.addRelativePosition(x, y, z);
} else {
positionStorage.setPosition(x, y, z);
}
}
public EntityPositionStorage getStorage(UserConnection user, int entityId) {
@@ -34,15 +34,15 @@ public abstract class EntityPositionStorage {
return z;
}
public void setCoordinates(double x, double y, double z, boolean relative) {
if (relative) {
this.x += x;
this.y += y;
this.z += z;
} else {
this.x = x;
this.y = y;
this.z = z;
}
public void setPosition(double x, double y, double z) {
this.x = x;
this.y = y;
this.z = z;
}
public void addRelativePosition(double relX, double relY, double relZ) {
this.x += relX;
this.y += relY;
this.z += relZ;
}
}
@@ -18,8 +18,6 @@
package com.viaversion.viabackwards.api.entities.storage;
import com.viaversion.viaversion.api.connection.StorableObject;
import com.viaversion.viaversion.api.protocol.packet.PacketWrapper;
import com.viaversion.viaversion.api.type.Types;
public abstract class PlayerPositionStorage implements StorableObject {
private double x;
@@ -53,19 +51,15 @@ public abstract class PlayerPositionStorage implements StorableObject {
this.z = z;
}
public void setCoordinates(PacketWrapper wrapper, boolean relative) {
setCoordinates(wrapper.get(Types.DOUBLE, 0), wrapper.get(Types.DOUBLE, 1), wrapper.get(Types.DOUBLE, 2), relative);
public void setPosition(double x, double y, double z) {
this.x = x;
this.y = y;
this.z = z;
}
public void setCoordinates(double x, double y, double z, boolean relative) {
if (relative) {
this.x += x;
this.y += y;
this.z += z;
} else {
this.x = x;
this.y = y;
this.z = z;
}
public void addRelativePosition(double relX, double relY, double relZ) {
this.x += relX;
this.y += relY;
this.z += relZ;
}
}
@@ -18,14 +18,17 @@
package com.viaversion.viabackwards.api.rewriters;
import com.viaversion.nbt.tag.CompoundTag;
import com.viaversion.nbt.tag.IntArrayTag;
import com.viaversion.nbt.tag.IntTag;
import com.viaversion.nbt.tag.ListTag;
import com.viaversion.nbt.tag.StringTag;
import com.viaversion.nbt.tag.Tag;
import com.viaversion.viabackwards.api.BackwardsProtocol;
import com.viaversion.viabackwards.api.data.BackwardsMappingData;
import com.viaversion.viabackwards.api.data.MappedItem;
import com.viaversion.viaversion.api.connection.UserConnection;
import com.viaversion.viaversion.api.minecraft.Particle;
import com.viaversion.viaversion.api.minecraft.Holder;
import com.viaversion.viaversion.api.minecraft.HolderSet;
import com.viaversion.viaversion.api.minecraft.data.StructuredDataContainer;
import com.viaversion.viaversion.api.minecraft.data.StructuredDataKey;
import com.viaversion.viaversion.api.minecraft.item.Item;
@@ -35,6 +38,8 @@ import com.viaversion.viaversion.api.type.Type;
import com.viaversion.viaversion.rewriter.StructuredItemRewriter;
import java.util.ArrayList;
import java.util.List;
import java.util.function.BiConsumer;
import java.util.function.Function;
import org.checkerframework.checker.nullness.qual.Nullable;
public class BackwardsStructuredItemRewriter<C extends ClientboundPacketType, S extends ServerboundPacketType,
@@ -43,10 +48,9 @@ public class BackwardsStructuredItemRewriter<C extends ClientboundPacketType, S
public BackwardsStructuredItemRewriter(
T protocol,
Type<Item> itemType, Type<Item[]> itemArrayType, Type<Item> mappedItemType, Type<Item[]> mappedItemArrayType,
Type<Item> itemCostType, Type<Item> optionalItemCostType, Type<Item> mappedItemCostType, Type<Item> mappedOptionalItemCostType,
Type<Particle> particleType, Type<Particle> mappedParticleType
Type<Item> itemCostType, Type<Item> optionalItemCostType, Type<Item> mappedItemCostType, Type<Item> mappedOptionalItemCostType
) {
super(protocol, itemType, itemArrayType, mappedItemType, mappedItemArrayType, itemCostType, optionalItemCostType, mappedItemCostType, mappedOptionalItemCostType, particleType, mappedParticleType);
super(protocol, itemType, itemArrayType, mappedItemType, mappedItemArrayType, itemCostType, optionalItemCostType, mappedItemCostType, mappedOptionalItemCostType);
}
public BackwardsStructuredItemRewriter(final T protocol, final Type<Item> itemType, final Type<Item[]> itemArrayType, final Type<Item> mappedItemType, final Type<Item[]> mappedItemArrayType) {
@@ -116,6 +120,7 @@ public class BackwardsStructuredItemRewriter<C extends ClientboundPacketType, S
if (customData != null) {
if (customData.remove(nbtTagName("id")) instanceof final IntTag originalTag) {
item.setIdentifier(originalTag.asInt());
removeCustomTag(dataContainer, customData);
}
}
@@ -166,6 +171,54 @@ public class BackwardsStructuredItemRewriter<C extends ClientboundPacketType, S
return new ArrayList<>(data.values());
}
protected Tag holderSetToTag(final HolderSet set) {
if (set.hasIds()) {
return new IntArrayTag(set.ids());
} else {
return new StringTag(set.tagKey());
}
}
protected HolderSet restoreHolderSet(final CompoundTag tag, final String key) {
final Tag savedTag = tag.get(key);
if (savedTag == null) {
return HolderSet.of(new int[0]);
}
if (savedTag instanceof StringTag tagKey) {
return HolderSet.of(tagKey.getValue());
} else if (savedTag instanceof IntArrayTag idsTag) {
return HolderSet.of(idsTag.getValue());
} else {
return HolderSet.of(new int[0]);
}
}
protected <V> Tag holderToTag(final Holder<V> holder, final BiConsumer<V, CompoundTag> valueSaveFunction) {
if (holder.hasId()) {
return new IntTag(holder.id());
} else {
final CompoundTag savedTag = new CompoundTag();
valueSaveFunction.accept(holder.value(), savedTag);
return savedTag;
}
}
protected <V> Holder<V> restoreHolder(final CompoundTag tag, final String key, final Function<CompoundTag, V> valueRestoreFunction) {
final Tag savedTag = tag.get(key);
if (savedTag == null) {
return Holder.of(0);
}
if (savedTag instanceof IntTag idTag) {
return Holder.of(idTag.asInt());
} else if (savedTag instanceof CompoundTag compoundTag) {
return Holder.of(valueRestoreFunction.apply(compoundTag));
} else {
return Holder.of(0);
}
}
@Override
public String nbtTagName() {
return "VB|" + protocol.getClass().getSimpleName();
@@ -25,7 +25,6 @@ import com.viaversion.viaversion.api.protocol.packet.ClientboundPacketType;
import com.viaversion.viaversion.api.protocol.packet.PacketWrapper;
import com.viaversion.viaversion.api.protocol.remapper.PacketHandler;
import com.viaversion.viaversion.api.protocol.remapper.PacketHandlers;
import com.viaversion.viaversion.api.type.Type;
import com.viaversion.viaversion.api.type.Types;
import com.viaversion.viaversion.api.type.types.version.Types1_14;
@@ -105,14 +104,11 @@ public abstract class EntityRewriter<C extends ClientboundPacketType, T extends
}
public void registerSpawnTracker(C packetType) {
protocol.registerClientbound(packetType, new PacketHandlers() {
@Override
public void register() {
map(Types.VAR_INT); // 0 - Entity ID
map(Types.UUID); // 1 - Entity UUID
map(Types.VAR_INT); // 2 - Entity Type
handler(wrapper -> trackAndMapEntity(wrapper));
}
protocol.registerClientbound(packetType, wrapper -> {
wrapper.passthrough(Types.VAR_INT); // Entity ID
wrapper.passthrough(Types.UUID); // Entity UUID
wrapper.passthrough(Types.VAR_INT); // Entity Type
trackAndMapEntity(wrapper);
});
}
@@ -185,7 +185,7 @@ public abstract class EntityRewriterBase<C extends ClientboundPacketType, T exte
data.setValue(protocol.getMappingData().getNewBlockStateId(value));
}
} else if (type == particleType) {
rewriteParticle(event.user(), data.value());
protocol.getParticleRewriter().rewriteParticle(event.user(), data.value());
} else if (type == optionalComponentType || type == componentType) {
JsonElement text = data.value();
protocol.getComponentRewriter().processText(event.user(), text);
@@ -215,11 +215,11 @@ public abstract class EntityRewriterBase<C extends ClientboundPacketType, T exte
data.setValue(protocol.getMappingData().getNewBlockStateId(value));
}
} else if (type == particleType) {
rewriteParticle(event.user(), data.value());
protocol.getParticleRewriter().rewriteParticle(event.user(), data.value());
} else if (type == particlesType) {
Particle[] particles = data.value();
for (final Particle particle : particles) {
rewriteParticle(event.user(), particle);
protocol.getParticleRewriter().rewriteParticle(event.user(), particle);
}
} else if (type == optionalComponentType || type == componentType) {
protocol.getComponentRewriter().processTag(event.user(), data.value());
@@ -240,7 +240,7 @@ public abstract class EntityRewriterBase<C extends ClientboundPacketType, T exte
}
protected PacketHandler getTrackerHandler(EntityType entityType) {
return wrapper -> tracker(wrapper.user()).addEntity((int) wrapper.get(Types.VAR_INT, 0), entityType);
return wrapper -> tracker(wrapper.user()).addEntity(wrapper.get(Types.VAR_INT, 0), entityType);
}
protected PacketHandler getPlayerTrackerHandler() {
@@ -23,7 +23,6 @@ import com.viaversion.viaversion.api.minecraft.SoundEvent;
import com.viaversion.viaversion.api.protocol.packet.ClientboundPacketType;
import com.viaversion.viaversion.api.protocol.packet.PacketWrapper;
import com.viaversion.viaversion.api.protocol.remapper.PacketHandler;
import com.viaversion.viaversion.api.protocol.remapper.PacketHandlers;
import com.viaversion.viaversion.api.type.Types;
public class SoundRewriter<C extends ClientboundPacketType> extends com.viaversion.viaversion.rewriter.SoundRewriter<C> {
@@ -36,22 +35,14 @@ public class SoundRewriter<C extends ClientboundPacketType> extends com.viaversi
}
public void registerNamedSound(final C packetType) {
protocol.registerClientbound(packetType, new PacketHandlers() {
@Override
public void register() {
map(Types.STRING); // Sound identifier
handler(getNamedSoundHandler());
}
protocol.registerClientbound(packetType, wrapper -> {
wrapper.passthrough(Types.STRING); // Sound identifier
getNamedSoundHandler().handle(wrapper);
});
}
public void registerStopSound(final C packetType) {
protocol.registerClientbound(packetType, new PacketHandlers() {
@Override
public void register() {
handler(getStopSoundHandler());
}
});
protocol.registerClientbound(packetType, wrapper -> getStopSoundHandler().handle(wrapper));
}
public PacketHandler getNamedSoundHandler() {
@@ -19,6 +19,7 @@ package com.viaversion.viabackwards.api.rewriters;
import com.viaversion.nbt.tag.CompoundTag;
import com.viaversion.nbt.tag.StringTag;
import com.viaversion.viabackwards.ViaBackwards;
import com.viaversion.viabackwards.api.BackwardsProtocol;
import com.viaversion.viabackwards.api.data.BackwardsMappingDataLoader;
import com.viaversion.viaversion.api.connection.UserConnection;
@@ -60,7 +61,7 @@ public class TranslatableRewriter<C extends ClientboundPacketType> extends Compo
super(protocol, type);
final Map<String, String> translatableMappings = getTranslatableMappings(version);
if (translatableMappings == null) {
protocol.getLogger().warning("Missing " + version + " translatables!");
ViaBackwards.getPlatform().getLogger().warning("Missing " + version + " translatables!");
this.translatables = new HashMap<>();
} else {
this.translatables = translatableMappings;
@@ -19,22 +19,22 @@ package com.viaversion.viabackwards.protocol.template;
import com.viaversion.viabackwards.api.rewriters.BackwardsStructuredItemRewriter;
import com.viaversion.viaversion.api.type.types.chunk.ChunkType1_20_2;
import com.viaversion.viaversion.api.type.types.version.Types1_21;
import com.viaversion.viaversion.protocols.v1_20_2to1_20_3.rewriter.RecipeRewriter1_20_3;
import com.viaversion.viaversion.protocols.v1_20_3to1_20_5.packet.ServerboundPacket1_20_5;
import com.viaversion.viaversion.protocols.v1_20_3to1_20_5.packet.ServerboundPackets1_20_5;
import com.viaversion.viaversion.protocols.v1_20_5to1_21.packet.ClientboundPacket1_21;
import com.viaversion.viaversion.protocols.v1_20_5to1_21.packet.ClientboundPackets1_21;
import com.viaversion.viaversion.api.type.types.version.Types1_21_2;
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.protocols.v1_21to1_21_2.packet.ServerboundPacket1_21_2;
import com.viaversion.viaversion.protocols.v1_21to1_21_2.packet.ServerboundPackets1_21_2;
import com.viaversion.viaversion.rewriter.BlockRewriter;
import com.viaversion.viaversion.rewriter.RecipeDisplayRewriter;
// To replace if needed:
// ChunkType1_20_2
// RecipeRewriter1_20_3
// Types1_21
final class BlockItemPacketRewriter1_99 extends BackwardsStructuredItemRewriter<ClientboundPacket1_21, ServerboundPacket1_20_5, Protocol1_98To1_99> {
final class BlockItemPacketRewriter1_99 extends BackwardsStructuredItemRewriter<ClientboundPacket1_21_2, ServerboundPacket1_21_2, Protocol1_98To1_99> {
public BlockItemPacketRewriter1_99(final Protocol1_98To1_99 protocol) {
super(protocol, Types1_21.ITEM, Types1_21.ITEM_ARRAY);
super(protocol, Types1_21_2.ITEM, Types1_21_2.ITEM_ARRAY);
/*super(protocol,
Types1_21.ITEM, Types1_21.ITEM_ARRAY, Types1_OLD.ITEM, Types1_OLD.ITEM_ARRAY,
Types1_21.ITEM_COST, Types1_21.OPTIONAL_ITEM_COST, Types1_OLD.ITEM_COST, Types1_OLD.OPTIONAL_ITEM_COST,
@@ -44,27 +44,29 @@ final class BlockItemPacketRewriter1_99 extends BackwardsStructuredItemRewriter<
@Override
public void registerPackets() {
final BlockRewriter<ClientboundPacket1_21> blockRewriter = BlockRewriter.for1_20_2(protocol);
blockRewriter.registerBlockEvent(ClientboundPackets1_21.BLOCK_EVENT);
blockRewriter.registerBlockUpdate(ClientboundPackets1_21.BLOCK_UPDATE);
blockRewriter.registerSectionBlocksUpdate1_20(ClientboundPackets1_21.SECTION_BLOCKS_UPDATE);
blockRewriter.registerLevelEvent1_21(ClientboundPackets1_21.LEVEL_EVENT, 2001);
blockRewriter.registerLevelChunk1_19(ClientboundPackets1_21.LEVEL_CHUNK_WITH_LIGHT, ChunkType1_20_2::new);
blockRewriter.registerBlockEntityData(ClientboundPackets1_21.BLOCK_ENTITY_DATA);
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);
// registerOpenWindow(ClientboundPackets1_21.OPEN_WINDOW);
registerCooldown(ClientboundPackets1_21.COOLDOWN);
registerSetContent1_17_1(ClientboundPackets1_21.CONTAINER_SET_CONTENT);
registerSetSlot1_17_1(ClientboundPackets1_21.CONTAINER_SET_SLOT);
registerAdvancements1_20_3(ClientboundPackets1_21.UPDATE_ADVANCEMENTS);
registerSetEquipment(ClientboundPackets1_21.SET_EQUIPMENT);
registerContainerClick1_17_1(ServerboundPackets1_20_5.CONTAINER_CLICK);
registerMerchantOffers1_20_5(ClientboundPackets1_21.MERCHANT_OFFERS);
registerSetCreativeModeSlot(ServerboundPackets1_20_5.SET_CREATIVE_MODE_SLOT);
registerContainerSetData(ClientboundPackets1_21.CONTAINER_SET_DATA);
registerLevelParticles1_20_5(ClientboundPackets1_21.LEVEL_PARTICLES);
registerExplosion(ClientboundPackets1_21.EXPLODE);
// registerOpenScreen(ClientboundPackets1_21_2.OPEN_SCREEN);
protocol.registerClientbound(ClientboundPackets1_21_2.SET_CURSOR_ITEM, this::passthroughClientboundItem);
registerCooldown1_21_2(ClientboundPackets1_21_2.COOLDOWN);
registerSetContent1_21_2(ClientboundPackets1_21_2.CONTAINER_SET_CONTENT);
registerSetSlot1_21_2(ClientboundPackets1_21_2.CONTAINER_SET_SLOT);
registerAdvancements1_20_3(ClientboundPackets1_21_2.UPDATE_ADVANCEMENTS);
registerSetEquipment(ClientboundPackets1_21_2.SET_EQUIPMENT);
registerMerchantOffers1_20_5(ClientboundPackets1_21_2.MERCHANT_OFFERS);
registerContainerSetData(ClientboundPackets1_21_2.CONTAINER_SET_DATA);
registerContainerClick1_21_2(ServerboundPackets1_21_2.CONTAINER_CLICK);
registerSetCreativeModeSlot(ServerboundPackets1_21_2.SET_CREATIVE_MODE_SLOT);
new RecipeRewriter1_20_3<>(protocol).register1_20_5(ClientboundPackets1_21.UPDATE_RECIPES);
final RecipeDisplayRewriter<ClientboundPacket1_21_2> recipeRewriter = new RecipeDisplayRewriter<>(protocol);
recipeRewriter.registerUpdateRecipes(ClientboundPackets1_21_2.UPDATE_RECIPES);
recipeRewriter.registerRecipeBookAdd(ClientboundPackets1_21_2.RECIPE_BOOK_ADD);
recipeRewriter.registerPlaceGhostRecipe(ClientboundPackets1_21_2.PLACE_GHOST_RECIPE);
}
}
@@ -0,0 +1,48 @@
/*
* This file is part of ViaBackwards - https://github.com/ViaVersion/ViaBackwards
* Copyright (C) 2016-2024 ViaVersion and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.viaversion.viabackwards.protocol.template;
import com.viaversion.nbt.tag.CompoundTag;
import com.viaversion.viabackwards.api.BackwardsProtocol;
import com.viaversion.viabackwards.api.rewriters.TranslatableRewriter;
import com.viaversion.viaversion.api.connection.UserConnection;
import com.viaversion.viaversion.protocols.v1_21to1_21_2.packet.ClientboundPacket1_21_2;
import com.viaversion.viaversion.util.SerializerVersion;
public class ComponentRewriter1_99 extends TranslatableRewriter<ClientboundPacket1_21_2> {
public ComponentRewriter1_99(final BackwardsProtocol<ClientboundPacket1_21_2, ?, ?, ?> protocol) {
super(protocol, ReadType.NBT);
}
@Override
protected void handleShowItem(final UserConnection connection, final CompoundTag itemTag, final CompoundTag componentsTag) {
super.handleShowItem(connection, itemTag, componentsTag);
if (componentsTag == null) {
return;
}
// Remove or update data from componentsTag
// New added data which is not handled otherwise needs to be removed to prevent errors on the client
}
@Override
protected SerializerVersion inputSerializerVersion() {
return SerializerVersion.V1_20_5;
}
}
@@ -18,21 +18,19 @@
package com.viaversion.viabackwards.protocol.template;
import com.viaversion.viabackwards.api.rewriters.EntityRewriter;
import com.viaversion.viaversion.api.minecraft.RegistryEntry;
import com.viaversion.viaversion.api.minecraft.entities.EntityType;
import com.viaversion.viaversion.api.minecraft.entities.EntityTypes1_20_5;
import com.viaversion.viaversion.api.protocol.remapper.PacketHandlers;
import com.viaversion.viaversion.api.type.Types;
import com.viaversion.viaversion.api.type.types.version.Types1_20_5;
import com.viaversion.viaversion.protocols.v1_20_5to1_21.packet.ClientboundConfigurationPackets1_21;
import com.viaversion.viaversion.protocols.v1_20_5to1_21.packet.ClientboundPacket1_21;
import com.viaversion.viaversion.protocols.v1_20_5to1_21.packet.ClientboundPackets1_21;
import com.viaversion.viaversion.util.Key;
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
// Types1_OLD
// Types1_21
final class EntityPacketRewriter1_99 extends EntityRewriter<ClientboundPacket1_21, Protocol1_98To1_99> {
final class EntityPacketRewriter1_99 extends EntityRewriter<ClientboundPacket1_21_2, Protocol1_98To1_99> {
public EntityPacketRewriter1_99(final Protocol1_98To1_99 protocol) {
super(protocol, Types1_20_5.ENTITY_DATA_TYPES.optionalComponentType, Types1_20_5.ENTITY_DATA_TYPES.booleanType);
@@ -40,36 +38,30 @@ final class EntityPacketRewriter1_99 extends EntityRewriter<ClientboundPacket1_2
@Override
public void registerPackets() {
registerTrackerWithData1_19(ClientboundPackets1_21.ADD_ENTITY, EntityTypes1_20_5.FALLING_BLOCK);
registerSetEntityData(ClientboundPackets1_21.SET_ENTITY_DATA, /*Types1_OLD.ENTITY_DATA_LIST, */Types1_20_5.ENTITY_DATA_LIST); // Specify old and new entity data list if changed
registerRemoveEntities(ClientboundPackets1_21.REMOVE_ENTITIES);
registerTrackerWithData1_19(ClientboundPackets1_21_2.ADD_ENTITY, EntityTypes1_20_5.FALLING_BLOCK);
registerSetEntityData(ClientboundPackets1_21_2.SET_ENTITY_DATA, /*Types1_OLD.ENTITY_DATA_LIST, */Types1_20_5.ENTITY_DATA_LIST); // Specify old and new entity data list if changed
registerRemoveEntities(ClientboundPackets1_21_2.REMOVE_ENTITIES);
// TODO Item and sound id changes in registries, probably others as well
protocol.registerClientbound(ClientboundConfigurationPackets1_21.REGISTRY_DATA, wrapper -> {
final String registryKey = Key.stripMinecraftNamespace(wrapper.passthrough(Types.STRING));
final RegistryEntry[] entries = wrapper.passthrough(Types.REGISTRY_ENTRY_ARRAY);
handleRegistryData1_20_5(wrapper.user(), registryKey, entries); // Caches dimensions to access data like height later and tracks the amount of biomes sent for chunk data
final RegistryDataRewriter registryDataRewriter = new RegistryDataRewriter(protocol);
protocol.registerClientbound(ClientboundConfigurationPackets1_21.REGISTRY_DATA, registryDataRewriter::handle);
protocol.registerClientbound(ClientboundPackets1_21_2.LOGIN, wrapper -> {
final int entityId = wrapper.passthrough(Types.INT); // Entity id
wrapper.passthrough(Types.BOOLEAN); // Hardcore
wrapper.passthrough(Types.STRING_ARRAY); // World List
wrapper.passthrough(Types.VAR_INT); // Max players
wrapper.passthrough(Types.VAR_INT); // View distance
wrapper.passthrough(Types.VAR_INT); // Simulation distance
wrapper.passthrough(Types.BOOLEAN); // Reduced debug info
wrapper.passthrough(Types.BOOLEAN); // Show death screen
wrapper.passthrough(Types.BOOLEAN); // Limited crafting
final int dimensionId = wrapper.passthrough(Types.VAR_INT);
final String world = wrapper.passthrough(Types.STRING);
trackWorldDataByKey1_20_5(wrapper.user(), dimensionId, world);
trackPlayer(wrapper.user(), entityId);
});
protocol.registerClientbound(ClientboundPackets1_21.LOGIN, new PacketHandlers() {
@Override
public void register() {
map(Types.INT); // Entity id
map(Types.BOOLEAN); // Hardcore
map(Types.STRING_ARRAY); // World List
map(Types.VAR_INT); // Max players
map(Types.VAR_INT); // View distance
map(Types.VAR_INT); // Simulation distance
map(Types.BOOLEAN); // Reduced debug info
map(Types.BOOLEAN); // Show death screen
map(Types.BOOLEAN); // Limited crafting
map(Types.VAR_INT); // Dimension key
map(Types.STRING); // World
handler(worldDataTrackerHandlerByKey1_20_5(3)); // Tracks world height and name for chunk data and entity (un)tracking
}
});
protocol.registerClientbound(ClientboundPackets1_21.RESPAWN, wrapper -> {
protocol.registerClientbound(ClientboundPackets1_21_2.RESPAWN, wrapper -> {
final int dimensionId = wrapper.passthrough(Types.VAR_INT);
final String world = wrapper.passthrough(Types.STRING);
trackWorldDataByKey1_20_5(wrapper.user(), dimensionId, world); // Tracks world height and name for chunk data and entity (un)tracking
@@ -20,20 +20,20 @@ package com.viaversion.viabackwards.protocol.template;
import com.viaversion.viabackwards.api.BackwardsProtocol;
import com.viaversion.viabackwards.api.data.BackwardsMappingData;
import com.viaversion.viabackwards.api.rewriters.SoundRewriter;
import com.viaversion.viabackwards.api.rewriters.TranslatableRewriter;
import com.viaversion.viaversion.api.connection.UserConnection;
import com.viaversion.viaversion.api.minecraft.entities.EntityTypes1_20_5;
import com.viaversion.viaversion.api.protocol.packet.provider.PacketTypesProvider;
import com.viaversion.viaversion.api.protocol.packet.provider.SimplePacketTypesProvider;
import com.viaversion.viaversion.api.type.types.version.Types1_21_2;
import com.viaversion.viaversion.data.entity.EntityTrackerBase;
import com.viaversion.viaversion.protocols.v1_20_3to1_20_5.packet.ServerboundConfigurationPackets1_20_5;
import com.viaversion.viaversion.protocols.v1_20_3to1_20_5.packet.ServerboundPacket1_20_5;
import com.viaversion.viaversion.protocols.v1_20_3to1_20_5.packet.ServerboundPackets1_20_5;
import com.viaversion.viaversion.protocols.v1_20_5to1_21.Protocol1_20_5To1_21;
import com.viaversion.viaversion.protocols.v1_20_5to1_21.packet.ClientboundConfigurationPackets1_21;
import com.viaversion.viaversion.protocols.v1_20_5to1_21.packet.ClientboundPacket1_21;
import com.viaversion.viaversion.protocols.v1_20_5to1_21.packet.ClientboundPackets1_21;
import com.viaversion.viaversion.rewriter.ComponentRewriter.ReadType;
import com.viaversion.viaversion.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.protocols.v1_21to1_21_2.packet.ServerboundPacket1_21_2;
import com.viaversion.viaversion.protocols.v1_21to1_21_2.packet.ServerboundPackets1_21_2;
import com.viaversion.viaversion.rewriter.ParticleRewriter;
import com.viaversion.viaversion.rewriter.StatisticsRewriter;
import com.viaversion.viaversion.rewriter.TagRewriter;
@@ -42,52 +42,59 @@ import static com.viaversion.viaversion.util.ProtocolUtil.packetTypeMap;
// Placeholders to replace (in the entire package):
// Protocol1_98To1_99, EntityPacketRewriter1_99, BlockItemPacketRewriter1_99
// Protocol1_20_5To1_21 (the ViaVersion protocol class the mappings depend on)
// ClientboundPacket1_21
// ServerboundPacket1_20_5
// ClientboundPacket1_21_2
// ServerboundPacket1_21_2
// ClientboundConfigurationPackets1_21
// ServerboundConfigurationPackets1_20_5
// EntityTypes1_20_5 (UNMAPPED type)
// Types1_21_2.PARTICLE
// 1.99, 1.98
final class Protocol1_98To1_99 extends BackwardsProtocol<ClientboundPacket1_21, ClientboundPacket1_21, ServerboundPacket1_20_5, ServerboundPacket1_20_5> {
final class Protocol1_98To1_99 extends BackwardsProtocol<ClientboundPacket1_21_2, ClientboundPacket1_21_2, ServerboundPacket1_21_2, ServerboundPacket1_21_2> {
// ViaBackwards uses its own mappings and also needs a translatablerewriter for translation mappings
public static final BackwardsMappingData MAPPINGS = new BackwardsMappingData("1.99", "1.98", Protocol1_20_5To1_21.class);
private final EntityPacketRewriter1_99 entityRewriter = new EntityPacketRewriter1_99(this);
private final BlockItemPacketRewriter1_99 itemRewriter = new BlockItemPacketRewriter1_99(this);
private final TranslatableRewriter<ClientboundPacket1_21> translatableRewriter = new TranslatableRewriter<>(this, ReadType.NBT);
private final TagRewriter<ClientboundPacket1_21> tagRewriter = new TagRewriter<>(this);
private final ParticleRewriter<ClientboundPacket1_21_2> particleRewriter = new ParticleRewriter<>(this, Types1_21_2.PARTICLE/*, Types1_OLD.PARTICLE*/);
private final ComponentRewriter1_99 translatableRewriter = new ComponentRewriter1_99(this);
private final TagRewriter<ClientboundPacket1_21_2> tagRewriter = new TagRewriter<>(this);
public Protocol1_98To1_99() {
super(ClientboundPacket1_21.class, ClientboundPacket1_21.class, ServerboundPacket1_20_5.class, ServerboundPacket1_20_5.class);
super(ClientboundPacket1_21_2.class, ClientboundPacket1_21_2.class, ServerboundPacket1_21_2.class, ServerboundPacket1_21_2.class);
}
@Override
protected void registerPackets() {
super.registerPackets();
tagRewriter.registerGeneric(ClientboundPackets1_21.UPDATE_TAGS);
tagRewriter.registerGeneric(ClientboundPackets1_21_2.UPDATE_TAGS);
tagRewriter.registerGeneric(ClientboundConfigurationPackets1_21.UPDATE_TAGS);
final SoundRewriter<ClientboundPacket1_21> soundRewriter = new SoundRewriter<>(this);
soundRewriter.registerSound1_19_3(ClientboundPackets1_21.SOUND);
soundRewriter.registerSound1_19_3(ClientboundPackets1_21.SOUND_ENTITY);
soundRewriter.registerStopSound(ClientboundPackets1_21.STOP_SOUND);
final SoundRewriter<ClientboundPacket1_21_2> soundRewriter = new SoundRewriter<>(this);
soundRewriter.registerSound1_19_3(ClientboundPackets1_21_2.SOUND);
soundRewriter.registerSound1_19_3(ClientboundPackets1_21_2.SOUND_ENTITY);
soundRewriter.registerStopSound(ClientboundPackets1_21_2.STOP_SOUND);
new StatisticsRewriter<>(this).register(ClientboundPackets1_21.AWARD_STATS);
//new AttributeRewriter<>(this).register1_21(ClientboundPackets1_21.ENTITY_PROPERTIES);
new StatisticsRewriter<>(this).register(ClientboundPackets1_21_2.AWARD_STATS);
//new AttributeRewriter<>(this).register1_21(ClientboundPackets1_21_2.UPDATE_ATTRIBUTES);
// Registers translatable mappings (missing a whole bunch still)
//translatableRewriter.registerOpenWindow(ClientboundPackets1_21.OPEN_WINDOW); // Handled by registerOpenWindow in item rewriters
translatableRewriter.registerComponentPacket(ClientboundPackets1_21.SET_ACTION_BAR_TEXT);
translatableRewriter.registerComponentPacket(ClientboundPackets1_21.SET_TITLE_TEXT);
translatableRewriter.registerComponentPacket(ClientboundPackets1_21.SET_SUBTITLE_TEXT);
translatableRewriter.registerBossEvent(ClientboundPackets1_21.BOSS_EVENT);
translatableRewriter.registerComponentPacket(ClientboundPackets1_21.DISCONNECT);
translatableRewriter.registerTabList(ClientboundPackets1_21.TAB_LIST);
translatableRewriter.registerPlayerCombatKill1_20(ClientboundPackets1_21.PLAYER_COMBAT_KILL);
translatableRewriter.registerComponentPacket(ClientboundPackets1_21.SYSTEM_CHAT);
translatableRewriter.registerComponentPacket(ClientboundPackets1_21.DISGUISED_CHAT);
//translatableRewriter.registerOpenScreen(ClientboundPackets1_21_2.OPEN_SCREEN); // Handled by registerOpenScreen in item rewriters
translatableRewriter.registerComponentPacket(ClientboundPackets1_21_2.SET_ACTION_BAR_TEXT);
translatableRewriter.registerComponentPacket(ClientboundPackets1_21_2.SET_TITLE_TEXT);
translatableRewriter.registerComponentPacket(ClientboundPackets1_21_2.SET_SUBTITLE_TEXT);
translatableRewriter.registerBossEvent(ClientboundPackets1_21_2.BOSS_EVENT);
translatableRewriter.registerComponentPacket(ClientboundPackets1_21_2.DISCONNECT);
translatableRewriter.registerTabList(ClientboundPackets1_21_2.TAB_LIST);
translatableRewriter.registerPlayerCombatKill1_20(ClientboundPackets1_21_2.PLAYER_COMBAT_KILL);
translatableRewriter.registerComponentPacket(ClientboundPackets1_21_2.SYSTEM_CHAT);
translatableRewriter.registerComponentPacket(ClientboundPackets1_21_2.DISGUISED_CHAT);
translatableRewriter.registerPlayerInfoUpdate1_21_2(ClientboundPackets1_21_2.PLAYER_INFO_UPDATE);
translatableRewriter.registerPing();
// If needed for any particle, item, or block changes. Extend ParticleRewriter for particle serializer changes
particleRewriter.registerLevelParticles1_20_5(ClientboundPackets1_21_2.LEVEL_PARTICLES);
particleRewriter.registerExplode1_21_2(ClientboundPackets1_21_2.EXPLODE);
}
@Override
@@ -111,22 +118,27 @@ final class Protocol1_98To1_99 extends BackwardsProtocol<ClientboundPacket1_21,
}
@Override
public TranslatableRewriter<ClientboundPacket1_21> getComponentRewriter() {
public ParticleRewriter<ClientboundPacket1_21_2> getParticleRewriter() {
return particleRewriter;
}
@Override
public ComponentRewriter1_99 getComponentRewriter() {
return translatableRewriter;
}
@Override
public TagRewriter<ClientboundPacket1_21> getTagRewriter() {
public TagRewriter<ClientboundPacket1_21_2> getTagRewriter() {
return tagRewriter;
}
@Override
protected PacketTypesProvider<ClientboundPacket1_21, ClientboundPacket1_21, ServerboundPacket1_20_5, ServerboundPacket1_20_5> createPacketTypesProvider() {
protected PacketTypesProvider<ClientboundPacket1_21_2, ClientboundPacket1_21_2, ServerboundPacket1_21_2, ServerboundPacket1_21_2> createPacketTypesProvider() {
return new SimplePacketTypesProvider<>(
packetTypeMap(unmappedClientboundPacketType, ClientboundPackets1_21.class, ClientboundConfigurationPackets1_21.class),
packetTypeMap(mappedClientboundPacketType, ClientboundPackets1_21.class, ClientboundConfigurationPackets1_21.class),
packetTypeMap(mappedServerboundPacketType, ServerboundPackets1_20_5.class, ServerboundConfigurationPackets1_20_5.class),
packetTypeMap(unmappedServerboundPacketType, ServerboundPackets1_20_5.class, ServerboundConfigurationPackets1_20_5.class)
packetTypeMap(unmappedClientboundPacketType, ClientboundPackets1_21_2.class, ClientboundConfigurationPackets1_21.class),
packetTypeMap(mappedClientboundPacketType, ClientboundPackets1_21_2.class, ClientboundConfigurationPackets1_21.class),
packetTypeMap(mappedServerboundPacketType, ServerboundPackets1_21_2.class, ServerboundConfigurationPackets1_20_5.class),
packetTypeMap(unmappedServerboundPacketType, ServerboundPackets1_21_2.class, ServerboundConfigurationPackets1_20_5.class)
);
}
}
@@ -41,6 +41,7 @@ import com.viaversion.viaversion.protocols.v1_12_2to1_13.packet.ClientboundPacke
import com.viaversion.viaversion.protocols.v1_12_2to1_13.packet.ServerboundPackets1_13;
import com.viaversion.viaversion.protocols.v1_13to1_13_1.Protocol1_13To1_13_1;
import com.viaversion.viaversion.rewriter.ComponentRewriter;
import com.viaversion.viaversion.rewriter.ParticleRewriter;
import com.viaversion.viaversion.rewriter.StatisticsRewriter;
import com.viaversion.viaversion.rewriter.TagRewriter;
import com.viaversion.viaversion.util.ComponentUtil;
@@ -50,6 +51,7 @@ public class Protocol1_13_1To1_13 extends BackwardsProtocol<ClientboundPackets1_
public static final BackwardsMappingData MAPPINGS = new BackwardsMappingData("1.13.2", "1.13", Protocol1_13To1_13_1.class);
private final EntityPacketRewriter1_13_1 entityRewriter = new EntityPacketRewriter1_13_1(this);
private final ItemPacketRewriter1_13_1 itemRewriter = new ItemPacketRewriter1_13_1(this);
private final ParticleRewriter<ClientboundPackets1_13> particleRewriter = new ParticleRewriter<>(this);
private final TranslatableRewriter<ClientboundPackets1_13> translatableRewriter = new TranslatableRewriter<>(this, ComponentRewriter.ReadType.JSON);
private final TagRewriter<ClientboundPackets1_13> tagRewriter = new TagRewriter<>(this);
@@ -72,6 +74,8 @@ public class Protocol1_13_1To1_13 extends BackwardsProtocol<ClientboundPackets1_
new CommandRewriter1_13_1(this).registerDeclareCommands(ClientboundPackets1_13.COMMANDS);
particleRewriter.registerLevelParticles1_13(ClientboundPackets1_13.LEVEL_PARTICLES, Types.FLOAT);
registerServerbound(ServerboundPackets1_13.COMMAND_SUGGESTION, new PacketHandlers() {
@Override
public void register() {
@@ -221,6 +225,11 @@ public class Protocol1_13_1To1_13 extends BackwardsProtocol<ClientboundPackets1_
return itemRewriter;
}
@Override
public ParticleRewriter<ClientboundPackets1_13> getParticleRewriter() {
return particleRewriter;
}
public TranslatableRewriter<ClientboundPackets1_13> translatableRewriter() {
return translatableRewriter;
}
@@ -22,8 +22,8 @@ import com.viaversion.viabackwards.protocol.v1_13_1to1_13.Protocol1_13_1To1_13;
import com.viaversion.viaversion.api.minecraft.Particle;
import com.viaversion.viaversion.api.minecraft.entities.EntityType;
import com.viaversion.viaversion.api.minecraft.entities.EntityTypes1_13;
import com.viaversion.viaversion.api.minecraft.item.Item;
import com.viaversion.viaversion.api.minecraft.entitydata.EntityData;
import com.viaversion.viaversion.api.minecraft.item.Item;
import com.viaversion.viaversion.api.protocol.remapper.PacketHandlers;
import com.viaversion.viaversion.api.type.Types;
import com.viaversion.viaversion.api.type.types.version.Types1_13;
@@ -138,7 +138,7 @@ public class EntityPacketRewriter1_13_1 extends LegacyEntityRewriter<Clientbound
int value = (int) data.getValue();
data.setValue(protocol.getMappingData().getNewBlockStateId(value));
} else if (data.dataType() == Types1_13.ENTITY_DATA_TYPES.particleType) {
rewriteParticle(event.user(), (Particle) data.getValue());
protocol.getParticleRewriter().rewriteParticle(event.user(), (Particle) data.getValue());
} else if (data.dataType() == Types1_13.ENTITY_DATA_TYPES.optionalComponentType || data.dataType() == Types1_13.ENTITY_DATA_TYPES.componentType) {
JsonElement element = data.value();
protocol.translatableRewriter().processText(event.user(), element);
@@ -19,7 +19,6 @@ package com.viaversion.viabackwards.protocol.v1_13_1to1_13.rewriter;
import com.viaversion.viabackwards.protocol.v1_13_1to1_13.Protocol1_13_1To1_13;
import com.viaversion.viaversion.api.minecraft.item.Item;
import com.viaversion.viaversion.api.type.Type;
import com.viaversion.viaversion.api.type.Types;
import com.viaversion.viaversion.protocols.v1_12_2to1_13.packet.ClientboundPackets1_13;
import com.viaversion.viaversion.protocols.v1_12_2to1_13.packet.ServerboundPackets1_13;
@@ -68,7 +67,5 @@ public class ItemPacketRewriter1_13_1 extends ItemRewriter<ClientboundPackets1_1
registerSetEquippedItem(ClientboundPackets1_13.SET_EQUIPPED_ITEM);
registerContainerClick(ServerboundPackets1_13.CONTAINER_CLICK);
registerSetCreativeModeSlot(ServerboundPackets1_13.SET_CREATIVE_MODE_SLOT);
registerLevelParticles(ClientboundPackets1_13.LEVEL_PARTICLES, Types.FLOAT);
}
}
@@ -18,9 +18,12 @@
package com.viaversion.viabackwards.protocol.v1_13_2to1_13_1.rewriter;
import com.viaversion.viabackwards.protocol.v1_13_2to1_13_1.Protocol1_13_2To1_13_1;
import com.viaversion.viaversion.api.minecraft.Particle;
import com.viaversion.viaversion.api.minecraft.entitydata.EntityData;
import com.viaversion.viaversion.api.minecraft.entitydata.EntityDataType;
import com.viaversion.viaversion.api.minecraft.item.Item;
import com.viaversion.viaversion.api.protocol.packet.PacketWrapper;
import com.viaversion.viaversion.api.protocol.remapper.PacketHandlers;
import com.viaversion.viaversion.api.type.Type;
import com.viaversion.viaversion.api.type.Types;
import com.viaversion.viaversion.api.type.types.version.Types1_13;
import com.viaversion.viaversion.api.type.types.version.Types1_13_2;
@@ -47,11 +50,7 @@ public class EntityPacketRewriter1_13_2 {
map(Types.SHORT); // 11 - Velocity Z
map(Types1_13_2.ENTITY_DATA_LIST, Types1_13.ENTITY_DATA_LIST); // 12 - Entity data
handler(wrapper -> {
for (EntityData entityData : wrapper.get(Types1_13.ENTITY_DATA_LIST, 0)) {
entityData.setDataType(Types1_13.ENTITY_DATA_TYPES.byId(entityData.dataType().typeId()));
}
});
handler(EntityPacketRewriter1_13_2::updateEntityData);
}
});
@@ -67,11 +66,7 @@ public class EntityPacketRewriter1_13_2 {
map(Types.BYTE); // 6 - Pitch
map(Types1_13_2.ENTITY_DATA_LIST, Types1_13.ENTITY_DATA_LIST); // 7 - Entity data
handler(wrapper -> {
for (EntityData entityData : wrapper.get(Types1_13.ENTITY_DATA_LIST, 0)) {
entityData.setDataType(Types1_13.ENTITY_DATA_TYPES.byId(entityData.dataType().typeId()));
}
});
handler(EntityPacketRewriter1_13_2::updateEntityData);
}
});
@@ -81,13 +76,23 @@ public class EntityPacketRewriter1_13_2 {
map(Types.VAR_INT); // 0 - Entity ID
map(Types1_13_2.ENTITY_DATA_LIST, Types1_13.ENTITY_DATA_LIST); // 1 - Entity data list
handler(wrapper -> {
for (EntityData entityData : wrapper.get(Types1_13.ENTITY_DATA_LIST, 0)) {
entityData.setDataType(Types1_13.ENTITY_DATA_TYPES.byId(entityData.dataType().typeId()));
}
});
handler(EntityPacketRewriter1_13_2::updateEntityData);
}
});
}
private static void updateEntityData(final PacketWrapper wrapper) {
for (final EntityData data : wrapper.get(Types1_13.ENTITY_DATA_LIST, 0)) {
final EntityDataType dataType = Types1_13.ENTITY_DATA_TYPES.byId(data.dataType().typeId());
data.setDataType(dataType);
if (dataType == Types1_13.ENTITY_DATA_TYPES.particleType) {
final Particle particle = data.value();
if (particle.id() == 27) {
final Item item = particle.<Item>getArgument(0).getValue();
particle.set(0, Types.ITEM1_13, item);
}
}
}
}
}
@@ -31,10 +31,11 @@ import com.viaversion.viaversion.api.minecraft.ClientWorld;
import com.viaversion.viaversion.api.minecraft.Particle;
import com.viaversion.viaversion.api.minecraft.entities.EntityType;
import com.viaversion.viaversion.api.minecraft.entities.EntityTypes1_13;
import com.viaversion.viaversion.api.minecraft.item.Item;
import com.viaversion.viaversion.api.minecraft.entitydata.EntityData;
import com.viaversion.viaversion.api.minecraft.entitydata.types.EntityDataTypes1_12;
import com.viaversion.viaversion.api.minecraft.item.Item;
import com.viaversion.viaversion.api.protocol.packet.PacketWrapper;
import com.viaversion.viaversion.api.protocol.remapper.PacketHandler;
import com.viaversion.viaversion.api.protocol.remapper.PacketHandlers;
import com.viaversion.viaversion.api.type.Types;
import com.viaversion.viaversion.api.type.types.version.Types1_12;
@@ -236,20 +237,18 @@ public class EntityPacketRewriter1_13 extends LegacyEntityRewriter<ClientboundPa
positionAndLook.send(Protocol1_13To1_12_2.class);
});
if (ViaBackwards.getConfig().isFix1_13FacePlayer()) {
PacketHandlers movementRemapper = new PacketHandlers() {
@Override
public void register() {
map(Types.DOUBLE);
map(Types.DOUBLE);
map(Types.DOUBLE);
handler(wrapper -> wrapper.user().get(PlayerPositionStorage1_13.class).setCoordinates(wrapper, false));
}
};
protocol.registerServerbound(ServerboundPackets1_12_1.MOVE_PLAYER_POS, movementRemapper); // Player Position
protocol.registerServerbound(ServerboundPackets1_12_1.MOVE_PLAYER_POS_ROT, movementRemapper); // Player Position And Look (serverbound)
protocol.registerServerbound(ServerboundPackets1_12_1.MOVE_VEHICLE, movementRemapper); // Vehicle Move (serverbound)
}
PacketHandler movementRemapper = wrapper -> {
if (!ViaBackwards.getConfig().isFix1_13FacePlayer()) {
return;
}
final double x = wrapper.passthrough(Types.DOUBLE);
final double y = wrapper.passthrough(Types.DOUBLE);
final double z = wrapper.passthrough(Types.DOUBLE);
wrapper.user().get(PlayerPositionStorage1_13.class).setPosition(x, y, z);
};
protocol.registerServerbound(ServerboundPackets1_12_1.MOVE_PLAYER_POS, movementRemapper); // Player Position
protocol.registerServerbound(ServerboundPackets1_12_1.MOVE_PLAYER_POS_ROT, movementRemapper); // Player Position And Look (serverbound)
protocol.registerServerbound(ServerboundPackets1_12_1.MOVE_VEHICLE, movementRemapper); // Vehicle Move (serverbound)
}
@Override
@@ -469,7 +469,7 @@ public class PlayerPacketRewriter1_13 extends RewriterBase<Protocol1_13To1_12_2>
wrapper.write(Types.STRING, newChannel);
if (newChannel.equals("minecraft:register") || newChannel.equals("minecraft:unregister")) {
String[] channels = new String(wrapper.read(Types.REMAINING_BYTES), StandardCharsets.UTF_8).split("\0");
String[] channels = new String(wrapper.read(Types.SERVERBOUND_CUSTOM_PAYLOAD_DATA), StandardCharsets.UTF_8).split("\0");
List<String> rewrittenChannels = new ArrayList<>();
for (String s : channels) {
String rewritten = ItemPacketRewriter1_13.getNewPluginChannelId(s);
@@ -480,7 +480,7 @@ public class PlayerPacketRewriter1_13 extends RewriterBase<Protocol1_13To1_12_2>
}
}
if (!rewrittenChannels.isEmpty()) {
wrapper.write(Types.REMAINING_BYTES, Joiner.on('\0').join(rewrittenChannels).getBytes(StandardCharsets.UTF_8));
wrapper.write(Types.SERVERBOUND_CUSTOM_PAYLOAD_DATA, Joiner.on('\0').join(rewrittenChannels).getBytes(StandardCharsets.UTF_8));
} else {
wrapper.cancel();
}
@@ -20,8 +20,8 @@ package com.viaversion.viabackwards.protocol.v1_14to1_13_2;
import com.viaversion.viabackwards.api.BackwardsProtocol;
import com.viaversion.viabackwards.api.data.BackwardsMappingData;
import com.viaversion.viabackwards.api.rewriters.TranslatableRewriter;
import com.viaversion.viabackwards.protocol.v1_14to1_13_2.rewriter.CommandRewriter1_14;
import com.viaversion.viabackwards.protocol.v1_14to1_13_2.rewriter.BlockItemPacketRewriter1_14;
import com.viaversion.viabackwards.protocol.v1_14to1_13_2.rewriter.CommandRewriter1_14;
import com.viaversion.viabackwards.protocol.v1_14to1_13_2.rewriter.EntityPacketRewriter1_14;
import com.viaversion.viabackwards.protocol.v1_14to1_13_2.rewriter.PlayerPacketRewriter1_14;
import com.viaversion.viabackwards.protocol.v1_14to1_13_2.rewriter.SoundPacketRewriter1_14;
@@ -38,6 +38,7 @@ import com.viaversion.viaversion.protocols.v1_13_2to1_14.Protocol1_13_2To1_14;
import com.viaversion.viaversion.protocols.v1_13_2to1_14.packet.ClientboundPackets1_14;
import com.viaversion.viaversion.protocols.v1_13_2to1_14.packet.ServerboundPackets1_14;
import com.viaversion.viaversion.rewriter.ComponentRewriter;
import com.viaversion.viaversion.rewriter.ParticleRewriter;
import com.viaversion.viaversion.rewriter.StatisticsRewriter;
public class Protocol1_14To1_13_2 extends BackwardsProtocol<ClientboundPackets1_14, ClientboundPackets1_13, ServerboundPackets1_14, ServerboundPackets1_13> {
@@ -45,6 +46,7 @@ public class Protocol1_14To1_13_2 extends BackwardsProtocol<ClientboundPackets1_
public static final BackwardsMappingData MAPPINGS = new BackwardsMappingData("1.14", "1.13.2", Protocol1_13_2To1_14.class);
private final EntityPacketRewriter1_14 entityRewriter = new EntityPacketRewriter1_14(this);
private final BlockItemPacketRewriter1_14 itemRewriter = new BlockItemPacketRewriter1_14(this);
private final ParticleRewriter<ClientboundPackets1_14> particleRewriter = new ParticleRewriter<>(this);
private final TranslatableRewriter<ClientboundPackets1_14> translatableRewriter = new TranslatableRewriter<>(this, ComponentRewriter.ReadType.JSON);
public Protocol1_14To1_13_2() {
@@ -63,6 +65,8 @@ public class Protocol1_14To1_13_2 extends BackwardsProtocol<ClientboundPackets1_
translatableRewriter.registerTitle(ClientboundPackets1_14.SET_TITLES);
translatableRewriter.registerPing();
particleRewriter.registerLevelParticles1_13(ClientboundPackets1_14.LEVEL_PARTICLES, Types.FLOAT);
new CommandRewriter1_14(this).registerDeclareCommands(ClientboundPackets1_14.COMMANDS);
new PlayerPacketRewriter1_14(this).register();
new SoundPacketRewriter1_14(this).register();
@@ -187,6 +191,11 @@ public class Protocol1_14To1_13_2 extends BackwardsProtocol<ClientboundPackets1_
return itemRewriter;
}
@Override
public ParticleRewriter<ClientboundPackets1_14> getParticleRewriter() {
return particleRewriter;
}
@Override
public TranslatableRewriter<ClientboundPackets1_14> getComponentRewriter() {
return translatableRewriter;
@@ -18,6 +18,9 @@
package com.viaversion.viabackwards.protocol.v1_14to1_13_2.rewriter;
import com.google.common.collect.ImmutableSet;
import com.viaversion.nbt.tag.CompoundTag;
import com.viaversion.nbt.tag.ListTag;
import com.viaversion.nbt.tag.StringTag;
import com.viaversion.viabackwards.api.rewriters.BackwardsItemRewriter;
import com.viaversion.viabackwards.api.rewriters.EnchantmentRewriter;
import com.viaversion.viabackwards.api.rewriters.TranslatableRewriter;
@@ -35,8 +38,8 @@ import com.viaversion.viaversion.api.minecraft.chunks.DataPalette;
import com.viaversion.viaversion.api.minecraft.chunks.PaletteType;
import com.viaversion.viaversion.api.minecraft.entities.EntityType;
import com.viaversion.viaversion.api.minecraft.entities.EntityTypes1_14;
import com.viaversion.viaversion.api.minecraft.item.Item;
import com.viaversion.viaversion.api.minecraft.entitydata.EntityData;
import com.viaversion.viaversion.api.minecraft.item.Item;
import com.viaversion.viaversion.api.protocol.remapper.PacketHandlers;
import com.viaversion.viaversion.api.type.Types;
import com.viaversion.viaversion.api.type.types.chunk.ChunkType1_13;
@@ -45,9 +48,6 @@ import com.viaversion.viaversion.api.type.types.version.Types1_13;
import com.viaversion.viaversion.api.type.types.version.Types1_13_2;
import com.viaversion.viaversion.libs.gson.JsonElement;
import com.viaversion.viaversion.libs.gson.JsonObject;
import com.viaversion.nbt.tag.CompoundTag;
import com.viaversion.nbt.tag.ListTag;
import com.viaversion.nbt.tag.StringTag;
import com.viaversion.viaversion.libs.gson.JsonParseException;
import com.viaversion.viaversion.libs.mcstructs.text.utils.TextUtils;
import com.viaversion.viaversion.protocols.v1_12_2to1_13.Protocol1_12_2To1_13;
@@ -369,7 +369,7 @@ public class BlockItemPacketRewriter1_14 extends BackwardsItemRewriter<Clientbou
ChunkSection section = chunk.getSections()[i];
if (section == null) continue;
ChunkSectionLight sectionLight = new ChunkSectionLightImpl();
ChunkSectionLight sectionLight = ChunkSectionLightImpl.createWithBlockLight();
section.setLight(sectionLight);
if (chunkLight == null) {
sectionLight.setBlockLight(ChunkLightStorage.FULL_LIGHT);
@@ -430,8 +430,6 @@ public class BlockItemPacketRewriter1_14 extends BackwardsItemRewriter<Clientbou
}
});
registerLevelParticles(ClientboundPackets1_14.LEVEL_PARTICLES, Types.FLOAT);
protocol.registerClientbound(ClientboundPackets1_14.MAP_ITEM_DATA, new PacketHandlers() {
@Override
public void register() {
@@ -17,17 +17,17 @@
*/
package com.viaversion.viabackwards.protocol.v1_14to1_13_2.rewriter;
import com.viaversion.viabackwards.api.entities.storage.EntityReplacement;
import com.viaversion.viabackwards.api.entities.storage.EntityPositionHandler;
import com.viaversion.viabackwards.api.entities.storage.EntityReplacement;
import com.viaversion.viabackwards.api.rewriters.LegacyEntityRewriter;
import com.viaversion.viabackwards.protocol.v1_14to1_13_2.Protocol1_14To1_13_2;
import com.viaversion.viabackwards.protocol.v1_14to1_13_2.storage.ChunkLightStorage;
import com.viaversion.viabackwards.protocol.v1_14to1_13_2.storage.DifficultyStorage;
import com.viaversion.viabackwards.protocol.v1_14to1_13_2.storage.EntityPositionStorage1_14;
import com.viaversion.viaversion.api.data.entity.EntityTracker;
import com.viaversion.viaversion.api.minecraft.BlockPosition;
import com.viaversion.viaversion.api.minecraft.ClientWorld;
import com.viaversion.viaversion.api.minecraft.Particle;
import com.viaversion.viaversion.api.minecraft.BlockPosition;
import com.viaversion.viaversion.api.minecraft.VillagerData;
import com.viaversion.viaversion.api.minecraft.entities.EntityType;
import com.viaversion.viaversion.api.minecraft.entities.EntityTypes1_13;
@@ -377,7 +377,7 @@ public class EntityPacketRewriter1_14 extends LegacyEntityRewriter<ClientboundPa
filter().type(EntityTypes1_14.ABSTRACT_RAIDER).removeIndex(14); // Celebrating
filter().type(EntityTypes1_14.AREA_EFFECT_CLOUD).index(10).handler((event, data) -> {
rewriteParticle(event.user(), (Particle) data.getValue());
protocol.getParticleRewriter().rewriteParticle(event.user(), (Particle) data.getValue());
});
filter().type(EntityTypes1_14.FIREWORK_ROCKET).index(8).handler((event, data) -> {
@@ -21,9 +21,9 @@ import com.viaversion.viabackwards.api.BackwardsProtocol;
import com.viaversion.viabackwards.api.data.BackwardsMappingData;
import com.viaversion.viabackwards.api.rewriters.SoundRewriter;
import com.viaversion.viabackwards.api.rewriters.TranslatableRewriter;
import com.viaversion.viabackwards.protocol.v1_15to1_14_4.storage.ImmediateRespawnStorage;
import com.viaversion.viabackwards.protocol.v1_15to1_14_4.rewriter.BlockItemPacketRewriter1_15;
import com.viaversion.viabackwards.protocol.v1_15to1_14_4.rewriter.EntityPacketRewriter1_15;
import com.viaversion.viabackwards.protocol.v1_15to1_14_4.storage.ImmediateRespawnStorage;
import com.viaversion.viaversion.api.connection.UserConnection;
import com.viaversion.viaversion.api.minecraft.ClientWorld;
import com.viaversion.viaversion.api.minecraft.RegistryType;
@@ -37,6 +37,7 @@ import com.viaversion.viaversion.protocols.v1_14_3to1_14_4.packet.ClientboundPac
import com.viaversion.viaversion.protocols.v1_14_4to1_15.Protocol1_14_4To1_15;
import com.viaversion.viaversion.protocols.v1_14_4to1_15.packet.ClientboundPackets1_15;
import com.viaversion.viaversion.rewriter.ComponentRewriter;
import com.viaversion.viaversion.rewriter.ParticleRewriter;
import com.viaversion.viaversion.rewriter.StatisticsRewriter;
import com.viaversion.viaversion.rewriter.TagRewriter;
@@ -45,6 +46,7 @@ public class Protocol1_15To1_14_4 extends BackwardsProtocol<ClientboundPackets1_
public static final BackwardsMappingData MAPPINGS = new BackwardsMappingData("1.15", "1.14", Protocol1_14_4To1_15.class);
private final EntityPacketRewriter1_15 entityRewriter = new EntityPacketRewriter1_15(this);
private final BlockItemPacketRewriter1_15 blockItemPackets = new BlockItemPacketRewriter1_15(this);
private final ParticleRewriter<ClientboundPackets1_15> particleRewriter = new ParticleRewriter<>(this);
private final TranslatableRewriter<ClientboundPackets1_15> translatableRewriter = new TranslatableRewriter<>(this, ComponentRewriter.ReadType.JSON);
private final TagRewriter<ClientboundPackets1_15> tagRewriter = new TagRewriter<>(this);
@@ -124,6 +126,11 @@ public class Protocol1_15To1_14_4 extends BackwardsProtocol<ClientboundPackets1_
return blockItemPackets;
}
@Override
public ParticleRewriter<ClientboundPackets1_15> getParticleRewriter() {
return particleRewriter;
}
@Override
public TagRewriter<ClientboundPackets1_15> getTagRewriter() {
return tagRewriter;
@@ -21,8 +21,8 @@ import com.viaversion.viabackwards.api.BackwardsProtocol;
import com.viaversion.viabackwards.api.data.BackwardsMappingData;
import com.viaversion.viabackwards.api.rewriters.SoundRewriter;
import com.viaversion.viabackwards.api.rewriters.TranslatableRewriter;
import com.viaversion.viabackwards.protocol.v1_16_2to1_16_1.rewriter.CommandRewriter1_16_2;
import com.viaversion.viabackwards.protocol.v1_16_2to1_16_1.rewriter.BlockItemPacketRewriter1_16_2;
import com.viaversion.viabackwards.protocol.v1_16_2to1_16_1.rewriter.CommandRewriter1_16_2;
import com.viaversion.viabackwards.protocol.v1_16_2to1_16_1.rewriter.EntityPacketRewriter1_16_2;
import com.viaversion.viabackwards.protocol.v1_16_2to1_16_1.storage.BiomeStorage;
import com.viaversion.viaversion.api.connection.UserConnection;
@@ -38,6 +38,7 @@ import com.viaversion.viaversion.protocols.v1_16_1to1_16_2.Protocol1_16_1To1_16_
import com.viaversion.viaversion.protocols.v1_16_1to1_16_2.packet.ClientboundPackets1_16_2;
import com.viaversion.viaversion.protocols.v1_16_1to1_16_2.packet.ServerboundPackets1_16_2;
import com.viaversion.viaversion.rewriter.ComponentRewriter;
import com.viaversion.viaversion.rewriter.ParticleRewriter;
import com.viaversion.viaversion.rewriter.StatisticsRewriter;
import com.viaversion.viaversion.rewriter.TagRewriter;
import com.viaversion.viaversion.util.ProtocolLogger;
@@ -48,6 +49,7 @@ public class Protocol1_16_2To1_16_1 extends BackwardsProtocol<ClientboundPackets
public static final ProtocolLogger LOGGER = new ProtocolLogger(Protocol1_16_2To1_16_1.class);
private final EntityPacketRewriter1_16_2 entityRewriter = new EntityPacketRewriter1_16_2(this);
private final BlockItemPacketRewriter1_16_2 blockItemPackets = new BlockItemPacketRewriter1_16_2(this);
private final ParticleRewriter<ClientboundPackets1_16_2> particleRewriter = new ParticleRewriter<>(this);
private final TranslatableRewriter<ClientboundPackets1_16_2> translatableRewriter = new TranslatableRewriter<>(this, ComponentRewriter.ReadType.JSON);
private final TagRewriter<ClientboundPackets1_16_2> tagRewriter = new TagRewriter<>(this);
@@ -67,6 +69,8 @@ public class Protocol1_16_2To1_16_1 extends BackwardsProtocol<ClientboundPackets
translatableRewriter.registerOpenScreen(ClientboundPackets1_16_2.OPEN_SCREEN);
translatableRewriter.registerPing();
particleRewriter.registerLevelParticles1_13(ClientboundPackets1_16_2.LEVEL_PARTICLES, Types.DOUBLE);
new CommandRewriter1_16_2(this).registerDeclareCommands(ClientboundPackets1_16_2.COMMANDS);
SoundRewriter<ClientboundPackets1_16_2> soundRewriter = new SoundRewriter<>(this);
@@ -151,6 +155,11 @@ public class Protocol1_16_2To1_16_1 extends BackwardsProtocol<ClientboundPackets
return blockItemPackets;
}
@Override
public ParticleRewriter<ClientboundPackets1_16_2> getParticleRewriter() {
return particleRewriter;
}
@Override
public TagRewriter<ClientboundPackets1_16_2> getTagRewriter() {
return tagRewriter;
@@ -114,8 +114,6 @@ public class BlockItemPacketRewriter1_16_2 extends BackwardsItemRewriter<Clientb
blockRewriter.registerLevelEvent(ClientboundPackets1_16_2.LEVEL_EVENT, 1010, 2001);
registerLevelParticles(ClientboundPackets1_16_2.LEVEL_PARTICLES, Types.DOUBLE);
registerContainerClick(ServerboundPackets1_16.CONTAINER_CLICK);
registerSetCreativeModeSlot(ServerboundPackets1_16.SET_CREATIVE_MODE_SLOT);
protocol.registerServerbound(ServerboundPackets1_16.EDIT_BOOK, wrapper -> handleItemToServer(wrapper.user(), wrapper.passthrough(Types.ITEM1_13_2)));
@@ -19,14 +19,14 @@ package com.viaversion.viabackwards.protocol.v1_16to1_15_2;
import com.viaversion.viabackwards.api.BackwardsProtocol;
import com.viaversion.viabackwards.api.rewriters.SoundRewriter;
import com.viaversion.viabackwards.protocol.v1_16to1_15_2.rewriter.TranslatableRewriter1_16;
import com.viaversion.viabackwards.protocol.v1_16to1_15_2.data.BackwardsMappingData1_16;
import com.viaversion.viabackwards.protocol.v1_16to1_15_2.rewriter.CommandRewriter1_16;
import com.viaversion.viabackwards.protocol.v1_16to1_15_2.storage.PlayerAttributesStorage;
import com.viaversion.viabackwards.protocol.v1_16to1_15_2.storage.WorldNameTracker;
import com.viaversion.viabackwards.protocol.v1_16to1_15_2.rewriter.BlockItemPacketRewriter1_16;
import com.viaversion.viabackwards.protocol.v1_16to1_15_2.rewriter.CommandRewriter1_16;
import com.viaversion.viabackwards.protocol.v1_16to1_15_2.rewriter.EntityPacketRewriter1_16;
import com.viaversion.viabackwards.protocol.v1_16to1_15_2.rewriter.TranslatableRewriter1_16;
import com.viaversion.viabackwards.protocol.v1_16to1_15_2.storage.PlayerAttributesStorage;
import com.viaversion.viabackwards.protocol.v1_16to1_15_2.storage.PlayerSneakStorage;
import com.viaversion.viabackwards.protocol.v1_16to1_15_2.storage.WorldNameTracker;
import com.viaversion.viaversion.api.connection.UserConnection;
import com.viaversion.viaversion.api.minecraft.ClientWorld;
import com.viaversion.viaversion.api.minecraft.RegistryType;
@@ -43,6 +43,7 @@ import com.viaversion.viaversion.protocols.v1_13_2to1_14.packet.ServerboundPacke
import com.viaversion.viaversion.protocols.v1_14_4to1_15.packet.ClientboundPackets1_15;
import com.viaversion.viaversion.protocols.v1_15_2to1_16.packet.ClientboundPackets1_16;
import com.viaversion.viaversion.protocols.v1_15_2to1_16.packet.ServerboundPackets1_16;
import com.viaversion.viaversion.rewriter.ParticleRewriter;
import com.viaversion.viaversion.rewriter.StatisticsRewriter;
import com.viaversion.viaversion.rewriter.TagRewriter;
import com.viaversion.viaversion.util.GsonUtil;
@@ -53,6 +54,7 @@ public class Protocol1_16To1_15_2 extends BackwardsProtocol<ClientboundPackets1_
public static final BackwardsMappingData1_16 MAPPINGS = new BackwardsMappingData1_16();
private final EntityPacketRewriter1_16 entityRewriter = new EntityPacketRewriter1_16(this);
private final BlockItemPacketRewriter1_16 blockItemPackets = new BlockItemPacketRewriter1_16(this);
private final ParticleRewriter<ClientboundPackets1_16> particleRewriter = new ParticleRewriter<>(this);
private final TranslatableRewriter1_16 translatableRewriter = new TranslatableRewriter1_16(this);
private final TagRewriter<ClientboundPackets1_16> tagRewriter = new TagRewriter<>(this);
@@ -71,6 +73,8 @@ public class Protocol1_16To1_15_2 extends BackwardsProtocol<ClientboundPackets1_
translatableRewriter.registerTitle(ClientboundPackets1_16.SET_TITLES);
translatableRewriter.registerPing();
particleRewriter.registerLevelParticles1_13(ClientboundPackets1_16.LEVEL_PARTICLES, Types.DOUBLE);
new CommandRewriter1_16(this).registerDeclareCommands(ClientboundPackets1_16.COMMANDS);
registerClientbound(State.STATUS, ClientboundStatusPackets.STATUS_RESPONSE, wrapper -> {
@@ -116,7 +120,7 @@ public class Protocol1_16To1_15_2 extends BackwardsProtocol<ClientboundPackets1_
soundRewriter.registerStopSound(ClientboundPackets1_16.STOP_SOUND);
// Login success
registerClientbound(State.LOGIN, ClientboundLoginPackets.GAME_PROFILE, wrapper -> {
registerClientbound(State.LOGIN, ClientboundLoginPackets.LOGIN_FINISHED, wrapper -> {
// Transform uuid to plain string
UUID uuid = wrapper.read(Types.UUID);
wrapper.write(Types.STRING, uuid.toString());
@@ -196,6 +200,11 @@ public class Protocol1_16To1_15_2 extends BackwardsProtocol<ClientboundPackets1_
return blockItemPackets;
}
@Override
public ParticleRewriter<ClientboundPackets1_16> getParticleRewriter() {
return particleRewriter;
}
@Override
public TagRewriter<ClientboundPackets1_16> getTagRewriter() {
return tagRewriter;
@@ -17,12 +17,18 @@
*/
package com.viaversion.viabackwards.protocol.v1_16to1_15_2.rewriter;
import com.viaversion.nbt.tag.CompoundTag;
import com.viaversion.nbt.tag.IntArrayTag;
import com.viaversion.nbt.tag.ListTag;
import com.viaversion.nbt.tag.LongArrayTag;
import com.viaversion.nbt.tag.StringTag;
import com.viaversion.nbt.tag.Tag;
import com.viaversion.viabackwards.api.rewriters.BackwardsItemRewriter;
import com.viaversion.viabackwards.api.rewriters.EnchantmentRewriter;
import com.viaversion.viabackwards.api.rewriters.MapColorRewriter;
import com.viaversion.viabackwards.protocol.v1_16_2to1_16_1.storage.BiomeStorage;
import com.viaversion.viabackwards.protocol.v1_16to1_15_2.Protocol1_16To1_15_2;
import com.viaversion.viabackwards.protocol.v1_16to1_15_2.data.MapColorMappings1_15_2;
import com.viaversion.viabackwards.protocol.v1_16_2to1_16_1.storage.BiomeStorage;
import com.viaversion.viaversion.api.connection.UserConnection;
import com.viaversion.viaversion.api.minecraft.item.Item;
import com.viaversion.viaversion.api.protocol.packet.PacketWrapper;
@@ -33,12 +39,6 @@ import com.viaversion.viaversion.api.type.types.chunk.ChunkType1_15;
import com.viaversion.viaversion.api.type.types.chunk.ChunkType1_16;
import com.viaversion.viaversion.libs.gson.JsonElement;
import com.viaversion.viaversion.protocols.v1_13_2to1_14.packet.ServerboundPackets1_14;
import com.viaversion.nbt.tag.CompoundTag;
import com.viaversion.nbt.tag.IntArrayTag;
import com.viaversion.nbt.tag.ListTag;
import com.viaversion.nbt.tag.LongArrayTag;
import com.viaversion.nbt.tag.StringTag;
import com.viaversion.nbt.tag.Tag;
import com.viaversion.viaversion.protocols.v1_14_4to1_15.packet.ClientboundPackets1_15;
import com.viaversion.viaversion.protocols.v1_15_2to1_16.packet.ClientboundPackets1_16;
import com.viaversion.viaversion.protocols.v1_15_2to1_16.rewriter.ItemPacketRewriter1_16;
@@ -179,8 +179,6 @@ public class BlockItemPacketRewriter1_16 extends BackwardsItemRewriter<Clientbou
blockRewriter.registerLevelEvent(ClientboundPackets1_16.LEVEL_EVENT, 1010, 2001);
registerLevelParticles(ClientboundPackets1_16.LEVEL_PARTICLES, Types.DOUBLE);
protocol.registerClientbound(ClientboundPackets1_16.CONTAINER_SET_DATA, new PacketHandlers() {
@Override
public void register() {
@@ -20,17 +20,17 @@ package com.viaversion.viabackwards.protocol.v1_16to1_15_2.rewriter;
import com.viaversion.viabackwards.api.rewriters.EntityRewriter;
import com.viaversion.viabackwards.protocol.v1_16to1_15_2.Protocol1_16To1_15_2;
import com.viaversion.viabackwards.protocol.v1_16to1_15_2.storage.PlayerAttributesStorage;
import com.viaversion.viabackwards.protocol.v1_16to1_15_2.storage.WorldNameTracker;
import com.viaversion.viabackwards.protocol.v1_16to1_15_2.storage.WolfDataMaskStorage;
import com.viaversion.viabackwards.protocol.v1_16to1_15_2.storage.WorldNameTracker;
import com.viaversion.viaversion.api.Via;
import com.viaversion.viaversion.api.data.entity.StoredEntityData;
import com.viaversion.viaversion.api.minecraft.ClientWorld;
import com.viaversion.viaversion.api.minecraft.Particle;
import com.viaversion.viaversion.api.minecraft.entities.EntityType;
import com.viaversion.viaversion.api.minecraft.entities.EntityTypes1_16;
import com.viaversion.viaversion.api.minecraft.item.Item;
import com.viaversion.viaversion.api.minecraft.entitydata.EntityData;
import com.viaversion.viaversion.api.minecraft.entitydata.EntityDataType;
import com.viaversion.viaversion.api.minecraft.item.Item;
import com.viaversion.viaversion.api.protocol.packet.PacketWrapper;
import com.viaversion.viaversion.api.protocol.remapper.PacketHandlers;
import com.viaversion.viaversion.api.protocol.remapper.ValueTransformer;
@@ -263,7 +263,7 @@ public class EntityPacketRewriter1_16 extends EntityRewriter<ClientboundPackets1
} else if (type == Types1_14.ENTITY_DATA_TYPES.optionalBlockStateType) {
data.setValue(protocol.getMappingData().getNewBlockStateId((int) data.getValue()));
} else if (type == Types1_14.ENTITY_DATA_TYPES.particleType) {
rewriteParticle(event.user(), (Particle) data.getValue());
protocol.getParticleRewriter().rewriteParticle(event.user(), (Particle) data.getValue());
} else if (type == Types1_14.ENTITY_DATA_TYPES.optionalComponentType) {
JsonElement text = data.value();
if (text != null) {
@@ -42,6 +42,7 @@ import com.viaversion.viaversion.protocols.v1_16_4to1_17.packet.ClientboundPacke
import com.viaversion.viaversion.protocols.v1_16_4to1_17.packet.ServerboundPackets1_17;
import com.viaversion.viaversion.rewriter.ComponentRewriter;
import com.viaversion.viaversion.rewriter.IdRewriteFunction;
import com.viaversion.viaversion.rewriter.ParticleRewriter;
import com.viaversion.viaversion.rewriter.StatisticsRewriter;
import com.viaversion.viaversion.rewriter.TagRewriter;
import com.viaversion.viaversion.util.Key;
@@ -57,6 +58,7 @@ public final class Protocol1_17To1_16_4 extends BackwardsProtocol<ClientboundPac
private static final int[] EMPTY_ARRAY = {};
private final EntityPacketRewriter1_17 entityRewriter = new EntityPacketRewriter1_17(this);
private final BlockItemPacketRewriter1_17 blockItemPackets = new BlockItemPacketRewriter1_17(this);
private final ParticleRewriter<ClientboundPackets1_17> particleRewriter = new ParticleRewriter<>(this);
private final TranslatableRewriter<ClientboundPackets1_17> translatableRewriter = new TranslatableRewriter<>(this, ComponentRewriter.ReadType.JSON);
private final TagRewriter<ClientboundPackets1_17> tagRewriter = new TagRewriter<>(this);
@@ -254,6 +256,11 @@ public final class Protocol1_17To1_16_4 extends BackwardsProtocol<ClientboundPac
return blockItemPackets;
}
@Override
public ParticleRewriter<ClientboundPackets1_17> getParticleRewriter() {
return particleRewriter;
}
@Override
public TagRewriter<ClientboundPackets1_17> getTagRewriter() {
return tagRewriter;
@@ -204,7 +204,7 @@ public final class BlockItemPacketRewriter1_17 extends BackwardsItemRewriter<Cli
wrapper.cancel();
}
});
handler(levelParticlesHandler());
handler(protocol.getParticleRewriter().levelParticlesHandler1_13(Types.INT));
}
});
@@ -17,6 +17,10 @@
*/
package com.viaversion.viabackwards.protocol.v1_17to1_16_4.rewriter;
import com.viaversion.nbt.tag.CompoundTag;
import com.viaversion.nbt.tag.ListTag;
import com.viaversion.nbt.tag.NumberTag;
import com.viaversion.nbt.tag.StringTag;
import com.viaversion.viabackwards.ViaBackwards;
import com.viaversion.viabackwards.api.rewriters.EntityRewriter;
import com.viaversion.viabackwards.protocol.v1_17to1_16_4.Protocol1_17To1_16_4;
@@ -30,7 +34,6 @@ import com.viaversion.viaversion.api.type.Types;
import com.viaversion.viaversion.api.type.types.version.Types1_16;
import com.viaversion.viaversion.api.type.types.version.Types1_17;
import com.viaversion.viaversion.protocols.v1_16_1to1_16_2.packet.ClientboundPackets1_16_2;
import com.viaversion.nbt.tag.*;
import com.viaversion.viaversion.protocols.v1_16_4to1_17.packet.ClientboundPackets1_17;
import com.viaversion.viaversion.util.TagUtil;
@@ -185,7 +188,7 @@ public final class EntityPacketRewriter1_17 extends EntityRewriter<ClientboundPa
return;
}
rewriteParticle(event.user(), particle);
protocol.getParticleRewriter().rewriteParticle(event.user(), particle);
} else if (type == Types1_16.ENTITY_DATA_TYPES.poseType) {
// Goat LONG_JUMP added at 6
int pose = data.value();
@@ -28,13 +28,13 @@ import com.viaversion.viaversion.api.minecraft.RegistryType;
import com.viaversion.viaversion.api.minecraft.entities.EntityTypes1_17;
import com.viaversion.viaversion.api.protocol.remapper.PacketHandler;
import com.viaversion.viaversion.api.protocol.remapper.PacketHandlers;
import com.viaversion.viaversion.api.type.Type;
import com.viaversion.viaversion.api.type.Types;
import com.viaversion.viaversion.data.entity.EntityTrackerBase;
import com.viaversion.viaversion.protocols.v1_16_4to1_17.packet.ServerboundPackets1_17;
import com.viaversion.viaversion.protocols.v1_17_1to1_18.packet.ClientboundPackets1_18;
import com.viaversion.viaversion.protocols.v1_17to1_17_1.packet.ClientboundPackets1_17_1;
import com.viaversion.viaversion.rewriter.ComponentRewriter;
import com.viaversion.viaversion.rewriter.ParticleRewriter;
import com.viaversion.viaversion.rewriter.TagRewriter;
public final class Protocol1_18To1_17_1 extends BackwardsProtocol<ClientboundPackets1_18, ClientboundPackets1_17_1, ServerboundPackets1_17, ServerboundPackets1_17> {
@@ -42,6 +42,7 @@ public final class Protocol1_18To1_17_1 extends BackwardsProtocol<ClientboundPac
private static final BackwardsMappingData1_18 MAPPINGS = new BackwardsMappingData1_18();
private final EntityPacketRewriter1_18 entityRewriter = new EntityPacketRewriter1_18(this);
private final BlockItemPacketRewriter1_18 itemRewriter = new BlockItemPacketRewriter1_18(this);
private final ParticleRewriter<ClientboundPackets1_18> particleRewriter = new ParticleRewriter<>(this);
private final TranslatableRewriter<ClientboundPackets1_18> translatableRewriter = new TranslatableRewriter<>(this, ComponentRewriter.ReadType.JSON);
private final TagRewriter<ClientboundPackets1_18> tagRewriter = new TagRewriter<>(this);
@@ -151,6 +152,11 @@ public final class Protocol1_18To1_17_1 extends BackwardsProtocol<ClientboundPac
return itemRewriter;
}
@Override
public ParticleRewriter<ClientboundPackets1_18> getParticleRewriter() {
return particleRewriter;
}
@Override
public TranslatableRewriter<ClientboundPackets1_18> getComponentRewriter() {
return translatableRewriter;
@@ -17,6 +17,9 @@
*/
package com.viaversion.viabackwards.protocol.v1_18to1_17_1.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.EntityRewriter;
import com.viaversion.viabackwards.protocol.v1_18to1_17_1.Protocol1_18To1_17_1;
import com.viaversion.viaversion.api.minecraft.Particle;
@@ -28,9 +31,6 @@ import com.viaversion.viaversion.api.type.Types;
import com.viaversion.viaversion.api.type.types.version.Types1_17;
import com.viaversion.viaversion.api.type.types.version.Types1_18;
import com.viaversion.viaversion.protocols.v1_17_1to1_18.packet.ClientboundPackets1_18;
import com.viaversion.nbt.tag.CompoundTag;
import com.viaversion.nbt.tag.ListTag;
import com.viaversion.nbt.tag.StringTag;
import com.viaversion.viaversion.util.TagUtil;
public final class EntityPacketRewriter1_18 extends EntityRewriter<ClientboundPackets1_18, Protocol1_18To1_17_1> {
@@ -110,7 +110,7 @@ public final class EntityPacketRewriter1_18 extends EntityRewriter<ClientboundPa
return;
}
rewriteParticle(event.user(), particle);
protocol.getParticleRewriter().rewriteParticle(event.user(), particle);
}
});
@@ -21,13 +21,13 @@ import com.google.common.base.Preconditions;
import com.viaversion.viabackwards.api.BackwardsProtocol;
import com.viaversion.viabackwards.api.rewriters.SoundRewriter;
import com.viaversion.viabackwards.api.rewriters.TranslatableRewriter;
import com.viaversion.viabackwards.protocol.v1_19_1to1_19.Protocol1_19_1To1_19;
import com.viaversion.viabackwards.protocol.v1_19_3to1_19_1.data.BackwardsMappingData1_19_3;
import com.viaversion.viabackwards.protocol.v1_19_3to1_19_1.rewriter.BlockItemPacketRewriter1_19_3;
import com.viaversion.viabackwards.protocol.v1_19_3to1_19_1.rewriter.EntityPacketRewriter1_19_3;
import com.viaversion.viabackwards.protocol.v1_19_3to1_19_1.storage.ChatSessionStorage;
import com.viaversion.viabackwards.protocol.v1_19_3to1_19_1.storage.ChatTypeStorage1_19_3;
import com.viaversion.viabackwards.protocol.v1_19_3to1_19_1.storage.NonceStorage;
import com.viaversion.viabackwards.protocol.v1_19_1to1_19.Protocol1_19_1To1_19;
import com.viaversion.viaversion.api.Via;
import com.viaversion.viaversion.api.connection.UserConnection;
import com.viaversion.viaversion.api.minecraft.Holder;
@@ -42,7 +42,6 @@ import com.viaversion.viaversion.api.minecraft.signature.storage.ChatSession1_19
import com.viaversion.viaversion.api.protocol.packet.PacketWrapper;
import com.viaversion.viaversion.api.protocol.packet.State;
import com.viaversion.viaversion.api.protocol.remapper.PacketHandlers;
import com.viaversion.viaversion.api.type.Type;
import com.viaversion.viaversion.api.type.Types;
import com.viaversion.viaversion.api.type.types.BitSetType;
import com.viaversion.viaversion.api.type.types.ByteArrayType;
@@ -56,6 +55,7 @@ import com.viaversion.viaversion.protocols.v1_19to1_19_1.packet.ClientboundPacke
import com.viaversion.viaversion.protocols.v1_19to1_19_1.packet.ServerboundPackets1_19_1;
import com.viaversion.viaversion.rewriter.CommandRewriter;
import com.viaversion.viaversion.rewriter.ComponentRewriter;
import com.viaversion.viaversion.rewriter.ParticleRewriter;
import com.viaversion.viaversion.rewriter.StatisticsRewriter;
import com.viaversion.viaversion.rewriter.TagRewriter;
import com.viaversion.viaversion.util.CipherUtil;
@@ -73,6 +73,7 @@ public final class Protocol1_19_3To1_19_1 extends BackwardsProtocol<ClientboundP
public static final ByteArrayType SIGNATURE_BYTES_TYPE = new ByteArrayType(256);
private final EntityPacketRewriter1_19_3 entityRewriter = new EntityPacketRewriter1_19_3(this);
private final BlockItemPacketRewriter1_19_3 itemRewriter = new BlockItemPacketRewriter1_19_3(this);
private final ParticleRewriter<ClientboundPackets1_19_3> particleRewriter = new ParticleRewriter<>(this);
private final TranslatableRewriter<ClientboundPackets1_19_3> translatableRewriter = new TranslatableRewriter<>(this, ComponentRewriter.ReadType.JSON);
private final TagRewriter<ClientboundPackets1_19_3> tagRewriter = new TagRewriter<>(this);
@@ -95,6 +96,8 @@ public final class Protocol1_19_3To1_19_1 extends BackwardsProtocol<ClientboundP
translatableRewriter.registerPlayerCombatKill(ClientboundPackets1_19_3.PLAYER_COMBAT_KILL);
translatableRewriter.registerPing();
particleRewriter.registerLevelParticles1_19(ClientboundPackets1_19_3.LEVEL_PARTICLES);
final SoundRewriter<ClientboundPackets1_19_3> soundRewriter = new SoundRewriter<>(this);
soundRewriter.registerStopSound(ClientboundPackets1_19_3.STOP_SOUND);
registerClientbound(ClientboundPackets1_19_3.SOUND, wrapper -> {
@@ -412,6 +415,11 @@ public final class Protocol1_19_3To1_19_1 extends BackwardsProtocol<ClientboundP
return itemRewriter;
}
@Override
public ParticleRewriter<ClientboundPackets1_19_3> getParticleRewriter() {
return particleRewriter;
}
@Override
public EntityPacketRewriter1_19_3 getEntityRewriter() {
return entityRewriter;
@@ -54,7 +54,6 @@ public final class BlockItemPacketRewriter1_19_3 extends BackwardsItemRewriter<C
registerMerchantOffers1_19(ClientboundPackets1_19_3.MERCHANT_OFFERS);
registerSetCreativeModeSlot(ServerboundPackets1_19_1.SET_CREATIVE_MODE_SLOT);
registerContainerSetData(ClientboundPackets1_19_3.CONTAINER_SET_DATA);
registerLevelParticles1_19(ClientboundPackets1_19_3.LEVEL_PARTICLES);
protocol.registerClientbound(ClientboundPackets1_19_3.EXPLODE, new PacketHandlers() {
@Override
@@ -28,7 +28,6 @@ import com.viaversion.viaversion.api.minecraft.signature.storage.ChatSession1_19
import com.viaversion.viaversion.api.protocol.packet.PacketWrapper;
import com.viaversion.viaversion.api.protocol.remapper.PacketHandlers;
import com.viaversion.viaversion.api.type.Types;
import com.viaversion.viaversion.api.type.types.BitSetType;
import com.viaversion.viaversion.api.type.types.version.Types1_19;
import com.viaversion.viaversion.api.type.types.version.Types1_19_3;
import com.viaversion.viaversion.libs.gson.JsonElement;
@@ -45,7 +44,6 @@ import org.checkerframework.checker.nullness.qual.Nullable;
public final class EntityPacketRewriter1_19_3 extends EntityRewriter<ClientboundPackets1_19_3, Protocol1_19_3To1_19_1> {
private static final BitSetType PROFILE_ACTIONS_ENUM_TYPE = new BitSetType(6);
private static final int[] PROFILE_ACTIONS = {2, 3, 4, 5}; // Ignore initialize chat; add player already handled before
private static final int ADD_PLAYER = 0;
private static final int INITIALIZE_CHAT = 1;
@@ -123,7 +121,7 @@ public final class EntityPacketRewriter1_19_3 extends EntityRewriter<Clientbound
protocol.registerClientbound(ClientboundPackets1_19_3.PLAYER_INFO_UPDATE, ClientboundPackets1_19_1.PLAYER_INFO, wrapper -> {
wrapper.cancel();
final BitSet actions = wrapper.read(PROFILE_ACTIONS_ENUM_TYPE);
final BitSet actions = wrapper.read(Types.PROFILE_ACTIONS_ENUM1_19_3);
final int entries = wrapper.read(Types.VAR_INT);
if (actions.get(ADD_PLAYER)) {
// Special case, as we need to write everything into one action
@@ -23,11 +23,10 @@ import com.viaversion.viabackwards.api.rewriters.SoundRewriter;
import com.viaversion.viabackwards.api.rewriters.TranslatableRewriter;
import com.viaversion.viabackwards.protocol.v1_19_4to1_19_3.rewriter.BlockItemPacketRewriter1_19_4;
import com.viaversion.viabackwards.protocol.v1_19_4to1_19_3.rewriter.EntityPacketRewriter1_19_4;
import com.viaversion.viabackwards.protocol.v1_19_4to1_19_3.storage.EntityTracker1_19_4;
import com.viaversion.viaversion.api.connection.UserConnection;
import com.viaversion.viaversion.api.minecraft.entities.EntityTypes1_19_4;
import com.viaversion.viaversion.api.protocol.packet.PacketWrapper;
import com.viaversion.viaversion.api.type.Types;
import com.viaversion.viaversion.data.entity.EntityTrackerBase;
import com.viaversion.viaversion.libs.gson.JsonElement;
import com.viaversion.viaversion.protocols.v1_19_1to1_19_3.packet.ClientboundPackets1_19_3;
import com.viaversion.viaversion.protocols.v1_19_1to1_19_3.packet.ServerboundPackets1_19_3;
@@ -36,6 +35,7 @@ import com.viaversion.viaversion.protocols.v1_19_3to1_19_4.packet.ClientboundPac
import com.viaversion.viaversion.protocols.v1_19_3to1_19_4.packet.ServerboundPackets1_19_4;
import com.viaversion.viaversion.rewriter.CommandRewriter;
import com.viaversion.viaversion.rewriter.ComponentRewriter;
import com.viaversion.viaversion.rewriter.ParticleRewriter;
import com.viaversion.viaversion.rewriter.StatisticsRewriter;
import com.viaversion.viaversion.rewriter.TagRewriter;
import java.nio.charset.StandardCharsets;
@@ -46,6 +46,7 @@ public final class Protocol1_19_4To1_19_3 extends BackwardsProtocol<ClientboundP
public static final BackwardsMappingData MAPPINGS = new BackwardsMappingData("1.19.4", "1.19.3", Protocol1_19_3To1_19_4.class);
private final EntityPacketRewriter1_19_4 entityRewriter = new EntityPacketRewriter1_19_4(this);
private final BlockItemPacketRewriter1_19_4 itemRewriter = new BlockItemPacketRewriter1_19_4(this);
private final ParticleRewriter<ClientboundPackets1_19_4> particleRewriter = new ParticleRewriter<>(this);
private final TranslatableRewriter<ClientboundPackets1_19_4> translatableRewriter = new TranslatableRewriter<>(this, ComponentRewriter.ReadType.JSON);
private final TagRewriter<ClientboundPackets1_19_4> tagRewriter = new TagRewriter<>(this);
@@ -74,6 +75,8 @@ public final class Protocol1_19_4To1_19_3 extends BackwardsProtocol<ClientboundP
translatableRewriter.registerComponentPacket(ClientboundPackets1_19_4.DISGUISED_CHAT);
translatableRewriter.registerPing();
particleRewriter.registerLevelParticles1_19(ClientboundPackets1_19_4.LEVEL_PARTICLES);
new CommandRewriter<>(this) {
@Override
public void handleArgument(final PacketWrapper wrapper, final String argumentType) {
@@ -110,7 +113,7 @@ public final class Protocol1_19_4To1_19_3 extends BackwardsProtocol<ClientboundP
@Override
public void init(final UserConnection user) {
addEntityTracker(user, new EntityTrackerBase(user, EntityTypes1_19_4.PLAYER));
addEntityTracker(user, new EntityTracker1_19_4(user));
}
@Override
@@ -123,6 +126,11 @@ public final class Protocol1_19_4To1_19_3 extends BackwardsProtocol<ClientboundP
return itemRewriter;
}
@Override
public ParticleRewriter<ClientboundPackets1_19_4> getParticleRewriter() {
return particleRewriter;
}
@Override
public EntityPacketRewriter1_19_4 getEntityRewriter() {
return entityRewriter;
@@ -137,4 +145,4 @@ public final class Protocol1_19_4To1_19_3 extends BackwardsProtocol<ClientboundP
public TagRewriter<ClientboundPackets1_19_4> getTagRewriter() {
return tagRewriter;
}
}
}
@@ -73,7 +73,6 @@ public final class BlockItemPacketRewriter1_19_4 extends BackwardsItemRewriter<C
registerMerchantOffers1_19(ClientboundPackets1_19_4.MERCHANT_OFFERS);
registerSetCreativeModeSlot(ServerboundPackets1_19_3.SET_CREATIVE_MODE_SLOT);
registerContainerSetData(ClientboundPackets1_19_4.CONTAINER_SET_DATA);
registerLevelParticles1_19(ClientboundPackets1_19_4.LEVEL_PARTICLES);
final RecipeRewriter1_19_3<ClientboundPackets1_19_4> recipeRewriter = new RecipeRewriter1_19_3<>(protocol) {
@Override
@@ -121,4 +120,4 @@ public final class BlockItemPacketRewriter1_19_4 extends BackwardsItemRewriter<C
wrapper.set(Types.VAR_INT, 0, newSize);
});
}
}
}
@@ -20,17 +20,24 @@ package com.viaversion.viabackwards.protocol.v1_19_4to1_19_3.rewriter;
import com.viaversion.nbt.tag.CompoundTag;
import com.viaversion.nbt.tag.ListTag;
import com.viaversion.nbt.tag.NumberTag;
import com.viaversion.viabackwards.api.entities.storage.EntityPositionHandler;
import com.viaversion.viabackwards.api.entities.storage.EntityReplacement;
import com.viaversion.viabackwards.api.rewriters.EntityRewriter;
import com.viaversion.viabackwards.protocol.v1_19_4to1_19_3.Protocol1_19_4To1_19_3;
import com.viaversion.viabackwards.protocol.v1_19_4to1_19_3.storage.EntityTracker1_19_4;
import com.viaversion.viabackwards.protocol.v1_19_4to1_19_3.storage.LinkedEntityStorage;
import com.viaversion.viaversion.api.data.entity.StoredEntityData;
import com.viaversion.viaversion.api.minecraft.entities.EntityType;
import com.viaversion.viaversion.api.minecraft.entities.EntityTypes1_19_3;
import com.viaversion.viaversion.api.minecraft.entities.EntityTypes1_19_4;
import com.viaversion.viaversion.api.minecraft.entitydata.EntityData;
import com.viaversion.viaversion.api.minecraft.item.Item;
import com.viaversion.viaversion.api.protocol.packet.PacketWrapper;
import com.viaversion.viaversion.api.protocol.remapper.PacketHandler;
import com.viaversion.viaversion.api.protocol.remapper.PacketHandlers;
import com.viaversion.viaversion.api.type.Types;
import com.viaversion.viaversion.api.type.types.version.Types1_19_3;
import com.viaversion.viaversion.api.type.types.version.Types1_19_4;
import com.viaversion.viaversion.libs.gson.JsonElement;
import com.viaversion.viaversion.protocols.v1_19_1to1_19_3.packet.ClientboundPackets1_19_3;
import com.viaversion.viaversion.protocols.v1_19_3to1_19_4.packet.ClientboundPackets1_19_4;
import com.viaversion.viaversion.util.TagUtil;
@@ -43,10 +50,45 @@ public final class EntityPacketRewriter1_19_4 extends EntityRewriter<Clientbound
@Override
public void registerPackets() {
registerTrackerWithData1_19(ClientboundPackets1_19_4.ADD_ENTITY, EntityTypes1_19_4.FALLING_BLOCK);
registerRemoveEntities(ClientboundPackets1_19_4.REMOVE_ENTITIES);
registerSetEntityData(ClientboundPackets1_19_4.SET_ENTITY_DATA, Types1_19_4.ENTITY_DATA_LIST, Types1_19_3.ENTITY_DATA_LIST);
protocol.registerClientbound(ClientboundPackets1_19_4.ADD_ENTITY, new PacketHandlers() {
@Override
public void register() {
map(Types.VAR_INT); // Entity id
map(Types.UUID); // Entity UUID
map(Types.VAR_INT); // Entity type
map(Types.DOUBLE); // X
map(Types.DOUBLE); // Y
map(Types.DOUBLE); // Z
map(Types.BYTE); // Pitch
map(Types.BYTE); // Yaw
map(Types.BYTE); // Head yaw
map(Types.VAR_INT); // Data
handler(wrapper -> {
final int entityId = wrapper.get(Types.VAR_INT, 0);
final int entityType = wrapper.get(Types.VAR_INT, 1);
// 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()) {
return;
}
final StoredEntityData data = tracker(wrapper.user()).entityData(entityId);
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);
}
});
}
});
protocol.registerClientbound(ClientboundPackets1_19_4.LOGIN, new PacketHandlers() {
@Override
public void register() {
@@ -137,6 +179,40 @@ public final class EntityPacketRewriter1_19_4 extends EntityRewriter<Clientbound
final int duration = wrapper.read(Types.VAR_INT);
wrapper.write(Types.VAR_INT, duration == -1 ? 999999 : duration);
});
// Track the position of block display entities to later spawn the linked entities, we will put them
// as passengers but the spawn position needs to be in the players view distance
protocol.registerClientbound(ClientboundPackets1_19_4.TELEPORT_ENTITY, wrapper -> {
final int entityId = wrapper.passthrough(Types.VAR_INT);
final double x = wrapper.passthrough(Types.DOUBLE);
final double y = wrapper.passthrough(Types.DOUBLE);
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;
}
storage.setPosition(x, y, z);
});
final PacketHandler entityPositionHandler = wrapper -> {
final int entityId = wrapper.passthrough(Types.VAR_INT);
final double x = wrapper.passthrough(Types.SHORT) / EntityPositionHandler.RELATIVE_MOVE_FACTOR;
final double y = wrapper.passthrough(Types.SHORT) / EntityPositionHandler.RELATIVE_MOVE_FACTOR;
final double z = wrapper.passthrough(Types.SHORT) / EntityPositionHandler.RELATIVE_MOVE_FACTOR;
final EntityTracker1_19_4 tracker = tracker(wrapper.user());
final LinkedEntityStorage storage = tracker.linkedEntityStorage(entityId);
if (storage == null) {
return;
}
storage.addRelativePosition(x, y, z);
};
protocol.registerClientbound(ClientboundPackets1_19_4.MOVE_ENTITY_POS, entityPositionHandler);
protocol.registerClientbound(ClientboundPackets1_19_4.MOVE_ENTITY_POS_ROT, entityPositionHandler);
}
@Override
@@ -168,8 +244,35 @@ public final class EntityPacketRewriter1_19_4 extends EntityRewriter<Clientbound
data.setDataType(Types1_19_3.ENTITY_DATA_TYPES.optionalComponentType);
event.createExtraData(new EntityData(3, Types1_19_3.ENTITY_DATA_TYPES.booleanType, true)); // Show custom name
}));
filter().type(EntityTypes1_19_4.BLOCK_DISPLAY).index(22).handler((event, data) -> {
final int value = data.value();
final EntityTracker1_19_4 tracker = tracker(event.user());
tracker.clearLinkedEntities(event.entityId());
final LinkedEntityStorage storage = tracker.linkedEntityStorage(event.entityId());
if (storage == null) {
return;
}
final int linkedEntity = tracker.spawnEntity(EntityTypes1_19_3.FALLING_BLOCK, storage.x(), storage.y(), storage.z(), value);
storage.setEntities(linkedEntity);
final PacketWrapper wrapper = PacketWrapper.create(ClientboundPackets1_19_3.SET_PASSENGERS, event.user());
wrapper.write(Types.VAR_INT, event.entityId()); // Entity id
wrapper.write(Types.VAR_INT_ARRAY_PRIMITIVE, new int[] { linkedEntity }); // Passenger entity ids
wrapper.send(Protocol1_19_4To1_19_3.class);
});
filter().type(EntityTypes1_19_4.ITEM_DISPLAY).index(22).handler((event, data) -> {
final Item value = data.value();
final PacketWrapper setEquipment = PacketWrapper.create(ClientboundPackets1_19_3.SET_EQUIPMENT, event.user());
setEquipment.write(Types.VAR_INT, event.entityId()); // Entity id
setEquipment.write(Types.BYTE, (byte) 5); // Slot - head
setEquipment.write(Types.ITEM1_13_2, value);
setEquipment.send(Protocol1_19_4To1_19_3.class);
});
filter().type(EntityTypes1_19_4.DISPLAY).handler((event, data) -> {
// TODO Maybe spawn an extra entity to ride the armor stand for blocks and items
// Remove a large heap of display entity data
if (event.index() > 7) {
event.cancel();
@@ -0,0 +1,104 @@
/*
* This file is part of ViaBackwards - https://github.com/ViaVersion/ViaBackwards
* Copyright (C) 2016-2024 ViaVersion and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.viaversion.viabackwards.protocol.v1_19_4to1_19_3.storage;
import com.viaversion.viabackwards.protocol.v1_19_4to1_19_3.Protocol1_19_4To1_19_3;
import com.viaversion.viaversion.api.connection.UserConnection;
import com.viaversion.viaversion.api.data.entity.TrackedEntity;
import com.viaversion.viaversion.api.minecraft.entities.EntityTypes1_19_3;
import com.viaversion.viaversion.api.minecraft.entities.EntityTypes1_19_4;
import com.viaversion.viaversion.api.protocol.packet.PacketWrapper;
import com.viaversion.viaversion.api.type.Types;
import com.viaversion.viaversion.data.entity.EntityTrackerBase;
import com.viaversion.viaversion.libs.fastutil.ints.IntOpenHashSet;
import com.viaversion.viaversion.libs.fastutil.ints.IntSet;
import com.viaversion.viaversion.protocols.v1_19_1to1_19_3.packet.ClientboundPackets1_19_3;
import java.util.UUID;
import java.util.concurrent.ThreadLocalRandom;
public final class EntityTracker1_19_4 extends EntityTrackerBase {
private final IntSet generatedEntities = new IntOpenHashSet(); // Track entities spawned to prevent duplicated entity ids
public EntityTracker1_19_4(final UserConnection connection) {
super(connection, EntityTypes1_19_4.PLAYER);
}
public int spawnEntity(final EntityTypes1_19_3 entityType, final double x, final double y, final double z, final int data) {
final int entityId = nextEntityId();
final PacketWrapper addEntity = PacketWrapper.create(ClientboundPackets1_19_3.ADD_ENTITY, user());
addEntity.write(Types.VAR_INT, entityId); // Entity id
addEntity.write(Types.UUID, UUID.randomUUID()); // Entity UUID
addEntity.write(Types.VAR_INT, entityType.getId()); // Entity type
addEntity.write(Types.DOUBLE, x); // X
addEntity.write(Types.DOUBLE, y); // Y
addEntity.write(Types.DOUBLE, z); // Z
addEntity.write(Types.BYTE, (byte) 0); // Pitch
addEntity.write(Types.BYTE, (byte) 0); // Yaw
addEntity.write(Types.BYTE, (byte) 0); // Head yaw
addEntity.write(Types.VAR_INT, data); // Data
addEntity.write(Types.SHORT, (short) 0); // Velocity X
addEntity.write(Types.SHORT, (short) 0); // Velocity Y
addEntity.write(Types.SHORT, (short) 0); // Velocity Z
addEntity.send(Protocol1_19_4To1_19_3.class);
generatedEntities.add(entityId);
return entityId;
}
@Override
public void clearEntities() {
for (final int id : entities.keySet()) {
clearLinkedEntities(id);
}
super.clearEntities();
}
@Override
public void removeEntity(final int id) {
clearLinkedEntities(id);
super.removeEntity(id);
}
public void clearLinkedEntities(final int id) {
final LinkedEntityStorage storage = linkedEntityStorage(id);
if (storage != null && storage.entities() != null) {
storage.remove(user());
generatedEntities.remove(id);
}
}
public LinkedEntityStorage linkedEntityStorage(final int id) {
final TrackedEntity entity = entity(id);
if (entity != null && entity.hasData()) {
return entity.data().get(LinkedEntityStorage.class);
}
return null;
}
private int nextEntityId() {
final int entityId = -ThreadLocalRandom.current().nextInt(10_000);
if (generatedEntities.contains(entityId)) {
return nextEntityId();
}
return entityId;
}
}
@@ -0,0 +1,46 @@
/*
* This file is part of ViaBackwards - https://github.com/ViaVersion/ViaBackwards
* Copyright (C) 2016-2024 ViaVersion and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.viaversion.viabackwards.protocol.v1_19_4to1_19_3.storage;
import com.viaversion.viabackwards.api.entities.storage.EntityPositionStorage;
import com.viaversion.viabackwards.protocol.v1_19_4to1_19_3.Protocol1_19_4To1_19_3;
import com.viaversion.viaversion.api.connection.StorableObject;
import com.viaversion.viaversion.api.connection.UserConnection;
import com.viaversion.viaversion.api.protocol.packet.PacketWrapper;
import com.viaversion.viaversion.api.type.Types;
import com.viaversion.viaversion.protocols.v1_19_1to1_19_3.packet.ClientboundPackets1_19_3;
public class LinkedEntityStorage extends EntityPositionStorage implements StorableObject {
private int[] entities;
public int[] entities() {
return entities;
}
public void setEntities(final int... entities) {
this.entities = entities;
}
public void remove(final UserConnection connection) {
final PacketWrapper wrapper = PacketWrapper.create(ClientboundPackets1_19_3.REMOVE_ENTITIES, connection);
wrapper.write(Types.VAR_INT_ARRAY_PRIMITIVE, entities);
wrapper.send(Protocol1_19_4To1_19_3.class);
}
}
@@ -18,21 +18,21 @@
package com.viaversion.viabackwards.protocol.v1_19to1_18_2;
import com.google.common.primitives.Longs;
import com.viaversion.viabackwards.ViaBackwards;
import com.viaversion.nbt.tag.CompoundTag;
import com.viaversion.viabackwards.api.BackwardsProtocol;
import com.viaversion.viabackwards.api.rewriters.SoundRewriter;
import com.viaversion.viabackwards.api.rewriters.TranslatableRewriter;
import com.viaversion.viabackwards.protocol.v1_19_1to1_19.Protocol1_19_1To1_19;
import com.viaversion.viabackwards.protocol.v1_19to1_18_2.data.BackwardsMappingData1_19;
import com.viaversion.viabackwards.protocol.v1_19to1_18_2.rewriter.CommandRewriter1_19;
import com.viaversion.viabackwards.protocol.v1_19to1_18_2.rewriter.BlockItemPacketRewriter1_19;
import com.viaversion.viabackwards.protocol.v1_19to1_18_2.rewriter.CommandRewriter1_19;
import com.viaversion.viabackwards.protocol.v1_19to1_18_2.rewriter.EntityPacketRewriter1_19;
import com.viaversion.viabackwards.protocol.v1_19to1_18_2.storage.DimensionRegistryStorage;
import com.viaversion.viabackwards.protocol.v1_19to1_18_2.storage.EntityTracker1_19;
import com.viaversion.viabackwards.protocol.v1_19to1_18_2.storage.NonceStorage;
import com.viaversion.viabackwards.protocol.v1_19_1to1_19.Protocol1_19_1To1_19;
import com.viaversion.viaversion.api.Via;
import com.viaversion.viaversion.api.connection.UserConnection;
import com.viaversion.viaversion.api.minecraft.RegistryType;
import com.viaversion.viaversion.api.minecraft.entities.EntityTypes1_19;
import com.viaversion.viaversion.api.minecraft.signature.SignableCommandArgumentsProvider;
import com.viaversion.viaversion.api.minecraft.signature.model.DecoratableMessage;
import com.viaversion.viaversion.api.minecraft.signature.model.MessageMetadata;
@@ -40,9 +40,7 @@ import com.viaversion.viaversion.api.minecraft.signature.storage.ChatSession1_19
import com.viaversion.viaversion.api.protocol.packet.State;
import com.viaversion.viaversion.api.protocol.remapper.PacketHandlers;
import com.viaversion.viaversion.api.type.Types;
import com.viaversion.viaversion.data.entity.EntityTrackerBase;
import com.viaversion.viaversion.libs.gson.JsonElement;
import com.viaversion.nbt.tag.CompoundTag;
import com.viaversion.viaversion.protocols.base.ClientboundLoginPackets;
import com.viaversion.viaversion.protocols.base.ServerboundLoginPackets;
import com.viaversion.viaversion.protocols.v1_16_4to1_17.packet.ServerboundPackets1_17;
@@ -53,6 +51,7 @@ import com.viaversion.viaversion.protocols.v1_19to1_19_1.Protocol1_19To1_19_1;
import com.viaversion.viaversion.protocols.v1_19to1_19_1.data.ChatDecorationResult;
import com.viaversion.viaversion.rewriter.CommandRewriter;
import com.viaversion.viaversion.rewriter.ComponentRewriter;
import com.viaversion.viaversion.rewriter.ParticleRewriter;
import com.viaversion.viaversion.rewriter.StatisticsRewriter;
import com.viaversion.viaversion.rewriter.TagRewriter;
import com.viaversion.viaversion.util.Pair;
@@ -69,6 +68,7 @@ public final class Protocol1_19To1_18_2 extends BackwardsProtocol<ClientboundPac
private static final byte[] EMPTY_BYTES = new byte[0];
private final EntityPacketRewriter1_19 entityRewriter = new EntityPacketRewriter1_19(this);
private final BlockItemPacketRewriter1_19 blockItemPackets = new BlockItemPacketRewriter1_19(this);
private final ParticleRewriter<ClientboundPackets1_19> particleRewriter = new ParticleRewriter<>(this);
private final TranslatableRewriter<ClientboundPackets1_19> translatableRewriter = new TranslatableRewriter<>(this, ComponentRewriter.ReadType.JSON);
private final TagRewriter<ClientboundPackets1_19> tagRewriter = new TagRewriter<>(this);
@@ -291,7 +291,7 @@ public final class Protocol1_19To1_18_2 extends BackwardsProtocol<ClientboundPac
});
// Login changes
registerClientbound(State.LOGIN, ClientboundLoginPackets.GAME_PROFILE, new PacketHandlers() {
registerClientbound(State.LOGIN, ClientboundLoginPackets.LOGIN_FINISHED, new PacketHandlers() {
@Override
public void register() {
map(Types.UUID); // UUID
@@ -363,7 +363,7 @@ public final class Protocol1_19To1_18_2 extends BackwardsProtocol<ClientboundPac
@Override
public void init(final UserConnection user) {
user.put(new DimensionRegistryStorage());
addEntityTracker(user, new EntityTrackerBase(user, EntityTypes1_19.PLAYER));
addEntityTracker(user, new EntityTracker1_19(user));
}
@Override
@@ -386,6 +386,11 @@ public final class Protocol1_19To1_18_2 extends BackwardsProtocol<ClientboundPac
return blockItemPackets;
}
@Override
public ParticleRewriter<ClientboundPackets1_19> getParticleRewriter() {
return particleRewriter;
}
@Override
public TagRewriter<ClientboundPackets1_19> getTagRewriter() {
return tagRewriter;
@@ -141,7 +141,7 @@ public final class BlockItemPacketRewriter1_19 extends BackwardsItemRewriter<Cli
wrapper.cancel();
}
});
handler(levelParticlesHandler());
handler(protocol.getParticleRewriter().levelParticlesHandler1_13(Types.INT));
}
});
@@ -17,16 +17,21 @@
*/
package com.viaversion.viabackwards.protocol.v1_19to1_18_2.rewriter;
import com.viaversion.nbt.tag.CompoundTag;
import com.viaversion.nbt.tag.ListTag;
import com.viaversion.nbt.tag.NumberTag;
import com.viaversion.viabackwards.ViaBackwards;
import com.viaversion.viabackwards.api.rewriters.EntityRewriter;
import com.viaversion.viabackwards.protocol.v1_19to1_18_2.Protocol1_19To1_18_2;
import com.viaversion.viabackwards.protocol.v1_19to1_18_2.storage.DimensionRegistryStorage;
import com.viaversion.viabackwards.protocol.v1_19to1_18_2.storage.EntityTracker1_19;
import com.viaversion.viabackwards.protocol.v1_19to1_18_2.storage.LastDeathPosition;
import com.viaversion.viabackwards.protocol.v1_19to1_18_2.storage.StoredPainting;
import com.viaversion.viaversion.api.data.ParticleMappings;
import com.viaversion.viaversion.api.data.entity.StoredEntityData;
import com.viaversion.viaversion.api.minecraft.BlockPosition;
import com.viaversion.viaversion.api.minecraft.GlobalBlockPosition;
import com.viaversion.viaversion.api.minecraft.Particle;
import com.viaversion.viaversion.api.minecraft.BlockPosition;
import com.viaversion.viaversion.api.minecraft.entities.EntityType;
import com.viaversion.viaversion.api.minecraft.entities.EntityTypes1_19;
import com.viaversion.viaversion.api.minecraft.entitydata.EntityDataType;
@@ -37,9 +42,6 @@ import com.viaversion.viaversion.api.type.types.version.Types1_18;
import com.viaversion.viaversion.api.type.types.version.Types1_19;
import com.viaversion.viaversion.protocols.v1_17_1to1_18.packet.ClientboundPackets1_18;
import com.viaversion.viaversion.protocols.v1_18_2to1_19.packet.ClientboundPackets1_19;
import com.viaversion.nbt.tag.CompoundTag;
import com.viaversion.nbt.tag.ListTag;
import com.viaversion.nbt.tag.NumberTag;
import com.viaversion.viaversion.util.Key;
import com.viaversion.viaversion.util.TagUtil;
@@ -111,6 +113,50 @@ public final class EntityPacketRewriter1_19 extends EntityRewriter<ClientboundPa
handler(wrapper -> {
// Remove factor data
wrapper.read(Types.OPTIONAL_NAMED_COMPOUND_TAG);
if (!ViaBackwards.getConfig().mapDarknessEffect()) {
return;
}
final EntityTracker1_19 tracker = tracker(wrapper.user());
final int entityId = wrapper.get(Types.VAR_INT, 0);
final int effectId = wrapper.get(Types.VAR_INT, 1);
if (effectId == 33) { // Newly added darkness, rewrite to blindness
tracker.getAffectedByDarkness().add(entityId);
wrapper.set(Types.VAR_INT, 1, 15);
} else if (effectId == 15) { // Track actual blindness effect for removal later
tracker.getAffectedByBlindness().add(entityId);
}
});
}
});
protocol.registerClientbound(ClientboundPackets1_19.REMOVE_MOB_EFFECT, new PacketHandlers() {
@Override
protected void register() {
map(Types.VAR_INT); // Entity id
map(Types.VAR_INT); // Effect id
handler(wrapper -> {
if (!ViaBackwards.getConfig().mapDarknessEffect()) {
return;
}
final int entityId = wrapper.get(Types.VAR_INT, 0);
final int effectId = wrapper.get(Types.VAR_INT, 1);
final EntityTracker1_19 tracker = tracker(wrapper.user());
if (effectId == 33) { // Remove darkness and the fake blindness effect if the client doesn't have actual blindness
tracker.getAffectedByDarkness().rem(entityId);
if (!tracker.getAffectedByBlindness().contains(entityId)) {
wrapper.set(Types.VAR_INT, 1, 15);
}
} else if (effectId == 15) { // Remove blindness and cancel if the client has darkness (will be removed by darkness removal)
tracker.getAffectedByBlindness().rem(entityId);
if (tracker.getAffectedByDarkness().contains(entityId)) {
wrapper.cancel();
}
}
});
}
});
@@ -270,7 +316,7 @@ public final class EntityPacketRewriter1_19 extends EntityRewriter<ClientboundPa
return;
}
rewriteParticle(event.user(), particle);
protocol.getParticleRewriter().rewriteParticle(event.user(), particle);
} else if (type == Types1_18.ENTITY_DATA_TYPES.poseType) {
final int pose = data.value();
if (pose >= 8) {
@@ -0,0 +1,49 @@
/*
* This file is part of ViaBackwards - https://github.com/ViaVersion/ViaBackwards
* Copyright (C) 2016-2024 ViaVersion and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.viaversion.viabackwards.protocol.v1_19to1_18_2.storage;
import com.viaversion.viaversion.api.connection.UserConnection;
import com.viaversion.viaversion.api.minecraft.entities.EntityTypes1_19;
import com.viaversion.viaversion.data.entity.EntityTrackerBase;
import com.viaversion.viaversion.libs.fastutil.ints.IntArrayList;
import com.viaversion.viaversion.libs.fastutil.ints.IntList;
public final class EntityTracker1_19 extends EntityTrackerBase {
private final IntList affectedByBlindness = new IntArrayList();
private final IntList affectedByDarkness = new IntArrayList();
public EntityTracker1_19(final UserConnection connection) {
super(connection, EntityTypes1_19.PLAYER);
}
@Override
public void removeEntity(final int id) {
super.removeEntity(id);
this.affectedByBlindness.rem(id);
this.affectedByDarkness.rem(id);
}
public IntList getAffectedByBlindness() {
return affectedByBlindness;
}
public IntList getAffectedByDarkness() {
return affectedByDarkness;
}
}
@@ -17,6 +17,7 @@
*/
package com.viaversion.viabackwards.protocol.v1_20_2to1_20;
import com.viaversion.nbt.tag.CompoundTag;
import com.viaversion.viabackwards.api.BackwardsProtocol;
import com.viaversion.viabackwards.api.data.BackwardsMappingData;
import com.viaversion.viabackwards.api.rewriters.SoundRewriter;
@@ -36,7 +37,6 @@ import com.viaversion.viaversion.api.type.Types;
import com.viaversion.viaversion.data.entity.EntityTrackerBase;
import com.viaversion.viaversion.exception.CancelException;
import com.viaversion.viaversion.exception.InformativeException;
import com.viaversion.nbt.tag.CompoundTag;
import com.viaversion.viaversion.protocols.base.ClientboundLoginPackets;
import com.viaversion.viaversion.protocols.base.ServerboundLoginPackets;
import com.viaversion.viaversion.protocols.v1_19_3to1_19_4.packet.ClientboundPackets1_19_4;
@@ -46,6 +46,7 @@ import com.viaversion.viaversion.protocols.v1_20to1_20_2.packet.ClientboundConfi
import com.viaversion.viaversion.protocols.v1_20to1_20_2.packet.ClientboundPackets1_20_2;
import com.viaversion.viaversion.protocols.v1_20to1_20_2.packet.ServerboundConfigurationPackets1_20_2;
import com.viaversion.viaversion.protocols.v1_20to1_20_2.packet.ServerboundPackets1_20_2;
import com.viaversion.viaversion.rewriter.ParticleRewriter;
import com.viaversion.viaversion.rewriter.TagRewriter;
import java.util.UUID;
@@ -54,6 +55,7 @@ public final class Protocol1_20_2To1_20 extends BackwardsProtocol<ClientboundPac
public static final BackwardsMappingData MAPPINGS = new BackwardsMappingData("1.20.2", "1.20", Protocol1_20To1_20_2.class);
private final EntityPacketRewriter1_20_2 entityPacketRewriter = new EntityPacketRewriter1_20_2(this);
private final BlockItemPacketRewriter1_20_2 itemPacketRewriter = new BlockItemPacketRewriter1_20_2(this);
private final ParticleRewriter<ClientboundPackets1_20_2> particleRewriter = new ParticleRewriter<>(this);
private final TagRewriter<ClientboundPackets1_20_2> tagRewriter = new TagRewriter<>(this);
public Protocol1_20_2To1_20() {
@@ -71,12 +73,14 @@ public final class Protocol1_20_2To1_20 extends BackwardsProtocol<ClientboundPac
soundRewriter.registerSound1_19_3(ClientboundPackets1_20_2.SOUND_ENTITY);
soundRewriter.registerStopSound(ClientboundPackets1_20_2.STOP_SOUND);
particleRewriter.registerLevelParticles1_19(ClientboundPackets1_20_2.LEVEL_PARTICLES);
registerClientbound(ClientboundPackets1_20_2.SET_DISPLAY_OBJECTIVE, wrapper -> {
final int slot = wrapper.read(Types.VAR_INT);
wrapper.write(Types.BYTE, (byte) slot);
});
registerClientbound(State.LOGIN, ClientboundLoginPackets.GAME_PROFILE, wrapper -> {
registerClientbound(State.LOGIN, ClientboundLoginPackets.LOGIN_FINISHED, wrapper -> {
// We can't set the internal state to configuration here as protocols down the line will expect the state to be play
// Add this *before* sending the ack since the server might immediately answer
wrapper.user().put(new ConfigurationPacketStorage());
@@ -225,6 +229,11 @@ public final class Protocol1_20_2To1_20 extends BackwardsProtocol<ClientboundPac
return itemPacketRewriter;
}
@Override
public ParticleRewriter<ClientboundPackets1_20_2> getParticleRewriter() {
return particleRewriter;
}
@Override
public TagRewriter<ClientboundPackets1_20_2> getTagRewriter() {
return tagRewriter;
@@ -69,7 +69,6 @@ public final class BlockItemPacketRewriter1_20_2 extends BackwardsItemRewriter<C
registerContainerClick1_17_1(ServerboundPackets1_19_4.CONTAINER_CLICK);
registerMerchantOffers1_19(ClientboundPackets1_20_2.MERCHANT_OFFERS);
registerSetCreativeModeSlot(ServerboundPackets1_19_4.SET_CREATIVE_MODE_SLOT);
registerLevelParticles1_19(ClientboundPackets1_20_2.LEVEL_PARTICLES);
protocol.cancelClientbound(ClientboundPackets1_20_2.CHUNK_BATCH_START);
protocol.registerClientbound(ClientboundPackets1_20_2.CHUNK_BATCH_FINISHED, null, wrapper -> {
@@ -17,6 +17,7 @@
*/
package com.viaversion.viabackwards.protocol.v1_20_3to1_20_2;
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.SoundRewriter;
@@ -36,21 +37,21 @@ import com.viaversion.viaversion.api.protocol.remapper.PacketHandlers;
import com.viaversion.viaversion.api.type.Types;
import com.viaversion.viaversion.data.entity.EntityTrackerBase;
import com.viaversion.viaversion.libs.fastutil.Pair;
import com.viaversion.nbt.tag.Tag;
import com.viaversion.viaversion.protocols.v1_19_3to1_19_4.rewriter.CommandRewriter1_19_4;
import com.viaversion.viaversion.protocols.v1_20to1_20_2.packet.ClientboundConfigurationPackets1_20_2;
import com.viaversion.viaversion.protocols.v1_20to1_20_2.packet.ClientboundPacket1_20_2;
import com.viaversion.viaversion.protocols.v1_20to1_20_2.packet.ClientboundPackets1_20_2;
import com.viaversion.viaversion.protocols.v1_20to1_20_2.packet.ServerboundConfigurationPackets1_20_2;
import com.viaversion.viaversion.protocols.v1_20to1_20_2.packet.ServerboundPacket1_20_2;
import com.viaversion.viaversion.protocols.v1_20to1_20_2.packet.ServerboundPackets1_20_2;
import com.viaversion.viaversion.protocols.v1_20_2to1_20_3.Protocol1_20_2To1_20_3;
import com.viaversion.viaversion.protocols.v1_20_2to1_20_3.packet.ClientboundConfigurationPackets1_20_3;
import com.viaversion.viaversion.protocols.v1_20_2to1_20_3.packet.ClientboundPacket1_20_3;
import com.viaversion.viaversion.protocols.v1_20_2to1_20_3.packet.ClientboundPackets1_20_3;
import com.viaversion.viaversion.protocols.v1_20_2to1_20_3.packet.ServerboundPacket1_20_3;
import com.viaversion.viaversion.protocols.v1_20_2to1_20_3.packet.ServerboundPackets1_20_3;
import com.viaversion.viaversion.protocols.v1_20to1_20_2.packet.ClientboundConfigurationPackets1_20_2;
import com.viaversion.viaversion.protocols.v1_20to1_20_2.packet.ClientboundPacket1_20_2;
import com.viaversion.viaversion.protocols.v1_20to1_20_2.packet.ClientboundPackets1_20_2;
import com.viaversion.viaversion.protocols.v1_20to1_20_2.packet.ServerboundConfigurationPackets1_20_2;
import com.viaversion.viaversion.protocols.v1_20to1_20_2.packet.ServerboundPacket1_20_2;
import com.viaversion.viaversion.protocols.v1_20to1_20_2.packet.ServerboundPackets1_20_2;
import com.viaversion.viaversion.rewriter.ComponentRewriter.ReadType;
import com.viaversion.viaversion.rewriter.ParticleRewriter;
import com.viaversion.viaversion.rewriter.StatisticsRewriter;
import com.viaversion.viaversion.rewriter.TagRewriter;
import com.viaversion.viaversion.util.ComponentUtil;
@@ -64,6 +65,7 @@ public final class Protocol1_20_3To1_20_2 extends BackwardsProtocol<ClientboundP
public static final BackwardsMappingData MAPPINGS = new BackwardsMappingData("1.20.3", "1.20.2", Protocol1_20_2To1_20_3.class);
private final EntityPacketRewriter1_20_3 entityRewriter = new EntityPacketRewriter1_20_3(this);
private final BlockItemPacketRewriter1_20_3 itemRewriter = new BlockItemPacketRewriter1_20_3(this);
private final ParticleRewriter<ClientboundPacket1_20_3> particleRewriter = new ParticleRewriter<>(this);
private final TranslatableRewriter<ClientboundPacket1_20_3> translatableRewriter = new TranslatableRewriter<>(this, ReadType.NBT);
private final TagRewriter<ClientboundPacket1_20_3> tagRewriter = new TagRewriter<>(this);
@@ -283,7 +285,7 @@ public final class Protocol1_20_3To1_20_2 extends BackwardsProtocol<ClientboundP
}
});
registerClientbound(ClientboundPackets1_20_3.PLAYER_INFO_UPDATE, wrapper -> {
final BitSet actions = wrapper.passthrough(Types.PROFILE_ACTIONS_ENUM);
final BitSet actions = wrapper.passthrough(Types.PROFILE_ACTIONS_ENUM1_19_3);
final int entries = wrapper.passthrough(Types.VAR_INT);
for (int i = 0; i < entries; i++) {
wrapper.passthrough(Types.UUID);
@@ -392,6 +394,11 @@ public final class Protocol1_20_3To1_20_2 extends BackwardsProtocol<ClientboundP
return itemRewriter;
}
@Override
public ParticleRewriter<ClientboundPacket1_20_3> getParticleRewriter() {
return particleRewriter;
}
@Override
public EntityPacketRewriter1_20_3 getEntityRewriter() {
return entityRewriter;
@@ -416,4 +423,4 @@ public final class Protocol1_20_3To1_20_2 extends BackwardsProtocol<ClientboundP
packetTypeMap(unmappedServerboundPacketType, ServerboundPackets1_20_2.class, ServerboundConfigurationPackets1_20_2.class)
);
}
}
}
@@ -17,21 +17,19 @@
*/
package com.viaversion.viabackwards.protocol.v1_20_3to1_20_2.rewriter;
import com.viaversion.viabackwards.ViaBackwards;
import com.viaversion.viabackwards.api.rewriters.BackwardsItemRewriter;
import com.viaversion.viabackwards.protocol.v1_20_3to1_20_2.Protocol1_20_3To1_20_2;
import com.viaversion.viaversion.api.data.ParticleMappings;
import com.viaversion.viaversion.api.protocol.packet.PacketWrapper;
import com.viaversion.viaversion.api.protocol.remapper.PacketHandlers;
import com.viaversion.viaversion.api.type.Type;
import com.viaversion.viaversion.api.type.Types;
import com.viaversion.viaversion.api.type.types.chunk.ChunkType1_20_2;
import com.viaversion.viaversion.api.type.types.version.Types1_20_3;
import com.viaversion.viaversion.protocols.v1_20to1_20_2.packet.ServerboundPacket1_20_2;
import com.viaversion.viaversion.protocols.v1_20to1_20_2.packet.ServerboundPackets1_20_2;
import com.viaversion.viaversion.protocols.v1_20_2to1_20_3.packet.ClientboundPacket1_20_3;
import com.viaversion.viaversion.protocols.v1_20_2to1_20_3.packet.ClientboundPackets1_20_3;
import com.viaversion.viaversion.protocols.v1_20_2to1_20_3.rewriter.RecipeRewriter1_20_3;
import com.viaversion.viaversion.protocols.v1_20to1_20_2.packet.ServerboundPacket1_20_2;
import com.viaversion.viaversion.protocols.v1_20to1_20_2.packet.ServerboundPackets1_20_2;
import com.viaversion.viaversion.rewriter.BlockRewriter;
public final class BlockItemPacketRewriter1_20_3 extends BackwardsItemRewriter<ClientboundPacket1_20_3, ServerboundPacket1_20_2, Protocol1_20_3To1_20_2> {
@@ -87,7 +85,7 @@ public final class BlockItemPacketRewriter1_20_3 extends BackwardsItemRewriter<C
}
}
});
handler(levelParticlesHandler(Types.VAR_INT));
handler(protocol.getParticleRewriter().levelParticlesHandler1_13(Types.VAR_INT));
}
});
@@ -158,4 +156,4 @@ public final class BlockItemPacketRewriter1_20_3 extends BackwardsItemRewriter<C
wrapper.read(Types.OPTIONAL_FLOAT); // Sound range
});
}
}
}
@@ -58,6 +58,7 @@ import com.viaversion.viaversion.protocols.v1_20_3to1_20_5.storage.ArmorTrimStor
import com.viaversion.viaversion.protocols.v1_20_3to1_20_5.storage.BannerPatternStorage;
import com.viaversion.viaversion.protocols.v1_20to1_20_2.packet.ServerboundConfigurationPackets1_20_2;
import com.viaversion.viaversion.rewriter.ComponentRewriter.ReadType;
import com.viaversion.viaversion.rewriter.ParticleRewriter;
import com.viaversion.viaversion.rewriter.StatisticsRewriter;
import com.viaversion.viaversion.rewriter.TagRewriter;
@@ -68,6 +69,7 @@ public final class Protocol1_20_5To1_20_3 extends BackwardsProtocol<ClientboundP
public static final BackwardsMappingData MAPPINGS = new BackwardsMappingData("1.20.5", "1.20.3", Protocol1_20_3To1_20_5.class);
private final EntityPacketRewriter1_20_5 entityRewriter = new EntityPacketRewriter1_20_5(this);
private final BlockItemPacketRewriter1_20_5 itemRewriter = new BlockItemPacketRewriter1_20_5(this);
private final ParticleRewriter<ClientboundPacket1_20_5> particleRewriter = new ParticleRewriter<>(this);
private final TranslatableRewriter<ClientboundPacket1_20_5> translatableRewriter = new TranslatableRewriter<>(this, ReadType.NBT);
private final TagRewriter<ClientboundPacket1_20_5> tagRewriter = new TagRewriter<>(this);
@@ -109,6 +111,7 @@ public final class Protocol1_20_5To1_20_3 extends BackwardsProtocol<ClientboundP
translatableRewriter.registerPlayerCombatKill1_20(ClientboundPackets1_20_5.PLAYER_COMBAT_KILL);
translatableRewriter.registerComponentPacket(ClientboundPackets1_20_5.SYSTEM_CHAT);
translatableRewriter.registerComponentPacket(ClientboundPackets1_20_5.DISGUISED_CHAT);
translatableRewriter.registerPlayerInfoUpdate1_20_3(ClientboundPackets1_20_5.PLAYER_INFO_UPDATE);
translatableRewriter.registerPing();
registerClientbound(State.LOGIN, ClientboundLoginPackets.HELLO, wrapper -> {
@@ -157,7 +160,7 @@ public final class Protocol1_20_5To1_20_3 extends BackwardsProtocol<ClientboundP
}
}.registerDeclareCommands1_19(ClientboundPackets1_20_5.COMMANDS);
registerClientbound(State.LOGIN, ClientboundLoginPackets.GAME_PROFILE, wrapper -> {
registerClientbound(State.LOGIN, ClientboundLoginPackets.LOGIN_FINISHED, wrapper -> {
wrapper.passthrough(Types.UUID); // UUID
wrapper.passthrough(Types.STRING); // Name
@@ -246,6 +249,11 @@ public final class Protocol1_20_5To1_20_3 extends BackwardsProtocol<ClientboundP
return itemRewriter;
}
@Override
public ParticleRewriter<ClientboundPacket1_20_5> getParticleRewriter() {
return particleRewriter;
}
@Override
public TranslatableRewriter<ClientboundPacket1_20_5> getComponentRewriter() {
return translatableRewriter;
@@ -107,7 +107,7 @@ public final class BlockItemPacketRewriter1_20_5 extends BackwardsStructuredItem
// Move it to the beginning, move out arguments here
final Particle particle = wrapper.read(Types1_20_5.PARTICLE);
rewriteParticle(wrapper.user(), particle);
protocol.getParticleRewriter().rewriteParticle(wrapper.user(), particle);
if (particle.id() == protocol.getMappingData().getParticleMappings().mappedId("entity_effect")) {
// Remove color argument
final int color = particle.<Integer>removeArgument(0).getValue();
@@ -143,8 +143,8 @@ public final class BlockItemPacketRewriter1_20_5 extends BackwardsStructuredItem
final Particle smallExplosionParticle = wrapper.passthroughAndMap(Types1_20_5.PARTICLE, Types1_20_3.PARTICLE);
final Particle largeExplosionParticle = wrapper.passthroughAndMap(Types1_20_5.PARTICLE, Types1_20_3.PARTICLE);
rewriteParticle(wrapper.user(), smallExplosionParticle);
rewriteParticle(wrapper.user(), largeExplosionParticle);
protocol.getParticleRewriter().rewriteParticle(wrapper.user(), smallExplosionParticle);
protocol.getParticleRewriter().rewriteParticle(wrapper.user(), largeExplosionParticle);
final Holder<SoundEvent> soundEventHolder = wrapper.read(Types.SOUND_EVENT);
if (soundEventHolder.isDirect()) {
@@ -380,10 +380,11 @@ public final class BlockItemPacketRewriter1_20_5 extends BackwardsStructuredItem
if (customData != null) {
// We later don't know which tags are custom data and which are not because the VV conversion
// keeps converted data, so we backup the original custom data and restore it later
if (oldItem.tag() == null) {
oldItem.setTag(new CompoundTag());
}
oldItem.tag().put(nbtTagName(), customData.copy());
}
if (oldItem.tag() != null && oldItem.tag().isEmpty()) {
} else if (oldItem.tag() != null && oldItem.tag().isEmpty()) {
// Improve item equality checks by removing empty tags
oldItem.setTag(null);
}
@@ -243,14 +243,26 @@ public final class EntityPacketRewriter1_20_5 extends EntityRewriter<Clientbound
protocol.registerClientbound(ClientboundPackets1_20_5.UPDATE_MOB_EFFECT, wrapper -> {
wrapper.passthrough(Types.VAR_INT); // Entity ID
wrapper.passthrough(Types.VAR_INT); // Effect ID
final int effectId = wrapper.passthrough(Types.VAR_INT);
final int amplifier = wrapper.read(Types.VAR_INT);
wrapper.write(Types.BYTE, (byte) MathUtil.clamp(amplifier, Byte.MIN_VALUE, Byte.MAX_VALUE));
wrapper.passthrough(Types.VAR_INT); // Duration
wrapper.passthrough(Types.BYTE); // Flags
wrapper.write(Types.OPTIONAL_COMPOUND_TAG, null); // Add empty factor data
if (effectId == 32) { // Darkness, keep a stable effect
final CompoundTag factorData = new CompoundTag();
factorData.putInt("padding_duration", 22);
factorData.putBoolean("had_effect_last_tick", true);
factorData.putFloat("factor_previous_frame", 0);
factorData.putFloat("factor_start", 1);
factorData.putFloat("factor_target", 1);
factorData.putFloat("factor_current", 1);
wrapper.write(Types.OPTIONAL_COMPOUND_TAG, factorData);
} else {
wrapper.write(Types.OPTIONAL_COMPOUND_TAG, null);
}
});
protocol.registerClientbound(ClientboundPackets1_20_5.UPDATE_ATTRIBUTES, wrapper -> {
@@ -26,12 +26,12 @@ import com.viaversion.viabackwards.protocol.v1_20to1_19_4.rewriter.EntityPacketR
import com.viaversion.viaversion.api.connection.UserConnection;
import com.viaversion.viaversion.api.minecraft.RegistryType;
import com.viaversion.viaversion.api.minecraft.entities.EntityTypes1_19_4;
import com.viaversion.viaversion.api.type.Type;
import com.viaversion.viaversion.api.type.Types;
import com.viaversion.viaversion.data.entity.EntityTrackerBase;
import com.viaversion.viaversion.protocols.v1_19_3to1_19_4.packet.ClientboundPackets1_19_4;
import com.viaversion.viaversion.protocols.v1_19_3to1_19_4.packet.ServerboundPackets1_19_4;
import com.viaversion.viaversion.rewriter.ComponentRewriter;
import com.viaversion.viaversion.rewriter.ParticleRewriter;
import com.viaversion.viaversion.rewriter.StatisticsRewriter;
import com.viaversion.viaversion.rewriter.TagRewriter;
import com.viaversion.viaversion.util.ArrayUtil;
@@ -42,6 +42,7 @@ public final class Protocol1_20To1_19_4 extends BackwardsProtocol<ClientboundPac
private final TranslatableRewriter<ClientboundPackets1_19_4> translatableRewriter = new TranslatableRewriter<>(this, ComponentRewriter.ReadType.JSON);
private final EntityPacketRewriter1_20 entityRewriter = new EntityPacketRewriter1_20(this);
private final BlockItemPacketRewriter1_20 itemRewriter = new BlockItemPacketRewriter1_20(this);
private final ParticleRewriter<ClientboundPackets1_19_4> particleRewriter = new ParticleRewriter<>(this);
private final TagRewriter<ClientboundPackets1_19_4> tagRewriter = new TagRewriter<>(this);
public Protocol1_20To1_19_4() {
@@ -60,6 +61,8 @@ public final class Protocol1_20To1_19_4 extends BackwardsProtocol<ClientboundPac
soundRewriter.registerSound1_19_3(ClientboundPackets1_19_4.SOUND);
soundRewriter.registerSound1_19_3(ClientboundPackets1_19_4.SOUND_ENTITY);
particleRewriter.registerLevelParticles1_19(ClientboundPackets1_19_4.LEVEL_PARTICLES);
new StatisticsRewriter<>(this).register(ClientboundPackets1_19_4.AWARD_STATS);
translatableRewriter.registerComponentPacket(ClientboundPackets1_19_4.SET_ACTION_BAR_TEXT);
@@ -108,6 +111,11 @@ public final class Protocol1_20To1_19_4 extends BackwardsProtocol<ClientboundPac
return itemRewriter;
}
@Override
public ParticleRewriter<ClientboundPackets1_19_4> getParticleRewriter() {
return particleRewriter;
}
@Override
public TranslatableRewriter<ClientboundPackets1_19_4> getComponentRewriter() {
return translatableRewriter;
@@ -117,4 +125,4 @@ public final class Protocol1_20To1_19_4 extends BackwardsProtocol<ClientboundPac
public TagRewriter<ClientboundPackets1_19_4> getTagRewriter() {
return tagRewriter;
}
}
}
@@ -17,6 +17,10 @@
*/
package com.viaversion.viabackwards.protocol.v1_20to1_19_4.rewriter;
import com.viaversion.nbt.tag.CompoundTag;
import com.viaversion.nbt.tag.ListTag;
import com.viaversion.nbt.tag.StringTag;
import com.viaversion.nbt.tag.Tag;
import com.viaversion.viabackwards.api.rewriters.BackwardsItemRewriter;
import com.viaversion.viabackwards.protocol.v1_20to1_19_4.Protocol1_20To1_19_4;
import com.viaversion.viabackwards.protocol.v1_20to1_19_4.storage.BackSignEditStorage;
@@ -28,10 +32,6 @@ import com.viaversion.viaversion.api.minecraft.item.Item;
import com.viaversion.viaversion.api.protocol.remapper.PacketHandlers;
import com.viaversion.viaversion.api.type.Types;
import com.viaversion.viaversion.api.type.types.chunk.ChunkType1_18;
import com.viaversion.nbt.tag.CompoundTag;
import com.viaversion.nbt.tag.ListTag;
import com.viaversion.nbt.tag.StringTag;
import com.viaversion.nbt.tag.Tag;
import com.viaversion.viaversion.protocols.v1_19_3to1_19_4.packet.ClientboundPackets1_19_4;
import com.viaversion.viaversion.protocols.v1_19_3to1_19_4.packet.ServerboundPackets1_19_4;
import com.viaversion.viaversion.protocols.v1_19_3to1_19_4.rewriter.RecipeRewriter1_19_4;
@@ -100,7 +100,6 @@ public final class BlockItemPacketRewriter1_20 extends BackwardsItemRewriter<Cli
registerMerchantOffers1_19(ClientboundPackets1_19_4.MERCHANT_OFFERS);
registerSetCreativeModeSlot(ServerboundPackets1_19_4.SET_CREATIVE_MODE_SLOT);
registerContainerSetData(ClientboundPackets1_19_4.CONTAINER_SET_DATA);
registerLevelParticles1_19(ClientboundPackets1_19_4.LEVEL_PARTICLES);
protocol.registerClientbound(ClientboundPackets1_19_4.UPDATE_ADVANCEMENTS, wrapper -> {
wrapper.passthrough(Types.BOOLEAN); // Reset/clear
@@ -232,4 +231,4 @@ public final class BlockItemPacketRewriter1_20 extends BackwardsItemRewriter<Cli
}
}
}
}
@@ -0,0 +1,206 @@
/*
* This file is part of ViaBackwards - https://github.com/ViaVersion/ViaBackwards
* Copyright (C) 2016-2024 ViaVersion and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.viaversion.viabackwards.protocol.v1_21_2to1_21;
import com.viaversion.viabackwards.api.BackwardsProtocol;
import com.viaversion.viabackwards.api.data.BackwardsMappingData;
import com.viaversion.viabackwards.api.rewriters.SoundRewriter;
import com.viaversion.viabackwards.api.rewriters.TranslatableRewriter;
import com.viaversion.viabackwards.protocol.v1_21_2to1_21.rewriter.BlockItemPacketRewriter1_21_2;
import com.viaversion.viabackwards.protocol.v1_21_2to1_21.rewriter.ComponentRewriter1_21_2;
import com.viaversion.viabackwards.protocol.v1_21_2to1_21.rewriter.EntityPacketRewriter1_21_2;
import com.viaversion.viabackwards.protocol.v1_21_2to1_21.rewriter.ParticleRewriter1_21_2;
import com.viaversion.viabackwards.protocol.v1_21_2to1_21.storage.InventoryStateIdStorage;
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.viaversion.api.connection.UserConnection;
import com.viaversion.viaversion.api.minecraft.entities.EntityTypes1_20_5;
import com.viaversion.viaversion.api.protocol.packet.PacketWrapper;
import com.viaversion.viaversion.api.protocol.packet.State;
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;
import com.viaversion.viaversion.data.entity.EntityTrackerBase;
import com.viaversion.viaversion.protocols.base.ClientboundLoginPackets;
import com.viaversion.viaversion.protocols.v1_20_3to1_20_5.packet.ServerboundConfigurationPackets1_20_5;
import com.viaversion.viaversion.protocols.v1_20_3to1_20_5.packet.ServerboundPacket1_20_5;
import com.viaversion.viaversion.protocols.v1_20_3to1_20_5.packet.ServerboundPackets1_20_5;
import com.viaversion.viaversion.protocols.v1_20_5to1_21.packet.ClientboundConfigurationPackets1_21;
import com.viaversion.viaversion.protocols.v1_20_5to1_21.packet.ClientboundPacket1_21;
import com.viaversion.viaversion.protocols.v1_20_5to1_21.packet.ClientboundPackets1_21;
import com.viaversion.viaversion.protocols.v1_21to1_21_2.Protocol1_21To1_21_2;
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.protocols.v1_21to1_21_2.packet.ServerboundPacket1_21_2;
import com.viaversion.viaversion.protocols.v1_21to1_21_2.packet.ServerboundPackets1_21_2;
import com.viaversion.viaversion.rewriter.AttributeRewriter;
import com.viaversion.viaversion.rewriter.StatisticsRewriter;
import com.viaversion.viaversion.rewriter.TagRewriter;
import com.viaversion.viaversion.util.ArrayUtil;
import static com.viaversion.viaversion.util.ProtocolUtil.packetTypeMap;
public final class Protocol1_21_2To1_21 extends BackwardsProtocol<ClientboundPacket1_21_2, ClientboundPacket1_21, ServerboundPacket1_21_2, ServerboundPacket1_20_5> {
public static final BackwardsMappingData MAPPINGS = new BackwardsMappingData("1.21.2", "1.21", Protocol1_21To1_21_2.class);
private final EntityPacketRewriter1_21_2 entityRewriter = new EntityPacketRewriter1_21_2(this);
private final BlockItemPacketRewriter1_21_2 itemRewriter = new BlockItemPacketRewriter1_21_2(this);
private final ParticleRewriter1_21_2 particleRewriter = new ParticleRewriter1_21_2(this);
private final TranslatableRewriter<ClientboundPacket1_21_2> translatableRewriter = new ComponentRewriter1_21_2(this);
private final TagRewriter<ClientboundPacket1_21_2> tagRewriter = new TagRewriter<>(this);
public Protocol1_21_2To1_21() {
super(ClientboundPacket1_21_2.class, ClientboundPacket1_21.class, ServerboundPacket1_21_2.class, ServerboundPacket1_20_5.class);
}
@Override
protected void registerPackets() {
super.registerPackets();
registerClientbound(ClientboundPackets1_21_2.UPDATE_TAGS, this::storeTags);
registerClientbound(ClientboundConfigurationPackets1_21.UPDATE_TAGS, this::storeTags);
final SoundRewriter<ClientboundPacket1_21_2> soundRewriter = new SoundRewriter<>(this);
soundRewriter.registerSound1_19_3(ClientboundPackets1_21_2.SOUND);
soundRewriter.registerSound1_19_3(ClientboundPackets1_21_2.SOUND_ENTITY);
soundRewriter.registerStopSound(ClientboundPackets1_21_2.STOP_SOUND);
particleRewriter.registerLevelParticles1_20_5(ClientboundPackets1_21_2.LEVEL_PARTICLES);
new StatisticsRewriter<>(this).register(ClientboundPackets1_21_2.AWARD_STATS);
new AttributeRewriter<>(this).register1_21(ClientboundPackets1_21_2.UPDATE_ATTRIBUTES);
translatableRewriter.registerComponentPacket(ClientboundPackets1_21_2.SET_ACTION_BAR_TEXT);
translatableRewriter.registerComponentPacket(ClientboundPackets1_21_2.SET_TITLE_TEXT);
translatableRewriter.registerComponentPacket(ClientboundPackets1_21_2.SET_SUBTITLE_TEXT);
translatableRewriter.registerBossEvent(ClientboundPackets1_21_2.BOSS_EVENT);
translatableRewriter.registerComponentPacket(ClientboundPackets1_21_2.DISCONNECT);
translatableRewriter.registerTabList(ClientboundPackets1_21_2.TAB_LIST);
translatableRewriter.registerPlayerCombatKill1_20(ClientboundPackets1_21_2.PLAYER_COMBAT_KILL);
translatableRewriter.registerComponentPacket(ClientboundPackets1_21_2.SYSTEM_CHAT);
translatableRewriter.registerComponentPacket(ClientboundPackets1_21_2.DISGUISED_CHAT);
translatableRewriter.registerPing();
registerServerbound(ServerboundPackets1_20_5.CLIENT_INFORMATION, this::clientInformation);
registerServerbound(ServerboundConfigurationPackets1_20_5.CLIENT_INFORMATION, this::clientInformation);
registerClientbound(ClientboundConfigurationPackets1_21.UPDATE_ENABLED_FEATURES, wrapper -> {
final String[] enabledFeatures = wrapper.read(Types.STRING_ARRAY);
wrapper.write(Types.STRING_ARRAY, ArrayUtil.add(enabledFeatures, "bundle"));
});
cancelClientbound(ClientboundPackets1_21_2.MOVE_MINECART_ALONG_TRACK); // TODO
registerClientbound(State.LOGIN, ClientboundLoginPackets.LOGIN_FINISHED, wrapper -> {
wrapper.passthrough(Types.UUID); // UUID
wrapper.passthrough(Types.STRING); // Name
final int properties = wrapper.passthrough(Types.VAR_INT);
for (int i = 0; i < properties; i++) {
wrapper.passthrough(Types.STRING); // Name
wrapper.passthrough(Types.STRING); // Value
wrapper.passthrough(Types.OPTIONAL_STRING); // Signature
}
wrapper.write(Types.BOOLEAN, true); // Strict error handling. Always enabled for newer clients, so mimic that behavior
});
registerClientbound(ClientboundPackets1_21_2.SET_TIME, wrapper -> {
wrapper.passthrough(Types.LONG); // Game time
long dayTime = wrapper.read(Types.LONG);
final boolean daylightCycle = wrapper.read(Types.BOOLEAN);
if (!daylightCycle) {
if (dayTime == 0) {
dayTime = -1;
} else {
dayTime = -dayTime;
}
}
wrapper.write(Types.LONG, dayTime);
});
}
private void storeTags(final PacketWrapper wrapper) {
tagRewriter.handleGeneric(wrapper);
wrapper.resetReader();
wrapper.user().get(ItemTagStorage.class).readItemTags(wrapper);
}
private void clientInformation(final PacketWrapper wrapper) {
wrapper.passthrough(Types.STRING); // Locale
wrapper.passthrough(Types.BYTE); // View distance
wrapper.passthrough(Types.VAR_INT); // Chat visibility
wrapper.passthrough(Types.BOOLEAN); // Chat colors
wrapper.passthrough(Types.UNSIGNED_BYTE); // Skin parts
wrapper.passthrough(Types.VAR_INT); // Main hand
wrapper.passthrough(Types.BOOLEAN); // Text filtering enabled
wrapper.passthrough(Types.BOOLEAN); // Allow listing
wrapper.write(Types.VAR_INT, 0); // Particle status, assume 'all'
}
@Override
public void init(final UserConnection user) {
addEntityTracker(user, new EntityTrackerBase(user, EntityTypes1_20_5.PLAYER));
user.put(new InventoryStateIdStorage());
user.put(new ItemTagStorage());
user.put(new RecipeStorage(this));
user.put(new PlayerStorage());
}
@Override
public BackwardsMappingData getMappingData() {
return MAPPINGS;
}
@Override
public EntityPacketRewriter1_21_2 getEntityRewriter() {
return entityRewriter;
}
@Override
public BlockItemPacketRewriter1_21_2 getItemRewriter() {
return itemRewriter;
}
@Override
public ParticleRewriter1_21_2 getParticleRewriter() {
return particleRewriter;
}
@Override
public TranslatableRewriter<ClientboundPacket1_21_2> getComponentRewriter() {
return translatableRewriter;
}
@Override
public TagRewriter<ClientboundPacket1_21_2> getTagRewriter() {
return tagRewriter;
}
@Override
protected PacketTypesProvider<ClientboundPacket1_21_2, ClientboundPacket1_21, ServerboundPacket1_21_2, ServerboundPacket1_20_5> createPacketTypesProvider() {
return new SimplePacketTypesProvider<>(
packetTypeMap(unmappedClientboundPacketType, ClientboundPackets1_21_2.class, ClientboundConfigurationPackets1_21.class),
packetTypeMap(mappedClientboundPacketType, ClientboundPackets1_21.class, ClientboundConfigurationPackets1_21.class),
packetTypeMap(mappedServerboundPacketType, ServerboundPackets1_21_2.class, ServerboundConfigurationPackets1_20_5.class),
packetTypeMap(unmappedServerboundPacketType, ServerboundPackets1_20_5.class, ServerboundConfigurationPackets1_20_5.class)
);
}
}
@@ -0,0 +1,580 @@
/*
* This file is part of ViaBackwards - https://github.com/ViaVersion/ViaBackwards
* Copyright (C) 2016-2024 ViaVersion and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.viaversion.viabackwards.protocol.v1_21_2to1_21.rewriter;
import com.viaversion.nbt.tag.ByteTag;
import com.viaversion.nbt.tag.CompoundTag;
import com.viaversion.nbt.tag.FloatTag;
import com.viaversion.nbt.tag.IntTag;
import com.viaversion.nbt.tag.ListTag;
import com.viaversion.nbt.tag.Tag;
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.viaversion.api.connection.UserConnection;
import com.viaversion.viaversion.api.data.MappingData;
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.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.Consumable1_21_2;
import com.viaversion.viaversion.api.minecraft.item.data.DeathProtection;
import com.viaversion.viaversion.api.minecraft.item.data.Equippable;
import com.viaversion.viaversion.api.minecraft.item.data.FoodProperties1_20_5;
import com.viaversion.viaversion.api.minecraft.item.data.Instrument1_21_2;
import com.viaversion.viaversion.api.minecraft.item.data.PotionEffect;
import com.viaversion.viaversion.api.minecraft.item.data.PotionEffectData;
import com.viaversion.viaversion.api.minecraft.item.data.UseCooldown;
import com.viaversion.viaversion.api.protocol.packet.PacketWrapper;
import com.viaversion.viaversion.api.type.Types;
import com.viaversion.viaversion.api.type.types.chunk.ChunkType1_20_2;
import com.viaversion.viaversion.api.type.types.version.Types1_21;
import com.viaversion.viaversion.api.type.types.version.Types1_21_2;
import com.viaversion.viaversion.protocols.v1_20_3to1_20_5.packet.ServerboundPacket1_20_5;
import com.viaversion.viaversion.protocols.v1_20_3to1_20_5.packet.ServerboundPackets1_20_5;
import com.viaversion.viaversion.protocols.v1_20_5to1_21.packet.ClientboundPackets1_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.BlockRewriter;
import com.viaversion.viaversion.rewriter.SoundRewriter;
import com.viaversion.viaversion.util.Key;
import com.viaversion.viaversion.util.Limit;
import com.viaversion.viaversion.util.Unit;
import static com.viaversion.viaversion.protocols.v1_21to1_21_2.rewriter.BlockItemPacketRewriter1_21_2.downgradeItemData;
import static com.viaversion.viaversion.protocols.v1_21to1_21_2.rewriter.BlockItemPacketRewriter1_21_2.updateItemData;
public final class BlockItemPacketRewriter1_21_2 extends BackwardsStructuredItemRewriter<ClientboundPacket1_21_2, ServerboundPacket1_20_5, Protocol1_21_2To1_21> {
public BlockItemPacketRewriter1_21_2(final Protocol1_21_2To1_21 protocol) {
super(protocol,
Types1_21_2.ITEM, Types1_21_2.ITEM_ARRAY, Types1_21.ITEM, Types1_21.ITEM_ARRAY,
Types1_21_2.ITEM_COST, Types1_21_2.OPTIONAL_ITEM_COST, Types1_21.ITEM_COST, Types1_21.OPTIONAL_ITEM_COST
);
}
@Override
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);
registerSetEquipment(ClientboundPackets1_21_2.SET_EQUIPMENT);
registerMerchantOffers1_20_5(ClientboundPackets1_21_2.MERCHANT_OFFERS);
registerSetCreativeModeSlot(ServerboundPackets1_20_5.SET_CREATIVE_MODE_SLOT);
protocol.registerClientbound(ClientboundPackets1_21_2.COOLDOWN, wrapper -> {
final MappingData mappingData = protocol.getMappingData();
final String itemIdentifier = wrapper.read(Types.STRING);
final int id = mappingData.getFullItemMappings().id(itemIdentifier);
if (id != -1) {
final int mappedId = mappingData.getFullItemMappings().getNewId(id);
wrapper.write(Types.VAR_INT, mappedId);
} else {
wrapper.cancel();
}
});
protocol.registerClientbound(ClientboundPackets1_21_2.SET_CURSOR_ITEM, ClientboundPackets1_21.CONTAINER_SET_SLOT, wrapper -> {
wrapper.write(Types.UNSIGNED_BYTE, (short) -1); // Player inventory
wrapper.write(Types.VAR_INT, wrapper.user().get(InventoryStateIdStorage.class).stateId()); // State id; re-use the last known one
wrapper.write(Types.SHORT, (short) -1); // Cursor
passthroughClientboundItem(wrapper);
});
protocol.registerClientbound(ClientboundPackets1_21_2.OPEN_SCREEN, wrapper -> {
wrapper.passthrough(Types.VAR_INT); // Id
final int containerType = wrapper.passthrough(Types.VAR_INT);
if (containerType == 21) {
// Track smithing table to remove new data
wrapper.user().get(InventoryStateIdStorage.class).setSmithingTableOpen(true);
}
protocol.getComponentRewriter().passthroughAndProcess(wrapper);
});
protocol.registerClientbound(ClientboundPackets1_21_2.CONTAINER_SET_CONTENT, wrapper -> {
updateContainerId(wrapper);
final int stateId = wrapper.passthrough(Types.VAR_INT);
wrapper.user().get(InventoryStateIdStorage.class).setStateId(stateId);
final Item[] items = wrapper.read(itemArrayType());
wrapper.write(mappedItemArrayType(), items);
for (int i = 0; i < items.length; i++) {
items[i] = handleItemToClient(wrapper.user(), items[i]);
}
passthroughClientboundItem(wrapper);
});
protocol.registerClientbound(ClientboundPackets1_21_2.CONTAINER_SET_SLOT, wrapper -> {
updateContainerId(wrapper);
final int stateId = wrapper.passthrough(Types.VAR_INT);
wrapper.user().get(InventoryStateIdStorage.class).setStateId(stateId);
wrapper.passthrough(Types.SHORT); // Slot id
passthroughClientboundItem(wrapper);
});
protocol.registerClientbound(ClientboundPackets1_21_2.CONTAINER_SET_DATA, wrapper -> {
updateContainerId(wrapper);
if (wrapper.user().get(InventoryStateIdStorage.class).smithingTableOpen()) {
// Cancel new data for smithing table
wrapper.cancel();
}
});
protocol.registerClientbound(ClientboundPackets1_21_2.CONTAINER_CLOSE, wrapper -> {
updateContainerId(wrapper);
wrapper.user().get(InventoryStateIdStorage.class).setSmithingTableOpen(false);
});
protocol.registerClientbound(ClientboundPackets1_21_2.SET_HELD_SLOT, ClientboundPackets1_21.SET_CARRIED_ITEM);
protocol.registerClientbound(ClientboundPackets1_21_2.HORSE_SCREEN_OPEN, this::updateContainerId);
protocol.registerServerbound(ServerboundPackets1_20_5.CONTAINER_CLOSE, wrapper -> {
updateContainerIdServerbound(wrapper);
wrapper.user().get(InventoryStateIdStorage.class).setSmithingTableOpen(false);
});
protocol.registerServerbound(ServerboundPackets1_20_5.CONTAINER_CLICK, wrapper -> {
updateContainerIdServerbound(wrapper);
wrapper.passthrough(Types.VAR_INT); // State id
wrapper.passthrough(Types.SHORT); // Slot
wrapper.passthrough(Types.BYTE); // Button
wrapper.passthrough(Types.VAR_INT); // Mode
final int length = Limit.max(wrapper.passthrough(Types.VAR_INT), 128);
for (int i = 0; i < length; i++) {
wrapper.passthrough(Types.SHORT); // Slot
passthroughServerboundItem(wrapper);
}
passthroughServerboundItem(wrapper);
});
protocol.registerServerbound(ServerboundPackets1_20_5.USE_ITEM_ON, wrapper -> {
wrapper.passthrough(Types.VAR_INT); // Hand
wrapper.passthrough(Types.BLOCK_POSITION1_14); // Block position
wrapper.passthrough(Types.VAR_INT); // Direction
wrapper.passthrough(Types.FLOAT); // X
wrapper.passthrough(Types.FLOAT); // Y
wrapper.passthrough(Types.FLOAT); // Z
wrapper.passthrough(Types.BOOLEAN); // Inside
wrapper.write(Types.BOOLEAN, false); // World border hit
});
protocol.registerClientbound(ClientboundPackets1_21_2.SET_PLAYER_INVENTORY, ClientboundPackets1_21.CONTAINER_SET_SLOT, wrapper -> {
wrapper.write(Types.UNSIGNED_BYTE, (short) -2); // Player inventory
wrapper.write(Types.VAR_INT, 0); // 0 state id
final int slot = wrapper.read(Types.VAR_INT);
wrapper.write(Types.SHORT, (short) slot);
passthroughClientboundItem(wrapper);
});
protocol.registerClientbound(ClientboundPackets1_21_2.EXPLODE, wrapper -> {
wrapper.passthrough(Types.DOUBLE); // Center X
wrapper.passthrough(Types.DOUBLE); // Center Y
wrapper.passthrough(Types.DOUBLE); // Center Z
// The server will already send block changes separately
wrapper.write(Types.FLOAT, 0F); // Power
wrapper.write(Types.VAR_INT, 0); // No blocks affected
double knockbackX = 0;
double knockbackY = 0;
double knockbackZ = 0;
if (wrapper.read(Types.BOOLEAN)) {
knockbackX = wrapper.read(Types.DOUBLE);
knockbackY = wrapper.read(Types.DOUBLE);
knockbackZ = wrapper.read(Types.DOUBLE);
}
wrapper.write(Types.FLOAT, (float) knockbackX);
wrapper.write(Types.FLOAT, (float) knockbackY);
wrapper.write(Types.FLOAT, (float) knockbackZ);
wrapper.write(Types.VAR_INT, 0); // Block interaction type
final Particle explosionParticle = wrapper.read(Types1_21.PARTICLE);
protocol.getParticleRewriter().rewriteParticle(wrapper.user(), explosionParticle);
// As small and large explosion particle
wrapper.write(Types1_21_2.PARTICLE, explosionParticle);
wrapper.write(Types1_21_2.PARTICLE, explosionParticle);
new SoundRewriter<>(protocol).soundHolderHandler().handle(wrapper);
});
protocol.registerClientbound(ClientboundPackets1_21_2.RECIPE_BOOK_ADD, null, wrapper -> {
final RecipeStorage recipeStorage = wrapper.user().get(RecipeStorage.class);
final int size = wrapper.read(Types.VAR_INT);
for (int i = 0; i < size; i++) {
recipeStorage.readRecipe(wrapper);
}
final boolean replace = wrapper.read(Types.BOOLEAN);
if (replace) {
recipeStorage.clearRecipes();
}
recipeStorage.sendRecipes(wrapper.user());
wrapper.cancel();
});
protocol.registerClientbound(ClientboundPackets1_21_2.RECIPE_BOOK_REMOVE, ClientboundPackets1_21.RECIPE, wrapper -> {
final RecipeStorage recipeStorage = wrapper.user().get(RecipeStorage.class);
final int[] ids = wrapper.read(Types.VAR_INT_ARRAY_PRIMITIVE);
recipeStorage.lockRecipes(wrapper, ids);
});
protocol.registerClientbound(ClientboundPackets1_21_2.RECIPE_BOOK_SETTINGS, null, wrapper -> {
final RecipeStorage recipeStorage = wrapper.user().get(RecipeStorage.class);
final boolean[] settings = new boolean[RecipeStorage.RECIPE_BOOK_SETTINGS];
for (int i = 0; i < RecipeStorage.RECIPE_BOOK_SETTINGS; i++) {
settings[i] = wrapper.read(Types.BOOLEAN);
}
recipeStorage.setRecipeBookSettings(settings);
wrapper.cancel();
});
protocol.registerClientbound(ClientboundPackets1_21_2.UPDATE_RECIPES, wrapper -> {
// Inputs for furnaces etc. Old clients get these from the full recipes
final int size = wrapper.passthrough(Types.VAR_INT);
for (int i = 0; i < size; i++) {
wrapper.read(Types.STRING); // Recipe group
wrapper.read(Types.VAR_INT_ARRAY_PRIMITIVE); // Items
}
final RecipeStorage recipeStorage = wrapper.user().get(RecipeStorage.class);
recipeStorage.readStoneCutterRecipes(wrapper);
// Send later with the recipe book init
wrapper.cancel();
});
protocol.registerClientbound(ClientboundPackets1_21_2.PLACE_GHOST_RECIPE, wrapper -> {
this.updateContainerId(wrapper);
wrapper.cancel(); // Full recipe display, this doesn't look mappable
});
protocol.registerServerbound(ServerboundPackets1_20_5.PLACE_RECIPE, wrapper -> {
this.updateContainerIdServerbound(wrapper);
final String recipe = Key.stripMinecraftNamespace(wrapper.read(Types.STRING));
wrapper.write(Types.VAR_INT, Integer.parseInt(recipe));
});
protocol.registerServerbound(ServerboundPackets1_20_5.RECIPE_BOOK_SEEN_RECIPE, wrapper -> {
final String recipe = Key.stripMinecraftNamespace(wrapper.read(Types.STRING));
wrapper.write(Types.VAR_INT, Integer.parseInt(recipe));
});
}
private void updateContainerId(final PacketWrapper wrapper) {
final int containerId = wrapper.read(Types.VAR_INT);
wrapper.write(Types.UNSIGNED_BYTE, (short) containerId);
}
private void updateContainerIdServerbound(final PacketWrapper wrapper) {
final short containerId = wrapper.read(Types.UNSIGNED_BYTE);
final int intId = (byte) containerId;
wrapper.write(Types.VAR_INT, intId);
}
@Override
public Item handleItemToClient(final UserConnection connection, final Item item) {
backupInconvertibleData(item);
super.handleItemToClient(connection, item);
downgradeItemData(item);
return item;
}
@Override
public Item handleItemToServer(final UserConnection connection, final Item item) {
super.handleItemToServer(connection, item);
// Handle food properties item manually here - the only protocol that has it
// The other way around it's handled by the super handleItemToClient method
final StructuredDataContainer data = item.dataContainer();
final FoodProperties1_20_5 food = data.get(StructuredDataKey.FOOD1_21);
if (food != null && food.usingConvertsTo() != null) {
this.handleItemToServer(connection, food.usingConvertsTo());
}
updateItemData(item);
restoreInconvertibleData(item);
return item;
}
// Backup inconvertible data and later restore to prevent data loss for creative mode clients
private void backupInconvertibleData(final Item item) {
final StructuredDataContainer data = item.dataContainer();
data.setIdLookup(protocol, true);
final CompoundTag backupTag = new CompoundTag();
final Holder<Instrument1_21_2> instrument = data.get(StructuredDataKey.INSTRUMENT1_21_2);
if (instrument != null && instrument.isDirect()) {
backupTag.put("instrument_description", instrument.value().description());
}
final HolderSet repairable = data.get(StructuredDataKey.REPAIRABLE);
if (repairable != null) {
backupTag.put("repairable", holderSetToTag(repairable));
}
final Integer enchantable = data.get(StructuredDataKey.ENCHANTABLE);
if (enchantable != null) {
backupTag.putInt("enchantable", enchantable);
}
final UseCooldown useCooldown = data.get(StructuredDataKey.USE_COOLDOWN);
if (useCooldown != null) {
final CompoundTag tag = new CompoundTag();
tag.putFloat("seconds", useCooldown.seconds());
if (useCooldown.cooldownGroup() != null) {
tag.putString("cooldown_group", useCooldown.cooldownGroup());
}
backupTag.put("use_cooldown", tag);
}
final String itemModel = data.get(StructuredDataKey.ITEM_MODEL);
if (itemModel != null) {
backupTag.putString("item_model", itemModel);
}
final Equippable equippable = data.get(StructuredDataKey.EQUIPPABLE);
if (equippable != null) {
final CompoundTag tag = new CompoundTag();
tag.putInt("equipment_slot", equippable.equipmentSlot());
convertSoundEventHolder(tag, equippable.soundEvent());
final String model = equippable.model();
if (model != null) {
tag.putString("model", model);
}
final String cameraOverlay = equippable.cameraOverlay();
if (cameraOverlay != null) {
tag.putString("camera_overlay", cameraOverlay);
}
if (equippable.allowedEntities() != null) {
tag.put("allowed_entities", holderSetToTag(equippable.allowedEntities()));
}
tag.putBoolean("dispensable", equippable.dispensable());
tag.putBoolean("swappable", equippable.swappable());
tag.putBoolean("damage_on_hurt", equippable.damageOnHurt());
backupTag.put("equippable", tag);
}
final Unit glider = data.get(StructuredDataKey.GLIDER);
if (glider != null) {
backupTag.putBoolean("glider", true);
}
final String tooltipStyle = data.get(StructuredDataKey.TOOLTIP_STYLE);
if (tooltipStyle != null) {
backupTag.putString("tooltip_style", tooltipStyle);
}
final DeathProtection deathProtection = data.get(StructuredDataKey.DEATH_PROTECTION);
if (deathProtection != null) {
final ListTag<CompoundTag> tag = new ListTag<>(CompoundTag.class);
for (final Consumable1_21_2.ConsumeEffect<?> effect : deathProtection.deathEffects()) {
final CompoundTag effectTag = new CompoundTag();
convertConsumableEffect(effectTag, effect);
tag.add(effectTag);
}
backupTag.put("death_protection", tag);
}
if (!backupTag.isEmpty()) {
saveTag(createCustomTag(item), backupTag, "inconvertible_data");
}
}
private void convertConsumableEffect(final CompoundTag tag, Consumable1_21_2.ConsumeEffect<?> effect) {
tag.putInt("id", effect.id());
if (effect.type() == Consumable1_21_2.ApplyStatusEffects.TYPE && effect.value() instanceof Consumable1_21_2.ApplyStatusEffects value) {
tag.putString("type", "apply_effects");
final ListTag<CompoundTag> effects = new ListTag<>(CompoundTag.class);
for (final PotionEffect potionEffect : value.effects()) {
final CompoundTag effectTag = new CompoundTag();
effectTag.putInt("effect", potionEffect.effect());
convertPotionEffectData(effectTag, potionEffect.effectData());
effects.add(effectTag);
}
tag.put("effects", effects);
tag.putFloat("probability", value.probability());
} else if (effect.type() == Types.HOLDER_SET && effect.value() instanceof HolderSet set) {
tag.putString("type", "remove_effects");
tag.put("remove_effects", holderSetToTag(set));
} else if (effect.type() == Types.EMPTY) {
tag.putString("type", "clear_all_effects");
} else if (effect.type() == Types.FLOAT) {
tag.putString("type", "teleport_randomly");
tag.putFloat("probability", (Float) effect.value());
} else if (effect.type() == Types.SOUND_EVENT && effect.value() instanceof Holder sound) {
tag.putString("type", "play_sound");
convertSoundEventHolder(tag, sound);
}
}
private void convertPotionEffectData(final CompoundTag tag, final PotionEffectData data) {
tag.putInt("amplifier", data.amplifier());
tag.putInt("duration", data.duration());
tag.putBoolean("ambient", data.ambient());
tag.putBoolean("show_particles", data.showParticles());
tag.putBoolean("show_icon", data.showIcon());
if (data.hiddenEffect() != null) {
final CompoundTag hiddenEffect = new CompoundTag();
convertPotionEffectData(hiddenEffect, data.hiddenEffect());
tag.put("hidden_effect", hiddenEffect);
}
}
private void convertSoundEventHolder(final CompoundTag tag, final Holder<SoundEvent> holder) {
tag.put("sound_event", holderToTag(holder, (event, soundEventTag) -> {
soundEventTag.putString("identifier", event.identifier());
if (event.fixedRange() != null) {
soundEventTag.putFloat("fixed_range", event.fixedRange());
}
}));
}
private Consumable1_21_2.ConsumeEffect<?> convertConsumableEffect(final CompoundTag tag) {
final int id = tag.getInt("id");
final String type = tag.getString("type");
if ("apply_effects".equals(type)) {
final ListTag<CompoundTag> effects = tag.getListTag("effects", CompoundTag.class);
final PotionEffect[] potionEffects = new PotionEffect[effects.size()];
for (int i = 0; i < effects.size(); i++) {
final CompoundTag effectTag = effects.get(i);
final int effect = effectTag.getInt("effect");
final PotionEffectData data = convertPotionEffectData(effectTag.getCompoundTag("data"));
potionEffects[i] = new PotionEffect(effect, data);
}
final float probability = tag.getFloat("probability");
return new Consumable1_21_2.ConsumeEffect<>(id, Consumable1_21_2.ApplyStatusEffects.TYPE, new Consumable1_21_2.ApplyStatusEffects(potionEffects, probability));
} else if ("remove_effects".equals(type)) {
final HolderSet set = restoreHolderSet(tag, "remove_effects");
return new Consumable1_21_2.ConsumeEffect<>(id, Types.HOLDER_SET, set);
} else if ("clear_all_effects".equals(type)) {
return new Consumable1_21_2.ConsumeEffect<>(id, Types.EMPTY, Unit.INSTANCE);
} else if ("teleport_randomly".equals(type)) {
final float probability = tag.getFloat("probability");
return new Consumable1_21_2.ConsumeEffect<>(id, Types.FLOAT, probability);
} else if ("play_sound".equals(type)) {
final Holder<SoundEvent> sound = convertSoundEventHolder(tag);
return new Consumable1_21_2.ConsumeEffect<>(id, Types.SOUND_EVENT, sound);
}
return null;
}
private PotionEffectData convertPotionEffectData(final CompoundTag tag) {
final int amplifier = tag.getInt("amplifier");
final int duration = tag.getInt("duration");
final boolean ambient = tag.getBoolean("ambient");
final boolean showParticles = tag.getBoolean("show_particles");
final boolean showIcon = tag.getBoolean("show_icon");
final CompoundTag hiddenEffect = tag.getCompoundTag("hidden_effect");
return new PotionEffectData(amplifier, duration, ambient, showParticles, showIcon, hiddenEffect != null ? convertPotionEffectData(hiddenEffect) : null);
}
private Holder<SoundEvent> convertSoundEventHolder(final CompoundTag tag) {
return restoreHolder(tag, "sound_event", soundEventTag -> {
final String identifier = soundEventTag.getString("identifier");
final FloatTag fixedRange = soundEventTag.getFloatTag("fixed_range");
return new SoundEvent(identifier, fixedRange != null ? fixedRange.asFloat() : null);
});
}
private void restoreInconvertibleData(final Item item) {
final StructuredDataContainer data = item.dataContainer();
final CompoundTag customData = data.get(StructuredDataKey.CUSTOM_DATA);
if (customData == null || !(customData.remove(nbtTagName("inconvertible_data")) instanceof CompoundTag backupTag)) {
return;
}
final Holder<Instrument1_21_2> instrument = data.get(StructuredDataKey.INSTRUMENT1_21_2);
if (instrument != null && instrument.isDirect()) {
final Tag description = backupTag.get("instrument_description");
if (description != null) {
final Instrument1_21_2 delegate = instrument.value();
data.set(StructuredDataKey.INSTRUMENT1_21_2, Holder.of(new Instrument1_21_2(delegate.soundEvent(), delegate.useDuration(), delegate.range(), description)));
}
}
if (backupTag.contains("repairable")) {
data.set(StructuredDataKey.REPAIRABLE, restoreHolderSet(backupTag, "repairable"));
}
final IntTag enchantable = backupTag.getIntTag("enchantable");
if (enchantable != null) {
data.set(StructuredDataKey.ENCHANTABLE, enchantable.asInt());
}
final CompoundTag useCooldown = backupTag.getCompoundTag("use_cooldown");
if (useCooldown != null) {
final float seconds = useCooldown.getFloat("seconds");
final String cooldownGroup = useCooldown.getString("cooldown_group");
data.set(StructuredDataKey.USE_COOLDOWN, new UseCooldown(seconds, cooldownGroup));
}
final String itemModel = backupTag.getString("item_model");
if (itemModel != null) {
data.set(StructuredDataKey.ITEM_MODEL, itemModel);
}
final CompoundTag equippable = backupTag.getCompoundTag("equippable");
if (equippable != null) {
final int equipmentSlot = equippable.getInt("equipment_slot");
final Holder<SoundEvent> soundEvent = convertSoundEventHolder(equippable);
final String model = equippable.getString("model");
final String cameraOverlay = equippable.getString("camera_overlay");
final HolderSet allowedEntities = equippable.contains("allowed_entities") ? restoreHolderSet(equippable, "allowed_entities") : null;
final boolean dispensable = equippable.getBoolean("dispensable");
final boolean swappable = equippable.getBoolean("swappable");
final boolean damageOnHurt = equippable.getBoolean("damage_on_hurt");
data.set(StructuredDataKey.EQUIPPABLE, new Equippable(equipmentSlot, soundEvent, model, cameraOverlay, allowedEntities, dispensable, swappable, damageOnHurt));
}
final ByteTag glider = backupTag.getByteTag("glider");
if (glider != null) {
data.set(StructuredDataKey.GLIDER, Unit.INSTANCE);
}
final String tooltipStyle = backupTag.getString("tooltip_style");
if (tooltipStyle != null) {
data.set(StructuredDataKey.TOOLTIP_STYLE, tooltipStyle);
}
final ListTag<CompoundTag> deathProtection = backupTag.getListTag("death_protection", CompoundTag.class);
if (deathProtection != null) {
final Consumable1_21_2.ConsumeEffect<?>[] effects = new Consumable1_21_2.ConsumeEffect[deathProtection.size()];
for (int i = 0; i < deathProtection.size(); i++) {
effects[i] = convertConsumableEffect(deathProtection.get(i));
}
data.set(StructuredDataKey.DEATH_PROTECTION, new DeathProtection(effects));
}
removeCustomTag(data, customData);
}
}
@@ -0,0 +1,75 @@
/*
* This file is part of ViaVersion - https://github.com/ViaVersion/ViaVersion
* Copyright (C) 2016-2024 ViaVersion and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.viaversion.viabackwards.protocol.v1_21_2to1_21.rewriter;
import com.viaversion.nbt.tag.CompoundTag;
import com.viaversion.viabackwards.api.rewriters.TranslatableRewriter;
import com.viaversion.viabackwards.protocol.v1_21_2to1_21.Protocol1_21_2To1_21;
import com.viaversion.viaversion.api.connection.UserConnection;
import com.viaversion.viaversion.protocols.v1_21to1_21_2.packet.ClientboundPacket1_21_2;
import com.viaversion.viaversion.util.SerializerVersion;
import com.viaversion.viaversion.util.TagUtil;
public final class ComponentRewriter1_21_2 extends TranslatableRewriter<ClientboundPacket1_21_2> {
public ComponentRewriter1_21_2(final Protocol1_21_2To1_21 protocol) {
super(protocol, ReadType.NBT);
}
@Override
protected void handleShowItem(final UserConnection connection, final CompoundTag itemTag, final CompoundTag componentsTag) {
super.handleShowItem(connection, itemTag, componentsTag);
if (componentsTag == null) {
return;
}
com.viaversion.viaversion.protocols.v1_21to1_21_2.rewriter.ComponentRewriter1_21_2.convertAttributes(componentsTag, protocol.getMappingData().getAttributeMappings());
final CompoundTag instrument = TagUtil.getNamespacedCompoundTag(componentsTag, "instrument");
if (instrument != null) {
instrument.remove("description");
}
final CompoundTag useRemainder = TagUtil.getNamespacedCompoundTag(componentsTag, "use_remainder");
final CompoundTag food = TagUtil.getNamespacedCompoundTag(componentsTag, "food");
if (food != null) {
if (useRemainder != null) {
food.put("using_converts_to", useRemainder);
}
food.putFloat("eat_seconds", 1.6F);
}
TagUtil.removeNamespaced(componentsTag, "repairable");
TagUtil.removeNamespaced(componentsTag, "enchantable");
TagUtil.removeNamespaced(componentsTag, "consumable");
TagUtil.removeNamespaced(componentsTag, "use_remainder");
TagUtil.removeNamespaced(componentsTag, "use_cooldown");
TagUtil.removeNamespaced(componentsTag, "item_model");
TagUtil.removeNamespaced(componentsTag, "equippable");
TagUtil.removeNamespaced(componentsTag, "glider");
TagUtil.removeNamespaced(componentsTag, "tooltip_style");
TagUtil.removeNamespaced(componentsTag, "death_protection");
TagUtil.removeNamespaced(componentsTag, "damage_resistant");
TagUtil.removeNamespaced(componentsTag, "lock");
}
@Override
protected SerializerVersion inputSerializerVersion() {
return SerializerVersion.V1_20_5;
}
}
@@ -0,0 +1,660 @@
/*
* This file is part of ViaBackwards - https://github.com/ViaVersion/ViaBackwards
* Copyright (C) 2016-2024 ViaVersion and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.viaversion.viabackwards.protocol.v1_21_2to1_21.rewriter;
import com.viaversion.nbt.tag.CompoundTag;
import com.viaversion.nbt.tag.FloatTag;
import com.viaversion.nbt.tag.IntTag;
import com.viaversion.nbt.tag.ListTag;
import com.viaversion.nbt.tag.Tag;
import com.viaversion.viabackwards.ViaBackwards;
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.viaversion.api.minecraft.Holder;
import com.viaversion.viaversion.api.minecraft.Particle;
import com.viaversion.viaversion.api.minecraft.RegistryEntry;
import com.viaversion.viaversion.api.minecraft.SoundEvent;
import com.viaversion.viaversion.api.minecraft.entities.EntityType;
import com.viaversion.viaversion.api.minecraft.entities.EntityTypes1_21_2;
import com.viaversion.viaversion.api.minecraft.entitydata.EntityData;
import com.viaversion.viaversion.api.protocol.packet.PacketWrapper;
import com.viaversion.viaversion.api.protocol.remapper.PacketHandlers;
import com.viaversion.viaversion.api.type.Types;
import com.viaversion.viaversion.api.type.types.version.Types1_21;
import com.viaversion.viaversion.api.type.types.version.Types1_21_2;
import com.viaversion.viaversion.protocols.v1_20_3to1_20_5.packet.ServerboundPackets1_20_5;
import com.viaversion.viaversion.protocols.v1_20_5to1_21.packet.ClientboundConfigurationPackets1_21;
import com.viaversion.viaversion.protocols.v1_20_5to1_21.packet.ClientboundPackets1_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.protocols.v1_21to1_21_2.packet.ServerboundPackets1_21_2;
import com.viaversion.viaversion.protocols.v1_21to1_21_2.storage.ClientVehicleStorage;
import com.viaversion.viaversion.rewriter.RegistryDataRewriter;
import com.viaversion.viaversion.util.Key;
import java.util.ArrayList;
import java.util.BitSet;
import java.util.List;
import org.checkerframework.checker.nullness.qual.Nullable;
public final class EntityPacketRewriter1_21_2 extends EntityRewriter<ClientboundPacket1_21_2, Protocol1_21_2To1_21> {
private static final int REL_X = 0;
private static final int REL_Y = 1;
private static final int REL_Z = 2;
private static final int REL_Y_ROT = 3;
private static final int REL_X_ROT = 4;
private static final int REL_DELTA_X = 5;
private static final int REL_DELTA_Y = 6;
private static final int REL_DELTA_Z = 7;
private static final int REL_ROTATE_DELTA = 8;
private boolean warned = ViaBackwards.getConfig().suppressEmulationWarnings();
public EntityPacketRewriter1_21_2(final Protocol1_21_2To1_21 protocol) {
super(protocol, Types1_21.ENTITY_DATA_TYPES.optionalComponentType, Types1_21.ENTITY_DATA_TYPES.booleanType);
}
@Override
public void registerPackets() {
registerSetEntityData(ClientboundPackets1_21_2.SET_ENTITY_DATA, Types1_21_2.ENTITY_DATA_LIST, Types1_21.ENTITY_DATA_LIST);
registerRemoveEntities(ClientboundPackets1_21_2.REMOVE_ENTITIES);
protocol.registerClientbound(ClientboundPackets1_21_2.ADD_ENTITY, wrapper -> {
final int entityId = wrapper.passthrough(Types.VAR_INT);
wrapper.passthrough(Types.UUID); // Entity UUID
final int entityTypeId = wrapper.passthrough(Types.VAR_INT);
wrapper.passthrough(Types.DOUBLE); // X
wrapper.passthrough(Types.DOUBLE); // Y
wrapper.passthrough(Types.DOUBLE); // Z
wrapper.passthrough(Types.BYTE); // Pitch
wrapper.passthrough(Types.BYTE); // Yaw
wrapper.passthrough(Types.BYTE); // Head yaw
wrapper.passthrough(Types.VAR_INT); // Data
getSpawnTrackerWithDataHandler1_19(EntityTypes1_21_2.FALLING_BLOCK).handle(wrapper);
final EntityType type = EntityTypes1_21_2.getTypeFromId(entityTypeId);
if (type.isOrHasParent(EntityTypes1_21_2.ABSTRACT_BOAT)) {
wrapper.send(Protocol1_21_2To1_21.class);
wrapper.cancel();
// Add boat type to entity data
final List<EntityData> data = new ArrayList<>();
final int boatType = type.isOrHasParent(EntityTypes1_21_2.ABSTRACT_CHEST_BOAT) ? chestBoatTypeFromEntityType(type) : boatTypeFromEntityType(type);
data.add(new EntityData(11, Types1_21.ENTITY_DATA_TYPES.varIntType, boatType));
final PacketWrapper entityDataPacket = wrapper.create(ClientboundPackets1_21.SET_ENTITY_DATA);
entityDataPacket.write(Types.VAR_INT, entityId);
entityDataPacket.write(Types1_21.ENTITY_DATA_LIST, data);
entityDataPacket.send(Protocol1_21_2To1_21.class);
}
});
final RegistryDataRewriter registryDataRewriter = new RegistryDataRewriter(protocol);
registryDataRewriter.addEnchantmentEffectRewriter("change_item_damage", tag -> tag.putString("type", "damage_item"));
protocol.registerClientbound(ClientboundConfigurationPackets1_21.REGISTRY_DATA, wrapper -> {
final String registryKey = Key.stripMinecraftNamespace(wrapper.passthrough(Types.STRING));
final RegistryEntry[] entries = wrapper.read(Types.REGISTRY_ENTRY_ARRAY);
if (registryKey.equals("instrument")) {
wrapper.cancel();
return;
}
if (registryKey.equals("worldgen/biome")) {
for (final RegistryEntry entry : entries) {
if (entry.tag() == null) {
continue;
}
final CompoundTag effects = ((CompoundTag) entry.tag()).getCompoundTag("effects");
final CompoundTag particle = effects.getCompoundTag("particle");
if (particle == null) {
continue;
}
final CompoundTag particleOptions = particle.getCompoundTag("options");
final String particleType = particleOptions.getString("type");
updateParticleFormat(particleOptions, Key.stripMinecraftNamespace(particleType));
}
}
wrapper.write(Types.REGISTRY_ENTRY_ARRAY, registryDataRewriter.handle(wrapper.user(), registryKey, entries));
});
protocol.registerClientbound(ClientboundPackets1_21_2.LOGIN, new PacketHandlers() {
@Override
public void register() {
map(Types.INT); // Entity id
map(Types.BOOLEAN); // Hardcore
map(Types.STRING_ARRAY); // World List
map(Types.VAR_INT); // Max players
map(Types.VAR_INT); // View distance
map(Types.VAR_INT); // Simulation distance
map(Types.BOOLEAN); // Reduced debug info
map(Types.BOOLEAN); // Show death screen
map(Types.BOOLEAN); // Limited crafting
map(Types.VAR_INT); // Dimension key
map(Types.STRING); // World
map(Types.LONG); // Seed
map(Types.BYTE); // Gamemode
map(Types.BYTE); // Previous gamemode
map(Types.BOOLEAN); // Debug
map(Types.BOOLEAN); // Flat
map(Types.OPTIONAL_GLOBAL_POSITION); // Last death location
map(Types.VAR_INT); // Portal cooldown
handler(worldDataTrackerHandlerByKey1_20_5(3));
handler(playerTrackerHandler());
read(Types.VAR_INT); // Sea level
}
});
protocol.registerClientbound(ClientboundPackets1_21_2.RESPAWN, wrapper -> {
final int dimensionId = wrapper.passthrough(Types.VAR_INT);
final String world = wrapper.passthrough(Types.STRING);
wrapper.passthrough(Types.LONG); // Seed
wrapper.passthrough(Types.BYTE); // Gamemode
wrapper.passthrough(Types.BYTE); // Previous gamemode
wrapper.passthrough(Types.BOOLEAN); // Debug
wrapper.passthrough(Types.BOOLEAN); // Flat
wrapper.passthrough(Types.OPTIONAL_GLOBAL_POSITION); // Last death location
wrapper.passthrough(Types.VAR_INT); // Portal cooldown
wrapper.read(Types.VAR_INT); // Sea level
trackWorldDataByKey1_20_5(wrapper.user(), dimensionId, world);
});
protocol.registerClientbound(ClientboundPackets1_21_2.ENTITY_POSITION_SYNC, ClientboundPackets1_21.TELEPORT_ENTITY, wrapper -> {
wrapper.passthrough(Types.VAR_INT); // Entity ID
wrapper.passthrough(Types.DOUBLE); // X
wrapper.passthrough(Types.DOUBLE); // Y
wrapper.passthrough(Types.DOUBLE); // Z
// Unused
wrapper.read(Types.DOUBLE); // Delta movement X
wrapper.read(Types.DOUBLE); // Delta movement Y
wrapper.read(Types.DOUBLE); // Delta movement Z
final float yaw = wrapper.read(Types.FLOAT);
final float pitch = wrapper.read(Types.FLOAT);
writePackedRotation(wrapper, yaw, pitch);
});
protocol.registerClientbound(ClientboundPackets1_21_2.PLAYER_ROTATION, ClientboundPackets1_21.PLAYER_LOOK_AT, wrapper -> {
final float yaw = wrapper.passthrough(Types.FLOAT);
final float pitch = wrapper.passthrough(Types.FLOAT);
final double yRadians = Math.toRadians(yaw);
final double xRadians = Math.toRadians(pitch);
final double factor = -Math.cos(-xRadians);
final double deltaX = Math.sin(-yRadians - (float) Math.PI) * factor;
final double deltaY = Math.sin(-xRadians);
final double deltaZ = Math.cos(-yRadians - (float) Math.PI) * factor;
final PlayerStorage storage = wrapper.user().get(PlayerStorage.class);
wrapper.write(Types.VAR_INT, 0); // From anchor
wrapper.write(Types.DOUBLE, storage.x() + deltaX); // X
wrapper.write(Types.DOUBLE, storage.y() + deltaY); // Y
wrapper.write(Types.DOUBLE, storage.z() + deltaZ); // Z
wrapper.write(Types.BOOLEAN, false); // At entity
final PacketWrapper entityMotionPacket = PacketWrapper.create(ServerboundPackets1_21_2.MOVE_PLAYER_ROT, wrapper.user());
entityMotionPacket.write(Types.FLOAT, yaw);
entityMotionPacket.write(Types.FLOAT, pitch);
entityMotionPacket.write(Types.UNSIGNED_BYTE, (short) 0); // On ground and horizontal collision
entityMotionPacket.sendToServer(Protocol1_21_2To1_21.class);
});
protocol.registerClientbound(ClientboundPackets1_21_2.TELEPORT_ENTITY, wrapper -> {
final int entityId = wrapper.passthrough(Types.VAR_INT);
final double x = wrapper.passthrough(Types.DOUBLE);
final double y = wrapper.passthrough(Types.DOUBLE);
final double z = wrapper.passthrough(Types.DOUBLE);
final double movementX = wrapper.read(Types.DOUBLE);
final double movementY = wrapper.read(Types.DOUBLE);
final double movementZ = wrapper.read(Types.DOUBLE);
final float yaw = wrapper.read(Types.FLOAT);
final float pitch = wrapper.read(Types.FLOAT);
writePackedRotation(wrapper, yaw, pitch);
final int relativeArguments = wrapper.read(Types.INT);
// Send alongside separate entity motion
wrapper.send(Protocol1_21_2To1_21.class);
wrapper.cancel();
handleRelativeArguments(wrapper, x, y, z, yaw, pitch, relativeArguments, movementX, movementY, movementZ, entityId);
});
protocol.registerClientbound(ClientboundPackets1_21_2.PLAYER_POSITION, wrapper -> {
final int teleportId = wrapper.read(Types.VAR_INT);
final double x = wrapper.passthrough(Types.DOUBLE);
final double y = wrapper.passthrough(Types.DOUBLE);
final double z = wrapper.passthrough(Types.DOUBLE);
final double movementX = wrapper.read(Types.DOUBLE);
final double movementY = wrapper.read(Types.DOUBLE);
final double movementZ = wrapper.read(Types.DOUBLE);
final float yaw = wrapper.passthrough(Types.FLOAT);
final float pitch = wrapper.passthrough(Types.FLOAT);
// Just keep the new values in there
final int relativeArguments = wrapper.read(Types.INT);
wrapper.write(Types.BYTE, (byte) relativeArguments);
wrapper.write(Types.VAR_INT, teleportId);
// Send alongside separate entity motion
wrapper.send(Protocol1_21_2To1_21.class);
wrapper.cancel();
handleRelativeArguments(wrapper, x, y, z, yaw, pitch, relativeArguments, movementX, movementY, movementZ, null);
});
protocol.registerServerbound(ServerboundPackets1_20_5.PLAYER_COMMAND, wrapper -> {
wrapper.passthrough(Types.VAR_INT);
final int action = wrapper.passthrough(Types.VAR_INT);
final PlayerStorage storage = wrapper.user().get(PlayerStorage.class);
if (action == 0) {
storage.setPlayerCommandTrackedSneaking(true);
} else if (action == 1) {
storage.setPlayerCommandTrackedSneaking(false);
} else if (action == 3) {
storage.setPlayerCommandTrackedSprinting(true);
} else if (action == 4) {
storage.setPlayerCommandTrackedSprinting(false);
}
});
// Now also sent by the player if not in a vehicle, but we can't emulate that here, and otherwise only used in predicates
protocol.registerServerbound(ServerboundPackets1_20_5.PLAYER_INPUT, wrapper -> {
final float sideways = wrapper.read(Types.FLOAT);
final float forward = wrapper.read(Types.FLOAT);
final byte flags = wrapper.read(Types.BYTE);
byte updatedFlags = 0;
if (forward > 0) {
updatedFlags |= 1;
} else if (forward < 0) {
updatedFlags |= 1 << 1;
}
if (sideways < 0) {
updatedFlags |= 1 << 2;
} else if (sideways > 0) {
updatedFlags |= 1 << 3;
}
if ((flags & 1) != 0) { // Jumping
updatedFlags |= 1 << 4;
}
final boolean sneaking = (flags & 2) != 0;
if (sneaking) {
updatedFlags |= 1 << 5;
}
// Sprinting we don't know...
wrapper.write(Types.BYTE, updatedFlags);
// Player input no longer sets the sneaking state on the server
// Send the change separately if needed (= when in a vehicle and player commands aren't sent by the old client)
final PlayerStorage sneakingStorage = wrapper.user().get(PlayerStorage.class);
if (sneakingStorage.setSneaking(sneaking)) {
final PacketWrapper playerCommandPacket = wrapper.create(ServerboundPackets1_21_2.PLAYER_COMMAND);
playerCommandPacket.write(Types.VAR_INT, tracker(wrapper.user()).clientEntityId());
playerCommandPacket.write(Types.VAR_INT, sneaking ? 0 : 1); // Start/stop sneaking
playerCommandPacket.write(Types.VAR_INT, 0); // Data
playerCommandPacket.sendToServer(Protocol1_21_2To1_21.class);
}
});
protocol.registerServerbound(ServerboundPackets1_20_5.MOVE_PLAYER_POS, wrapper -> {
final double x = wrapper.passthrough(Types.DOUBLE);
final double y = wrapper.passthrough(Types.DOUBLE);
final double z = wrapper.passthrough(Types.DOUBLE);
fixOnGround(wrapper);
final PlayerStorage storage = wrapper.user().get(PlayerStorage.class);
storage.setPosition(x, y, z);
});
protocol.registerServerbound(ServerboundPackets1_20_5.MOVE_PLAYER_POS_ROT, wrapper -> {
final double x = wrapper.passthrough(Types.DOUBLE);
final double y = wrapper.passthrough(Types.DOUBLE);
final double z = wrapper.passthrough(Types.DOUBLE);
final float yaw = wrapper.passthrough(Types.FLOAT);
final float pitch = wrapper.passthrough(Types.FLOAT);
fixOnGround(wrapper);
final PlayerStorage storage = wrapper.user().get(PlayerStorage.class);
storage.setPosition(x, y, z);
storage.setRotation(yaw, pitch);
});
protocol.registerServerbound(ServerboundPackets1_20_5.MOVE_PLAYER_ROT, wrapper -> {
final float yaw = wrapper.passthrough(Types.FLOAT);
final float pitch = wrapper.passthrough(Types.FLOAT);
fixOnGround(wrapper);
final PlayerStorage storage = wrapper.user().get(PlayerStorage.class);
storage.setRotation(yaw, pitch);
});
protocol.registerServerbound(ServerboundPackets1_20_5.MOVE_PLAYER_STATUS_ONLY, this::fixOnGround);
protocol.registerServerbound(ServerboundPackets1_20_5.MOVE_VEHICLE, wrapper -> {
final double x = wrapper.passthrough(Types.DOUBLE);
final double y = wrapper.passthrough(Types.DOUBLE);
final double z = wrapper.passthrough(Types.DOUBLE);
final float yaw = wrapper.passthrough(Types.FLOAT);
final float pitch = wrapper.passthrough(Types.FLOAT);
final PlayerStorage storage = wrapper.user().get(PlayerStorage.class);
storage.setPosition(x, y, z);
storage.setRotation(yaw, pitch);
});
protocol.registerClientbound(ClientboundPackets1_21_2.PLAYER_INFO_UPDATE, wrapper -> {
final BitSet actions = wrapper.read(Types.PROFILE_ACTIONS_ENUM1_21_2);
// We need to recreate the BitSet field itself to remove the new action
final BitSet updatedActions = new BitSet(6);
for (int i = 0; i < 6; i++) {
if (actions.get(i)) {
updatedActions.set(i);
}
}
wrapper.write(Types.PROFILE_ACTIONS_ENUM1_19_3, updatedActions);
final int entries = wrapper.passthrough(Types.VAR_INT);
for (int i = 0; i < entries; i++) {
wrapper.passthrough(Types.UUID);
if (actions.get(0)) {
wrapper.passthrough(Types.STRING); // Player Name
final int properties = wrapper.passthrough(Types.VAR_INT);
for (int j = 0; j < properties; j++) {
wrapper.passthrough(Types.STRING); // Name
wrapper.passthrough(Types.STRING); // Value
wrapper.passthrough(Types.OPTIONAL_STRING); // Signature
}
}
if (actions.get(1) && wrapper.passthrough(Types.BOOLEAN)) {
wrapper.passthrough(Types.UUID); // Session UUID
wrapper.passthrough(Types.PROFILE_KEY);
}
if (actions.get(2)) {
wrapper.passthrough(Types.VAR_INT); // Gamemode
}
if (actions.get(3)) {
wrapper.passthrough(Types.BOOLEAN); // Listed
}
if (actions.get(4)) {
wrapper.passthrough(Types.VAR_INT); // Latency
}
if (actions.get(5)) {
final Tag displayName = wrapper.passthrough(Types.OPTIONAL_TAG);
protocol.getComponentRewriter().processTag(wrapper.user(), displayName);
}
// New one
if (actions.get(6)) {
wrapper.read(Types.VAR_INT); // List order
}
}
});
protocol.registerClientbound(ClientboundPackets1_21_2.SET_PASSENGERS, wrapper -> {
final int vehicleId = wrapper.passthrough(Types.VAR_INT);
final int[] passengerIds = wrapper.passthrough(Types.VAR_INT_ARRAY_PRIMITIVE);
final ClientVehicleStorage storage = wrapper.user().get(ClientVehicleStorage.class);
if (storage != null && vehicleId == storage.vehicleId()) {
wrapper.user().remove(ClientVehicleStorage.class);
}
final int clientEntityId = tracker(wrapper.user()).clientEntityId();
for (final int passenger : passengerIds) {
if (passenger == clientEntityId) {
wrapper.user().put(new ClientVehicleStorage(vehicleId));
break;
}
}
});
protocol.appendClientbound(ClientboundPackets1_21_2.REMOVE_ENTITIES, wrapper -> {
final ClientVehicleStorage vehicleStorage = wrapper.user().get(ClientVehicleStorage.class);
if (vehicleStorage == null) {
return;
}
final int[] entityIds = wrapper.get(Types.VAR_INT_ARRAY_PRIMITIVE, 0);
for (final int entityId : entityIds) {
if (entityId == vehicleStorage.vehicleId()) {
wrapper.user().remove(ClientVehicleStorage.class);
break;
}
}
});
}
private void updateParticleFormat(final CompoundTag options, final String particleType) {
// Have to be float lists in older versions
if ("dust_color_transition".equals(particleType)) {
replaceColor(options, "from_color");
replaceColor(options, "to_color");
} else if ("dust".equals(particleType)) {
replaceColor(options, "color");
}
}
private void replaceColor(final CompoundTag options, final String to_color) {
final IntTag toColorTag = options.getIntTag(to_color);
if (toColorTag == null) {
return;
}
final int rgb = toColorTag.asInt();
final float r = ((rgb >> 16) & 0xFF) / 255F;
final float g = ((rgb >> 8) & 0xFF) / 255F;
final float b = (rgb & 0xFF) / 255F;
options.put(to_color, new ListTag<>(List.of(new FloatTag(r), new FloatTag(g), new FloatTag(b))));
}
private void writePackedRotation(final PacketWrapper wrapper, final float yaw, final float pitch) {
// Pack y and x rot
wrapper.write(Types.BYTE, (byte) Math.floor(yaw * 256F / 360F));
wrapper.write(Types.BYTE, (byte) Math.floor(pitch * 256F / 360F));
}
private void handleRelativeArguments(
final PacketWrapper wrapper,
double x, double y, double z,
float yaw, float pitch,
final int relativeArguments,
double movementX, double movementY, double movementZ,
@Nullable final Integer entityId
) {
// Position and rotation
final PlayerStorage storage = wrapper.user().get(PlayerStorage.class);
if ((relativeArguments & 1 << REL_X) != 0) {
x += storage.x();
}
if ((relativeArguments & 1 << REL_Y) != 0) {
y += storage.y();
}
if ((relativeArguments & 1 << REL_Z) != 0) {
z += storage.z();
}
if ((relativeArguments & 1 << REL_Y_ROT) != 0) {
yaw += storage.yaw();
}
if ((relativeArguments & 1 << REL_X_ROT) != 0) {
pitch += storage.pitch();
}
// Movement rotation
if ((relativeArguments & 1 << REL_ROTATE_DELTA) != 0) {
final double deltaYaw = Math.toRadians(storage.yaw() - yaw);
final double deltaYawCos = Math.cos(deltaYaw);
final double deltaYawSin = Math.sin(deltaYaw);
movementX = movementX * deltaYawCos + movementZ * deltaYawSin;
movementZ = movementZ * deltaYawCos - movementX * deltaYawSin;
final double deltaPitch = Math.toRadians(storage.pitch() - pitch);
final double deltaPitchCos = Math.cos(deltaPitch);
final double deltaPitchSin = Math.sin(deltaPitch);
movementY = movementY * deltaPitchCos + movementZ * deltaPitchSin;
movementZ = movementZ * deltaPitchCos - movementY * deltaPitchSin;
}
final boolean relativeDeltaX = (relativeArguments & 1 << REL_DELTA_X) != 0;
final boolean relativeDeltaY = (relativeArguments & 1 << REL_DELTA_Y) != 0;
final boolean relativeDeltaZ = (relativeArguments & 1 << REL_DELTA_Z) != 0;
// Update after having used its previous data
storage.setPosition(x, y, z);
storage.setRotation(yaw, pitch);
// Movement
if (relativeDeltaX && relativeDeltaY && relativeDeltaZ) {
if (entityId != null && entityId != tracker(wrapper.user()).clientEntityId()) {
// Can only handle the client entity
return;
}
final PacketWrapper explosionPacket = wrapper.create(ClientboundPackets1_21.EXPLODE);
explosionPacket.write(Types.DOUBLE, 0.0); // Center X
explosionPacket.write(Types.DOUBLE, 0.0); // Center Y
explosionPacket.write(Types.DOUBLE, 0.0); // Center Z
explosionPacket.write(Types.FLOAT, 0F); // Power
explosionPacket.write(Types.VAR_INT, 0); // Blocks affected
explosionPacket.write(Types.FLOAT, (float) movementX);
explosionPacket.write(Types.FLOAT, (float) movementY);
explosionPacket.write(Types.FLOAT, (float) movementZ);
explosionPacket.write(Types.VAR_INT, 0); // Block interaction
explosionPacket.write(Types1_21.PARTICLE, new Particle(0)); // Small explosion
explosionPacket.write(Types1_21.PARTICLE, new Particle(0)); // Large explosion
explosionPacket.write(Types.SOUND_EVENT, Holder.of(new SoundEvent("", null))); // Explosion sound
explosionPacket.send(Protocol1_21_2To1_21.class);
} else if (!relativeDeltaX && !relativeDeltaY && !relativeDeltaZ) {
final PacketWrapper entityMotionPacket = wrapper.create(ClientboundPackets1_21.SET_ENTITY_MOTION);
entityMotionPacket.write(Types.VAR_INT, entityId != null ? entityId : tracker(wrapper.user()).clientEntityId());
entityMotionPacket.write(Types.SHORT, (short) (movementX * 8000));
entityMotionPacket.write(Types.SHORT, (short) (movementY * 8000));
entityMotionPacket.write(Types.SHORT, (short) (movementZ * 8000));
entityMotionPacket.send(Protocol1_21_2To1_21.class);
} else if (!warned) {
// Mixed combinations of relative and absolute would require tracking the previous delta movement
// which is quite impossible without doing massive player simulation on protocol level.
// This is bad but so is life.
protocol.getLogger().warning("Mixed combinations of relative and absolute delta movements are not supported for 1.21.1 players. " +
"This will result in incorrect movement for the player. ");
warned = true;
}
}
private int boatTypeFromEntityType(final EntityType type) {
if (type == EntityTypes1_21_2.OAK_BOAT) {
return 0;
} else if (type == EntityTypes1_21_2.SPRUCE_BOAT) {
return 1;
} else if (type == EntityTypes1_21_2.BIRCH_BOAT) {
return 2;
} else if (type == EntityTypes1_21_2.JUNGLE_BOAT) {
return 3;
} else if (type == EntityTypes1_21_2.ACACIA_BOAT) {
return 4;
} else if (type == EntityTypes1_21_2.CHERRY_BOAT) {
return 5;
} else if (type == EntityTypes1_21_2.DARK_OAK_BOAT) {
return 6;
} else if (type == EntityTypes1_21_2.MANGROVE_BOAT) {
return 7;
} else if (type == EntityTypes1_21_2.BAMBOO_RAFT) {
return 8;
} else {
return 0;
}
}
private int chestBoatTypeFromEntityType(final EntityType type) {
if (type == EntityTypes1_21_2.OAK_CHEST_BOAT) {
return 0;
} else if (type == EntityTypes1_21_2.SPRUCE_CHEST_BOAT) {
return 1;
} else if (type == EntityTypes1_21_2.BIRCH_CHEST_BOAT) {
return 2;
} else if (type == EntityTypes1_21_2.JUNGLE_CHEST_BOAT) {
return 3;
} else if (type == EntityTypes1_21_2.ACACIA_CHEST_BOAT) {
return 4;
} else if (type == EntityTypes1_21_2.CHERRY_CHEST_BOAT) {
return 5;
} else if (type == EntityTypes1_21_2.DARK_OAK_CHEST_BOAT) {
return 6;
} else if (type == EntityTypes1_21_2.MANGROVE_CHEST_BOAT) {
return 7;
} else if (type == EntityTypes1_21_2.BAMBOO_CHEST_RAFT) {
return 8;
} else {
return 0;
}
}
private void fixOnGround(final PacketWrapper wrapper) {
final boolean data = wrapper.read(Types.BOOLEAN);
wrapper.write(Types.UNSIGNED_BYTE, data ? (short) 1 : 0); // Carries more data now
}
@Override
protected void registerRewrites() {
filter().mapDataType(Types1_21.ENTITY_DATA_TYPES::byId);
registerEntityDataTypeHandler1_20_3(
Types1_21.ENTITY_DATA_TYPES.itemType,
Types1_21.ENTITY_DATA_TYPES.blockStateType,
Types1_21.ENTITY_DATA_TYPES.optionalBlockStateType,
Types1_21.ENTITY_DATA_TYPES.particleType,
Types1_21.ENTITY_DATA_TYPES.particlesType,
Types1_21.ENTITY_DATA_TYPES.componentType,
Types1_21.ENTITY_DATA_TYPES.optionalComponentType
);
registerBlockStateHandler(EntityTypes1_21_2.ABSTRACT_MINECART, 11);
filter().type(EntityTypes1_21_2.CREAKING).cancel(17); // Active
filter().type(EntityTypes1_21_2.CREAKING).cancel(16); // Can move
filter().type(EntityTypes1_21_2.ABSTRACT_BOAT).addIndex(11); // Boat type
filter().type(EntityTypes1_21_2.SALMON).removeIndex(17); // Data type
filter().type(EntityTypes1_21_2.AGEABLE_WATER_CREATURE).removeIndex(16); // Baby
filter().type(EntityTypes1_21_2.ABSTRACT_ARROW).removeIndex(10); // In ground
}
@Override
public EntityType typeFromId(final int type) {
return EntityTypes1_21_2.getTypeFromId(type);
}
@Override
public void onMappingDataLoaded() {
mapTypes();
mapEntityTypeWithData(EntityTypes1_21_2.CREAKING, EntityTypes1_21_2.WARDEN).tagName();
mapEntityTypeWithData(EntityTypes1_21_2.CREAKING_TRANSIENT, EntityTypes1_21_2.WARDEN).tagName();
}
}
@@ -0,0 +1,62 @@
/*
* This file is part of ViaBackwards - https://github.com/ViaVersion/ViaBackwards
* Copyright (C) 2016-2024 ViaVersion and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.viaversion.viabackwards.protocol.v1_21_2to1_21.rewriter;
import com.viaversion.viaversion.api.connection.UserConnection;
import com.viaversion.viaversion.api.minecraft.Particle;
import com.viaversion.viaversion.api.protocol.Protocol;
import com.viaversion.viaversion.api.type.Types;
import com.viaversion.viaversion.api.type.types.version.Types1_21;
import com.viaversion.viaversion.api.type.types.version.Types1_21_2;
import com.viaversion.viaversion.protocols.v1_21to1_21_2.packet.ClientboundPacket1_21_2;
import com.viaversion.viaversion.rewriter.ParticleRewriter;
public final class ParticleRewriter1_21_2 extends ParticleRewriter<ClientboundPacket1_21_2> {
public ParticleRewriter1_21_2(final Protocol<ClientboundPacket1_21_2, ?, ?, ?> protocol) {
super(protocol, Types1_21_2.PARTICLE, Types1_21.PARTICLE);
}
@Override
public void rewriteParticle(final UserConnection connection, final Particle particle) {
final String identifier = protocol.getMappingData().getParticleMappings().identifier(particle.id());
super.rewriteParticle(connection, particle);
if (identifier.equals("minecraft:dust_color_transition")) {
argbToVector(particle, 0);
argbToVector(particle, 3);
} else if (identifier.equals("minecraft:dust")) {
argbToVector(particle, 0);
} else if (identifier.equals("minecraft:trail")) {
// Remove target
particle.removeArgument(2);
particle.removeArgument(1);
particle.removeArgument(0);
}
}
private void argbToVector(final Particle particle, final int index) {
final int argb = particle.<Integer>removeArgument(index).getValue();
final float r = ((argb >> 16) & 0xFF) / 255F;
final float g = ((argb >> 8) & 0xFF) / 255F;
final float b = (argb & 0xFF) / 255F;
particle.add(index, Types.FLOAT, r);
particle.add(index + 1, Types.FLOAT, g);
particle.add(index + 2, Types.FLOAT, b);
}
}
@@ -0,0 +1,42 @@
/*
* This file is part of ViaBackwards - https://github.com/ViaVersion/ViaBackwards
* Copyright (C) 2016-2024 ViaVersion and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.viaversion.viabackwards.protocol.v1_21_2to1_21.storage;
import com.viaversion.viaversion.api.connection.StorableObject;
public final class InventoryStateIdStorage implements StorableObject {
private boolean smithingTableOpen;
private int stateId = -1;
public int stateId() {
return stateId;
}
public void setStateId(final int stateId) {
this.stateId = stateId;
}
public boolean smithingTableOpen() {
return smithingTableOpen;
}
public void setSmithingTableOpen(final boolean smithingTableOpen) {
this.smithingTableOpen = smithingTableOpen;
}
}
@@ -0,0 +1,56 @@
/*
* This file is part of ViaBackwards - https://github.com/ViaVersion/ViaBackwards
* Copyright (C) 2016-2024 ViaVersion and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.viaversion.viabackwards.protocol.v1_21_2to1_21.storage;
import com.viaversion.viaversion.api.connection.StorableObject;
import com.viaversion.viaversion.api.protocol.packet.PacketWrapper;
import com.viaversion.viaversion.api.type.Types;
import com.viaversion.viaversion.util.Key;
import java.util.HashMap;
import java.util.Map;
import org.checkerframework.checker.nullness.qual.Nullable;
public final class ItemTagStorage implements StorableObject {
private Map<String, int[]> itemTags = new HashMap<>();
public int @Nullable [] itemTag(final String key) {
return itemTags.get(Key.stripMinecraftNamespace(key));
}
public void readItemTags(final PacketWrapper wrapper) {
final int length = wrapper.passthrough(Types.VAR_INT);
for (int i = 0; i < length; i++) {
final String registryKey = wrapper.passthrough(Types.STRING);
final int tagsSize = wrapper.passthrough(Types.VAR_INT);
final boolean itemRegistry = Key.stripMinecraftNamespace(registryKey).equals("item");
if (itemRegistry) {
this.itemTags = new HashMap<>(tagsSize);
}
for (int j = 0; j < tagsSize; j++) {
final String key = wrapper.passthrough(Types.STRING);
final int[] ids = wrapper.passthrough(Types.VAR_INT_ARRAY_PRIMITIVE);
if (itemRegistry) {
this.itemTags.put(Key.stripMinecraftNamespace(key), ids);
}
}
}
}
}
@@ -0,0 +1,117 @@
/*
* This file is part of ViaBackwards - https://github.com/ViaVersion/ViaBackwards
* Copyright (C) 2016-2024 ViaVersion and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.viaversion.viabackwards.protocol.v1_21_2to1_21.storage;
import com.viaversion.viabackwards.api.entities.storage.PlayerPositionStorage;
import com.viaversion.viabackwards.protocol.v1_21_2to1_21.Protocol1_21_2To1_21;
import com.viaversion.viaversion.api.connection.UserConnection;
import com.viaversion.viaversion.api.protocol.packet.PacketWrapper;
import com.viaversion.viaversion.api.type.Types;
import com.viaversion.viaversion.protocols.v1_21to1_21_2.packet.ServerboundPackets1_21_2;
public final class PlayerStorage extends PlayerPositionStorage {
private static final PlayerInput EMPTY = new PlayerInput(false, false, false, false, false, false, false);
private static final float PLAYER_JUMP_HEIGHT = 0.42F;
private float yaw;
private float pitch;
private boolean playerCommandTrackedSneaking;
private boolean playerCommandTrackedSprinting;
private PlayerInput lastInput = EMPTY;
private double prevX;
private double prevY;
private double prevZ;
public void tick(final UserConnection user) {
final double deltaX = x() - prevX;
final double deltaY = y() - prevY;
final double deltaZ = z() - prevZ;
final double magnitude = Math.sqrt(deltaX * deltaX + deltaZ * deltaZ);
double directionX = magnitude > 0 ? deltaX / magnitude : 0;
double directionZ = magnitude > 0 ? deltaZ / magnitude : 0;
directionX = Math.max(-1, Math.min(1, directionX));
directionZ = Math.max(-1, Math.min(1, directionZ));
final double angle = Math.toRadians(-yaw);
final double newDirectionX = directionX * Math.cos(angle) - directionZ * Math.sin(angle);
final double newDirectionZ = directionX * Math.sin(angle) + directionZ * Math.cos(angle);
final boolean forward = newDirectionZ >= 0.65F;
final boolean backwards = newDirectionZ <= -0.65F;
final boolean left = newDirectionX >= 0.65F;
final boolean right = newDirectionX <= -0.65F;
final boolean jump = Math.abs(deltaY - PLAYER_JUMP_HEIGHT) <= 1E-4F;
final PlayerInput input = new PlayerInput(forward, backwards, left, right, jump, playerCommandTrackedSneaking, playerCommandTrackedSprinting);
if (!lastInput.equals(input)) {
final PacketWrapper playerInputPacket = PacketWrapper.create(ServerboundPackets1_21_2.PLAYER_INPUT, user);
byte flags = 0;
flags = (byte) (flags | (input.forward() ? 1 : 0));
flags = (byte) (flags | (input.backward() ? 2 : 0));
flags = (byte) (flags | (input.left() ? 4 : 0));
flags = (byte) (flags | (input.right() ? 8 : 0));
flags = (byte) (flags | (input.jump() ? 16 : 0));
flags = (byte) (flags | (input.sneak() ? 32 : 0));
flags = (byte) (flags | (input.sprint() ? 64 : 0));
playerInputPacket.write(Types.BYTE, flags);
playerInputPacket.sendToServer(Protocol1_21_2To1_21.class);
lastInput = input;
}
this.prevX = x();
this.prevY = y();
this.prevZ = z();
}
public float yaw() {
return yaw;
}
public float pitch() {
return pitch;
}
public void setRotation(final float yaw, final float pitch) {
this.yaw = yaw;
this.pitch = pitch;
}
public void setPlayerCommandTrackedSneaking(final boolean playerCommandTrackedSneaking) {
this.playerCommandTrackedSneaking = playerCommandTrackedSneaking;
}
public void setPlayerCommandTrackedSprinting(final boolean playerCommandTrackedSprinting) {
this.playerCommandTrackedSprinting = playerCommandTrackedSprinting;
}
public boolean setSneaking(final boolean sneaking) {
final boolean changed = this.playerCommandTrackedSneaking != sneaking;
this.playerCommandTrackedSneaking = sneaking;
return changed;
}
public record PlayerInput(boolean forward, boolean backward, boolean left, boolean right, boolean jump,
boolean sneak, boolean sprint) {
}
}
@@ -0,0 +1,463 @@
/*
* This file is part of ViaBackwards - https://github.com/ViaVersion/ViaBackwards
* Copyright (C) 2016-2024 ViaVersion and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.viaversion.viabackwards.protocol.v1_21_2to1_21.storage;
import com.google.common.base.Preconditions;
import com.viaversion.viabackwards.protocol.v1_21_2to1_21.Protocol1_21_2To1_21;
import com.viaversion.viaversion.api.connection.StorableObject;
import com.viaversion.viaversion.api.connection.UserConnection;
import com.viaversion.viaversion.api.minecraft.HolderSet;
import com.viaversion.viaversion.api.minecraft.item.Item;
import com.viaversion.viaversion.api.minecraft.item.StructuredItem;
import com.viaversion.viaversion.api.protocol.packet.PacketWrapper;
import com.viaversion.viaversion.api.type.Types;
import com.viaversion.viaversion.api.type.types.version.Types1_21_2;
import com.viaversion.viaversion.protocols.v1_20_5to1_21.packet.ClientboundPackets1_21;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;
// Mostly a lost cause as the server will not send all the necessary data.
// Recipe displays can also be different from the actual recipe - at the end of the same,
// the server will still properly handle inputs, but we can't fully reconstruct the recipe book.
public final class RecipeStorage implements StorableObject {
// Pairs of open + filtering for: Crafting, furnace, blast furnace, smoker
public static final int RECIPE_BOOK_SETTINGS = 4 * 2;
private static final String[] EMPTY_STRINGS = new String[0];
private final List<Recipe> recipes = new ArrayList<>(); // Recipes, excluding stone cutter recipes, in the order they were received
private final List<Recipe> tempRecipes = new ArrayList<>(); // Recipes received in the current batch
private final List<StoneCutterRecipe> stoneCutterRecipes = new ArrayList<>();
private boolean[] recipeBookSettings = new boolean[RECIPE_BOOK_SETTINGS];
private final Protocol1_21_2To1_21 protocol;
public RecipeStorage(final Protocol1_21_2To1_21 protocol) {
this.protocol = protocol;
}
abstract static class Recipe {
private static final int FOOD_CRAFTING_BOOK_CATEGORY = 0;
private static final int BLOCKS_CRAFTING_BOOK_CATEGORY = 1;
private static final int MISC_CRAFTING_BOOK_CATEGORY = 2;
protected int index;
private Integer group;
private int category;
private boolean highlight;
abstract void write(PacketWrapper wrapper);
void writeGroup(final PacketWrapper wrapper) {
wrapper.write(Types.STRING, group != null ? Integer.toString(group) : "");
}
void writeIngredients(final PacketWrapper wrapper, final Item[][] ingredients) {
wrapper.write(Types.VAR_INT, ingredients.length);
for (final Item[] ingredient : ingredients) {
writeIngredient(wrapper, ingredient);
}
}
void writeIngredient(final PacketWrapper wrapper, final Item[] ingredient) {
final Item[] copy = new Item[ingredient.length];
for (int i = 0; i < ingredient.length; i++) {
copy[i] = ingredient[i].copy();
}
wrapper.write(Types1_21_2.ITEM_ARRAY, copy);
}
void writeResult(final PacketWrapper wrapper, final Item result) {
wrapper.write(Types1_21_2.ITEM, result.copy());
}
void writeCategory(final PacketWrapper wrapper) {
// TODO Doesn't translate exactly
final int craftingBookCategory = switch (category) {
case 4, 9, 12 -> FOOD_CRAFTING_BOOK_CATEGORY;
case 0, 5, 7, 10 -> BLOCKS_CRAFTING_BOOK_CATEGORY;
case 1, 2, 3, 6, 8, 11 -> MISC_CRAFTING_BOOK_CATEGORY;
default -> MISC_CRAFTING_BOOK_CATEGORY;
};
wrapper.write(Types.VAR_INT, craftingBookCategory);
}
int category() {
return category;
}
}
public void sendRecipes(final UserConnection connection) {
// Fill from temp recipes so we can clear before if needed
if (!tempRecipes.isEmpty()) {
this.recipes.addAll(tempRecipes);
tempRecipes.clear();
}
int highestIndex = -1;
for (final Recipe recipe : recipes) {
highestIndex = Math.max(highestIndex, recipe.index);
}
// Add stonecutter recipes from update_recipes
final List<Recipe> recipes = new ArrayList<>(this.recipes);
for (final StoneCutterRecipe recipe : stoneCutterRecipes) {
recipe.index = ++highestIndex;
recipes.add(recipe);
}
// Sort by id
recipes.sort(Comparator.comparingInt(a -> a.index));
// Since the server only sends unlocked recipes, we need to re-send all recipes in UPDATE_RECIPES
final PacketWrapper updateRecipesPacket = PacketWrapper.create(ClientboundPackets1_21.UPDATE_RECIPES, connection);
updateRecipesPacket.write(Types.VAR_INT, recipes.size());
for (final Recipe recipe : recipes) {
updateRecipesPacket.write(Types.STRING, identifier(recipe.index));
recipe.write(updateRecipesPacket);
}
updateRecipesPacket.send(Protocol1_21_2To1_21.class);
sendUnlockedRecipes(connection, recipes);
}
private static String identifier(final int recipeIndex) {
// Use index as the recipe identifier, add leading zeros to keept it sorted
return String.format("%06d", recipeIndex);
}
public void lockRecipes(final PacketWrapper wrapper, final int[] ids) {
for (final int id : ids) {
recipes.removeIf(recipe -> recipe.index == id);
}
wrapper.write(Types.VAR_INT, 2); // Remove recipes
for (final boolean recipeBookSetting : recipeBookSettings) {
wrapper.write(Types.BOOLEAN, recipeBookSetting);
}
final String[] recipeKeys = new String[ids.length];
for (int i = 0; i < ids.length; i++) {
recipeKeys[i] = identifier(ids[i]);
}
wrapper.write(Types.STRING_ARRAY, recipeKeys);
}
private void sendUnlockedRecipes(final UserConnection connection, final List<Recipe> recipes) {
final PacketWrapper wrapper = PacketWrapper.create(ClientboundPackets1_21.RECIPE, connection);
wrapper.write(Types.VAR_INT, 0); // Init recipes
for (final boolean recipeBookSetting : recipeBookSettings) {
wrapper.write(Types.BOOLEAN, recipeBookSetting);
}
// Use index as the recipe identifier. We only know the unlocked ones, so send all
final String[] recipeKeys = new String[recipes.size()];
final List<String> highlightRecipes = new ArrayList<>();
for (int i = 0; i < recipes.size(); i++) {
recipeKeys[i] = identifier(i);
if (recipes.get(i).highlight) {
highlightRecipes.add(recipeKeys[i]);
}
}
wrapper.write(Types.STRING_ARRAY, recipeKeys);
wrapper.write(Types.STRING_ARRAY, highlightRecipes.toArray(EMPTY_STRINGS));
wrapper.send(Protocol1_21_2To1_21.class);
}
public void readRecipe(final PacketWrapper wrapper) {
final int id = wrapper.read(Types.VAR_INT);
final int type = wrapper.passthrough(Types.VAR_INT);
final Recipe recipe = switch (type) {
case 0 -> readShapeless(wrapper);
case 1 -> readShaped(wrapper);
case 2 -> readFurnace(wrapper);
case 3 -> readStoneCutter(wrapper);
case 4 -> readSmithing(wrapper);
default -> null;
};
final Integer group = wrapper.read(Types.OPTIONAL_VAR_INT);
final int category = wrapper.read(Types.VAR_INT);
if (wrapper.read(Types.BOOLEAN)) {
final int ingredientsSize = wrapper.read(Types.VAR_INT);
for (int j = 0; j < ingredientsSize; j++) {
//handleIngredient(wrapper); // Items //TODO ?
wrapper.read(Types.HOLDER_SET);
}
}
final byte flags = wrapper.read(Types.BYTE);
if (recipe != null) {
recipe.index = id;
recipe.group = group;
recipe.category = category;
recipe.highlight = (flags & 2) != 0;
}
}
private Recipe readShapeless(final PacketWrapper wrapper) {
final Item[][] ingredients = readSlotDisplayList(wrapper);
final Item result = readSingleSlotDisplay(wrapper);
readSlotDisplay(wrapper); // Crafting station
return add(new ShapelessRecipe(ingredients, result));
}
private Recipe readShaped(final PacketWrapper wrapper) {
final int width = wrapper.passthrough(Types.VAR_INT);
final int height = wrapper.passthrough(Types.VAR_INT);
final Item[][] ingredients = readSlotDisplayList(wrapper);
final Item result = readSingleSlotDisplay(wrapper);
readSlotDisplay(wrapper); // Crafting station
return add(new ShapedRecipe(width, height, ingredients, result));
}
private Recipe readFurnace(final PacketWrapper wrapper) {
final Item[] ingredient = readSlotDisplay(wrapper);
readSlotDisplay(wrapper); // Fuel
final Item result = readSingleSlotDisplay(wrapper);
readSlotDisplay(wrapper); // Crafting station
final int duration = wrapper.read(Types.VAR_INT);
final float experience = wrapper.read(Types.FLOAT);
return add(new FurnaceRecipe(ingredient, result, duration, experience));
}
private Recipe readStoneCutter(final PacketWrapper wrapper) {
// Use values from UPDATE_RECIPES instead
readSlotDisplay(wrapper); // Input
readSlotDisplay(wrapper); // Result
readSlotDisplay(wrapper); // Crafting station
return null;
}
private Recipe readSmithing(final PacketWrapper wrapper) {
// TODO Combine with update_recipes?
readSlotDisplay(wrapper); // Template
readSlotDisplay(wrapper); // Base
readSlotDisplay(wrapper); // Addition
readSlotDisplay(wrapper); // Result
readSlotDisplay(wrapper); // Crafting station
return null;
}
private Recipe add(final Recipe recipe) {
tempRecipes.add(recipe);
return recipe;
}
private Item[][] readSlotDisplayList(final PacketWrapper wrapper) {
final int size = wrapper.passthrough(Types.VAR_INT);
final Item[][] ingredients = new Item[size][];
for (int i = 0; i < size; i++) {
ingredients[i] = readSlotDisplay(wrapper);
}
return ingredients;
}
private Item readSingleSlotDisplay(final PacketWrapper wrapper) {
final Item[] items = readSlotDisplay(wrapper);
return items.length == 0 ? new StructuredItem(1, 1) : items[0];
}
private Item[] readSlotDisplay(final PacketWrapper wrapper) {
// empty, any_fuel, smithing_trim are empty
final int type = wrapper.read(Types.VAR_INT);
return switch (type) {
case 2 -> {
final int id = wrapper.read(Types.VAR_INT);
if (id == 0) {
protocol.getLogger().warning("Empty item id in recipe");
yield new Item[0];
}
yield new Item[]{new StructuredItem(rewriteItemId(id), 1)};
}
case 3 -> {
final Item item = wrapper.read(Types1_21_2.ITEM);
protocol.getItemRewriter().handleItemToClient(wrapper.user(), item);
if (item.isEmpty()) {
protocol.getLogger().warning("Empty item in recipe");
yield new Item[0];
}
yield new Item[]{item};
}
case 4 -> {
wrapper.read(Types.STRING); // Tag key // TODO Probably not even worth the effort
yield new Item[0];
}
case 5 -> {
readSlotDisplay(wrapper); // Base
readSlotDisplay(wrapper); // Material
readSlotDisplay(wrapper); // Pattern
yield new Item[0];
}
case 6 -> {
readSlotDisplay(wrapper); // Input
readSlotDisplay(wrapper); // Remainder
yield new Item[0];
}
case 7 -> readSlotDisplayList(wrapper)[0]; // Composite
default -> new Item[0];
};
}
private int rewriteItemId(final int id) {
return protocol.getMappingData().getNewItemId(id);
}
public void readStoneCutterRecipes(final PacketWrapper wrapper) {
stoneCutterRecipes.clear();
final int stonecutterRecipesSize = wrapper.read(Types.VAR_INT);
for (int i = 0; i < stonecutterRecipesSize; i++) {
// The ingredients are what's actually used in client prediction, they're the important part
final Item[] ingredient = readHolderSet(wrapper);
// TODO Probably not actually the result, might have to combine with update_recipes
final Item result = readSingleSlotDisplay(wrapper);
stoneCutterRecipes.add(new StoneCutterRecipe(ingredient, result));
}
}
private Item[] readHolderSet(final PacketWrapper wrapper) {
final HolderSet holderSet = wrapper.read(Types.HOLDER_SET);
if (holderSet.hasTagKey()) {
return new Item[]{new StructuredItem(1, 1)}; // TODO Probably not even worth the effort
}
final int[] ids = holderSet.ids();
for (int i = 0; i < ids.length; i++) {
ids[i] = rewriteItemId(ids[i]);
}
final Item[] ingredient = new Item[ids.length];
for (int i = 0; i < ingredient.length; i++) {
ingredient[i] = new StructuredItem(ids[i], 1);
}
return ingredient;
}
private static final class ShapelessRecipe extends Recipe {
private static final int SERIALIZER_ID = 1;
private final Item[][] ingredients;
private final Item result;
private ShapelessRecipe(final Item[][] ingredients, final Item result) {
this.ingredients = ingredients;
this.result = result;
}
@Override
public void write(final PacketWrapper wrapper) {
wrapper.write(Types.VAR_INT, SERIALIZER_ID);
writeGroup(wrapper);
writeCategory(wrapper);
writeIngredients(wrapper, ingredients);
writeResult(wrapper, result);
}
}
private static final class ShapedRecipe extends Recipe {
private static final int SERIALIZER_ID = 0;
private final int width;
private final int height;
private final Item[][] ingredients;
private final Item result;
private ShapedRecipe(final int width, final int height, final Item[][] ingredients, final Item result) {
this.width = width;
this.height = height;
this.ingredients = ingredients;
this.result = result;
}
@Override
public void write(final PacketWrapper wrapper) {
wrapper.write(Types.VAR_INT, SERIALIZER_ID);
writeGroup(wrapper);
writeCategory(wrapper);
wrapper.write(Types.VAR_INT, width);
wrapper.write(Types.VAR_INT, height);
Preconditions.checkArgument(width * height == ingredients.length, "Invalid shaped recipe");
// No length prefix
for (final Item[] ingredient : ingredients) {
writeIngredient(wrapper, ingredient);
}
writeResult(wrapper, result);
wrapper.write(Types.BOOLEAN, false); // Doesn't matter for the init
}
}
private static final class FurnaceRecipe extends Recipe {
private final Item[] ingredient;
private final Item result;
private final float experience;
private final int cookingTime;
private FurnaceRecipe(final Item[] ingredient, final Item result, final int cookingTime, final float experience) {
this.ingredient = ingredient;
this.result = result;
this.experience = experience;
this.cookingTime = cookingTime;
}
@Override
public void write(final PacketWrapper wrapper) {
wrapper.write(Types.VAR_INT, serializerId());
writeGroup(wrapper);
writeCategory(wrapper);
writeIngredient(wrapper, ingredient);
writeResult(wrapper, result);
wrapper.write(Types.FLOAT, experience);
wrapper.write(Types.VAR_INT, cookingTime);
}
private int serializerId() {
return switch (category()) {
case 4, 5, 6 -> 15; // Furnace food, bocks, misc
case 7, 8 -> 16; // Blast furnace blocks, misc
case 9 -> 17; // Smoker
case 12 -> 18; // Campfire
default -> 15;
};
}
}
private static final class StoneCutterRecipe extends Recipe {
private static final int SERIALIZER_ID = 19;
private final Item[] ingredient;
private final Item result;
private StoneCutterRecipe(final Item[] ingredient, final Item result) {
this.ingredient = ingredient;
this.result = result;
}
@Override
public void write(final PacketWrapper wrapper) {
wrapper.write(Types.VAR_INT, SERIALIZER_ID);
writeGroup(wrapper);
writeIngredient(wrapper, ingredient);
writeResult(wrapper, result);
}
}
public void setRecipeBookSettings(final boolean[] recipeBookSettings) {
this.recipeBookSettings = recipeBookSettings;
}
public void clearRecipes() {
recipes.clear();
}
}
@@ -0,0 +1,63 @@
/*
* This file is part of ViaBackwards - https://github.com/ViaVersion/ViaBackwards
* Copyright (C) 2016-2024 ViaVersion and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.viaversion.viabackwards.protocol.v1_21_2to1_21.task;
import com.viaversion.viabackwards.ViaBackwards;
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.viaversion.api.Via;
import com.viaversion.viaversion.api.connection.UserConnection;
import com.viaversion.viaversion.api.protocol.packet.PacketWrapper;
import com.viaversion.viaversion.api.protocol.packet.State;
import com.viaversion.viaversion.protocols.v1_21to1_21_2.packet.ServerboundPackets1_21_2;
import com.viaversion.viaversion.protocols.v1_21to1_21_2.storage.ClientVehicleStorage;
import io.netty.channel.Channel;
import java.util.logging.Level;
public final class PlayerPacketsTickTask implements Runnable {
@Override
public void run() {
for (final UserConnection user : Via.getManager().getConnectionManager().getConnections()) {
if (user.getProtocolInfo().getClientState() != State.PLAY || !user.getProtocolInfo().getPipeline().contains(Protocol1_21_2To1_21.class)) {
continue;
}
final Channel channel = user.getChannel();
channel.eventLoop().submit(() -> {
if (!channel.isActive()) {
return;
}
try {
if (!user.has(ClientVehicleStorage.class)) {
final PlayerStorage playerStorage = user.get(PlayerStorage.class);
playerStorage.tick(user);
}
} catch (Throwable t) {
ViaBackwards.getPlatform().getLogger().log(Level.SEVERE, "Error while sending player input packet.", t);
}
try {
final PacketWrapper clientTickEndPacket = PacketWrapper.create(ServerboundPackets1_21_2.CLIENT_TICK_END, user);
clientTickEndPacket.sendToServer(Protocol1_21_2To1_21.class);
} catch (Throwable t) {
ViaBackwards.getPlatform().getLogger().log(Level.SEVERE, "Error while sending client tick end packet.", t);
}
});
}
}
}
@@ -34,6 +34,8 @@ import com.viaversion.viaversion.api.minecraft.item.data.ChatType;
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;
import com.viaversion.viaversion.api.type.types.version.Types1_20_5;
import com.viaversion.viaversion.api.type.types.version.Types1_21;
import com.viaversion.viaversion.data.entity.EntityTrackerBase;
import com.viaversion.viaversion.protocols.v1_20_3to1_20_5.packet.ClientboundConfigurationPackets1_20_5;
import com.viaversion.viaversion.protocols.v1_20_3to1_20_5.packet.ClientboundPacket1_20_5;
@@ -45,6 +47,7 @@ import com.viaversion.viaversion.protocols.v1_20_5to1_21.Protocol1_20_5To1_21;
import com.viaversion.viaversion.protocols.v1_20_5to1_21.packet.ClientboundConfigurationPackets1_21;
import com.viaversion.viaversion.protocols.v1_20_5to1_21.packet.ClientboundPacket1_21;
import com.viaversion.viaversion.protocols.v1_20_5to1_21.packet.ClientboundPackets1_21;
import com.viaversion.viaversion.rewriter.ParticleRewriter;
import com.viaversion.viaversion.rewriter.StatisticsRewriter;
import com.viaversion.viaversion.rewriter.TagRewriter;
import com.viaversion.viaversion.util.ArrayUtil;
@@ -56,6 +59,7 @@ public final class Protocol1_21To1_20_5 extends BackwardsProtocol<ClientboundPac
public static final BackwardsMappingData MAPPINGS = new BackwardsMappingData("1.21", "1.20.5", Protocol1_20_5To1_21.class);
private final EntityPacketRewriter1_21 entityRewriter = new EntityPacketRewriter1_21(this);
private final BlockItemPacketRewriter1_21 itemRewriter = new BlockItemPacketRewriter1_21(this);
private final ParticleRewriter<ClientboundPacket1_21> particleRewriter = new ParticleRewriter<>(this, Types1_21.PARTICLE, Types1_20_5.PARTICLE);
private final TranslatableRewriter<ClientboundPacket1_21> translatableRewriter = new ComponentRewriter1_21(this);
private final TagRewriter<ClientboundPacket1_21> tagRewriter = new TagRewriter<>(this);
@@ -75,6 +79,9 @@ public final class Protocol1_21To1_20_5 extends BackwardsProtocol<ClientboundPac
soundRewriter.registerSound1_19_3(ClientboundPackets1_21.SOUND_ENTITY);
soundRewriter.registerStopSound(ClientboundPackets1_21.STOP_SOUND);
particleRewriter.registerLevelParticles1_20_5(ClientboundPackets1_21.LEVEL_PARTICLES);
particleRewriter.registerExplode1_20_5(ClientboundPackets1_21.EXPLODE);
new StatisticsRewriter<>(this).register(ClientboundPackets1_21.AWARD_STATS);
translatableRewriter.registerComponentPacket(ClientboundPackets1_21.SET_ACTION_BAR_TEXT);
@@ -206,6 +213,11 @@ public final class Protocol1_21To1_20_5 extends BackwardsProtocol<ClientboundPac
return itemRewriter;
}
@Override
public ParticleRewriter<ClientboundPacket1_21> getParticleRewriter() {
return particleRewriter;
}
@Override
public TranslatableRewriter<ClientboundPacket1_21> getComponentRewriter() {
return translatableRewriter;
@@ -18,6 +18,7 @@
package com.viaversion.viabackwards.protocol.v1_21to1_20_5.rewriter;
import com.viaversion.nbt.tag.ByteTag;
import com.viaversion.nbt.tag.CompoundTag;
import com.viaversion.nbt.tag.StringTag;
import com.viaversion.nbt.tag.Tag;
import com.viaversion.viabackwards.api.rewriters.BackwardsStructuredItemRewriter;
@@ -28,10 +29,13 @@ import com.viaversion.viabackwards.protocol.v1_21to1_20_5.storage.EnchantmentsPa
import com.viaversion.viabackwards.protocol.v1_21to1_20_5.storage.OpenScreenStorage;
import com.viaversion.viabackwards.protocol.v1_21to1_20_5.storage.PlayerRotationStorage;
import com.viaversion.viaversion.api.connection.UserConnection;
import com.viaversion.viaversion.api.minecraft.Holder;
import com.viaversion.viaversion.api.minecraft.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.Enchantments;
import com.viaversion.viaversion.api.minecraft.item.data.JukeboxPlayable;
import com.viaversion.viaversion.api.type.Types;
import com.viaversion.viaversion.api.type.types.chunk.ChunkType1_20_2;
import com.viaversion.viaversion.api.type.types.version.Types1_20_5;
@@ -48,12 +52,12 @@ import com.viaversion.viaversion.protocols.v1_20_5to1_21.packet.ClientboundPacke
import com.viaversion.viaversion.protocols.v1_20_5to1_21.packet.ClientboundPackets1_21;
import com.viaversion.viaversion.rewriter.BlockRewriter;
import com.viaversion.viaversion.rewriter.IdRewriteFunction;
import com.viaversion.viaversion.util.Either;
import com.viaversion.viaversion.util.SerializerVersion;
import java.util.ArrayList;
import java.util.List;
import static com.viaversion.viaversion.protocols.v1_20_5to1_21.rewriter.BlockItemPacketRewriter1_21.downgradeItemData;
import static com.viaversion.viaversion.protocols.v1_20_5to1_21.rewriter.BlockItemPacketRewriter1_21.resetRarityValues;
import static com.viaversion.viaversion.protocols.v1_20_5to1_21.rewriter.BlockItemPacketRewriter1_21.updateItemData;
public final class BlockItemPacketRewriter1_21 extends BackwardsStructuredItemRewriter<ClientboundPacket1_21, ServerboundPacket1_20_5, Protocol1_21To1_20_5> {
@@ -63,8 +67,7 @@ public final class BlockItemPacketRewriter1_21 extends BackwardsStructuredItemRe
public BlockItemPacketRewriter1_21(final Protocol1_21To1_20_5 protocol) {
super(protocol,
Types1_21.ITEM, Types1_21.ITEM_ARRAY, Types1_20_5.ITEM, Types1_20_5.ITEM_ARRAY,
Types1_21.ITEM_COST, Types1_21.OPTIONAL_ITEM_COST, Types1_20_5.ITEM_COST, Types1_20_5.OPTIONAL_ITEM_COST,
Types1_21.PARTICLE, Types1_20_5.PARTICLE
Types1_21.ITEM_COST, Types1_21.OPTIONAL_ITEM_COST, Types1_20_5.ITEM_COST, Types1_20_5.OPTIONAL_ITEM_COST
);
}
@@ -85,8 +88,6 @@ public final class BlockItemPacketRewriter1_21 extends BackwardsStructuredItemRe
registerContainerClick1_17_1(ServerboundPackets1_20_5.CONTAINER_CLICK);
registerMerchantOffers1_20_5(ClientboundPackets1_21.MERCHANT_OFFERS);
registerSetCreativeModeSlot(ServerboundPackets1_20_5.SET_CREATIVE_MODE_SLOT);
registerLevelParticles1_20_5(ClientboundPackets1_21.LEVEL_PARTICLES);
registerExplosion(ClientboundPackets1_21.EXPLODE);
protocol.registerClientbound(ClientboundPackets1_21.OPEN_SCREEN, wrapper -> {
wrapper.passthrough(Types.VAR_INT); // Id
@@ -190,18 +191,17 @@ public final class BlockItemPacketRewriter1_21 extends BackwardsStructuredItemRe
final int identifier = item.identifier();
// Order is important
backupInconvertibleData(item);
super.handleItemToClient(connection, item);
downgradeItemData(item);
final StructuredDataContainer dataContainer = item.dataContainer();
if (dataContainer.has(StructuredDataKey.RARITY)) {
if (data.has(StructuredDataKey.RARITY)) {
return item;
}
// Change rarity of trident and piglin banner pattern
final boolean trident = identifier == 1188;
if (trident || identifier == 1200) {
dataContainer.set(StructuredDataKey.RARITY, trident ? 3 : 1); // Epic or Uncommon
data.set(StructuredDataKey.RARITY, trident ? 3 : 1); // Epic or Uncommon
saveTag(createCustomTag(item), new ByteTag(true), "rarity");
}
return item;
@@ -213,8 +213,8 @@ public final class BlockItemPacketRewriter1_21 extends BackwardsStructuredItemRe
return item;
}
final StructuredDataContainer dataContainer = item.dataContainer();
dataContainer.setIdLookup(protocol, false);
final StructuredDataContainer data = item.dataContainer();
data.setIdLookup(protocol, false);
// Rewrite enchantments
final EnchantmentsPaintingsStorage storage = connection.get(EnchantmentsPaintingsStorage.class);
@@ -227,7 +227,16 @@ public final class BlockItemPacketRewriter1_21 extends BackwardsStructuredItemRe
// Order is important
super.handleItemToServer(connection, item);
updateItemData(item);
resetRarityValues(item, nbtTagName("rarity"));
restoreInconvertibleData(item);
final CompoundTag customData = data.get(StructuredDataKey.CUSTOM_DATA);
if (customData == null) {
return item;
}
if (customData.remove(nbtTagName("rarity")) != null) {
data.remove(StructuredDataKey.RARITY);
removeCustomTag(data, customData);
}
return item;
}
@@ -261,6 +270,67 @@ public final class BlockItemPacketRewriter1_21 extends BackwardsStructuredItemRe
}
}
private void backupInconvertibleData(final Item item) {
final StructuredDataContainer data = item.dataContainer();
data.setIdLookup(protocol, true);
final JukeboxPlayable jukeboxPlayable = data.get(StructuredDataKey.JUKEBOX_PLAYABLE);
if (jukeboxPlayable == null) {
return;
}
final CompoundTag tag = new CompoundTag();
if (jukeboxPlayable.song().isLeft()) {
final Holder<JukeboxPlayable.JukeboxSong> songHolder = jukeboxPlayable.song().left();
tag.put("song", holderToTag(songHolder, (song, songTag) -> {
songTag.put("sound_event", holderToTag(song.soundEvent(), (soundEvent, soundEventTag) -> {
soundEventTag.putString("identifier", soundEvent.identifier());
if (soundEvent.fixedRange() != null) {
soundEventTag.putFloat("fixed_range", soundEvent.fixedRange());
}
}));
songTag.put("description", song.description());
songTag.putFloat("length_in_seconds", song.lengthInSeconds());
songTag.putInt("comparator_output", song.comparatorOutput());
}));
} else {
tag.putString("song_identifier", jukeboxPlayable.song().right());
}
tag.putBoolean("show_in_tooltip", jukeboxPlayable.showInTooltip());
saveTag(createCustomTag(item), tag, "jukebox_playable");
}
private void restoreInconvertibleData(final Item item) {
final StructuredDataContainer data = item.dataContainer();
final CompoundTag customData = data.get(StructuredDataKey.CUSTOM_DATA);
if (customData == null || !(customData.remove(nbtTagName("jukebox_playable")) instanceof CompoundTag tag)) {
return;
}
final Either<Holder<JukeboxPlayable.JukeboxSong>, String> song;
final String songIdentifier = tag.getString("song_identifier");
if (songIdentifier != null) {
song = Either.right(tag.getString(songIdentifier));
} else {
song = Either.left(restoreHolder(tag, "song", songTag -> {
final Holder<SoundEvent> soundEvent = restoreHolder(songTag, "sound_event", soundTag -> {
final String identifier = soundTag.getString("identifier");
final Float fixedRange = soundTag.contains("fixed_range") ? soundTag.getFloat("fixed_range") : null;
return new SoundEvent(identifier, fixedRange);
});
final Tag description = songTag.get("description");
final float lengthInSeconds = songTag.getFloat("length_in_seconds");
final int comparatorOutput = songTag.getInt("comparator_output");
return new JukeboxPlayable.JukeboxSong(soundEvent, description, lengthInSeconds, comparatorOutput);
}));
}
final JukeboxPlayable jukeboxPlayable = new JukeboxPlayable(song, tag.getBoolean("show_in_tooltip"));
data.set(StructuredDataKey.JUKEBOX_PLAYABLE, jukeboxPlayable);
removeCustomTag(data, customData);
}
private record PendingIdChange(int id, int mappedId, int level) {
}
}
@@ -40,6 +40,7 @@ import com.viaversion.viaversion.protocols.v1_20_5to1_21.data.Paintings1_20_5;
import com.viaversion.viaversion.protocols.v1_20_5to1_21.packet.ClientboundConfigurationPackets1_21;
import com.viaversion.viaversion.protocols.v1_20_5to1_21.packet.ClientboundPacket1_21;
import com.viaversion.viaversion.protocols.v1_20_5to1_21.packet.ClientboundPackets1_21;
import com.viaversion.viaversion.rewriter.RegistryDataRewriter;
import com.viaversion.viaversion.util.Key;
import com.viaversion.viaversion.util.KeyMappings;
import java.util.HashMap;
@@ -64,6 +65,7 @@ public final class EntityPacketRewriter1_21 extends EntityRewriter<ClientboundPa
registerSetEntityData(ClientboundPackets1_21.SET_ENTITY_DATA, Types1_21.ENTITY_DATA_LIST, Types1_20_5.ENTITY_DATA_LIST);
registerRemoveEntities(ClientboundPackets1_21.REMOVE_ENTITIES);
final RegistryDataRewriter registryDataRewriter = new RegistryDataRewriter(protocol);
protocol.registerClientbound(ClientboundConfigurationPackets1_21.REGISTRY_DATA, wrapper -> {
final String key = Key.stripMinecraftNamespace(wrapper.passthrough(Types.STRING));
final RegistryEntry[] entries = wrapper.passthrough(Types.REGISTRY_ENTRY_ARRAY);
@@ -99,7 +101,7 @@ public final class EntityPacketRewriter1_21 extends EntityRewriter<ClientboundPa
wrapper.cancel();
} else {
handleRegistryData1_20_5(wrapper.user(), key, entries);
registryDataRewriter.trackDimensionAndBiomes(wrapper.user(), key, entries);
}
});
@@ -215,4 +217,4 @@ public final class EntityPacketRewriter1_21 extends EntityRewriter<ClientboundPa
private record PaintingData(PaintingVariant painting, int id) {
}
}
}
@@ -28,5 +28,8 @@ bedrock-at-y-0: false
# If disabled, the client will see them as end portal frames.
sculk-shriekers-to-crying-obsidian: true
#
# Maps the darkness effect to blindness for 1.18.2 clients on 1.19+ servers.
map-darkness-effect: true
#
# Suppresses warnings of missing emulations for certain features that are not supported (e.g. world height in 1.17+).
suppress-emulation-warnings: false
suppress-emulation-warnings: false
@@ -1,4 +1,114 @@
{
"1.21.2": {
"attribute.name.tempt_range": "Mob Tempt Range",
"block.minecraft.creaking_heart": "Creaking Heart",
"block.minecraft.pale_hanging_moss": "Pale Hanging Moss",
"block.minecraft.pale_moss_block": "Pale Moss Block",
"block.minecraft.pale_moss_carpet": "Pale Moss Carpet",
"block.minecraft.pale_oak_button": "Pale Oak Button",
"block.minecraft.pale_oak_door": "Pale Oak Door",
"block.minecraft.pale_oak_fence": "Pale Oak Fence",
"block.minecraft.pale_oak_fence_gate": "Pale Oak Fence Gate",
"block.minecraft.pale_oak_hanging_sign": "Pale Oak Hanging Sign",
"block.minecraft.pale_oak_leaves": "Pale Oak Leaves",
"block.minecraft.pale_oak_log": "Pale Oak Log",
"block.minecraft.pale_oak_planks": "Pale Oak Planks",
"block.minecraft.pale_oak_pressure_plate": "Pale Oak Pressure Plate",
"block.minecraft.pale_oak_sapling": "Pale Oak Sapling",
"block.minecraft.pale_oak_sign": "Pale Oak Sign",
"block.minecraft.pale_oak_slab": "Pale Oak Slab",
"block.minecraft.pale_oak_stairs": "Pale Oak Stairs",
"block.minecraft.pale_oak_trapdoor": "Pale Oak Trapdoor",
"block.minecraft.pale_oak_wood": "Pale Oak Wood",
"block.minecraft.potted_pale_oak_sapling": "Potted Pale Oak Sapling",
"block.minecraft.stripped_pale_oak_log": "Stripped Pale Oak Log",
"block.minecraft.stripped_pale_oak_wood": "Stripped Pale Oak Wood",
"commands.drop.no_loot_table.block": "Block %s has no loot table",
"commands.rotate.success": "Rotated %s",
"commands.schedule.macro": "Can't schedule a macro",
"commands.setidletimeout.success.disabled": "The player idle timeout is now disabled",
"container.beehive.bees": "Bees: %s / %s",
"container.beehive.honey": "Honey: %s / %s",
"dataPack.minecart_improvements.description": "Improved movement for Minecarts",
"dataPack.minecart_improvements.name": "Minecart Improvements",
"dataPack.redstone_experiments.description": "Experimental Redstone changes",
"dataPack.redstone_experiments.name": "Redstone Experiments",
"dataPack.winter_drop.description": "New features and content for the Winter Drop",
"dataPack.winter_drop.name": "Winter Drop",
"death.attack.mace_smash": "%1$s was smashed by %2$s",
"death.attack.mace_smash.item": "%1$s was smashed by %2$s with %3$s",
"entity.minecraft.creaking": "Creaking",
"entity.minecraft.creaking_transient": "Creaking",
"entity.minecraft.pale_oak_boat": "Pale Oak Boat",
"entity.minecraft.pale_oak_chest_boat": "Pale Oak Boat with Chest",
"gamerule.disablePlayerMovementCheck": "Disable player movement check",
"gamerule.minecartMaxSpeed": "Minecart max speed",
"gamerule.minecartMaxSpeed.description": "Maximum default speed of a moving Minecart on land.",
"gui.abuseReport.name.comment_box_label": "Please describe why you want to report this name:",
"gui.abuseReport.reason.sexually_inappropriate": "Sexually inappropriate",
"gui.abuseReport.reason.sexually_inappropriate.description": "Skins that are graphic in nature relating to sexual acts, sexual organs, and sexual violence.",
"item.minecraft.black_bundle": "Black Bundle",
"item.minecraft.blue_bundle": "Blue Bundle",
"item.minecraft.bordure_indented_banner_pattern": "Bordure Indented Banner Pattern",
"item.minecraft.brown_bundle": "Brown Bundle",
"item.minecraft.bundle.empty.description": "Can hold a mixed stack of items",
"item.minecraft.bundle.full": "Full",
"item.minecraft.creaking_spawn_egg": "Creaking Spawn Egg",
"item.minecraft.creeper_banner_pattern.new": "Creeper Charge Banner Pattern",
"item.minecraft.cyan_bundle": "Cyan Bundle",
"item.minecraft.field_masoned_banner_pattern": "Field Masoned Banner Pattern",
"item.minecraft.flow_banner_pattern.new": "Flow Banner Pattern",
"item.minecraft.flower_banner_pattern.new": "Flower Charge Banner Pattern",
"item.minecraft.globe_banner_pattern.new": "Globe Banner Pattern",
"item.minecraft.gray_bundle": "Gray Bundle",
"item.minecraft.green_bundle": "Green Bundle",
"item.minecraft.guster_banner_pattern.new": "Guster Banner Pattern",
"item.minecraft.light_blue_bundle": "Light Blue Bundle",
"item.minecraft.light_gray_bundle": "Light Gray Bundle",
"item.minecraft.lime_bundle": "Lime Bundle",
"item.minecraft.magenta_bundle": "Magenta Bundle",
"item.minecraft.mojang_banner_pattern.new": "Thing Banner Pattern",
"item.minecraft.orange_bundle": "Orange Bundle",
"item.minecraft.pale_oak_boat": "Pale Oak Boat",
"item.minecraft.pale_oak_chest_boat": "Pale Oak Boat with Chest",
"item.minecraft.piglin_banner_pattern.new": "Snout Banner Pattern",
"item.minecraft.pink_bundle": "Pink Bundle",
"item.minecraft.purple_bundle": "Purple Bundle",
"item.minecraft.red_bundle": "Red Bundle",
"item.minecraft.skull_banner_pattern.new": "Skull Charge Banner Pattern",
"item.minecraft.white_bundle": "White Bundle",
"item.minecraft.yellow_bundle": "Yellow Bundle",
"mco.create.world.failed": "Failed to create world!",
"mco.errorMessage.initialize.failed": "Failed to initialize Realm",
"mco.upload.failed.too_big.description": "The selected world is too big. The maximum allowed size is %s.",
"mco.upload.failed.too_big.title": "World too big",
"optimizeWorld.confirm.proceed": "Create Backup and Optimize",
"options.accessibility.high_contrast_block_outline": "High Contrast Block Outlines",
"options.accessibility.high_contrast_block_outline.tooltip": "Enhances the block outline contrast of targeted block.",
"options.inactivityFpsLimit": "Reduce FPS when",
"options.inactivityFpsLimit.afk": "AFK",
"options.inactivityFpsLimit.afk.tooltip": "Limits framerate to 30 when the game is not getting any player input for more than a minute. Further limits it to 10 after 9 more minutes.",
"options.inactivityFpsLimit.minimized": "Minimized",
"options.inactivityFpsLimit.minimized.tooltip": "Limits framerate only when the game window is minimized.",
"options.rotateWithMinecart": "Rotate with Minecarts",
"options.rotateWithMinecart.tooltip": "Whether the player's view should rotate with a turning Minecart. Only available in worlds with the 'Minecart Improvements' experimental setting turned on.",
"resourcePack.runtime_failure": "Resource pack error detected",
"subtitles.block.creaking_heart.hurt": "Creaking Heart screams",
"subtitles.block.creaking_heart.spawn": "Creaking Heart awakens",
"subtitles.entity.creaking.activate": "Creaking activates",
"subtitles.entity.creaking.ambient": "Creaking creaks",
"subtitles.entity.creaking.angry": "Creaking sees player",
"subtitles.entity.creaking.attack": "Creaking attacks",
"subtitles.entity.creaking.deactivate": "Creaking deactivates",
"subtitles.entity.creaking.death": "Creaking dies",
"subtitles.entity.creaking.freeze": "Creaking stops",
"subtitles.entity.creaking.spawn": "Creaking lives",
"subtitles.entity.creaking.sway": "Creaking is shielded",
"subtitles.entity.creaking.unfreeze": "Creaking moves",
"subtitles.entity.parrot.imitate.creaking": "Parrot creaks",
"subtitles.item.bundle.insert_fail": "Bundle full",
"subtitles.ui.hud.bubble_pop": "Breath meter dropping"
},
"1.21": {
"argument.entity.selector.nearestEntity": "Nearest entity",
"attribute.name.generic.burning_time": "Burning Time",
@@ -4691,4 +4801,4 @@
"entity.MinecartChest.name": "Minecart with Chest",
"attribute.name.generic.armorToughness": "Armor Toughness"
}
}
}
@@ -35,6 +35,7 @@ public class ViaFabricAddon implements ViaBackwardsPlatform, Runnable {
Path configDirPath = FabricLoader.getInstance().getConfigDir().resolve("ViaBackwards");
configDir = configDirPath.toFile();
this.init(new File(getDataFolder(), "config.yml"));
this.enable();
}
@Override
+4 -4
View File
@@ -1,6 +1,6 @@
projectVersion=5.0.4
projectVersion=5.1.2-SNAPSHOT
# Smile emoji
mcVersions=1.21.1,1.21,1.20.6,1.20.5,1.20.4, 1.20.3, 1.20.2, 1.20.1, 1.20, 1.19.4, 1.19.3, 1.19.2, 1.19.1, 1.19, 1.18.2, 1.18.1, 1.18, 1.17.1, 1.17, 1.16.5, 1.16.4, 1.16.3, 1.16.2, 1.16.1, 1.16, 1.15.2, 1.15.1, 1.15, 1.14.4, 1.14.3, 1.14.2, 1.14.1, 1.14, 1.13.2, 1.13.1, 1.13, 1.12.2, 1.12.1, 1.12, 1.11.2, 1.11.1, 1.11, 1.10.2, 1.10.1, 1.10
mcVersionRange=1.10-1.21.1
velocityVersion=3.3
mcVersions=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.3
velocityVersion=3.4
+3 -2
View File
@@ -3,7 +3,7 @@ metadata.format.version = "1.1"
[versions]
# ViaVersion
viaver = "5.0.4-SNAPSHOT"
viaver = "5.1.2-SNAPSHOT"
# Common provided
netty = "4.0.20.Final"
@@ -16,7 +16,7 @@ checkerQual = "3.39.0"
paper = "1.16.5-R0.1-SNAPSHOT"
velocity = "3.1.1"
fabricLoader = "0.11.6"
viaProxy = "3.3.5"
[libraries]
@@ -31,3 +31,4 @@ checkerQual = { group = "org.checkerframework", name = "checker-qual", version.r
paper = { group = "com.destroystokyo.paper", name = "paper-api", version.ref = "paper" }
velocity = { group = "com.velocitypowered", name = "velocity-api", version.ref = "velocity" }
fabricLoader = { group = "net.fabricmc", name = "fabric-loader", version.ref = "fabricLoader" }
viaProxy = { group = "net.raphimc", name = "ViaProxy", version.ref = "viaProxy" }
+2 -2
View File
@@ -1,7 +1,7 @@
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
distributionSha256Sum=31c55713e40233a8303827ceb42ca48a47267a0ad4bab9177123121e71524c26
distributionUrl=https\://services.gradle.org/distributions/gradle-8.10.2-bin.zip
distributionSha256Sum=f397b287023acdba1e9f6fc5ea72d22dd63669d59ed4a289a29b1a76eee151c6
distributionUrl=https\://services.gradle.org/distributions/gradle-8.11.1-bin.zip
networkTimeout=10000
validateDistributionUrl=true
zipStoreBase=GRADLE_USER_HOME
@@ -52,6 +52,7 @@ public class VelocityPlugin implements ViaBackwardsPlatform {
public void onProxyStart(ProxyInitializeEvent event) {
this.logger = new LoggerWrapper(loggerSlf4j);
Via.getManager().addEnableListener(() -> this.init(new File(getDataFolder(), "config.yml")));
Via.getManager().addPostEnableListener(this::enable);
}
@Override