Compare commits

...
53 Commits
Author SHA1 Message Date
Nassim Jahnke f923648fe8 4.8.1 Release 2023-10-03 20:58:18 +10:00
Nassim Jahnke 92c160c43a Fix trade list sending
Forgot to remove cancellation from initial configuration testing
Fixes #594
2023-09-28 11:19:36 +10:00
Nassim Jahnke cc7df5a4fc Fix serverbound beacon secondary effect 2023-09-28 09:36:41 +10:00
Nassim Jahnke 8e6727c350 Handle changed custom potion effects tag 2023-09-27 14:58:03 +10:00
Nassim Jahnke e73eeeb434 Update branch check again 2023-09-26 10:48:42 +10:00
Brokkonaut 96650decae Fix packet id of player velocity packets (#593) 2023-09-26 10:47:57 +10:00
Nassim Jahnke 1d35b1cdb2 [ci skip] Fix branch check in publishing 2023-09-26 00:24:36 +10:00
Nassim Jahnke c6711919b1 Add separate client and server state handling 2023-09-25 18:34:03 +10:00
Nassim Jahnke 67f7a66ca5 Fix 1.20.2->1.20 if run on the backend 2023-09-25 10:54:52 +10:00
Nassim Jahnke 4cba8072c4 Fix implementation version 2023-09-24 23:56:29 +10:00
Nassim Jahnke cfbe287361 Bump version to 4.8.1-SNAPSHOT 2023-09-24 23:55:25 +10:00
Nassim Jahnke f254869c66 4.8.0 Release 2023-09-21 10:35:54 +10:00
Nassim Jahnke 57ca5f1bf5 Fix particle handling 2023-09-21 10:35:42 +10:00
Nassim Jahnke b69ebe6657 Send the config ack packet 2023-09-19 13:25:25 +10:00
Nassim Jahnke ea2fac0788 Handle configuration start
TODO: Check whether all the necessary data for the join game packet is always expected by the client or if we need to cache it from the initial login
2023-09-19 13:20:19 +10:00
Nassim Jahnke 2b2384acc1 Remove new trim patterns in 1.20->1.19
Fixes #570
2023-09-15 18:13:12 +10:00
SplotyCode 643c6b18dd Fix scoreboard component coversion (#586) 2023-09-08 12:22:16 +10:00
Nassim Jahnke 80438807cc 1.20.2-pre2 2023-09-08 09:33:31 +10:00
Nassim Jahnke 2f373adad4 [ci skip] Update Blossom 2023-09-06 11:30:10 +10:00
Nassim Jahnke e2546b8471 1.20.2-pre1 2023-09-06 00:59:17 +10:00
Nassim Jahnke 88fd52ac6e [ci skip] Update Gradle wrapper and checkout actions 2023-09-05 21:29:01 +10:00
Nassim Jahnke c13c3f17fc Fix scoreboard objective reading 2023-08-31 11:48:48 +10:00
Nassim Jahnke 3b9354c4f6 23w35a (untested) 2023-08-31 00:53:48 +10:00
Nassim Jahnke 83636ecf51 Fix 1.16->1.15 hover components in books
Fixes #572
2023-08-27 18:52:43 +10:00
Nassim Jahnke 082b61a956 [ci skip] Update Hangar publish plugin 2023-08-26 20:05:17 +10:00
Nassim Jahnke 108e96ec6d Move world data tracker into first join game handler 2023-08-18 01:36:37 +10:00
Nassim Jahnke 6dd5cb20d9 23w33a 2023-08-18 01:32:50 +10:00
EnZaXD 2a2a0d8a72 Adde1.9 protocols from ViaVersion to ViaBackwards (#580) 2023-08-14 11:06:59 +10:00
Nassim Jahnke 9c68b30865 Merge remote-tracking branch 'origin/master' into dev
# Conflicts:
#	.github/workflows/gradle.yml
2023-08-14 10:15:19 +10:00
EnZaXD e0b7426dc9 Remove unused chat-types setting from config.yml (#579) 2023-08-14 10:04:02 +10:00
EnZaXD 43e2b242c4 Fix 1.19.4 -> 1.19.3 precipitation reading (#578) 2023-08-14 10:02:52 +10:00
Nassim Jahnke 567725d996 Update README 2023-08-11 21:36:20 +10:00
Nassim Jahnke 4fa985f131 Also publish dev branch builds to Hangar 2023-08-11 20:34:24 +10:00
Nassim Jahnke 2e8d6bcc9f Include link to commit in autopublished changelog 2023-08-11 16:26:17 +10:00
Nassim Jahnke 95e3446e8c Add mappings for changed block states and sounds 2023-08-11 16:08:10 +10:00
Nassim Jahnke 725e505514 Also handle release versions on publish 2023-08-11 15:54:59 +10:00
Nassim Jahnke c053975535 Finish publish action 2023-08-11 12:16:42 +10:00
Nassim Jahnke 70725d4aaf Add Hangar publishing 2023-08-11 00:26:51 +10:00
Nassim Jahnke 0d147653f3 Fix spawn tracker mapping data check 2023-08-10 17:13:08 +10:00
Nassim Jahnke f4cc9d4730 Fix double register 2023-08-10 17:06:49 +10:00
Nassim Jahnke 406733b13a 23w32a 2023-08-10 16:55:03 +10:00
Nassim Jahnke 9df7debb7e Finish 23w31a 2023-08-06 13:17:31 +10:00
Nassim Jahnke e12d491b53 Start working on 23w31a 2023-08-05 14:12:45 +10:00
Kichura 4d4e739939 Friendly names in CI, Update Blossom. (#562) 2023-07-25 11:08:22 +10:00
Nassim Jahnke 2904ad54c6 Fix non item display rotation 2023-07-24 20:58:30 +10:00
Nassim Jahnke 92e5fe8a9b Update gradle wrapper 2023-07-11 23:34:47 +02:00
Nassim Jahnke bc0cb7702c Properly handle changed item display rotation 2023-07-03 20:16:52 +02:00
Nassim Jahnke 04d75264e0 Add required 1.18(.1) tag
Fixes #558
2023-06-15 10:10:32 +02:00
tahmid-23 4a308f9d81 Fix 1.19.3->1.19.1 entity sound packet (#555) 2023-06-15 09:56:59 +02:00
EnZaXD 4627142700 Emulate "trim_pattern" registry in 1.19.4 -> 1.20 if not present (#557) 2023-06-14 19:04:28 +02:00
Nassim Jahnke 817080b7a6 Extend correct item rewriter
Fixes #551
2023-06-10 10:14:40 +02:00
Nassim Jahnke 8f51ab2f6a Fix display rotation change 2023-06-09 12:28:08 +02:00
Nassim Jahnke 359cdb13eb Bump version to 4.7.1-SNAPSHOT 2023-06-09 12:19:34 +02:00
47 changed files with 1766 additions and 199 deletions

No files matched your search

+5 -6
View File
@@ -9,16 +9,15 @@ jobs:
runs-on: ubuntu-22.04
steps:
- uses: actions/checkout@v3
- uses: gradle/wrapper-validation-action@v1
- name: Checkout Repository
uses: actions/checkout@v4
- name: Validate Gradle Wrapper
uses: gradle/wrapper-validation-action@v1
- name: Set up JDK 11
uses: actions/setup-java@v3
with:
distribution: 'temurin'
java-version: 11
check-latest: true
- name: Build with Gradle
run: ./gradlew build
- uses: actions/upload-artifact@v3
with:
name: artifact
path: build/libs
+25
View File
@@ -0,0 +1,25 @@
name: Publish to Hangar and Modrinth
on:
push:
branches:
- master
- dev
jobs:
publish:
if: github.repository_owner == 'ViaVersion'
runs-on: ubuntu-22.04
steps:
- uses: actions/checkout@v4
- uses: gradle/wrapper-validation-action@v1
- name: Set up JDK 17
uses: actions/setup-java@v3
with:
distribution: 'temurin'
java-version: 17
check-latest: true
- name: Publish
env:
HANGAR_TOKEN: ${{ secrets.HANGAR_TOKEN }}
MODRINTH_TOKEN: ${{ secrets.MODRINTH_TOKEN }}
run: ./gradlew build modrinth publishAllPublicationsToHangar --stacktrace
+24 -16
View File
@@ -4,43 +4,51 @@
[![Build Status](https://github.com/ViaVersion/ViaBackwards/actions/workflows/gradle.yml/badge.svg?branch=master)](https://github.com/ViaVersion/ViaBackwards/actions)
[![Discord](https://img.shields.io/badge/chat-on%20discord-blue.svg)](https://viaversion.com/discord)
**Allows older Minecraft client versions to connect to newer server versions**
**Allows older Minecraft client versions to connect to newer server versions.**
Requires [ViaVersion](https://hangar.papermc.io/ViaVersion/ViaVersion) to be installed..
Supported Versions
-
**Green** = ViaVersion\
**Purple** = ViaBackwards addition
As a plugin, ViaBackwards runs on servers on releases 1.10-latest. Versions from the dev branch will also support the
latest snapshot. You can also use ViaBackwards in ViaFabric or ViaFabricPlus.
![supported_versions](https://i.imgur.com/KpLsMHj.png)
See [HERE](https://github.com/ViaVersion) for an overview of the different Via* projects.
Releases / Dev Builds
Releases/Dev Builds
-
**Requires [ViaVersion](https://www.spigotmc.org/resources/viaversion.19254/) to be installed**
You can find the latest dev builds here:\
**Jenkins:** https://ci.viaversion.com/view/ViaBackwards/
You can find releases in the following places:
**Spigot page:** https://www.spigotmc.org/resources/viabackwards.27448/
- **Hangar (for our plugins)**: https://hangar.papermc.io/ViaVersion/ViaBackwards
- **Modrinth (for our mods)**: https://modrinth.com/mod/viabackwards
- **GitHub**: https://github.com/ViaVersion/ViaBackwards/releases
**CurseForge page:** https://www.curseforge.com/minecraft/mc-mods/viabackwards
Dev builds for **all** of our projects are on our Jenkins server:
- **Jenkins**: https://ci.viaversion.com/view/ViaBackwards/
Known issues
-
* Custom 1.17+ min_y and height world values are not and will (most likely) never be supported => Clients older than 1.17 will not be able to see or interact with blocks below y=0 and above y=255
* < 1.17 clients on 1.17+ servers might experience inventory desyncs on certain inventory click actions
* 1.17+ min_y and height world values that are not 0/256 **are not supported**. Clients older than
1.17 will not be able to see or interact with blocks below y=0 and above y=255
* <1.17 clients on 1.17+ servers might experience inventory desyncs on certain inventory click actions
* Sound mappings are incomplete ([see here](https://github.com/ViaVersion/ViaBackwards/issues/326))
Other Links
-
**Maven:** https://repo.viaversion.com
**Issue tracker:** https://github.com/ViaVersion/ViaBackwards/issues
**List of contributors:** https://github.com/ViaVersion/ViaBackwards/graphs/contributors
Building
-
After cloning this repository, build the project with Gradle by running `./gradlew build` and take the created jar out
of the `build/libs` directory.
License
-
This project is licensed under the [GNU General Public License](LICENSE).
This project is licensed under the [GNU General Public License Version 3](LICENSE).
Special Thanks
-
+27
View File
@@ -38,6 +38,33 @@ fun Project.latestCommitHash(): String {
return byteOut.toString(Charsets.UTF_8.name()).trim()
}
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()
}
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()
}
fun Project.parseMinecraftSnapshotVersion(version: String): String? {
val separatorIndex = version.indexOf('-')
val lastSeparatorIndex = version.lastIndexOf('-')
if (separatorIndex == -1 || separatorIndex == lastSeparatorIndex) {
return null
}
return version.substring(separatorIndex + 1, lastSeparatorIndex)
}
fun JavaPluginExtension.javaTarget(version: Int) {
sourceCompatibility = JavaVersion.toVersion(version)
targetCompatibility = JavaVersion.toVersion(version)
+1 -1
View File
@@ -5,7 +5,7 @@ plugins {
allprojects {
group = "com.viaversion"
version = "4.7.0"
version = property("projectVersion") as String // from gradle.properties
description = "Allow older clients to join newer server versions."
}
+10 -3
View File
@@ -1,10 +1,17 @@
plugins {
id("net.kyori.blossom")
id("org.jetbrains.gradle.plugin.idea-ext")
}
blossom {
replaceToken("\$VERSION", project.version)
replaceToken("\$IMPL_VERSION", "git-ViaBackwards-${project.version}:${rootProject.latestCommitHash()}")
sourceSets {
main {
blossom {
javaSources {
property("version", project.version.toString())
property("impl_version", "git-ViaBackwards-${project.version}:${rootProject.latestCommitHash()}")
}
}
}
}
dependencies {
@@ -17,7 +17,16 @@
*/
package com.viaversion.viabackwards.utils;
public class VersionInfo {
public final class VersionInfo {
public static final String VERSION = "$VERSION";
public static final String VERSION = "{{ version }}";
private static final String IMPLEMENTATION_VERSION = "{{ impl_version }}";
public static String getVersion() {
return VERSION;
}
public static String getImplementationVersion() {
return IMPLEMENTATION_VERSION;
}
}
@@ -21,10 +21,8 @@ import com.viaversion.viaversion.util.Config;
import java.io.File;
import java.net.URL;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.checkerframework.checker.nullness.qual.Nullable;
public class ViaBackwardsConfig extends Config implements com.viaversion.viabackwards.api.ViaBackwardsConfig {
@@ -34,7 +32,6 @@ public class ViaBackwardsConfig extends Config implements com.viaversion.viaback
private boolean alwaysShowOriginalMobName;
private boolean fix1_13FormattedInventoryTitles;
private boolean handlePingsAsInvAcknowledgements;
private Map<String, String> chatTypeFormats;
public ViaBackwardsConfig(File configFile) {
super(configFile);
@@ -53,7 +50,6 @@ public class ViaBackwardsConfig extends Config implements com.viaversion.viaback
fix1_13FormattedInventoryTitles = getBoolean("fix-formatted-inventory-titles", true);
alwaysShowOriginalMobName = getBoolean("always-show-original-mob-name", true);
handlePingsAsInvAcknowledgements = getBoolean("handle-pings-as-inv-acknowledgements", false);
chatTypeFormats = get("chat-types-1_19_1", Map.class, new HashMap<String, String>());
}
@Override
@@ -86,11 +82,6 @@ public class ViaBackwardsConfig extends Config implements com.viaversion.viaback
return handlePingsAsInvAcknowledgements || Boolean.getBoolean("com.viaversion.handlePingsAsInvAcknowledgements");
}
@Override
public @Nullable String chatTypeFormat(final String translationKey) {
return chatTypeFormats.get(translationKey);
}
@Override
public URL getDefaultConfigURL() {
return getClass().getClassLoader().getResource("assets/viabackwards/config.yml");
@@ -17,8 +17,6 @@
*/
package com.viaversion.viabackwards.api;
import org.checkerframework.checker.nullness.qual.Nullable;
public interface ViaBackwardsConfig {
/**
@@ -42,6 +40,11 @@ public interface ViaBackwardsConfig {
*/
boolean isFix1_13FacePlayer();
/**
* Converts the 1.13 face look-at packet for 1.12- players. Requires a bit of extra caching.
*
* @return true if enabled
*/
boolean fix1_13FormattedInventoryTitle();
/**
@@ -51,7 +54,11 @@ public interface ViaBackwardsConfig {
*/
boolean alwaysShowOriginalMobName();
/**
* Sends inventory acknowledgement packets to act as a replacement for ping packets for sub 1.17 clients.
* This only takes effect for ids in the short range. Useful for anticheat compatibility.
*
* @return true if enabled
*/
boolean handlePingsAsInvAcknowledgements();
@Nullable String chatTypeFormat(String translationKey);
}
@@ -51,18 +51,22 @@ import com.viaversion.viabackwards.protocol.protocol1_19_1to1_19_3.Protocol1_19_
import com.viaversion.viabackwards.protocol.protocol1_19_3to1_19_4.Protocol1_19_3To1_19_4;
import com.viaversion.viabackwards.protocol.protocol1_19_4to1_20.Protocol1_19_4To1_20;
import com.viaversion.viabackwards.protocol.protocol1_19to1_19_1.Protocol1_19To1_19_1;
import com.viaversion.viabackwards.protocol.protocol1_20to1_20_2.Protocol1_20To1_20_2;
import com.viaversion.viabackwards.protocol.protocol1_9_1_2to1_9_3_4.Protocol1_9_1_2To1_9_3_4;
import com.viaversion.viabackwards.protocol.protocol1_9_4to1_10.Protocol1_9_4To1_10;
import com.viaversion.viabackwards.protocol.protocol1_9to1_9_1.Protocol1_9To1_9_1;
import com.viaversion.viabackwards.utils.VersionInfo;
import com.viaversion.viaversion.api.Via;
import com.viaversion.viaversion.api.protocol.ProtocolManager;
import com.viaversion.viaversion.api.protocol.version.ProtocolVersion;
import com.viaversion.viaversion.update.Version;
import java.io.File;
import java.util.Arrays;
import java.util.logging.Logger;
public interface ViaBackwardsPlatform {
String MINIMUM_VV_VERSION = "4.7.0";
String IMPL_VERSION = "$IMPL_VERSION";
String MINIMUM_VV_VERSION = "4.8.1";
/**
* Initialize ViaBackwards.
@@ -78,13 +82,15 @@ public interface ViaBackwardsPlatform {
return;
}
Via.getManager().getSubPlatforms().add(IMPL_VERSION);
Via.getManager().getSubPlatforms().add(VersionInfo.getImplementationVersion());
getLogger().info("Loading translations...");
TranslatableRewriter.loadTranslatables();
getLogger().info("Registering protocols...");
final ProtocolManager protocolManager = Via.getManager().getProtocolManager();
protocolManager.registerProtocol(new Protocol1_9To1_9_1(), ProtocolVersion.v1_9, ProtocolVersion.v1_9_1);
protocolManager.registerProtocol(new Protocol1_9_1_2To1_9_3_4(), Arrays.asList(ProtocolVersion.v1_9_1.getVersion(), ProtocolVersion.v1_9_2.getVersion()), ProtocolVersion.v1_9_3.getVersion());
protocolManager.registerProtocol(new Protocol1_9_4To1_10(), ProtocolVersion.v1_9_3, ProtocolVersion.v1_10);
protocolManager.registerProtocol(new Protocol1_10To1_11(), ProtocolVersion.v1_10, ProtocolVersion.v1_11);
@@ -126,6 +132,7 @@ public interface ViaBackwardsPlatform {
protocolManager.registerProtocol(new Protocol1_19_3To1_19_4(), ProtocolVersion.v1_19_3, ProtocolVersion.v1_19_4);
protocolManager.registerProtocol(new Protocol1_19_4To1_20(), ProtocolVersion.v1_19_4, ProtocolVersion.v1_20);
protocolManager.registerProtocol(new Protocol1_20To1_20_2(), ProtocolVersion.v1_20, ProtocolVersion.v1_20_2);
}
/**
@@ -90,6 +90,10 @@ public abstract class EntityRewriter<C extends ClientboundPacketType, T extends
public PacketHandler getSpawnTrackerWithDataHandler1_19(EntityType fallingBlockType) {
return wrapper -> {
if (protocol.getMappingData() == null) {
return;
}
// Check against the UNMAPPED entity type
EntityType entityType = trackAndMapEntity(wrapper);
if (entityType == fallingBlockType) {
@@ -40,6 +40,10 @@ public class ItemRewriter<C extends ClientboundPacketType, S extends Serverbound
super(protocol, true);
}
public ItemRewriter(T protocol, Type<Item> itemType, Type<Item[]> itemArrayType) {
super(protocol, itemType, itemArrayType, true);
}
@Override
public @Nullable Item handleItemToClient(@Nullable Item item) {
if (item == null) {
@@ -82,7 +86,7 @@ public class ItemRewriter<C extends ClientboundPacketType, S extends Serverbound
}
}
MappedItem data = protocol.getMappingData().getMappedItem(item.identifier());
MappedItem data = protocol.getMappingData() != null ? protocol.getMappingData().getMappedItem(item.identifier()) : null;
if (data == null) {
// Just rewrite the id
return super.handleItemToClient(item);
@@ -21,6 +21,7 @@ import com.viaversion.viabackwards.api.BackwardsProtocol;
import com.viaversion.viaversion.api.minecraft.item.Item;
import com.viaversion.viaversion.api.protocol.packet.ClientboundPacketType;
import com.viaversion.viaversion.api.protocol.packet.ServerboundPacketType;
import com.viaversion.viaversion.api.type.Type;
import com.viaversion.viaversion.libs.opennbt.tag.builtin.CompoundTag;
import com.viaversion.viaversion.libs.opennbt.tag.builtin.ListTag;
import com.viaversion.viaversion.libs.opennbt.tag.builtin.StringTag;
@@ -35,7 +36,11 @@ public abstract class ItemRewriterBase<C extends ClientboundPacketType, S extend
protected final boolean jsonNameFormat;
protected ItemRewriterBase(T protocol, boolean jsonNameFormat) {
super(protocol);
this(protocol, Type.FLAT_VAR_INT_ITEM, Type.FLAT_VAR_INT_ITEM_ARRAY_VAR_INT, jsonNameFormat);
}
public ItemRewriterBase(T protocol, Type<Item> itemType, Type<Item[]> itemArrayType, boolean jsonNameFormat) {
super(protocol, itemType, itemArrayType);
this.jsonNameFormat = jsonNameFormat;
nbtTagName = "VB|" + protocol.getClass().getSimpleName();
}
@@ -41,10 +41,11 @@ import com.viaversion.viaversion.libs.opennbt.tag.builtin.ListTag;
import com.viaversion.viaversion.libs.opennbt.tag.builtin.StringTag;
import com.viaversion.viaversion.libs.opennbt.tag.builtin.Tag;
import com.viaversion.viaversion.protocols.protocol1_11to1_10.EntityIdRewriter;
import com.viaversion.viaversion.protocols.protocol1_9_1_2to1_9_3_4.types.Chunk1_9_3_4Type;
import com.viaversion.viaversion.protocols.protocol1_9_3to1_9_1_2.ClientboundPackets1_9_3;
import com.viaversion.viaversion.protocols.protocol1_9_3to1_9_1_2.ServerboundPackets1_9_3;
import com.viaversion.viaversion.protocols.protocol1_9_3to1_9_1_2.storage.ClientWorld;
import com.viaversion.viaversion.protocols.protocol1_9_3to1_9_1_2.types.Chunk1_9_3_4Type;
import java.util.Arrays;
import java.util.Optional;
@@ -33,11 +33,12 @@ import com.viaversion.viaversion.libs.opennbt.tag.builtin.LongArrayTag;
import com.viaversion.viaversion.libs.opennbt.tag.builtin.Tag;
import com.viaversion.viaversion.protocols.protocol1_12to1_11_1.ClientboundPackets1_12;
import com.viaversion.viaversion.protocols.protocol1_12to1_11_1.ServerboundPackets1_12;
import com.viaversion.viaversion.protocols.protocol1_9_1_2to1_9_3_4.types.Chunk1_9_3_4Type;
import com.viaversion.viaversion.protocols.protocol1_9_3to1_9_1_2.ServerboundPackets1_9_3;
import com.viaversion.viaversion.protocols.protocol1_9_3to1_9_1_2.storage.ClientWorld;
import java.util.Iterator;
import java.util.Map;
import com.viaversion.viaversion.protocols.protocol1_9_3to1_9_1_2.types.Chunk1_9_3_4Type;
import org.checkerframework.checker.nullness.qual.Nullable;
public class BlockItemPackets1_12 extends LegacyBlockItemRewriter<ClientboundPackets1_12, ServerboundPackets1_9_3, Protocol1_11_1To1_12> {
@@ -54,8 +54,8 @@ import com.viaversion.viaversion.protocols.protocol1_13to1_12_2.Protocol1_13To1_
import com.viaversion.viaversion.protocols.protocol1_13to1_12_2.data.BlockIdData;
import com.viaversion.viaversion.protocols.protocol1_13to1_12_2.data.SpawnEggRewriter;
import com.viaversion.viaversion.protocols.protocol1_13to1_12_2.types.Chunk1_13Type;
import com.viaversion.viaversion.protocols.protocol1_9_1_2to1_9_3_4.types.Chunk1_9_3_4Type;
import com.viaversion.viaversion.protocols.protocol1_9_3to1_9_1_2.storage.ClientWorld;
import com.viaversion.viaversion.protocols.protocol1_9_3to1_9_1_2.types.Chunk1_9_3_4Type;
import com.viaversion.viaversion.util.Key;
import java.util.ArrayList;
import java.util.HashMap;
@@ -240,7 +240,7 @@ public class BlockItemPackets1_13 extends com.viaversion.viabackwards.api.rewrit
map(Type.UNSIGNED_BYTE);
map(Type.FLAT_ITEM_ARRAY, Type.ITEM_ARRAY);
handler(itemArrayHandler(Type.ITEM_ARRAY));
handler(itemArrayToClientHandler(Type.ITEM_ARRAY));
}
});
@@ -203,11 +203,7 @@ public class PlayerPacket1_13 extends RewriterBase<Protocol1_12_2To1_13> {
if (mode == 0 || mode == 2) {
JsonElement value = wrapper.read(Type.COMPONENT);
String legacyValue = protocol.jsonToLegacy(value);
if (legacyValue.length() > 32) {
legacyValue = legacyValue.substring(0, 32);
}
wrapper.write(Type.STRING, legacyValue);
wrapper.write(Type.STRING, ChatUtil.fromLegacy(legacyValue, 'f', 32));
int type = wrapper.read(Type.VAR_INT);
wrapper.write(Type.STRING, type == 1 ? "hearts" : "integer");
}
@@ -225,11 +221,7 @@ public class PlayerPacket1_13 extends RewriterBase<Protocol1_12_2To1_13> {
if (action == 0 || action == 2) {
JsonElement displayName = wrapper.read(Type.COMPONENT);
String legacyTextDisplayName = protocol.jsonToLegacy(displayName);
legacyTextDisplayName = ChatUtil.removeUnusedColor(legacyTextDisplayName, 'f');
if (legacyTextDisplayName.length() > 32) {
legacyTextDisplayName = legacyTextDisplayName.substring(0, 32);
}
wrapper.write(Type.STRING, legacyTextDisplayName);
wrapper.write(Type.STRING, ChatUtil.fromLegacy(legacyTextDisplayName, 'f', 32));
byte flags = wrapper.read(Type.BYTE);
String nameTagVisibility = wrapper.read(Type.STRING);
@@ -247,18 +239,10 @@ public class PlayerPacket1_13 extends RewriterBase<Protocol1_12_2To1_13> {
if (ViaBackwards.getConfig().addTeamColorTo1_13Prefix()) {
prefix += "§" + (colour > -1 && colour <= 15 ? Integer.toHexString(colour) : "r");
}
prefix = ChatUtil.removeUnusedColor(prefix, 'f', true);
if (prefix.length() > 16) prefix = prefix.substring(0, 16);
if (prefix.endsWith("§")) prefix = prefix.substring(0, prefix.length() - 1);
String suffix = protocol.jsonToLegacy(suffixComponent);
suffix = ChatUtil.removeUnusedColor(suffix, '\0'); // Don't remove white coloring
if (suffix.length() > 16) suffix = suffix.substring(0, 16);
if (suffix.endsWith("§")) suffix = suffix.substring(0, suffix.length() - 1);
wrapper.write(Type.STRING, prefix);
wrapper.write(Type.STRING, suffix);
wrapper.write(Type.STRING, ChatUtil.fromLegacyPrefix(prefix, 'f', 16));
wrapper.write(Type.STRING, ChatUtil.fromLegacy(suffix, '\0', 16));
wrapper.write(Type.BYTE, flags);
wrapper.write(Type.STRING, nameTagVisibility);
@@ -33,8 +33,10 @@ import com.viaversion.viaversion.api.protocol.remapper.PacketHandlers;
import com.viaversion.viaversion.api.protocol.version.ProtocolVersion;
import com.viaversion.viaversion.api.type.Type;
import com.viaversion.viaversion.api.type.types.UUIDIntArrayType;
import com.viaversion.viaversion.libs.gson.JsonElement;
import com.viaversion.viaversion.libs.opennbt.tag.builtin.CompoundTag;
import com.viaversion.viaversion.libs.opennbt.tag.builtin.IntArrayTag;
import com.viaversion.viaversion.libs.opennbt.tag.builtin.ListTag;
import com.viaversion.viaversion.libs.opennbt.tag.builtin.LongArrayTag;
import com.viaversion.viaversion.libs.opennbt.tag.builtin.StringTag;
import com.viaversion.viaversion.libs.opennbt.tag.builtin.Tag;
@@ -302,6 +304,22 @@ public class BlockItemPackets1_16 extends com.viaversion.viabackwards.api.rewrit
}
}
// Handle hover event changes in book pages
if ((item.identifier() == 758 || item.identifier() == 759) && tag != null) {
Tag pagesTag = tag.get("pages");
if (pagesTag instanceof ListTag) {
for (Tag page : ((ListTag) pagesTag)) {
if (!(page instanceof StringTag)) {
continue;
}
StringTag pageTag = (StringTag) page;
JsonElement jsonElement = protocol.getTranslatableRewriter().processText(pageTag.getValue());
pageTag.setValue(jsonElement.toString());
}
}
}
InventoryPackets.newToOldAttributes(item);
enchantmentRewriter.handleToClient(item);
return item;
@@ -203,7 +203,7 @@ public final class BlockItemPackets1_17 extends ItemRewriter<ClientboundPackets1
wrapper.cancel();
}
});
handler(getSpawnParticleHandler(Type.FLAT_VAR_INT_ITEM));
handler(getSpawnParticleHandler());
}
});
@@ -134,7 +134,7 @@ public final class BlockItemPackets1_19 extends ItemRewriter<ClientboundPackets1
wrapper.cancel();
}
});
handler(getSpawnParticleHandler(Type.FLAT_VAR_INT_ITEM));
handler(getSpawnParticleHandler());
}
});
@@ -121,6 +121,7 @@ public final class Protocol1_19_1To1_19_3 extends BackwardsProtocol<ClientboundP
}
wrapper.write(Type.VAR_INT, mappedId);
return;
}
// Convert the resource location to the corresponding integer id
@@ -28,11 +28,7 @@ import com.viaversion.viaversion.api.type.Type;
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.libs.opennbt.tag.builtin.ByteTag;
import com.viaversion.viaversion.libs.opennbt.tag.builtin.CompoundTag;
import com.viaversion.viaversion.libs.opennbt.tag.builtin.ListTag;
import com.viaversion.viaversion.libs.opennbt.tag.builtin.StringTag;
import com.viaversion.viaversion.libs.opennbt.tag.builtin.Tag;
import com.viaversion.viaversion.libs.opennbt.tag.builtin.*;
import com.viaversion.viaversion.protocols.protocol1_19_3to1_19_1.ClientboundPackets1_19_3;
import com.viaversion.viaversion.protocols.protocol1_19_4to1_19_3.ClientboundPackets1_19_4;
@@ -72,7 +68,7 @@ public final class EntityPackets1_19_4 extends EntityRewriter<ClientboundPackets
final ListTag biomes = biomeRegistry.get("value");
for (final Tag biomeTag : biomes) {
final CompoundTag biomeData = ((CompoundTag) biomeTag).get("element");
final ByteTag hasPrecipitation = biomeData.get("has_precipitation");
final NumberTag hasPrecipitation = biomeData.get("has_precipitation");
biomeData.put("precipitation", new StringTag(hasPrecipitation.asByte() == 1 ? "rain" : "none"));
}
});
@@ -18,25 +18,25 @@
package com.viaversion.viabackwards.protocol.protocol1_19_4to1_20;
import com.viaversion.viabackwards.api.BackwardsProtocol;
import com.viaversion.viabackwards.api.data.BackwardsMappings;
import com.viaversion.viabackwards.api.rewriters.SoundRewriter;
import com.viaversion.viabackwards.api.rewriters.TranslatableRewriter;
import com.viaversion.viabackwards.protocol.protocol1_19_4to1_20.data.BackwardsMappings;
import com.viaversion.viabackwards.protocol.protocol1_19_4to1_20.packets.BlockItemPackets1_20;
import com.viaversion.viabackwards.protocol.protocol1_19_4to1_20.packets.EntityPackets1_20;
import com.viaversion.viaversion.api.connection.UserConnection;
import com.viaversion.viaversion.api.minecraft.RegistryType;
import com.viaversion.viaversion.api.minecraft.entities.Entity1_19_4Types;
import com.viaversion.viaversion.api.type.Type;
import com.viaversion.viaversion.data.entity.EntityTrackerBase;
import com.viaversion.viaversion.protocols.protocol1_19_4to1_19_3.ClientboundPackets1_19_4;
import com.viaversion.viaversion.protocols.protocol1_19_4to1_19_3.ServerboundPackets1_19_4;
import com.viaversion.viaversion.protocols.protocol1_20to1_19_4.Protocol1_20To1_19_4;
import com.viaversion.viaversion.rewriter.StatisticsRewriter;
import com.viaversion.viaversion.rewriter.TagRewriter;
import java.util.Arrays;
public final class Protocol1_19_4To1_20 extends BackwardsProtocol<ClientboundPackets1_19_4, ClientboundPackets1_19_4, ServerboundPackets1_19_4, ServerboundPackets1_19_4> {
public static final BackwardsMappings MAPPINGS = new BackwardsMappings("1.20", "1.19.4", Protocol1_20To1_19_4.class);
public static final BackwardsMappings MAPPINGS = new BackwardsMappings();
private final TranslatableRewriter<ClientboundPackets1_19_4> translatableRewriter = new TranslatableRewriter<>(this);
private final EntityPackets1_20 entityRewriter = new EntityPackets1_20(this);
private final BlockItemPackets1_20 itemRewriter = new BlockItemPackets1_20(this);
@@ -50,6 +50,7 @@ public final class Protocol1_19_4To1_20 extends BackwardsProtocol<ClientboundPac
super.registerPackets();
final TagRewriter<ClientboundPackets1_19_4> tagRewriter = new TagRewriter<>(this);
tagRewriter.addEmptyTag(RegistryType.BLOCK, "minecraft:replaceable_plants");
tagRewriter.registerGeneric(ClientboundPackets1_19_4.TAGS);
final SoundRewriter<ClientboundPackets1_19_4> soundRewriter = new SoundRewriter<>(this);
@@ -0,0 +1,49 @@
/*
* This file is part of ViaBackwards - https://github.com/ViaVersion/ViaBackwards
* Copyright (C) 2023 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.protocol1_19_4to1_20.data;
import com.viaversion.viabackwards.api.data.VBMappingDataLoader;
import com.viaversion.viaversion.api.minecraft.nbt.BinaryTagIO;
import com.viaversion.viaversion.libs.opennbt.tag.builtin.CompoundTag;
import com.viaversion.viaversion.protocols.protocol1_20to1_19_4.Protocol1_20To1_19_4;
import java.io.IOException;
public class BackwardsMappings extends com.viaversion.viabackwards.api.data.BackwardsMappings {
private CompoundTag trimPatternRegistry;
public BackwardsMappings() {
super("1.20", "1.19.4", Protocol1_20To1_19_4.class);
}
@Override
protected void loadExtras(CompoundTag data) {
super.loadExtras(data);
try {
trimPatternRegistry = BinaryTagIO.readInputStream(VBMappingDataLoader.getResource("trim_pattern-1.19.4.nbt"));
} catch (final IOException e) {
e.printStackTrace();
}
}
public CompoundTag getTrimPatternRegistry() {
return trimPatternRegistry;
}
}
@@ -17,25 +17,34 @@
*/
package com.viaversion.viabackwards.protocol.protocol1_19_4to1_20.packets;
import com.viaversion.viabackwards.api.rewriters.ItemRewriter;
import com.viaversion.viabackwards.protocol.protocol1_19_4to1_20.Protocol1_19_4To1_20;
import com.viaversion.viabackwards.protocol.protocol1_19_4to1_20.storage.BackSignEditStorage;
import com.viaversion.viaversion.api.minecraft.BlockChangeRecord;
import com.viaversion.viaversion.api.minecraft.Position;
import com.viaversion.viaversion.api.minecraft.blockentity.BlockEntity;
import com.viaversion.viaversion.api.minecraft.item.Item;
import com.viaversion.viaversion.api.protocol.remapper.PacketHandlers;
import com.viaversion.viaversion.api.type.Type;
import com.viaversion.viaversion.libs.opennbt.tag.builtin.CompoundTag;
import com.viaversion.viaversion.libs.opennbt.tag.builtin.ListTag;
import com.viaversion.viaversion.libs.opennbt.tag.builtin.StringTag;
import com.viaversion.viaversion.libs.opennbt.tag.builtin.Tag;
import com.viaversion.viaversion.protocols.protocol1_18to1_17_1.types.Chunk1_18Type;
import com.viaversion.viaversion.protocols.protocol1_19_4to1_19_3.ClientboundPackets1_19_4;
import com.viaversion.viaversion.protocols.protocol1_19_4to1_19_3.ServerboundPackets1_19_4;
import com.viaversion.viaversion.protocols.protocol1_19_4to1_19_3.rewriter.RecipeRewriter1_19_4;
import com.viaversion.viaversion.rewriter.BlockRewriter;
import com.viaversion.viaversion.rewriter.ItemRewriter;
import com.viaversion.viaversion.util.Key;
import java.util.Arrays;
import java.util.HashSet;
import java.util.Set;
import org.checkerframework.checker.nullness.qual.Nullable;
public final class BlockItemPackets1_20 extends ItemRewriter<ClientboundPackets1_19_4, ServerboundPackets1_19_4, Protocol1_19_4To1_20> {
private static final Set<String> NEW_TRIM_PATTERNS = new HashSet<>(Arrays.asList("host", "raiser", "shaper", "silence", "wayfinder"));
public BlockItemPackets1_20(final Protocol1_19_4To1_20 protocol) {
super(protocol);
}
@@ -140,6 +149,46 @@ public final class BlockItemPackets1_20 extends ItemRewriter<ClientboundPackets1
new RecipeRewriter1_19_4<>(protocol).register(ClientboundPackets1_19_4.DECLARE_RECIPES);
}
@Override
public @Nullable Item handleItemToClient(@Nullable final Item item) {
if (item == null) {
return null;
}
super.handleItemToClient(item);
// Remove new trim tags
final Tag trimTag;
if (item.tag() != null && (trimTag = item.tag().get("Trim")) instanceof CompoundTag) {
final Tag patternTag = ((CompoundTag) trimTag).get("pattern");
if (patternTag instanceof StringTag) {
final StringTag patternStringTag = (StringTag) patternTag;
final String pattern = Key.stripMinecraftNamespace(patternStringTag.getValue());
if (NEW_TRIM_PATTERNS.contains(pattern)) {
item.tag().remove("Trim");
item.tag().put(nbtTagName + "|Trim", trimTag);
}
}
}
return item;
}
@Override
public @Nullable Item handleItemToServer(@Nullable final Item item) {
if (item == null) {
return null;
}
super.handleItemToServer(item);
// Add back original trim tag
final Tag trimTag;
if (item.tag() != null && (trimTag = item.tag().remove(nbtTagName + "|Trim")) != null) {
item.tag().put("Trim", trimTag);
}
return item;
}
private void handleBlockEntity(final BlockEntity blockEntity) {
// Check for signs
if (blockEntity.typeId() != 7 && blockEntity.typeId() != 8) {
@@ -20,8 +20,10 @@ package com.viaversion.viabackwards.protocol.protocol1_19_4to1_20.packets;
import com.google.common.collect.Sets;
import com.viaversion.viabackwards.api.rewriters.EntityRewriter;
import com.viaversion.viabackwards.protocol.protocol1_19_4to1_20.Protocol1_19_4To1_20;
import com.viaversion.viaversion.api.minecraft.Quaternion;
import com.viaversion.viaversion.api.minecraft.entities.Entity1_19_4Types;
import com.viaversion.viaversion.api.minecraft.entities.EntityType;
import com.viaversion.viaversion.api.minecraft.metadata.Metadata;
import com.viaversion.viaversion.api.protocol.remapper.PacketHandlers;
import com.viaversion.viaversion.api.type.Type;
import com.viaversion.viaversion.api.type.types.version.Types1_19_4;
@@ -32,12 +34,14 @@ import com.viaversion.viaversion.libs.opennbt.tag.builtin.StringTag;
import com.viaversion.viaversion.libs.opennbt.tag.builtin.Tag;
import com.viaversion.viaversion.protocols.protocol1_19_4to1_19_3.ClientboundPackets1_19_4;
import com.viaversion.viaversion.util.Key;
import java.util.Set;
public final class EntityPackets1_20 extends EntityRewriter<ClientboundPackets1_19_4, Protocol1_19_4To1_20> {
private final Set<String> newTrimPatterns = Sets.newHashSet("host_armor_trim_smithing_template", "raiser_armor_trim_smithing_template",
"silence_armor_trim_smithing_template", "shaper_armor_trim_smithing_template", "wayfinder_armor_trim_smithing_template");
private static final Quaternion Y_FLIPPED_ROTATION = new Quaternion(0, 1, 0, 0);
public EntityPackets1_20(final Protocol1_19_4To1_20 protocol) {
super(protocol);
@@ -76,7 +80,17 @@ public final class EntityPackets1_20 extends EntityRewriter<ClientboundPackets1_
handler(worldDataTrackerHandlerByKey()); // Tracks world height and name for chunk data and entity (un)tracking
handler(wrapper -> {
final CompoundTag registry = wrapper.get(Type.NBT, 0);
final ListTag values = ((CompoundTag) registry.get("minecraft:trim_pattern")).get("value");
ListTag values;
// A 1.20 server can't send this element, and the 1.20 client still works, if the element is missing
// on a 1.19.4 client there is an exception, so in case the 1.20 server doesn't send the element we put in an original 1.20 element
if (registry.contains("minecraft:trim_pattern")) {
values = ((CompoundTag) registry.get("minecraft:trim_pattern")).get("value");
} else {
final CompoundTag trimPatternRegistry = Protocol1_19_4To1_20.MAPPINGS.getTrimPatternRegistry().clone();
registry.put("minecraft:trim_pattern", trimPatternRegistry);
values = trimPatternRegistry.get("value");
}
for (final Tag entry : values) {
final CompoundTag element = ((CompoundTag) entry).get("element");
final StringTag templateItem = element.get("template_item");
@@ -116,10 +130,29 @@ public final class EntityPackets1_20 extends EntityRewriter<ClientboundPackets1_
final int blockState = meta.value();
meta.setValue(protocol.getMappingData().getNewBlockStateId(blockState));
});
// Rotate item display by 180 degrees around the Y axis
filter().filterFamily(Entity1_19_4Types.ITEM_DISPLAY).handler((event, meta) -> {
if (event.trackedEntity().hasSentMetadata() || event.hasExtraMeta()) {
return;
}
if (event.metaAtIndex(12) == null) {
event.createExtraMeta(new Metadata(12, Types1_19_4.META_TYPES.quaternionType, Y_FLIPPED_ROTATION));
}
});
filter().filterFamily(Entity1_19_4Types.ITEM_DISPLAY).index(12).handler((event, meta) -> {
final Quaternion quaternion = meta.value();
meta.setValue(rotateY180(quaternion));
});
}
@Override
public EntityType typeFromId(final int type) {
return Entity1_19_4Types.getTypeFromId(type);
}
private Quaternion rotateY180(final Quaternion quaternion) {
return new Quaternion(-quaternion.z(), quaternion.w(), quaternion.x(), -quaternion.y());
}
}
@@ -0,0 +1,195 @@
/*
* This file is part of ViaBackwards - https://github.com/ViaVersion/ViaBackwards
* Copyright (C) 2023 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.protocol1_20to1_20_2;
import com.viaversion.viabackwards.api.BackwardsProtocol;
import com.viaversion.viabackwards.api.data.BackwardsMappings;
import com.viaversion.viabackwards.api.rewriters.SoundRewriter;
import com.viaversion.viabackwards.protocol.protocol1_20to1_20_2.rewriter.BlockItemPacketRewriter1_20_2;
import com.viaversion.viabackwards.protocol.protocol1_20to1_20_2.rewriter.EntityPacketRewriter1_20_2;
import com.viaversion.viabackwards.protocol.protocol1_20to1_20_2.storage.ConfigurationPacketStorage;
import com.viaversion.viaversion.api.connection.UserConnection;
import com.viaversion.viaversion.api.minecraft.entities.Entity1_19_4Types;
import com.viaversion.viaversion.api.protocol.packet.Direction;
import com.viaversion.viaversion.api.protocol.packet.PacketWrapper;
import com.viaversion.viaversion.api.protocol.packet.State;
import com.viaversion.viaversion.api.rewriter.EntityRewriter;
import com.viaversion.viaversion.api.rewriter.ItemRewriter;
import com.viaversion.viaversion.api.type.Type;
import com.viaversion.viaversion.data.entity.EntityTrackerBase;
import com.viaversion.viaversion.exception.CancelException;
import com.viaversion.viaversion.libs.opennbt.tag.builtin.CompoundTag;
import com.viaversion.viaversion.protocols.base.ClientboundLoginPackets;
import com.viaversion.viaversion.protocols.base.ServerboundLoginPackets;
import com.viaversion.viaversion.protocols.protocol1_19_4to1_19_3.ClientboundPackets1_19_4;
import com.viaversion.viaversion.protocols.protocol1_19_4to1_19_3.ServerboundPackets1_19_4;
import com.viaversion.viaversion.protocols.protocol1_20_2to1_20.Protocol1_20_2To1_20;
import com.viaversion.viaversion.protocols.protocol1_20_2to1_20.packet.ClientboundConfigurationPackets1_20_2;
import com.viaversion.viaversion.protocols.protocol1_20_2to1_20.packet.ClientboundPackets1_20_2;
import com.viaversion.viaversion.protocols.protocol1_20_2to1_20.packet.ServerboundConfigurationPackets1_20_2;
import com.viaversion.viaversion.protocols.protocol1_20_2to1_20.packet.ServerboundPackets1_20_2;
import java.util.UUID;
public final class Protocol1_20To1_20_2 extends BackwardsProtocol<ClientboundPackets1_20_2, ClientboundPackets1_19_4, ServerboundPackets1_20_2, ServerboundPackets1_19_4> {
public static final BackwardsMappings MAPPINGS = new BackwardsMappings("1.20.2", "1.20", Protocol1_20_2To1_20.class);
private final EntityPacketRewriter1_20_2 entityPacketRewriter = new EntityPacketRewriter1_20_2(this);
private final BlockItemPacketRewriter1_20_2 itemPacketRewriter = new BlockItemPacketRewriter1_20_2(this);
public Protocol1_20To1_20_2() {
super(ClientboundPackets1_20_2.class, ClientboundPackets1_19_4.class, ServerboundPackets1_20_2.class, ServerboundPackets1_19_4.class);
}
@Override
protected void registerPackets() {
super.registerPackets();
final SoundRewriter<ClientboundPackets1_20_2> soundRewriter = new SoundRewriter<>(this);
soundRewriter.register1_19_3Sound(ClientboundPackets1_20_2.SOUND);
soundRewriter.registerSound(ClientboundPackets1_20_2.ENTITY_SOUND);
soundRewriter.registerStopSound(ClientboundPackets1_20_2.STOP_SOUND);
registerClientbound(ClientboundPackets1_20_2.DISPLAY_SCOREBOARD, wrapper -> {
final int slot = wrapper.read(Type.VAR_INT);
wrapper.write(Type.BYTE, (byte) slot);
});
registerClientbound(State.LOGIN, ClientboundLoginPackets.GAME_PROFILE.getId(), ClientboundLoginPackets.GAME_PROFILE.getId(), 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());
// Overwrite what is set by the base protocol
wrapper.user().getProtocolInfo().setClientState(State.LOGIN);
// States set to configuration in the base protocol
wrapper.create(ServerboundLoginPackets.LOGIN_ACKNOWLEDGED).sendToServer(Protocol1_20To1_20_2.class);
});
registerClientbound(State.CONFIGURATION, ClientboundConfigurationPackets1_20_2.FINISH_CONFIGURATION.getId(), ClientboundConfigurationPackets1_20_2.FINISH_CONFIGURATION.getId(), wrapper -> {
wrapper.cancel();
wrapper.user().getProtocolInfo().setServerState(State.PLAY);
wrapper.user().get(ConfigurationPacketStorage.class).setFinished(true);
wrapper.create(ServerboundConfigurationPackets1_20_2.FINISH_CONFIGURATION).sendToServer(Protocol1_20To1_20_2.class);
wrapper.user().getProtocolInfo().setClientState(State.PLAY);
});
registerServerbound(State.LOGIN, ServerboundLoginPackets.HELLO.getId(), ServerboundLoginPackets.HELLO.getId(), wrapper -> {
wrapper.passthrough(Type.STRING); // Name
// TODO Bad
final UUID uuid = wrapper.read(Type.OPTIONAL_UUID);
wrapper.write(Type.UUID, uuid != null ? uuid : new UUID(0, 0));
});
registerClientbound(ClientboundPackets1_20_2.START_CONFIGURATION, null, wrapper -> {
wrapper.cancel();
wrapper.user().getProtocolInfo().setServerState(State.CONFIGURATION);
// TODO: Check whether all the necessary data for the join game packet is always expected by the client or if we need to cache it from the initial login
final PacketWrapper configAcknowledgedPacket = wrapper.create(ServerboundPackets1_20_2.CONFIGURATION_ACKNOWLEDGED);
configAcknowledgedPacket.sendToServer(Protocol1_20To1_20_2.class);
wrapper.user().getProtocolInfo().setClientState(State.CONFIGURATION);
wrapper.user().put(new ConfigurationPacketStorage());
});
cancelClientbound(ClientboundPackets1_20_2.PONG_RESPONSE);
// Some can be directly remapped to play packets, others need to be queued
registerClientbound(State.CONFIGURATION, ClientboundConfigurationPackets1_20_2.DISCONNECT.getId(), ClientboundPackets1_19_4.DISCONNECT.getId());
registerClientbound(State.CONFIGURATION, ClientboundConfigurationPackets1_20_2.KEEP_ALIVE.getId(), ClientboundPackets1_19_4.KEEP_ALIVE.getId());
registerClientbound(State.CONFIGURATION, ClientboundConfigurationPackets1_20_2.RESOURCE_PACK.getId(), ClientboundPackets1_19_4.RESOURCE_PACK.getId());
registerClientbound(State.CONFIGURATION, ClientboundConfigurationPackets1_20_2.REGISTRY_DATA.getId(), -1, wrapper -> {
wrapper.cancel();
final CompoundTag registry = wrapper.read(Type.NAMELESS_NBT);
entityPacketRewriter.trackBiomeSize(wrapper.user(), registry);
entityPacketRewriter.cacheDimensionData(wrapper.user(), registry);
wrapper.user().get(ConfigurationPacketStorage.class).setRegistry(registry);
});
registerClientbound(State.CONFIGURATION, ClientboundConfigurationPackets1_20_2.UPDATE_ENABLED_FEATURES.getId(), -1, wrapper -> {
wrapper.cancel();
final String[] enabledFeatures = wrapper.read(Type.STRING_ARRAY);
wrapper.user().get(ConfigurationPacketStorage.class).setEnabledFeatures(enabledFeatures);
});
registerClientbound(State.CONFIGURATION, ClientboundConfigurationPackets1_20_2.UPDATE_TAGS.getId(), -1, wrapper -> {
wrapper.cancel();
wrapper.user().get(ConfigurationPacketStorage.class).addRawPacket(wrapper, ClientboundPackets1_19_4.TAGS);
});
registerClientbound(State.CONFIGURATION, ClientboundConfigurationPackets1_20_2.CUSTOM_PAYLOAD.getId(), -1, wrapper -> {
wrapper.cancel();
wrapper.user().get(ConfigurationPacketStorage.class).addRawPacket(wrapper, ClientboundPackets1_19_4.PLUGIN_MESSAGE);
});
}
@Override
public void transform(final Direction direction, final State state, final PacketWrapper wrapper) throws Exception {
final ConfigurationPacketStorage configurationPacketStorage = wrapper.user().get(ConfigurationPacketStorage.class);
if (configurationPacketStorage == null || configurationPacketStorage.isFinished()) {
super.transform(direction, state, wrapper);
return;
}
if (direction == Direction.CLIENTBOUND) {
super.transform(direction, State.CONFIGURATION, wrapper);
return;
}
// Map some of the packets to their configuration counterparts
final int id = wrapper.getId();
if (id == ServerboundPackets1_19_4.CLIENT_SETTINGS.getId()) {
wrapper.setPacketType(ServerboundConfigurationPackets1_20_2.CLIENT_INFORMATION);
} else if (id == ServerboundPackets1_19_4.PLUGIN_MESSAGE.getId()) {
wrapper.setPacketType(ServerboundConfigurationPackets1_20_2.CUSTOM_PAYLOAD);
} else if (id == ServerboundPackets1_19_4.KEEP_ALIVE.getId()) {
wrapper.setPacketType(ServerboundConfigurationPackets1_20_2.KEEP_ALIVE);
} else if (id == ServerboundPackets1_19_4.PONG.getId()) {
wrapper.setPacketType(ServerboundConfigurationPackets1_20_2.PONG);
} else if (id == ServerboundPackets1_19_4.RESOURCE_PACK_STATUS.getId()) {
wrapper.setPacketType(ServerboundConfigurationPackets1_20_2.RESOURCE_PACK);
} else {
// TODO Queue
throw CancelException.generate();
}
}
@Override
protected void registerConfigurationChangeHandlers() {
// Don't register them in the transitioning protocol
}
@Override
public void init(final UserConnection connection) {
addEntityTracker(connection, new EntityTrackerBase(connection, Entity1_19_4Types.PLAYER));
}
@Override
public BackwardsMappings getMappingData() {
return MAPPINGS;
}
@Override
public EntityRewriter<Protocol1_20To1_20_2> getEntityRewriter() {
return entityPacketRewriter;
}
@Override
public ItemRewriter<Protocol1_20To1_20_2> getItemRewriter() {
return itemPacketRewriter;
}
}
@@ -0,0 +1,396 @@
/*
* This file is part of ViaBackwards - https://github.com/ViaVersion/ViaBackwards
* Copyright (C) 2023 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.protocol1_20to1_20_2.rewriter;
import com.viaversion.viabackwards.api.rewriters.ItemRewriter;
import com.viaversion.viabackwards.protocol.protocol1_20to1_20_2.Protocol1_20To1_20_2;
import com.viaversion.viaversion.api.data.ParticleMappings;
import com.viaversion.viaversion.api.data.entity.EntityTracker;
import com.viaversion.viaversion.api.minecraft.blockentity.BlockEntity;
import com.viaversion.viaversion.api.minecraft.chunks.Chunk;
import com.viaversion.viaversion.api.minecraft.chunks.ChunkSection;
import com.viaversion.viaversion.api.minecraft.chunks.DataPalette;
import com.viaversion.viaversion.api.minecraft.chunks.PaletteType;
import com.viaversion.viaversion.api.minecraft.item.Item;
import com.viaversion.viaversion.api.minecraft.metadata.ChunkPosition;
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.libs.opennbt.tag.builtin.CompoundTag;
import com.viaversion.viaversion.libs.opennbt.tag.builtin.IntTag;
import com.viaversion.viaversion.libs.opennbt.tag.builtin.StringTag;
import com.viaversion.viaversion.protocols.protocol1_18to1_17_1.types.Chunk1_18Type;
import com.viaversion.viaversion.protocols.protocol1_19_4to1_19_3.ServerboundPackets1_19_4;
import com.viaversion.viaversion.protocols.protocol1_20_2to1_20.packet.ClientboundPackets1_20_2;
import com.viaversion.viaversion.protocols.protocol1_20_2to1_20.packet.ServerboundPackets1_20_2;
import com.viaversion.viaversion.protocols.protocol1_20_2to1_20.rewriter.RecipeRewriter1_20_2;
import com.viaversion.viaversion.protocols.protocol1_20_2to1_20.type.ChunkType1_20_2;
import com.viaversion.viaversion.protocols.protocol1_20_2to1_20.util.PotionEffects;
import com.viaversion.viaversion.rewriter.BlockRewriter;
import com.viaversion.viaversion.util.Key;
import com.viaversion.viaversion.util.MathUtil;
import org.checkerframework.checker.nullness.qual.Nullable;
public final class BlockItemPacketRewriter1_20_2 extends ItemRewriter<ClientboundPackets1_20_2, ServerboundPackets1_19_4, Protocol1_20To1_20_2> {
public BlockItemPacketRewriter1_20_2(final Protocol1_20To1_20_2 protocol) {
super(protocol, Type.ITEM1_20_2, Type.ITEM1_20_2_VAR_INT_ARRAY);
}
@Override
public void registerPackets() {
final BlockRewriter<ClientboundPackets1_20_2> blockRewriter = new BlockRewriter<>(protocol, Type.POSITION1_14);
blockRewriter.registerBlockAction(ClientboundPackets1_20_2.BLOCK_ACTION);
blockRewriter.registerBlockChange(ClientboundPackets1_20_2.BLOCK_CHANGE);
blockRewriter.registerVarLongMultiBlockChange1_20(ClientboundPackets1_20_2.MULTI_BLOCK_CHANGE);
blockRewriter.registerEffect(ClientboundPackets1_20_2.EFFECT, 1010, 2001);
protocol.cancelClientbound(ClientboundPackets1_20_2.CHUNK_BATCH_START);
protocol.registerClientbound(ClientboundPackets1_20_2.CHUNK_BATCH_FINISHED, null, wrapper -> {
wrapper.cancel();
final PacketWrapper receivedPacket = wrapper.create(ServerboundPackets1_20_2.CHUNK_BATCH_RECEIVED);
receivedPacket.write(Type.FLOAT, 500F); // Requested next batch size... arbitrary value here
receivedPacket.sendToServer(Protocol1_20To1_20_2.class);
});
protocol.registerClientbound(ClientboundPackets1_20_2.UNLOAD_CHUNK, wrapper -> {
final ChunkPosition chunkPosition = wrapper.read(Type.CHUNK_POSITION);
wrapper.write(Type.INT, chunkPosition.chunkX());
wrapper.write(Type.INT, chunkPosition.chunkZ());
});
protocol.registerClientbound(ClientboundPackets1_20_2.NBT_QUERY, wrapper -> {
wrapper.passthrough(Type.VAR_INT); // Transaction id
wrapper.write(Type.NBT, wrapper.read(Type.NAMELESS_NBT));
});
protocol.registerClientbound(ClientboundPackets1_20_2.BLOCK_ENTITY_DATA, wrapper -> {
wrapper.passthrough(Type.POSITION1_14); // Position
wrapper.passthrough(Type.VAR_INT); // Type
wrapper.write(Type.NBT, handleBlockEntity(wrapper.read(Type.NAMELESS_NBT)));
});
protocol.registerClientbound(ClientboundPackets1_20_2.CHUNK_DATA, wrapper -> {
final EntityTracker tracker = protocol.getEntityRewriter().tracker(wrapper.user());
final Type<Chunk> chunkType = new ChunkType1_20_2(tracker.currentWorldSectionHeight(),
MathUtil.ceilLog2(protocol.getMappingData().getBlockStateMappings().size()),
MathUtil.ceilLog2(tracker.biomesSent()));
final Chunk chunk = wrapper.read(chunkType);
final Type<Chunk> newChunkType = new Chunk1_18Type(tracker.currentWorldSectionHeight(),
MathUtil.ceilLog2(protocol.getMappingData().getBlockStateMappings().mappedSize()),
MathUtil.ceilLog2(tracker.biomesSent()));
wrapper.write(newChunkType, chunk);
for (final ChunkSection section : chunk.getSections()) {
final DataPalette blockPalette = section.palette(PaletteType.BLOCKS);
for (int i = 0; i < blockPalette.size(); i++) {
final int id = blockPalette.idByIndex(i);
blockPalette.setIdByIndex(i, protocol.getMappingData().getNewBlockStateId(id));
}
}
for (final BlockEntity blockEntity : chunk.blockEntities()) {
handleBlockEntity(blockEntity.tag());
}
});
protocol.registerServerbound(ServerboundPackets1_19_4.SET_BEACON_EFFECT, wrapper -> {
// Effects start at 1 before 1.20.2
if (wrapper.passthrough(Type.BOOLEAN)) { // Primary effect
wrapper.write(Type.VAR_INT, wrapper.read(Type.VAR_INT) - 1);
}
if (wrapper.passthrough(Type.BOOLEAN)) { // Secondary effect
wrapper.write(Type.VAR_INT, wrapper.read(Type.VAR_INT) - 1);
}
});
// Replace the NBT type everywhere
protocol.registerClientbound(ClientboundPackets1_20_2.WINDOW_ITEMS, new PacketHandlers() {
@Override
public void register() {
map(Type.UNSIGNED_BYTE); // Window id
map(Type.VAR_INT); // State id
handler(wrapper -> {
final Item[] items = wrapper.read(Type.ITEM1_20_2_VAR_INT_ARRAY);
for (final Item item : items) {
handleItemToClient(item);
}
wrapper.write(Type.FLAT_VAR_INT_ITEM_ARRAY_VAR_INT, items);
wrapper.write(Type.FLAT_VAR_INT_ITEM, handleItemToClient(wrapper.read(Type.ITEM1_20_2))); // Carried item
});
}
});
protocol.registerClientbound(ClientboundPackets1_20_2.SET_SLOT, new PacketHandlers() {
@Override
public void register() {
map(Type.UNSIGNED_BYTE); // Window id
map(Type.VAR_INT); // State id
map(Type.SHORT); // Slot id
handler(wrapper -> wrapper.write(Type.FLAT_VAR_INT_ITEM, handleItemToClient(wrapper.read(Type.ITEM1_20_2))));
}
});
protocol.registerClientbound(ClientboundPackets1_20_2.ADVANCEMENTS, wrapper -> {
wrapper.passthrough(Type.BOOLEAN); // Reset/clear
final int size = wrapper.passthrough(Type.VAR_INT); // Mapping size
for (int i = 0; i < size; i++) {
wrapper.passthrough(Type.STRING); // Identifier
// Parent
if (wrapper.passthrough(Type.BOOLEAN)) {
wrapper.passthrough(Type.STRING);
}
// Display data
if (wrapper.passthrough(Type.BOOLEAN)) {
wrapper.passthrough(Type.COMPONENT); // Title
wrapper.passthrough(Type.COMPONENT); // Description
wrapper.write(Type.FLAT_VAR_INT_ITEM, handleItemToClient(wrapper.read(Type.ITEM1_20_2))); // Icon
wrapper.passthrough(Type.VAR_INT); // Frame type
final int flags = wrapper.passthrough(Type.INT); // Flags
if ((flags & 1) != 0) {
wrapper.passthrough(Type.STRING); // Background texture
}
wrapper.passthrough(Type.FLOAT); // X
wrapper.passthrough(Type.FLOAT); // Y
}
wrapper.write(Type.STRING_ARRAY, new String[0]); // Criteria
final int requirements = wrapper.passthrough(Type.VAR_INT);
for (int array = 0; array < requirements; array++) {
wrapper.passthrough(Type.STRING_ARRAY);
}
wrapper.passthrough(Type.BOOLEAN); // Send telemetry
}
});
protocol.registerClientbound(ClientboundPackets1_20_2.ENTITY_EQUIPMENT, new PacketHandlers() {
@Override
public void register() {
map(Type.VAR_INT); // 0 - Entity ID
handler(wrapper -> {
byte slot;
do {
slot = wrapper.passthrough(Type.BYTE);
wrapper.write(Type.FLAT_VAR_INT_ITEM, handleItemToClient(wrapper.read(Type.ITEM1_20_2)));
} while ((slot & 0xFFFFFF80) != 0);
});
}
});
protocol.registerServerbound(ServerboundPackets1_19_4.CLICK_WINDOW, new PacketHandlers() {
@Override
public void register() {
map(Type.UNSIGNED_BYTE); // Window Id
map(Type.VAR_INT); // State id
map(Type.SHORT); // Slot
map(Type.BYTE); // Button
map(Type.VAR_INT); // Mode
handler(wrapper -> {
// Affected items
final int length = wrapper.passthrough(Type.VAR_INT);
for (int i = 0; i < length; i++) {
wrapper.passthrough(Type.SHORT); // Slot
wrapper.write(Type.ITEM1_20_2, handleItemToServer(wrapper.read(Type.FLAT_VAR_INT_ITEM)));
}
// Carried item
wrapper.write(Type.ITEM1_20_2, handleItemToServer(wrapper.read(Type.FLAT_VAR_INT_ITEM)));
});
}
});
protocol.registerClientbound(ClientboundPackets1_20_2.TRADE_LIST, wrapper -> {
wrapper.passthrough(Type.VAR_INT); // Container id
final int size = wrapper.passthrough(Type.VAR_INT);
for (int i = 0; i < size; i++) {
wrapper.write(Type.FLAT_VAR_INT_ITEM, handleItemToClient(wrapper.read(Type.ITEM1_20_2))); // Input
wrapper.write(Type.FLAT_VAR_INT_ITEM, handleItemToClient(wrapper.read(Type.ITEM1_20_2))); // Output
wrapper.write(Type.FLAT_VAR_INT_ITEM, handleItemToClient(wrapper.read(Type.ITEM1_20_2))); // Second Item
wrapper.passthrough(Type.BOOLEAN); // Trade disabled
wrapper.passthrough(Type.INT); // Number of tools uses
wrapper.passthrough(Type.INT); // Maximum number of trade uses
wrapper.passthrough(Type.INT); // XP
wrapper.passthrough(Type.INT); // Special price
wrapper.passthrough(Type.FLOAT); // Price multiplier
wrapper.passthrough(Type.INT); // Demand
}
});
protocol.registerServerbound(ServerboundPackets1_19_4.CREATIVE_INVENTORY_ACTION, new PacketHandlers() {
@Override
public void register() {
map(Type.SHORT); // 0 - Slot
handler(wrapper -> wrapper.write(Type.ITEM1_20_2, handleItemToServer(wrapper.read(Type.FLAT_VAR_INT_ITEM)))); // 1 - Clicked Item
}
});
protocol.registerClientbound(ClientboundPackets1_20_2.SPAWN_PARTICLE, new PacketHandlers() {
@Override
public void register() {
map(Type.VAR_INT); // 0 - Particle ID
map(Type.BOOLEAN); // 1 - Long Distance
map(Type.DOUBLE); // 2 - X
map(Type.DOUBLE); // 3 - Y
map(Type.DOUBLE); // 4 - Z
map(Type.FLOAT); // 5 - Offset X
map(Type.FLOAT); // 6 - Offset Y
map(Type.FLOAT); // 7 - Offset Z
map(Type.FLOAT); // 8 - Particle Data
map(Type.INT); // 9 - Particle Count
handler(wrapper -> {
final int id = wrapper.get(Type.VAR_INT, 0);
final ParticleMappings mappings = Protocol1_20To1_20_2.MAPPINGS.getParticleMappings();
if (mappings.isBlockParticle(id)) {
final int data = wrapper.read(Type.VAR_INT);
wrapper.write(Type.VAR_INT, protocol.getMappingData().getNewBlockStateId(data));
} else if (mappings.isItemParticle(id)) {
wrapper.write(Type.FLAT_VAR_INT_ITEM, handleItemToClient(wrapper.read(Type.ITEM1_20_2)));
}
});
}
});
new RecipeRewriter1_20_2<ClientboundPackets1_20_2>(protocol) {
@Override
public void handleCraftingShapeless(final PacketWrapper wrapper) throws Exception {
wrapper.passthrough(Type.STRING); // Group
wrapper.passthrough(Type.VAR_INT); // Crafting book category
handleIngredients(wrapper);
final Item result = wrapper.read(itemType());
rewrite(result);
wrapper.write(Type.FLAT_VAR_INT_ITEM, result);
}
@Override
public void handleSmelting(final PacketWrapper wrapper) throws Exception {
wrapper.passthrough(Type.STRING); // Group
wrapper.passthrough(Type.VAR_INT); // Crafting book category
handleIngredient(wrapper);
final Item result = wrapper.read(itemType());
rewrite(result);
wrapper.write(Type.FLAT_VAR_INT_ITEM, result);
wrapper.passthrough(Type.FLOAT); // EXP
wrapper.passthrough(Type.VAR_INT); // Cooking time
}
@Override
public void handleCraftingShaped(final PacketWrapper wrapper) throws Exception {
final int ingredients = wrapper.passthrough(Type.VAR_INT) * wrapper.passthrough(Type.VAR_INT);
wrapper.passthrough(Type.STRING); // Group
wrapper.passthrough(Type.VAR_INT); // Crafting book category
for (int i = 0; i < ingredients; i++) {
handleIngredient(wrapper);
}
final Item result = wrapper.read(itemType());
rewrite(result);
wrapper.write(Type.FLAT_VAR_INT_ITEM, result);
wrapper.passthrough(Type.BOOLEAN); // Show notification
}
@Override
public void handleStonecutting(final PacketWrapper wrapper) throws Exception {
wrapper.passthrough(Type.STRING); // Group
handleIngredient(wrapper);
final Item result = wrapper.read(itemType());
rewrite(result);
wrapper.write(Type.FLAT_VAR_INT_ITEM, result);
}
@Override
public void handleSmithing(final PacketWrapper wrapper) throws Exception {
handleIngredient(wrapper); // Base
handleIngredient(wrapper); // Addition
final Item result = wrapper.read(itemType());
rewrite(result);
wrapper.write(Type.FLAT_VAR_INT_ITEM, result);
}
@Override
public void handleSmithingTransform(final PacketWrapper wrapper) throws Exception {
handleIngredient(wrapper); // Template
handleIngredient(wrapper); // Base
handleIngredient(wrapper); // Additions
final Item result = wrapper.read(itemType());
rewrite(result);
wrapper.write(Type.FLAT_VAR_INT_ITEM, result);
}
@Override
protected void handleIngredient(final PacketWrapper wrapper) throws Exception {
final Item[] items = wrapper.read(itemArrayType());
wrapper.write(Type.FLAT_VAR_INT_ITEM_ARRAY_VAR_INT, items);
for (final Item item : items) {
rewrite(item);
}
}
}.register(ClientboundPackets1_20_2.DECLARE_RECIPES);
}
@Override
public @Nullable Item handleItemToClient(@Nullable final Item item) {
if (item == null) {
return null;
}
if (item.tag() != null) {
com.viaversion.viaversion.protocols.protocol1_20_2to1_20.rewriter.BlockItemPacketRewriter1_20_2.to1_20_1Effects(item);
}
return super.handleItemToClient(item);
}
@Override
public @Nullable Item handleItemToServer(@Nullable final Item item) {
if (item == null) {
return null;
}
if (item.tag() != null) {
com.viaversion.viaversion.protocols.protocol1_20_2to1_20.rewriter.BlockItemPacketRewriter1_20_2.to1_20_2Effects(item);
}
return super.handleItemToServer(item);
}
private @Nullable CompoundTag handleBlockEntity(@Nullable final CompoundTag tag) {
if (tag == null) {
return null;
}
final StringTag primaryEffect = tag.remove("primary_effect");
if (primaryEffect != null) {
final String effectKey = Key.stripMinecraftNamespace(primaryEffect.getValue());
tag.put("Primary", new IntTag(PotionEffects.keyToId(effectKey)));
}
final StringTag secondaryEffect = tag.remove("secondary_effect");
if (secondaryEffect != null) {
final String effectKey = Key.stripMinecraftNamespace(secondaryEffect.getValue());
tag.put("Secondary", new IntTag(PotionEffects.keyToId(effectKey)));
}
return tag;
}
}
@@ -0,0 +1,210 @@
/*
* This file is part of ViaBackwards - https://github.com/ViaVersion/ViaBackwards
* Copyright (C) 2023 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.protocol1_20to1_20_2.rewriter;
import com.viaversion.viabackwards.api.rewriters.EntityRewriter;
import com.viaversion.viabackwards.protocol.protocol1_20to1_20_2.Protocol1_20To1_20_2;
import com.viaversion.viabackwards.protocol.protocol1_20to1_20_2.storage.ConfigurationPacketStorage;
import com.viaversion.viaversion.api.minecraft.GlobalPosition;
import com.viaversion.viaversion.api.minecraft.entities.Entity1_19_4Types;
import com.viaversion.viaversion.api.minecraft.entities.EntityType;
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.version.Types1_20;
import com.viaversion.viaversion.api.type.types.version.Types1_20_2;
import com.viaversion.viaversion.protocols.protocol1_19_4to1_19_3.ClientboundPackets1_19_4;
import com.viaversion.viaversion.protocols.protocol1_20_2to1_20.packet.ClientboundPackets1_20_2;
public final class EntityPacketRewriter1_20_2 extends EntityRewriter<ClientboundPackets1_20_2, Protocol1_20To1_20_2> {
public EntityPacketRewriter1_20_2(final Protocol1_20To1_20_2 protocol) {
super(protocol);
}
@Override
public void registerPackets() {
registerMetadataRewriter(ClientboundPackets1_20_2.ENTITY_METADATA, Types1_20_2.METADATA_LIST, Types1_20.METADATA_LIST);
registerRemoveEntities(ClientboundPackets1_20_2.REMOVE_ENTITIES);
protocol.registerClientbound(ClientboundPackets1_20_2.SPAWN_ENTITY, new PacketHandlers() {
@Override
protected void register() {
handler(wrapper -> {
final int entityId = wrapper.passthrough(Type.VAR_INT);
wrapper.passthrough(Type.UUID); // UUID
final int entityType = wrapper.read(Type.VAR_INT);
if (entityType != Entity1_19_4Types.PLAYER.getId()) {
wrapper.write(Type.VAR_INT, entityType);
if (entityType == Entity1_19_4Types.FALLING_BLOCK.getId()) {
wrapper.passthrough(Type.DOUBLE); // X
wrapper.passthrough(Type.DOUBLE); // Y
wrapper.passthrough(Type.DOUBLE); // Z
wrapper.passthrough(Type.BYTE); // Pitch
wrapper.passthrough(Type.BYTE); // Yaw
wrapper.passthrough(Type.BYTE); // Head yaw
final int blockState = wrapper.read(Type.VAR_INT); // Data
wrapper.write(Type.VAR_INT, protocol.getMappingData().getNewBlockStateId(blockState));
}
return;
}
// Map to spawn player packet
wrapper.setPacketType(ClientboundPackets1_19_4.SPAWN_PLAYER);
wrapper.passthrough(Type.DOUBLE); // X
wrapper.passthrough(Type.DOUBLE); // Y
wrapper.passthrough(Type.DOUBLE); // Z
final byte pitch = wrapper.read(Type.BYTE);
wrapper.passthrough(Type.BYTE); // Yaw
wrapper.write(Type.BYTE, pitch);
wrapper.read(Type.BYTE); // Head yaw
wrapper.read(Type.VAR_INT); // Data
final short velocityX = wrapper.read(Type.SHORT);
final short velocityY = wrapper.read(Type.SHORT);
final short velocityZ = wrapper.read(Type.SHORT);
if (velocityX == 0 && velocityY == 0 && velocityZ == 0) {
return;
}
// Follow up with velocity packet
wrapper.send(Protocol1_20To1_20_2.class);
wrapper.cancel();
final PacketWrapper velocityPacket = wrapper.create(ClientboundPackets1_19_4.ENTITY_VELOCITY);
velocityPacket.write(Type.VAR_INT, entityId);
velocityPacket.write(Type.SHORT, velocityX);
velocityPacket.write(Type.SHORT, velocityY);
velocityPacket.write(Type.SHORT, velocityZ);
velocityPacket.send(Protocol1_20To1_20_2.class);
});
}
});
protocol.registerClientbound(ClientboundPackets1_20_2.JOIN_GAME, new PacketHandlers() {
@Override
public void register() {
handler(wrapper -> {
final ConfigurationPacketStorage configurationPacketStorage = wrapper.user().remove(ConfigurationPacketStorage.class);
wrapper.passthrough(Type.INT); // Entity id
wrapper.passthrough(Type.BOOLEAN); // Hardcore
final String[] worlds = wrapper.read(Type.STRING_ARRAY);
final int maxPlayers = wrapper.read(Type.VAR_INT);
final int viewDistance = wrapper.read(Type.VAR_INT);
final int simulationDistance = wrapper.read(Type.VAR_INT);
final boolean reducedDebugInfo = wrapper.read(Type.BOOLEAN);
final boolean showRespawnScreen = wrapper.read(Type.BOOLEAN);
wrapper.read(Type.BOOLEAN); // Limited crafting
final String dimensionType = wrapper.read(Type.STRING);
final String world = wrapper.read(Type.STRING);
final long seed = wrapper.read(Type.LONG);
wrapper.write(Type.UNSIGNED_BYTE, wrapper.read(Type.BYTE).shortValue()); // Gamemode
wrapper.passthrough(Type.BYTE); // Previous gamemode
wrapper.write(Type.STRING_ARRAY, worlds);
wrapper.write(Type.NBT, configurationPacketStorage.registry());
wrapper.write(Type.STRING, dimensionType);
wrapper.write(Type.STRING, world);
wrapper.write(Type.LONG, seed);
wrapper.write(Type.VAR_INT, maxPlayers);
wrapper.write(Type.VAR_INT, viewDistance);
wrapper.write(Type.VAR_INT, simulationDistance);
wrapper.write(Type.BOOLEAN, reducedDebugInfo);
wrapper.write(Type.BOOLEAN, showRespawnScreen);
worldDataTrackerHandlerByKey().handle(wrapper);
wrapper.send(Protocol1_20To1_20_2.class);
wrapper.cancel();
final PacketWrapper featuresPacket = wrapper.create(ClientboundPackets1_19_4.UPDATE_ENABLED_FEATURES);
featuresPacket.write(Type.STRING_ARRAY, configurationPacketStorage.enabledFeatures());
featuresPacket.send(Protocol1_20To1_20_2.class);
configurationPacketStorage.sendQueuedPackets(wrapper.user());
});
}
});
protocol.registerClientbound(ClientboundPackets1_20_2.RESPAWN, new PacketHandlers() {
@Override
public void register() {
handler(wrapper -> {
wrapper.passthrough(Type.STRING); // Dimension type
wrapper.passthrough(Type.STRING); // World
wrapper.passthrough(Type.LONG); // Seed
wrapper.write(Type.UNSIGNED_BYTE, wrapper.read(Type.BYTE).shortValue()); // Gamemode
wrapper.passthrough(Type.BYTE); // Previous gamemode
wrapper.passthrough(Type.BOOLEAN); // Debug
wrapper.passthrough(Type.BOOLEAN); // Flat
final GlobalPosition lastDeathPosition = wrapper.read(Type.OPTIONAL_GLOBAL_POSITION);
final int portalCooldown = wrapper.read(Type.VAR_INT);
wrapper.passthrough(Type.BYTE); // Data to keep
wrapper.write(Type.OPTIONAL_GLOBAL_POSITION, lastDeathPosition);
wrapper.write(Type.VAR_INT, portalCooldown);
});
handler(worldDataTrackerHandlerByKey()); // Tracks world height and name for chunk data and entity (un)tracking
}
});
protocol.registerClientbound(ClientboundPackets1_20_2.ENTITY_EFFECT, wrapper -> {
wrapper.passthrough(Type.VAR_INT); // Entity id
wrapper.write(Type.VAR_INT, wrapper.read(Type.VAR_INT) + 1); // Effect id
wrapper.passthrough(Type.BYTE); // Amplifier
wrapper.passthrough(Type.VAR_INT); // Duration
wrapper.passthrough(Type.BYTE); // Flags
if (wrapper.passthrough(Type.BOOLEAN)) {
wrapper.write(Type.NBT, wrapper.read(Type.NAMELESS_NBT)); // Factor data
}
});
protocol.registerClientbound(ClientboundPackets1_20_2.REMOVE_ENTITY_EFFECT, wrapper -> {
wrapper.passthrough(Type.VAR_INT); // Entity id
wrapper.write(Type.VAR_INT, wrapper.read(Type.VAR_INT) + 1); // Effect id
});
}
@Override
protected void registerRewrites() {
filter().handler((event, meta) -> meta.setMetaType(Types1_20.META_TYPES.byId(meta.metaType().typeId())));
registerMetaTypeHandler(null, Types1_20.META_TYPES.blockStateType, Types1_20.META_TYPES.optionalBlockStateType, Types1_20.META_TYPES.particleType, null, null);
filter().filterFamily(Entity1_19_4Types.DISPLAY).removeIndex(10);
filter().filterFamily(Entity1_19_4Types.MINECART_ABSTRACT).index(11).handler((event, meta) -> {
final int blockState = meta.value();
meta.setValue(protocol.getMappingData().getNewBlockStateId(blockState));
});
}
@Override
public EntityType typeFromId(final int type) {
return Entity1_19_4Types.getTypeFromId(type);
}
}
@@ -0,0 +1,102 @@
/*
* This file is part of ViaBackwards - https://github.com/ViaVersion/ViaBackwards
* Copyright (C) 2023 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.protocol1_20to1_20_2.storage;
import com.google.common.base.Preconditions;
import com.viaversion.viabackwards.protocol.protocol1_20to1_20_2.Protocol1_20To1_20_2;
import com.viaversion.viaversion.api.connection.StorableObject;
import com.viaversion.viaversion.api.connection.UserConnection;
import com.viaversion.viaversion.api.protocol.packet.PacketType;
import com.viaversion.viaversion.api.protocol.packet.PacketWrapper;
import com.viaversion.viaversion.libs.opennbt.tag.builtin.CompoundTag;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import java.util.ArrayList;
import java.util.List;
public final class ConfigurationPacketStorage implements StorableObject {
private final List<QueuedPacket> rawPackets = new ArrayList<>();
private CompoundTag registry;
private String[] enabledFeatures;
private boolean finished;
public CompoundTag registry() {
Preconditions.checkNotNull(registry);
return registry;
}
public void setRegistry(final CompoundTag registry) {
this.registry = registry;
}
public String[] enabledFeatures() {
Preconditions.checkNotNull(enabledFeatures);
return enabledFeatures;
}
public void setEnabledFeatures(final String[] enabledFeatures) {
this.enabledFeatures = enabledFeatures;
}
public void addRawPacket(final PacketWrapper wrapper, final PacketType type) throws Exception {
// It's easier to just copy it to a byte array buffer than to manually read the data
final ByteBuf buf = Unpooled.buffer();
//noinspection deprecation
wrapper.setId(-1); // Don't write the packet id to the buffer
wrapper.writeToBuffer(buf);
rawPackets.add(new QueuedPacket(buf, type));
}
public void sendQueuedPackets(final UserConnection connection) throws Exception {
for (final QueuedPacket queuedPacket : rawPackets) {
try {
final PacketWrapper packet = PacketWrapper.create(queuedPacket.packetType(), queuedPacket.buf(), connection);
packet.send(Protocol1_20To1_20_2.class);
} finally {
queuedPacket.buf().release();
}
}
}
public boolean isFinished() {
return finished;
}
public void setFinished(final boolean finished) {
this.finished = finished;
}
public static final class QueuedPacket {
private final ByteBuf buf;
private final PacketType packetType;
public QueuedPacket(final ByteBuf buf, final PacketType packetType) {
this.buf = buf;
this.packetType = packetType;
}
public ByteBuf buf() {
return buf;
}
public PacketType packetType() {
return packetType;
}
}
}
@@ -0,0 +1,120 @@
/*
* This file is part of ViaBackwards - https://github.com/ViaVersion/ViaBackwards
* Copyright (C) 2016-2023 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.protocol1_9_1_2to1_9_3_4;
import com.viaversion.viabackwards.protocol.protocol1_9_1_2to1_9_3_4.chunks.BlockEntity;
import com.viaversion.viaversion.api.connection.UserConnection;
import com.viaversion.viaversion.api.minecraft.Position;
import com.viaversion.viaversion.api.minecraft.chunks.Chunk;
import com.viaversion.viaversion.api.protocol.AbstractProtocol;
import com.viaversion.viaversion.api.protocol.remapper.PacketHandlers;
import com.viaversion.viaversion.api.type.Type;
import com.viaversion.viaversion.libs.opennbt.tag.builtin.CompoundTag;
import com.viaversion.viaversion.libs.opennbt.tag.builtin.StringTag;
import com.viaversion.viaversion.libs.opennbt.tag.builtin.Tag;
import com.viaversion.viaversion.protocols.protocol1_9_1to1_9.types.Chunk1_9_1_2Type;
import com.viaversion.viaversion.protocols.protocol1_9_3to1_9_1_2.ClientboundPackets1_9_3;
import com.viaversion.viaversion.protocols.protocol1_9_3to1_9_1_2.ServerboundPackets1_9_3;
import com.viaversion.viaversion.protocols.protocol1_9_3to1_9_1_2.storage.ClientWorld;
import com.viaversion.viaversion.protocols.protocol1_9_3to1_9_1_2.types.Chunk1_9_3_4Type;
import com.viaversion.viaversion.protocols.protocol1_9to1_8.ClientboundPackets1_9;
import com.viaversion.viaversion.protocols.protocol1_9to1_8.ServerboundPackets1_9;
public class Protocol1_9_1_2To1_9_3_4 extends AbstractProtocol<ClientboundPackets1_9_3, ClientboundPackets1_9, ServerboundPackets1_9_3, ServerboundPackets1_9> {
public Protocol1_9_1_2To1_9_3_4() {
super(ClientboundPackets1_9_3.class, ClientboundPackets1_9.class, ServerboundPackets1_9_3.class, ServerboundPackets1_9.class);
}
@Override
protected void registerPackets() {
registerClientbound(ClientboundPackets1_9_3.BLOCK_ENTITY_DATA, new PacketHandlers() {
@Override
public void register() {
map(Type.POSITION); //Position
map(Type.UNSIGNED_BYTE); //Type
map(Type.NBT); //NBT
handler(wrapper -> {
if (wrapper.get(Type.UNSIGNED_BYTE, 0) == 9) {
Position position = wrapper.get(Type.POSITION, 0);
CompoundTag tag = wrapper.get(Type.NBT, 0);
wrapper.clearPacket(); //Clear the packet
wrapper.setPacketType(ClientboundPackets1_9.UPDATE_SIGN);
wrapper.write(Type.POSITION, position); // Position
for (int i = 1; i < 5; i++) {
// Should technically be written as COMPONENT, but left as String for simplification/to remove redundant wrapping for VR
Tag textTag = tag.get("Text" + i);
String line = textTag instanceof StringTag ? ((StringTag) textTag).getValue() : "";
wrapper.write(Type.STRING, line); // Sign line
}
}
});
}
});
registerClientbound(ClientboundPackets1_9_3.CHUNK_DATA, wrapper -> {
ClientWorld clientWorld = wrapper.user().get(ClientWorld.class);
Chunk1_9_3_4Type newType = new Chunk1_9_3_4Type(clientWorld);
Chunk1_9_1_2Type oldType = new Chunk1_9_1_2Type(clientWorld); // Get the old type to not write Block Entities
Chunk chunk = wrapper.read(newType);
wrapper.write(oldType, chunk);
BlockEntity.handle(chunk.getBlockEntities(), wrapper.user());
});
registerClientbound(ClientboundPackets1_9_3.JOIN_GAME, new PacketHandlers() {
@Override
public void register() {
map(Type.INT); // 0 - Entity ID
map(Type.UNSIGNED_BYTE); // 1 - Gamemode
map(Type.INT); // 2 - Dimension
handler(wrapper -> {
ClientWorld clientChunks = wrapper.user().get(ClientWorld.class);
int dimensionId = wrapper.get(Type.INT, 1);
clientChunks.setEnvironment(dimensionId);
});
}
});
registerClientbound(ClientboundPackets1_9_3.RESPAWN, new PacketHandlers() {
@Override
public void register() {
map(Type.INT); // 0 - Dimension ID
handler(wrapper -> {
ClientWorld clientWorld = wrapper.user().get(ClientWorld.class);
int dimensionId = wrapper.get(Type.INT, 0);
clientWorld.setEnvironment(dimensionId);
});
}
});
}
@Override
public void init(UserConnection userConnection) {
if (!userConnection.has(ClientWorld.class)) {
userConnection.put(new ClientWorld(userConnection));
}
}
}
@@ -0,0 +1,85 @@
/*
* This file is part of ViaBackwards - https://github.com/ViaVersion/ViaBackwards
* Copyright (C) 2016-2023 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.protocol1_9_1_2to1_9_3_4.chunks;
import com.viaversion.viabackwards.protocol.protocol1_9_1_2to1_9_3_4.Protocol1_9_1_2To1_9_3_4;
import com.viaversion.viaversion.api.Via;
import com.viaversion.viaversion.api.connection.UserConnection;
import com.viaversion.viaversion.api.minecraft.Position;
import com.viaversion.viaversion.api.protocol.packet.PacketWrapper;
import com.viaversion.viaversion.api.type.Type;
import com.viaversion.viaversion.libs.opennbt.tag.builtin.CompoundTag;
import com.viaversion.viaversion.libs.opennbt.tag.builtin.NumberTag;
import com.viaversion.viaversion.protocols.protocol1_9_3to1_9_1_2.ClientboundPackets1_9_3;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
public class BlockEntity {
private static final Map<String, Integer> types = new HashMap<>();
static {
types.put("MobSpawner", 1);
types.put("Control", 2);
types.put("Beacon", 3);
types.put("Skull", 4);
types.put("FlowerPot", 5);
types.put("Banner", 6);
types.put("UNKNOWN", 7);
types.put("EndGateway", 8);
types.put("Sign", 9);
}
public static void handle(List<CompoundTag> tags, UserConnection connection) {
for (CompoundTag tag : tags) {
try {
if (!tag.contains("id"))
throw new Exception("NBT tag not handled because the id key is missing");
String id = (String) tag.get("id").getValue();
if (!types.containsKey(id))
throw new Exception("Not handled id: " + id);
int newId = types.get(id);
if (newId == -1)
continue;
int x = ((NumberTag) tag.get("x")).asInt();
int y = ((NumberTag) tag.get("y")).asInt();
int z = ((NumberTag) tag.get("z")).asInt();
Position pos = new Position(x, (short) y, z);
updateBlockEntity(pos, (short) newId, tag, connection);
} catch (Exception e) {
if (Via.getManager().isDebug()) {
Via.getPlatform().getLogger().warning("Block Entity: " + e.getMessage() + ": " + tag);
}
}
}
}
private static void updateBlockEntity(Position pos, short id, CompoundTag tag, UserConnection connection) throws Exception {
PacketWrapper wrapper = PacketWrapper.create(ClientboundPackets1_9_3.BLOCK_ENTITY_DATA, null, connection);
wrapper.write(Type.POSITION, pos);
wrapper.write(Type.UNSIGNED_BYTE, id);
wrapper.write(Type.NBT, tag);
wrapper.scheduleSend(Protocol1_9_1_2To1_9_3_4.class, false);
}
}
@@ -25,10 +25,10 @@ import com.viaversion.viaversion.api.minecraft.chunks.Chunk;
import com.viaversion.viaversion.api.minecraft.item.Item;
import com.viaversion.viaversion.api.protocol.remapper.PacketHandlers;
import com.viaversion.viaversion.api.type.Type;
import com.viaversion.viaversion.protocols.protocol1_9_1_2to1_9_3_4.types.Chunk1_9_3_4Type;
import com.viaversion.viaversion.protocols.protocol1_9_3to1_9_1_2.ClientboundPackets1_9_3;
import com.viaversion.viaversion.protocols.protocol1_9_3to1_9_1_2.ServerboundPackets1_9_3;
import com.viaversion.viaversion.protocols.protocol1_9_3to1_9_1_2.storage.ClientWorld;
import com.viaversion.viaversion.protocols.protocol1_9_3to1_9_1_2.types.Chunk1_9_3_4Type;
public class BlockItemPackets1_10 extends LegacyBlockItemRewriter<ClientboundPackets1_9_3, ServerboundPackets1_9_3, Protocol1_9_4To1_10> {
@@ -0,0 +1,64 @@
/*
* This file is part of ViaBackwards - https://github.com/ViaVersion/ViaBackwards
* Copyright (C) 2016-2023 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.protocol1_9to1_9_1;
import com.viaversion.viaversion.api.protocol.AbstractProtocol;
import com.viaversion.viaversion.api.protocol.remapper.PacketHandlers;
import com.viaversion.viaversion.api.type.Type;
import com.viaversion.viaversion.protocols.protocol1_9to1_8.ClientboundPackets1_9;
import com.viaversion.viaversion.protocols.protocol1_9to1_8.ServerboundPackets1_9;
public class Protocol1_9To1_9_1 extends AbstractProtocol<ClientboundPackets1_9, ClientboundPackets1_9, ServerboundPackets1_9, ServerboundPackets1_9> {
public Protocol1_9To1_9_1() {
super(ClientboundPackets1_9.class, ClientboundPackets1_9.class, ServerboundPackets1_9.class, ServerboundPackets1_9.class);
}
@Override
protected void registerPackets() {
registerClientbound(ClientboundPackets1_9.JOIN_GAME, new PacketHandlers() {
@Override
public void register() {
map(Type.INT); // 0 - Player ID
map(Type.UNSIGNED_BYTE); // 1 - Player Gamemode
// 1.9.1 PRE 2 Changed this
map(Type.INT, Type.BYTE); // 2 - Player Dimension
map(Type.UNSIGNED_BYTE); // 3 - World Difficulty
map(Type.UNSIGNED_BYTE); // 4 - Max Players (Tab)
map(Type.STRING); // 5 - Level Type
map(Type.BOOLEAN); // 6 - Reduced Debug info
}
});
registerClientbound(ClientboundPackets1_9.SOUND, new PacketHandlers() {
@Override
public void register() {
map(Type.VAR_INT); // 0 - Sound ID
handler(wrapper -> {
int sound = wrapper.get(Type.VAR_INT, 0);
if (sound == 415) // Stop the Elytra sound for 1.9 (It's introduced in 1.9.2)
wrapper.cancel();
else if (sound >= 416) // Act like the Elytra sound never existed
wrapper.set(Type.VAR_INT, 0, sound - 1);
});
}
});
}
}
@@ -17,6 +17,9 @@
*/
package com.viaversion.viabackwards.utils;
import java.util.HashSet;
import java.util.Objects;
import java.util.Set;
import java.util.regex.Pattern;
public class ChatUtil {
@@ -27,25 +30,103 @@ public class ChatUtil {
return removeUnusedColor(legacy, defaultColor, false);
}
private static class ChatFormattingState {
private final Set<Character> formatting;
private final char defaultColor;
private char color;
private ChatFormattingState(char defaultColor) {
this(new HashSet<>(), defaultColor, defaultColor);
}
public ChatFormattingState(Set<Character> formatting, char defaultColor, char color) {
this.formatting = formatting;
this.defaultColor = defaultColor;
this.color = color;
}
private void setColor(char newColor) {
formatting.clear();
color = newColor;
}
public ChatFormattingState copy() {
return new ChatFormattingState(new HashSet<>(formatting), defaultColor, color);
}
public void appendTo(StringBuilder builder) {
builder.append('§').append(color);
for (Character formatCharacter : formatting) {
builder.append('§').append(formatCharacter);
}
}
@Override
public boolean equals(Object o) {
if (this == o) {
return true;
}
if (o == null || getClass() != o.getClass()) {
return false;
}
ChatFormattingState that = (ChatFormattingState) o;
return defaultColor == that.defaultColor
&& color == that.color
&& Objects.equals(formatting, that.formatting);
}
@Override
public int hashCode() {
return Objects.hash(formatting, defaultColor, color);
}
public void processNextControlChar(char controlChar) {
if (controlChar == 'r') {
setColor(defaultColor);
return;
}
if (controlChar == 'l' || controlChar == 'm' || controlChar == 'n' || controlChar == 'o') {
formatting.add(controlChar);
return;
}
setColor(controlChar);
}
}
public static String fromLegacy(String legacy, char defaultColor, int limit) {
return fromLegacy(legacy, defaultColor, limit, false);
}
public static String fromLegacyPrefix(String legacy, char defaultColor, int limit) {
return fromLegacy(legacy, defaultColor, limit, true);
}
public static String fromLegacy(String legacy, char defaultColor, int limit, boolean isPrefix) {
legacy = removeUnusedColor(legacy, defaultColor, isPrefix);
if (legacy.length() > limit) legacy = legacy.substring(0, limit);
if (legacy.endsWith("§")) legacy = legacy.substring(0, legacy.length() - 1);
return legacy;
}
public static String removeUnusedColor(String legacy, char defaultColor, boolean isPrefix) {
if (legacy == null) return null;
Pattern pattern = isPrefix ? UNUSED_COLOR_PATTERN_PREFIX : UNUSED_COLOR_PATTERN;
legacy = pattern.matcher(legacy).replaceAll("$1$2");
StringBuilder builder = new StringBuilder();
char last = defaultColor;
ChatFormattingState builderState = new ChatFormattingState(defaultColor);
ChatFormattingState lastState = new ChatFormattingState(defaultColor);
for (int i = 0; i < legacy.length(); i++) {
char current = legacy.charAt(i);
if (current != '§' || i == legacy.length() - 1) {
if (!lastState.equals(builderState)) {
lastState.appendTo(builder);
builderState = lastState.copy();
}
builder.append(current);
continue;
}
current = legacy.charAt(++i);
if (current != last) {
builder.append('§').append(current);
last = current;
}
lastState.processNextControlChar(current);
}
return builder.toString();
}
@@ -19,14 +19,4 @@ fix-formatted-inventory-titles: true
#
# Sends inventory acknowledgement packets to act as a replacement for ping packets for sub 1.17 clients.
# This only takes effect for ids in the short range. Useful for anticheat compatibility.
handle-pings-as-inv-acknowledgements: false
#
# 1.19.1 chat type formats.
chat-types-1_19_1:
"chat.type.text": "<%s> %s"
"chat.type.announcement": "[%s] %s"
"commands.message.display.incoming": "%s whispers to you: %s"
"commands.message.display.outgoing": "You whisper to %s: %s"
"chat.type.team.text": "%s <%s> %s"
"chat.type.team.sent": "-> %s <%s> %s"
"chat.type.emote": "* %s %s"
handle-pings-as-inv-acknowledgements: false
+7
View File
@@ -0,0 +1,7 @@
projectVersion=4.8.1
# Smile emoji
mcVersions=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.20.2
waterfallVersion=1.20
velocityVersion=3.2
+1 -1
View File
@@ -3,7 +3,7 @@ metadata.format.version = "1.1"
[versions]
# ViaVersion
viaver = "4.7.0-1.20-rc1-SNAPSHOT"
viaver = "4.8.1-SNAPSHOT"
# Common provided
netty = "4.0.20.Final"
Binary file not shown.
+2 -1
View File
@@ -1,6 +1,7 @@
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-8.1.1-bin.zip
distributionUrl=https\://services.gradle.org/distributions/gradle-8.3-bin.zip
networkTimeout=10000
validateDistributionUrl=true
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
Vendored
+6 -2
View File
@@ -83,7 +83,8 @@ done
# This is normally unused
# shellcheck disable=SC2034
APP_BASE_NAME=${0##*/}
APP_HOME=$( cd "${APP_HOME:-./}" && pwd -P ) || exit
# Discard cd standard output in case $CDPATH is set (https://github.com/gradle/gradle/issues/25036)
APP_HOME=$( cd "${APP_HOME:-./}" > /dev/null && pwd -P ) || exit
# Use the maximum available, or set MAX_FD != -1 to use that value.
MAX_FD=maximum
@@ -130,10 +131,13 @@ location of your Java installation."
fi
else
JAVACMD=java
which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
if ! command -v java >/dev/null 2>&1
then
die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
Please set the JAVA_HOME variable in your environment to match the
location of your Java installation."
fi
fi
# Increase the maximum file descriptors if we can.
Vendored
+92 -92
View File
@@ -1,92 +1,92 @@
@rem
@rem Copyright 2015 the original author or authors.
@rem
@rem Licensed under the Apache License, Version 2.0 (the "License");
@rem you may not use this file except in compliance with the License.
@rem You may obtain a copy of the License at
@rem
@rem https://www.apache.org/licenses/LICENSE-2.0
@rem
@rem Unless required by applicable law or agreed to in writing, software
@rem distributed under the License is distributed on an "AS IS" BASIS,
@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
@rem See the License for the specific language governing permissions and
@rem limitations under the License.
@rem
@if "%DEBUG%"=="" @echo off
@rem ##########################################################################
@rem
@rem Gradle startup script for Windows
@rem
@rem ##########################################################################
@rem Set local scope for the variables with windows NT shell
if "%OS%"=="Windows_NT" setlocal
set DIRNAME=%~dp0
if "%DIRNAME%"=="" set DIRNAME=.
@rem This is normally unused
set APP_BASE_NAME=%~n0
set APP_HOME=%DIRNAME%
@rem Resolve any "." and ".." in APP_HOME to make it shorter.
for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi
@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m"
@rem Find java.exe
if defined JAVA_HOME goto findJavaFromJavaHome
set JAVA_EXE=java.exe
%JAVA_EXE% -version >NUL 2>&1
if %ERRORLEVEL% equ 0 goto execute
echo.
echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
echo.
echo Please set the JAVA_HOME variable in your environment to match the
echo location of your Java installation.
goto fail
:findJavaFromJavaHome
set JAVA_HOME=%JAVA_HOME:"=%
set JAVA_EXE=%JAVA_HOME%/bin/java.exe
if exist "%JAVA_EXE%" goto execute
echo.
echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
echo.
echo Please set the JAVA_HOME variable in your environment to match the
echo location of your Java installation.
goto fail
:execute
@rem Setup the command line
set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
@rem Execute Gradle
"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %*
:end
@rem End local scope for the variables with windows NT shell
if %ERRORLEVEL% equ 0 goto mainEnd
:fail
rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
rem the _cmd.exe /c_ return code!
set EXIT_CODE=%ERRORLEVEL%
if %EXIT_CODE% equ 0 set EXIT_CODE=1
if not ""=="%GRADLE_EXIT_CONSOLE%" exit %EXIT_CODE%
exit /b %EXIT_CODE%
:mainEnd
if "%OS%"=="Windows_NT" endlocal
:omega
@rem
@rem Copyright 2015 the original author or authors.
@rem
@rem Licensed under the Apache License, Version 2.0 (the "License");
@rem you may not use this file except in compliance with the License.
@rem You may obtain a copy of the License at
@rem
@rem https://www.apache.org/licenses/LICENSE-2.0
@rem
@rem Unless required by applicable law or agreed to in writing, software
@rem distributed under the License is distributed on an "AS IS" BASIS,
@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
@rem See the License for the specific language governing permissions and
@rem limitations under the License.
@rem
@if "%DEBUG%"=="" @echo off
@rem ##########################################################################
@rem
@rem Gradle startup script for Windows
@rem
@rem ##########################################################################
@rem Set local scope for the variables with windows NT shell
if "%OS%"=="Windows_NT" setlocal
set DIRNAME=%~dp0
if "%DIRNAME%"=="" set DIRNAME=.
@rem This is normally unused
set APP_BASE_NAME=%~n0
set APP_HOME=%DIRNAME%
@rem Resolve any "." and ".." in APP_HOME to make it shorter.
for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi
@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m"
@rem Find java.exe
if defined JAVA_HOME goto findJavaFromJavaHome
set JAVA_EXE=java.exe
%JAVA_EXE% -version >NUL 2>&1
if %ERRORLEVEL% equ 0 goto execute
echo.
echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
echo.
echo Please set the JAVA_HOME variable in your environment to match the
echo location of your Java installation.
goto fail
:findJavaFromJavaHome
set JAVA_HOME=%JAVA_HOME:"=%
set JAVA_EXE=%JAVA_HOME%/bin/java.exe
if exist "%JAVA_EXE%" goto execute
echo.
echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
echo.
echo Please set the JAVA_HOME variable in your environment to match the
echo location of your Java installation.
goto fail
:execute
@rem Setup the command line
set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
@rem Execute Gradle
"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %*
:end
@rem End local scope for the variables with windows NT shell
if %ERRORLEVEL% equ 0 goto mainEnd
:fail
rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
rem the _cmd.exe /c_ return code!
set EXIT_CODE=%ERRORLEVEL%
if %EXIT_CODE% equ 0 set EXIT_CODE=1
if not ""=="%GRADLE_EXIT_CONSOLE%" exit %EXIT_CODE%
exit /b %EXIT_CODE%
:mainEnd
if "%OS%"=="Windows_NT" endlocal
:omega
+2 -1
View File
@@ -15,7 +15,8 @@ dependencyResolutionManagement {
pluginManagement {
plugins {
id("net.kyori.blossom") version "1.2.0"
id("net.kyori.blossom") version "2.1.0"
id("org.jetbrains.gradle.plugin.idea-ext") version "1.1.7"
id("com.github.johnrengelman.shadow") version "8.1.1"
}
}
+85
View File
@@ -1,7 +1,10 @@
import com.github.jengelman.gradle.plugins.shadow.tasks.ShadowJar
import io.papermc.hangarpublishplugin.model.Platforms
plugins {
id("com.github.johnrengelman.shadow")
id("io.papermc.hangar-publish-plugin") version "0.1.0"
id("com.modrinth.minotaur") version "2.+"
}
val platforms = setOf(
@@ -39,3 +42,85 @@ tasks {
}
publishShadowJar()
val branch = rootProject.branchName()
val baseVersion = project.version as String
val isRelease = !baseVersion.contains('-')
val isMainBranch = branch == "master"
if (!isRelease || isMainBranch) { // Only publish releases from the main branch
val suffixedVersion = if (isRelease) baseVersion else baseVersion + "+" + System.getenv("GITHUB_RUN_NUMBER")
val changelogContent = if (isRelease) {
"See [GitHub](https://github.com/ViaVersion/ViaBackwards) for release notes."
} else {
val commitHash = rootProject.latestCommitHash()
"[$commitHash](https://github.com/ViaVersion/ViaBackwards/commit/$commitHash) ${rootProject.latestCommitMessage()}"
}
modrinth {
// val snapshotVersion = rootProject.parseMinecraftSnapshotVersion(project.version as String)
val mcVersions: List<String> = (property("mcVersions") as String)
.split(",")
.map { it.trim() }
//.let { if (snapshotVersion != null) it + snapshotVersion else it } // We're usually too fast for modrinth
token.set(System.getenv("MODRINTH_TOKEN"))
projectId.set("viabackwards")
versionType.set(if (isRelease) "release" else if (isMainBranch) "beta" else "alpha")
versionNumber.set(suffixedVersion)
versionName.set(suffixedVersion)
changelog.set(changelogContent)
uploadFile.set(tasks.shadowJar.flatMap { it.archiveFile })
gameVersions.set(mcVersions)
loaders.add("fabric")
loaders.add("paper")
loaders.add("folia")
loaders.add("velocity")
loaders.add("bungeecord")
loaders.add("sponge")
autoAddDependsOn.set(false)
detectLoaders.set(false)
dependencies {
optional.project("viaversion")
optional.project("viafabric")
optional.project("viafabricplus")
}
}
hangarPublish {
publications.register("plugin") {
version.set(suffixedVersion)
id.set("ViaBackwards")
channel.set(if (isRelease) "Release" else if (isMainBranch) "Snapshot" else "Alpha")
changelog.set(changelogContent)
apiKey.set(System.getenv("HANGAR_TOKEN"))
platforms {
register(Platforms.PAPER) {
jar.set(tasks.shadowJar.flatMap { it.archiveFile })
platformVersions.set(listOf(property("mcVersionRange") as String))
dependencies {
hangar("ViaVersion") {
required.set(true)
}
}
}
register(Platforms.VELOCITY) {
jar.set(tasks.shadowJar.flatMap { it.archiveFile })
platformVersions.set(listOf(property("velocityVersion") as String))
dependencies {
hangar("ViaVersion") {
required.set(true)
}
}
}
register(Platforms.WATERFALL) {
jar.set(tasks.shadowJar.flatMap { it.archiveFile })
platformVersions.set(listOf(property("waterfallVersion") as String))
dependencies {
hangar("ViaVersion") {
required.set(true)
}
}
}
}
}
}
}