Compare commits

...
73 Commits
Author SHA1 Message Date
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
Nassim Jahnke 63a3908b53 4.7.0 Release 2023-06-07 11:36:14 +02:00
Nassim Jahnke ceb08c1e55 Update VV usage 2023-06-05 09:10:50 +02:00
Nassim Jahnke c468ec714c Handle servers not sending 1.16 expected tags
Fixes #548
2023-05-28 12:15:42 +02:00
Nassim Jahnke 4fb9fdab9b Add statistics handler to 1.19.4->1.19.3 protocol 2023-05-23 16:43:46 +02:00
Nassim Jahnke d271d3d687 1.20-pre3 2023-05-19 14:34:34 +02:00
Nassim Jahnke 9fa7af7c7b Update nbt file 2023-05-10 16:18:43 +02:00
Nassim Jahnke f591593992 1.20-pre1 2023-05-10 15:54:13 +02:00
Nassim Jahnke e74b5d661d 23w18a, maybe 2023-05-03 15:22:21 +02:00
Nassim Jahnke 483920b729 Sanity checks in item rewriting 2023-05-01 11:33:00 +02:00
Nassim Jahnke 73647ee4fb 23w17a 2023-04-26 19:06:30 +02:00
Nassim Jahnke 97f5ec322a 23w16a 2023-04-20 17:28:25 +02:00
Nassim Jahnke da35067e1d Handle optional block state entity meta 2023-04-18 13:39:59 +02:00
Kichura 65c8024ba7 Add ViaBackwards icon to Fabric (#543) 2023-04-15 14:14:40 +02:00
Nassim Jahnke 377f512f95 23w14a 2023-04-05 15:26:33 +02:00
RK_01 b174dd31b4 Fixed max player count value mapping (#541) 2023-03-31 09:40:18 +02:00
Nassim Jahnke 8eaadd0f18 23w13a 2023-03-29 16:34:17 +02:00
Nassim Jahnke ef1b062449 Handle changed sign nbt 2023-03-24 11:36:32 +01:00
Nassim Jahnke c1383baf14 23w12a 2023-03-22 19:41:00 +01:00
Nassim Jahnke 455e862089 Update mapping files 2023-03-20 10:32:27 +01:00
Nassim Jahnke 0d4257f228 Don't override getTranslatableRewriter in 1.13->1.12, 1.14->1.13 protocols
The method is used in item handling and would otherwise mess up the lore
2023-03-20 10:05:46 +01:00
Pantera (Mad_Daniel) 614207aeef Add remaining sound mappings 2023-03-18 18:24:41 +01:00
Nassim Jahnke 1b268ad4ec Use right type for component metadata 2023-03-18 13:56:53 +01:00
Nassim Jahnke 509055307a Handle 1.12 keybind components
Fixes #474
2023-03-18 13:55:16 +01:00
Nassim Jahnke 68e578a04e Handle translatables in 1.13.1 entity display names 2023-03-18 13:16:22 +01:00
Nassim Jahnke a07550363e Handle shifted 1.19.4 boat types 2023-03-18 12:27:46 +01:00
Nassim Jahnke eb6e9e016a Handle translatables in 1.14/1.15 entity display names 2023-03-18 12:23:14 +01:00
Nassim Jahnke 587a5e487f Improve 1.13->1.12 translatable handling 2023-03-18 10:02:23 +01:00
Nassim Jahnke efded25594 4.6.1 Release 2023-03-16 20:45:16 +01:00
Nassim Jahnke 11e71b1307 Fix #3252 2023-03-15 21:20:33 +01:00
riku6460 974b15243a Fix enchantments in 1.12 -> 1.13 (#533) 2023-03-14 20:01:25 +01:00
Nassim Jahnke e14da27093 Bump version to 4.6.1-SNAPSHOT 2023-03-14 20:01:14 +01:00
78 changed files with 2591 additions and 307 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
-
+1 -1
View File
@@ -8,5 +8,5 @@ repositories {
dependencies {
// version must be manually kept in sync with the one in root project settings.gradle.kts
implementation("com.github.johnrengelman", "shadow", "8.1.0")
implementation("com.github.johnrengelman", "shadow", "8.1.1")
}
+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", "branch")
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.6.0"
version = property("projectVersion") as String // from gradle.properties
description = "Allow older clients to join newer server versions."
}
@@ -25,7 +25,6 @@ import com.viaversion.viabackwards.listener.LecternInteractListener;
import com.viaversion.viabackwards.listener.PlayerItemDropListener;
import com.viaversion.viaversion.api.Via;
import com.viaversion.viaversion.api.protocol.version.ProtocolVersion;
import com.viaversion.viaversion.bukkit.platform.BukkitViaLoader;
import org.bukkit.plugin.java.JavaPlugin;
public class BukkitPlugin extends JavaPlugin implements ViaBackwardsPlatform {
@@ -45,19 +44,18 @@ public class BukkitPlugin extends JavaPlugin implements ViaBackwardsPlatform {
}
private void enable() {
BukkitViaLoader loader = (BukkitViaLoader) Via.getManager().getLoader();
int protocolVersion = Via.getAPI().getServerVersion().highestSupportedVersion();
if (protocolVersion >= ProtocolVersion.v1_17.getVersion()) {
loader.storeListener(new PlayerItemDropListener(this)).register();
new PlayerItemDropListener(this).register();
}
if (protocolVersion >= ProtocolVersion.v1_16.getVersion()) {
loader.storeListener(new FireExtinguishListener(this)).register();
new FireExtinguishListener(this).register();
}
if (protocolVersion >= ProtocolVersion.v1_14.getVersion()) {
loader.storeListener(new LecternInteractListener(this)).register();
new LecternInteractListener(this).register();
}
if (protocolVersion >= ProtocolVersion.v1_12.getVersion()) {
loader.storeListener(new FireDamageListener(this)).register();
new FireDamageListener(this).register();
}
}
+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);
}
@@ -49,18 +49,23 @@ import com.viaversion.viabackwards.protocol.protocol1_18_2to1_19.Protocol1_18_2T
import com.viaversion.viabackwards.protocol.protocol1_18to1_18_2.Protocol1_18To1_18_2;
import com.viaversion.viabackwards.protocol.protocol1_19_1to1_19_3.Protocol1_19_1To1_19_3;
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.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.6.0";
String MINIMUM_VV_VERSION = "4.8.0";
String IMPL_VERSION = "$IMPL_VERSION";
/**
@@ -84,6 +89,8 @@ public interface ViaBackwardsPlatform {
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);
@@ -123,6 +130,9 @@ public interface ViaBackwardsPlatform {
protocolManager.registerProtocol(new Protocol1_19To1_19_1(), ProtocolVersion.v1_19, ProtocolVersion.v1_19_1);
protocolManager.registerProtocol(new Protocol1_19_1To1_19_3(), ProtocolVersion.v1_19_1, ProtocolVersion.v1_19_3);
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) {
@@ -175,17 +175,29 @@ public abstract class EntityRewriterBase<C extends ClientboundPacketType, T exte
}
}
public void registerMetaTypeHandler(@Nullable MetaType itemType, @Nullable MetaType blockType, @Nullable MetaType particleType, @Nullable MetaType optChatType) {
public void registerMetaTypeHandler(
@Nullable MetaType itemType,
@Nullable MetaType blockStateType,
@Nullable MetaType optionalBlockStateType,
@Nullable MetaType particleType,
@Nullable MetaType componentType,
@Nullable MetaType optionalComponentType
) {
filter().handler((event, meta) -> {
MetaType type = meta.metaType();
if (itemType != null && type == itemType) {
if (type == itemType) {
protocol.getItemRewriter().handleItemToClient(meta.value());
} else if (blockType != null && type == blockType) {
} else if (type == blockStateType) {
int data = meta.value();
meta.setValue(protocol.getMappingData().getNewBlockStateId(data));
} else if (particleType != null && type == particleType) {
} else if (type == optionalBlockStateType) {
int data = meta.value();
if (data != 0) {
meta.setValue(protocol.getMappingData().getNewBlockStateId(data));
}
} else if (type == particleType) {
rewriteParticle(meta.value());
} else if (optChatType != null && type == optChatType) {
} else if (type == optionalComponentType || type == componentType) {
JsonElement text = meta.value();
if (text != null) {
protocol.getTranslatableRewriter().processText(text);
@@ -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) {
@@ -49,28 +53,32 @@ public class ItemRewriter<C extends ClientboundPacketType, S extends Serverbound
CompoundTag display = item.tag() != null ? item.tag().get("display") : null;
if (protocol.getTranslatableRewriter() != null && display != null) {
// Handle name and lore components
StringTag name = display.get("Name");
if (name != null) {
String newValue = protocol.getTranslatableRewriter().processText(name.getValue()).toString();
Tag name = display.get("Name");
if (name instanceof StringTag) {
StringTag nameStringTag = (StringTag) name;
String newValue = protocol.getTranslatableRewriter().processText(nameStringTag.getValue()).toString();
if (!newValue.equals(name.getValue())) {
saveStringTag(display, name, "Name");
saveStringTag(display, nameStringTag, "Name");
}
name.setValue(newValue);
nameStringTag.setValue(newValue);
}
ListTag lore = display.get("Lore");
if (lore != null) {
Tag lore = display.get("Lore");
if (lore instanceof ListTag) {
ListTag loreListTag = (ListTag) lore;
boolean changed = false;
for (Tag loreEntryTag : lore) {
if (!(loreEntryTag instanceof StringTag)) continue;
for (Tag loreEntryTag : loreListTag) {
if (!(loreEntryTag instanceof StringTag)) {
continue;
}
StringTag loreEntry = (StringTag) loreEntryTag;
String newValue = protocol.getTranslatableRewriter().processText(loreEntry.getValue()).toString();
if (!changed && !newValue.equals(loreEntry.getValue())) {
// Backup original lore before doing any modifications
changed = true;
saveListTag(display, lore, "Lore");
saveListTag(display, loreListTag, "Lore");
}
loreEntry.setValue(newValue);
@@ -78,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();
}
@@ -110,6 +110,16 @@ public class TranslatableRewriter<C extends ClientboundPacketType> extends Compo
});
}
public void registerCombatKill1_20(C packetType) {
protocol.registerClientbound(packetType, new PacketHandlers() {
@Override
public void register() {
map(Type.VAR_INT); // Duration
handler(wrapper -> processText(wrapper.passthrough(Type.COMPONENT)));
}
});
}
@Override
protected void handleTranslate(JsonObject root, String translate) {
String newTranslate = mappedTranslationKey(translate);
@@ -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> {
@@ -29,7 +29,24 @@ import com.viaversion.viaversion.rewriter.ComponentRewriter;
public class ChatPackets1_12 extends RewriterBase<Protocol1_11_1To1_12> {
private final ComponentRewriter<ClientboundPackets1_12> componentRewriter = new ComponentRewriter<ClientboundPackets1_12>() {
public static final ComponentRewriter<ClientboundPackets1_12> COMPONENT_REWRITER = new ComponentRewriter<ClientboundPackets1_12>() {
@Override
public void processText(JsonElement element) {
super.processText(element);
if (element == null || !element.isJsonObject()) {
return;
}
JsonObject object = element.getAsJsonObject();
JsonElement keybind = object.remove("keybind");
if (keybind == null) {
return;
}
//TODO Add nicer text for the key, also use this component rewriter in more packets
object.addProperty("text", keybind.getAsString());
}
@Override
protected void handleTranslate(JsonObject object, String translate) {
String text = AdvancementTranslations.get(translate);
@@ -47,7 +64,7 @@ public class ChatPackets1_12 extends RewriterBase<Protocol1_11_1To1_12> {
protected void registerPackets() {
protocol.registerClientbound(ClientboundPackets1_12.CHAT_MESSAGE, wrapper -> {
JsonElement element = wrapper.passthrough(Type.COMPONENT);
componentRewriter.processText(element);
COMPONENT_REWRITER.processText(element);
});
}
}
@@ -28,10 +28,12 @@ import com.viaversion.viaversion.api.minecraft.entities.Entity1_12Types;
import com.viaversion.viaversion.api.minecraft.entities.EntityType;
import com.viaversion.viaversion.api.minecraft.metadata.Metadata;
import com.viaversion.viaversion.api.minecraft.metadata.types.MetaType1_12;
import com.viaversion.viaversion.api.minecraft.metadata.types.MetaType1_9;
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_12;
import com.viaversion.viaversion.libs.gson.JsonElement;
import com.viaversion.viaversion.libs.opennbt.tag.builtin.CompoundTag;
import com.viaversion.viaversion.protocols.protocol1_12to1_11_1.ClientboundPackets1_12;
import com.viaversion.viaversion.protocols.protocol1_9_3to1_9_1_2.ClientboundPackets1_9_3;
@@ -205,6 +207,12 @@ public class EntityPackets1_12 extends LegacyEntityRewriter<ClientboundPackets1_
mapEntityTypeWithData(Entity1_12Types.EntityType.PARROT, Entity1_12Types.EntityType.BAT).plainName().spawnMetadata(storage -> storage.add(new Metadata(12, MetaType1_12.Byte, (byte) 0x00)));
mapEntityTypeWithData(Entity1_12Types.EntityType.ILLUSION_ILLAGER, Entity1_12Types.EntityType.EVOCATION_ILLAGER).plainName();
filter().handler((event, meta) -> {
if (meta.metaType() == MetaType1_12.Chat) {
ChatPackets1_12.COMPONENT_REWRITER.processText((JsonElement) meta.getValue());
}
});
// Handle Illager
filter().filterFamily(Entity1_12Types.EntityType.EVOCATION_ILLAGER).cancel(12);
filter().filterFamily(Entity1_12Types.EntityType.EVOCATION_ILLAGER).index(13).toIndex(12);
@@ -35,19 +35,43 @@ import com.viaversion.viaversion.api.Via;
import com.viaversion.viaversion.api.connection.UserConnection;
import com.viaversion.viaversion.api.minecraft.entities.Entity1_13Types;
import com.viaversion.viaversion.data.entity.EntityTrackerBase;
import com.viaversion.viaversion.libs.gson.JsonElement;
import com.viaversion.viaversion.libs.gson.JsonObject;
import com.viaversion.viaversion.libs.gson.JsonParser;
import com.viaversion.viaversion.libs.kyori.adventure.text.Component;
import com.viaversion.viaversion.libs.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer;
import com.viaversion.viaversion.protocols.protocol1_12_1to1_12.ClientboundPackets1_12_1;
import com.viaversion.viaversion.protocols.protocol1_12_1to1_12.ServerboundPackets1_12_1;
import com.viaversion.viaversion.protocols.protocol1_13to1_12_2.ChatRewriter;
import com.viaversion.viaversion.protocols.protocol1_13to1_12_2.ClientboundPackets1_13;
import com.viaversion.viaversion.protocols.protocol1_13to1_12_2.Protocol1_13To1_12_2;
import com.viaversion.viaversion.protocols.protocol1_13to1_12_2.ServerboundPackets1_13;
import com.viaversion.viaversion.protocols.protocol1_9_3to1_9_1_2.storage.ClientWorld;
import org.checkerframework.checker.nullness.qual.Nullable;
public class Protocol1_12_2To1_13 extends BackwardsProtocol<ClientboundPackets1_13, ClientboundPackets1_12_1, ServerboundPackets1_13, ServerboundPackets1_12_1> {
public static final BackwardsMappings MAPPINGS = new BackwardsMappings();
private final EntityPackets1_13 entityRewriter = new EntityPackets1_13(this);
private final BlockItemPackets1_13 blockItemPackets = new BlockItemPackets1_13(this);
private final TranslatableRewriter<ClientboundPackets1_13> translatableRewriter = new TranslatableRewriter<ClientboundPackets1_13>(this) {
@Override
protected void handleTranslate(JsonObject root, String translate) {
String mappedKey = mappedTranslationKey(translate);
if (mappedKey != null || (mappedKey = getMappingData().getTranslateMappings().get(translate)) != null) {
root.addProperty("translate", mappedKey);
}
}
};
private final TranslatableRewriter<ClientboundPackets1_13> translatableToLegacyRewriter = new TranslatableRewriter<ClientboundPackets1_13>(this) {
@Override
protected void handleTranslate(JsonObject root, String translate) {
String mappedKey = mappedTranslationKey(translate);
if (mappedKey != null || (mappedKey = getMappingData().getTranslateMappings().get(translate)) != null) {
root.addProperty("translate", Protocol1_13To1_12_2.MAPPINGS.getMojangTranslation().getOrDefault(mappedKey, mappedKey));
}
}
};
public Protocol1_12_2To1_13() {
super(ClientboundPackets1_13.class, ClientboundPackets1_12_1.class, ServerboundPackets1_13.class, ServerboundPackets1_12_1.class);
@@ -61,15 +85,6 @@ public class Protocol1_12_2To1_13 extends BackwardsProtocol<ClientboundPackets1_
Via.getManager().getProviders().register(BackwardsBlockEntityProvider.class, new BackwardsBlockEntityProvider());
});
TranslatableRewriter<ClientboundPackets1_13> translatableRewriter = new TranslatableRewriter<ClientboundPackets1_13>(this) {
@Override
protected void handleTranslate(JsonObject root, String translate) {
String newTranslate = mappedTranslationKey(translate);
if (newTranslate != null || (newTranslate = getMappingData().getTranslateMappings().get(translate)) != null) {
root.addProperty("translate", newTranslate);
}
}
};
translatableRewriter.registerPing();
translatableRewriter.registerBossBar(ClientboundPackets1_13.BOSSBAR);
translatableRewriter.registerComponentPacket(ClientboundPackets1_13.CHAT_MESSAGE);
@@ -126,4 +141,39 @@ public class Protocol1_12_2To1_13 extends BackwardsProtocol<ClientboundPackets1_
public BlockItemPackets1_13 getItemRewriter() {
return blockItemPackets;
}
// Don't override the parent method
public TranslatableRewriter<ClientboundPackets1_13> translatableRewriter() {
return translatableRewriter;
}
public String jsonToLegacy(String value) {
if (value.isEmpty()) {
return "";
}
try {
return jsonToLegacy(JsonParser.parseString(value));
} catch (Exception e) {
e.printStackTrace();
}
return "";
}
public String jsonToLegacy(@Nullable JsonElement value) {
if (value == null || value.isJsonNull()) {
return "";
}
translatableToLegacyRewriter.processText(value);
try {
Component component = ChatRewriter.HOVER_GSON_SERIALIZER.deserializeFromTree(value);
return LegacyComponentSerializer.legacySection().serialize(component);
} catch (Exception e) {
ViaBackwards.getPlatform().getLogger().warning("Error converting json text to legacy: " + value);
e.printStackTrace();
}
return "";
}
}
@@ -54,8 +54,9 @@ 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;
import java.util.List;
@@ -239,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));
}
});
@@ -549,7 +550,7 @@ public class BlockItemPackets1_13 extends com.viaversion.viabackwards.api.rewrit
StringTag name = display.get("Name");
if (name != null) {
display.put(extraNbtTag + "|Name", new StringTag(name.getValue()));
name.setValue(ChatRewriter.jsonToLegacyText(name.getValue()));
name.setValue(protocol.jsonToLegacy(name.getValue()));
}
}
@@ -634,7 +635,7 @@ public class BlockItemPackets1_13 extends com.viaversion.viabackwards.api.rewrit
lore.add(new StringTag(mappedEnchantmentId + " " + EnchantmentRewriter.getRomanNumber(level)));
noMapped.add(enchantmentEntry);
} else if (!newId.isEmpty()) {
Short oldId = Protocol1_13To1_12_2.MAPPINGS.getOldEnchantmentsIds().inverse().get(newId);
Short oldId = Protocol1_13To1_12_2.MAPPINGS.getOldEnchantmentsIds().inverse().get(Key.stripMinecraftNamespace(newId));
if (oldId == null) {
if (!newId.startsWith("viaversion:legacy/")) {
// Custom enchant (?)
@@ -37,9 +37,9 @@ import com.viaversion.viaversion.api.type.Type;
import com.viaversion.viaversion.api.type.types.Particle;
import com.viaversion.viaversion.api.type.types.version.Types1_12;
import com.viaversion.viaversion.api.type.types.version.Types1_13;
import com.viaversion.viaversion.libs.gson.JsonElement;
import com.viaversion.viaversion.protocols.protocol1_12_1to1_12.ClientboundPackets1_12_1;
import com.viaversion.viaversion.protocols.protocol1_12_1to1_12.ServerboundPackets1_12_1;
import com.viaversion.viaversion.protocols.protocol1_13to1_12_2.ChatRewriter;
import com.viaversion.viaversion.protocols.protocol1_13to1_12_2.ClientboundPackets1_13;
import java.util.Optional;
@@ -277,37 +277,22 @@ public class EntityPackets1_13 extends LegacyEntityRewriter<ClientboundPackets1_
// Rewrite Meta types
filter().handler((event, meta) -> {
int typeId = meta.metaType().typeId();
// Rewrite optional chat to string
if (typeId == 5) {
// Json -> Legacy is done below
meta.setTypeAndValue(MetaType1_12.String, meta.getValue() != null ? meta.getValue().toString() : "");
}
// Rewrite items
else if (typeId == 6) {
if (typeId == 4) {
JsonElement element = meta.value();
protocol.translatableRewriter().processText(element);
meta.setMetaType(MetaType1_12.Chat);
} else if (typeId == 5) {
// Rewrite optional chat to string
JsonElement element = meta.value();
meta.setTypeAndValue(MetaType1_12.String, protocol.jsonToLegacy(element));
} else if (typeId == 6) {
Item item = (Item) meta.getValue();
meta.setTypeAndValue(MetaType1_12.Slot, protocol.getItemRewriter().handleItemToClient(item));
}
// Discontinue particles
else if (typeId == 15) {
} else if (typeId == 15) {
// Discontinue particles
event.cancel();
}
// Rewrite to 1.12 ids
else if (typeId > 5) {
meta.setMetaType(MetaType1_12.byId(
typeId - 1
));
}
});
// Rewrite Custom Name from Chat to String
filter().filterFamily(Entity1_13Types.EntityType.ENTITY).index(2).handler((event, meta) -> {
String value = meta.getValue().toString();
if (!value.isEmpty()) {
meta.setValue(ChatRewriter.jsonToLegacyText(value));
} else {
meta.setMetaType(MetaType1_12.byId(typeId > 5 ? typeId - 1 : typeId));
}
});
@@ -35,7 +35,6 @@ import com.viaversion.viaversion.api.type.Type;
import com.viaversion.viaversion.libs.gson.JsonElement;
import com.viaversion.viaversion.protocols.protocol1_12_1to1_12.ClientboundPackets1_12_1;
import com.viaversion.viaversion.protocols.protocol1_12_1to1_12.ServerboundPackets1_12_1;
import com.viaversion.viaversion.protocols.protocol1_13to1_12_2.ChatRewriter;
import com.viaversion.viaversion.protocols.protocol1_13to1_12_2.ClientboundPackets1_13;
import com.viaversion.viaversion.protocols.protocol1_13to1_12_2.ServerboundPackets1_13;
import com.viaversion.viaversion.protocols.protocol1_13to1_12_2.packets.InventoryPackets;
@@ -202,13 +201,9 @@ public class PlayerPacket1_13 extends RewriterBase<Protocol1_12_2To1_13> {
handler(wrapper -> {
byte mode = wrapper.get(Type.BYTE, 0);
if (mode == 0 || mode == 2) {
String value = wrapper.read(Type.COMPONENT).toString();
value = ChatRewriter.jsonToLegacyText(value);
if (value.length() > 32) {
value = value.substring(0, 32);
}
wrapper.write(Type.STRING, value);
JsonElement value = wrapper.read(Type.COMPONENT);
String legacyValue = protocol.jsonToLegacy(value);
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,12 +220,8 @@ public class PlayerPacket1_13 extends RewriterBase<Protocol1_12_2To1_13> {
byte action = wrapper.get(Type.BYTE, 0);
if (action == 0 || action == 2) {
JsonElement displayName = wrapper.read(Type.COMPONENT);
String legacyTextDisplayName = displayName == null || displayName.isJsonNull() ? "" : ChatRewriter.jsonToLegacyText(displayName.toString());
legacyTextDisplayName = ChatUtil.removeUnusedColor(legacyTextDisplayName, 'f');
if (legacyTextDisplayName.length() > 32) {
legacyTextDisplayName = legacyTextDisplayName.substring(0, 32);
}
wrapper.write(Type.STRING, legacyTextDisplayName);
String legacyTextDisplayName = protocol.jsonToLegacy(displayName);
wrapper.write(Type.STRING, ChatUtil.fromLegacy(legacyTextDisplayName, 'f', 32));
byte flags = wrapper.read(Type.BYTE);
String nameTagVisibility = wrapper.read(Type.STRING);
@@ -244,22 +235,14 @@ public class PlayerPacket1_13 extends RewriterBase<Protocol1_12_2To1_13> {
JsonElement prefixComponent = wrapper.read(Type.COMPONENT);
JsonElement suffixComponent = wrapper.read(Type.COMPONENT);
String prefix = prefixComponent == null || prefixComponent.isJsonNull() ? "" : ChatRewriter.jsonToLegacyText(prefixComponent.toString());
String prefix = protocol.jsonToLegacy(prefixComponent);
if (ViaBackwards.getConfig().addTeamColorTo1_13Prefix()) {
prefix += "§" + (colour > -1 && colour <= 15 ? Integer.toHexString(colour) : "r");
}
String suffix = protocol.jsonToLegacy(suffixComponent);
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 = suffixComponent == null || suffixComponent.isJsonNull() ? "" : ChatRewriter.jsonToLegacyText(suffixComponent.toString());
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);
@@ -70,7 +70,6 @@ public class Protocol1_13_2To1_14 extends BackwardsProtocol<ClientboundPackets1_
cancelClientbound(ClientboundPackets1_14.UPDATE_VIEW_POSITION);
cancelClientbound(ClientboundPackets1_14.UPDATE_VIEW_DISTANCE);
cancelClientbound(ClientboundPackets1_14.ACKNOWLEDGE_PLAYER_DIGGING);
registerClientbound(ClientboundPackets1_14.TAGS, wrapper -> {
int blockTagsSize = wrapper.passthrough(Type.VAR_INT);
@@ -31,8 +31,6 @@ import com.viaversion.viaversion.api.minecraft.VillagerData;
import com.viaversion.viaversion.api.minecraft.entities.Entity1_13Types;
import com.viaversion.viaversion.api.minecraft.entities.Entity1_14Types;
import com.viaversion.viaversion.api.minecraft.entities.EntityType;
import com.viaversion.viaversion.api.minecraft.item.Item;
import com.viaversion.viaversion.api.minecraft.metadata.MetaType;
import com.viaversion.viaversion.api.minecraft.metadata.Metadata;
import com.viaversion.viaversion.api.protocol.packet.PacketWrapper;
import com.viaversion.viaversion.api.protocol.remapper.PacketHandlers;
@@ -348,18 +346,11 @@ public class EntityPackets1_14 extends LegacyEntityRewriter<ClientboundPackets1_
if (typeId <= 15) {
meta.setMetaType(Types1_13_2.META_TYPES.byId(typeId));
}
MetaType type = meta.metaType();
if (type == Types1_13_2.META_TYPES.itemType) {
Item item = (Item) meta.getValue();
meta.setValue(protocol.getItemRewriter().handleItemToClient(item));
} else if (type == Types1_13_2.META_TYPES.blockStateType) {
int blockstate = meta.value();
meta.setValue(protocol.getMappingData().getNewBlockStateId(blockstate));
}
});
registerMetaTypeHandler(Types1_13_2.META_TYPES.itemType, Types1_13_2.META_TYPES.blockStateType, null, null,
Types1_13_2.META_TYPES.componentType, Types1_13_2.META_TYPES.optionalComponentType);
filter().type(Entity1_14Types.PILLAGER).cancel(15);
filter().type(Entity1_14Types.FOX).cancel(15);
@@ -49,6 +49,7 @@ public class Protocol1_13To1_13_1 extends BackwardsProtocol<ClientboundPackets1_
public static final BackwardsMappings MAPPINGS = new BackwardsMappings("1.13.2", "1.13", Protocol1_13_1To1_13.class);
private final EntityPackets1_13_1 entityRewriter = new EntityPackets1_13_1(this);
private final InventoryPackets1_13_1 itemRewriter = new InventoryPackets1_13_1(this);
private final TranslatableRewriter<ClientboundPackets1_13> translatableRewriter = new TranslatableRewriter<>(this);
public Protocol1_13To1_13_1() {
super(ClientboundPackets1_13.class, ClientboundPackets1_13.class, ServerboundPackets1_13.class, ServerboundPackets1_13.class);
@@ -60,7 +61,6 @@ public class Protocol1_13To1_13_1 extends BackwardsProtocol<ClientboundPackets1_
WorldPackets1_13_1.register(this);
TranslatableRewriter<ClientboundPackets1_13> translatableRewriter = new TranslatableRewriter<>(this);
translatableRewriter.registerComponentPacket(ClientboundPackets1_13.CHAT_MESSAGE);
translatableRewriter.registerCombatEvent(ClientboundPackets1_13.COMBAT_EVENT);
translatableRewriter.registerDisconnect(ClientboundPackets1_13.DISCONNECT);
@@ -227,4 +227,8 @@ public class Protocol1_13To1_13_1 extends BackwardsProtocol<ClientboundPackets1_
public InventoryPackets1_13_1 getItemRewriter() {
return itemRewriter;
}
public TranslatableRewriter<ClientboundPackets1_13> translatableRewriter() {
return translatableRewriter;
}
}
@@ -28,6 +28,7 @@ import com.viaversion.viaversion.api.protocol.remapper.PacketHandlers;
import com.viaversion.viaversion.api.type.Type;
import com.viaversion.viaversion.api.type.types.Particle;
import com.viaversion.viaversion.api.type.types.version.Types1_13;
import com.viaversion.viaversion.libs.gson.JsonElement;
import com.viaversion.viaversion.protocols.protocol1_13to1_12_2.ClientboundPackets1_13;
import java.util.List;
@@ -139,6 +140,9 @@ public class EntityPackets1_13_1 extends LegacyEntityRewriter<ClientboundPackets
meta.setValue(protocol.getMappingData().getNewBlockStateId(data));
} else if (meta.metaType() == Types1_13.META_TYPES.particleType) {
rewriteParticle((Particle) meta.getValue());
} else if (meta.metaType() == Types1_13.META_TYPES.optionalComponentType || meta.metaType() == Types1_13.META_TYPES.componentType) {
JsonElement element = meta.value();
protocol.translatableRewriter().processText(element);
}
});
@@ -20,19 +20,20 @@ package com.viaversion.viabackwards.protocol.protocol1_14_3to1_14_4;
import com.viaversion.viabackwards.api.BackwardsProtocol;
import com.viaversion.viaversion.api.protocol.remapper.PacketHandlers;
import com.viaversion.viaversion.api.type.Type;
import com.viaversion.viaversion.protocols.protocol1_14_4to1_14_3.ClientboundPackets1_14_4;
import com.viaversion.viaversion.protocols.protocol1_14to1_13_2.ClientboundPackets1_14;
import com.viaversion.viaversion.protocols.protocol1_14to1_13_2.ServerboundPackets1_14;
public class Protocol1_14_3To1_14_4 extends BackwardsProtocol<ClientboundPackets1_14, ClientboundPackets1_14, ServerboundPackets1_14, ServerboundPackets1_14> {
public class Protocol1_14_3To1_14_4 extends BackwardsProtocol<ClientboundPackets1_14_4, ClientboundPackets1_14, ServerboundPackets1_14, ServerboundPackets1_14> {
public Protocol1_14_3To1_14_4() {
super(ClientboundPackets1_14.class, ClientboundPackets1_14.class, ServerboundPackets1_14.class, ServerboundPackets1_14.class);
super(ClientboundPackets1_14_4.class, ClientboundPackets1_14.class, ServerboundPackets1_14.class, ServerboundPackets1_14.class);
}
@Override
protected void registerPackets() {
// Acknowledge Player Digging - added in pre4
registerClientbound(ClientboundPackets1_14.ACKNOWLEDGE_PLAYER_DIGGING, ClientboundPackets1_14.BLOCK_CHANGE, new PacketHandlers() {
registerClientbound(ClientboundPackets1_14_4.ACKNOWLEDGE_PLAYER_DIGGING, ClientboundPackets1_14.BLOCK_CHANGE, new PacketHandlers() {
@Override
public void register() {
map(Type.POSITION1_14);
@@ -47,7 +48,7 @@ public class Protocol1_14_3To1_14_4 extends BackwardsProtocol<ClientboundPackets
}
});
registerClientbound(ClientboundPackets1_14.TRADE_LIST, wrapper -> {
registerClientbound(ClientboundPackets1_14_4.TRADE_LIST, wrapper -> {
wrapper.passthrough(Type.VAR_INT);
int size = wrapper.passthrough(Type.UNSIGNED_BYTE);
for (int i = 0; i < size; i++) {
@@ -31,14 +31,14 @@ 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.data.entity.EntityTrackerBase;
import com.viaversion.viaversion.protocols.protocol1_14to1_13_2.ClientboundPackets1_14;
import com.viaversion.viaversion.protocols.protocol1_14_4to1_14_3.ClientboundPackets1_14_4;
import com.viaversion.viaversion.protocols.protocol1_14to1_13_2.ServerboundPackets1_14;
import com.viaversion.viaversion.protocols.protocol1_15to1_14_4.ClientboundPackets1_15;
import com.viaversion.viaversion.protocols.protocol1_15to1_14_4.Protocol1_15To1_14_4;
import com.viaversion.viaversion.rewriter.StatisticsRewriter;
import com.viaversion.viaversion.rewriter.TagRewriter;
public class Protocol1_14_4To1_15 extends BackwardsProtocol<ClientboundPackets1_15, ClientboundPackets1_14, ServerboundPackets1_14, ServerboundPackets1_14> {
public class Protocol1_14_4To1_15 extends BackwardsProtocol<ClientboundPackets1_15, ClientboundPackets1_14_4, ServerboundPackets1_14, ServerboundPackets1_14> {
public static final BackwardsMappings MAPPINGS = new BackwardsMappings("1.15", "1.14", Protocol1_15To1_14_4.class);
private final EntityPackets1_15 entityRewriter = new EntityPackets1_15(this);
@@ -46,7 +46,7 @@ public class Protocol1_14_4To1_15 extends BackwardsProtocol<ClientboundPackets1_
private final TranslatableRewriter<ClientboundPackets1_15> translatableRewriter = new TranslatableRewriter<>(this);
public Protocol1_14_4To1_15() {
super(ClientboundPackets1_15.class, ClientboundPackets1_14.class, ServerboundPackets1_14.class, ServerboundPackets1_14.class);
super(ClientboundPackets1_15.class, ClientboundPackets1_14_4.class, ServerboundPackets1_14.class, ServerboundPackets1_14.class);
}
@Override
@@ -76,7 +76,7 @@ public class Protocol1_14_4To1_15 extends BackwardsProtocol<ClientboundPackets1_
map(Type.FLOAT); // y
map(Type.FLOAT); // z
handler(wrapper -> {
PacketWrapper soundPacket = wrapper.create(ClientboundPackets1_14.SOUND);
PacketWrapper soundPacket = wrapper.create(ClientboundPackets1_14_4.SOUND);
soundPacket.write(Type.VAR_INT, 243); // entity.generic.explode
soundPacket.write(Type.VAR_INT, 4); // blocks category
soundPacket.write(Type.INT, toEffectCoordinate(wrapper.get(Type.FLOAT, 0))); // x
@@ -192,7 +192,8 @@ public class EntityPackets1_15 extends EntityRewriter<ClientboundPackets1_15, Pr
@Override
protected void registerRewrites() {
registerMetaTypeHandler(Types1_14.META_TYPES.itemType, Types1_14.META_TYPES.blockStateType, Types1_14.META_TYPES.particleType, null);
registerMetaTypeHandler(Types1_14.META_TYPES.itemType, Types1_14.META_TYPES.blockStateType, null, Types1_14.META_TYPES.particleType,
Types1_14.META_TYPES.componentType, Types1_14.META_TYPES.optionalComponentType);
filter().filterFamily(Entity1_15Types.LIVINGENTITY).removeIndex(12);
@@ -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;
@@ -100,7 +100,7 @@ public class EntityPackets1_16_2 extends EntityRewriter<ClientboundPackets1_16_2
map(Type.LONG); // Seed
handler(wrapper -> {
int maxPlayers = wrapper.read(Type.VAR_INT);
wrapper.write(Type.UNSIGNED_BYTE, (short) Math.max(maxPlayers, 255));
wrapper.write(Type.UNSIGNED_BYTE, (short) Math.min(maxPlayers, 255));
});
// ...
handler(getTrackerHandler(Entity1_16_2Types.PLAYER, Type.INT));
@@ -122,8 +122,8 @@ public class EntityPackets1_16_2 extends EntityRewriter<ClientboundPackets1_16_2
@Override
protected void registerRewrites() {
registerMetaTypeHandler(Types1_16.META_TYPES.itemType, Types1_16.META_TYPES.blockStateType,
Types1_16.META_TYPES.particleType, Types1_16.META_TYPES.optionalComponentType);
registerMetaTypeHandler(Types1_16.META_TYPES.itemType, Types1_16.META_TYPES.blockStateType, null,
Types1_16.META_TYPES.particleType, Types1_16.META_TYPES.componentType, Types1_16.META_TYPES.optionalComponentType);
mapTypes(Entity1_16_2Types.values(), Entity1_16Types.class);
mapEntityTypeWithData(Entity1_16_2Types.PIGLIN_BRUTE, Entity1_16_2Types.PIGLIN).jsonName();
@@ -53,6 +53,7 @@ import java.util.Map;
public final class Protocol1_16_4To1_17 extends BackwardsProtocol<ClientboundPackets1_17, ClientboundPackets1_16_2, ServerboundPackets1_17, ServerboundPackets1_16_2> {
public static final BackwardsMappings MAPPINGS = new BackwardsMappings("1.17", "1.16.2", Protocol1_17To1_16_4.class);
private static final RegistryType[] TAG_REGISTRY_TYPES = {RegistryType.BLOCK, RegistryType.ITEM, RegistryType.FLUID, RegistryType.ENTITY};
private static final int[] EMPTY_ARRAY = {};
private final EntityPackets1_17 entityRewriter = new EntityPackets1_17(this);
private final BlockItemPackets1_17 blockItemPackets = new BlockItemPackets1_17(this);
@@ -98,8 +99,14 @@ public final class Protocol1_16_4To1_17 extends BackwardsProtocol<ClientboundPac
}
// Put them into the hardcoded order of Vanilla tags (and only those), rewrite ids
for (RegistryType type : RegistryType.getValues()) {
for (RegistryType type : TAG_REGISTRY_TYPES) {
List<TagData> tagList = tags.get(type.resourceLocation());
if (tagList == null) {
// Higher versions may not send the otherwise expected tags
wrapper.write(Type.VAR_INT, 0);
continue;
}
IdRewriteFunction rewriter = tagRewriter.getRewriter(type);
wrapper.write(Type.VAR_INT, tagList.size());
@@ -120,11 +127,6 @@ public final class Protocol1_16_4To1_17 extends BackwardsProtocol<ClientboundPac
wrapper.write(Type.STRING, tagData.identifier());
wrapper.write(Type.VAR_INT_ARRAY_PRIMITIVE, entries);
}
// Stop after the entity types
if (type == RegistryType.ENTITY) {
break;
}
}
});
@@ -203,7 +203,7 @@ public final class BlockItemPackets1_17 extends ItemRewriter<ClientboundPackets1
wrapper.cancel();
}
});
handler(getSpawnParticleHandler(Type.FLAT_VAR_INT_ITEM));
handler(getSpawnParticleHandler());
}
});
@@ -180,7 +180,8 @@ public final class EntityPackets1_17 extends EntityRewriter<ClientboundPackets1_
});
// Particles have already been handled
registerMetaTypeHandler(Types1_16.META_TYPES.itemType, Types1_16.META_TYPES.blockStateType, null, Types1_16.META_TYPES.optionalComponentType);
registerMetaTypeHandler(Types1_16.META_TYPES.itemType, Types1_16.META_TYPES.blockStateType, null, null,
Types1_16.META_TYPES.componentType, Types1_16.META_TYPES.optionalComponentType);
mapTypes(Entity1_17Types.values(), Entity1_16_2Types.class);
filter().type(Entity1_17Types.AXOLOTL).cancel(17);
@@ -117,7 +117,8 @@ public final class EntityPackets1_18 extends EntityRewriter<ClientboundPackets1_
});
// Particles have already been handled
registerMetaTypeHandler(Types1_17.META_TYPES.itemType, null, null, Types1_17.META_TYPES.optionalComponentType);
registerMetaTypeHandler(Types1_17.META_TYPES.itemType, null, null, null,
Types1_17.META_TYPES.componentType, Types1_17.META_TYPES.optionalComponentType);
}
@Override
@@ -42,7 +42,7 @@ public final class BackwardsMappings extends com.viaversion.viabackwards.api.dat
super.loadExtras(data);
try {
final ListTag chatTypes = BinaryTagIO.readCompressedInputStream(VBMappingDataLoader.getResource("chat-types-1.19.1.nbt")).get("values");
final ListTag chatTypes = BinaryTagIO.readInputStream(VBMappingDataLoader.getResource("chat-types-1.19.1.nbt")).get("values");
for (final Tag chatType : chatTypes) {
final CompoundTag chatTypeCompound = (CompoundTag) chatType;
final NumberTag idTag = chatTypeCompound.get("id");
@@ -134,7 +134,7 @@ public final class BlockItemPackets1_19 extends ItemRewriter<ClientboundPackets1
wrapper.cancel();
}
});
handler(getSpawnParticleHandler(Type.FLAT_VAR_INT_ITEM));
handler(getSpawnParticleHandler());
}
});
@@ -269,7 +269,8 @@ public final class EntityPackets1_19 extends EntityRewriter<ClientboundPackets1_
}
});
registerMetaTypeHandler(Types1_18.META_TYPES.itemType, Types1_18.META_TYPES.blockStateType, null, Types1_18.META_TYPES.optionalComponentType);
registerMetaTypeHandler(Types1_18.META_TYPES.itemType, Types1_18.META_TYPES.blockStateType, null, null,
Types1_18.META_TYPES.componentType, Types1_18.META_TYPES.optionalComponentType);
filter().filterFamily(Entity1_19Types.MINECART_ABSTRACT).index(11).handler((event, meta) -> {
final int data = (int) meta.getValue();
@@ -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
@@ -230,7 +230,8 @@ public final class EntityPackets1_19_3 extends EntityRewriter<ClientboundPackets
meta.setMetaType(Types1_19.META_TYPES.byId(id));
}
});
registerMetaTypeHandler(Types1_19.META_TYPES.itemType, Types1_19.META_TYPES.blockStateType, Types1_19.META_TYPES.particleType, Types1_19.META_TYPES.optionalComponentType);
registerMetaTypeHandler(Types1_19.META_TYPES.itemType, Types1_19.META_TYPES.blockStateType, null, Types1_19.META_TYPES.particleType,
Types1_19.META_TYPES.componentType, Types1_19.META_TYPES.optionalComponentType);
filter().index(6).handler((event, meta) -> {
// Sitting pose added
@@ -1,5 +1,5 @@
/*
* This file is part of ViaVersion - https://github.com/ViaVersion/ViaVersion
* 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
@@ -35,6 +35,7 @@ import com.viaversion.viaversion.protocols.protocol1_19_4to1_19_3.ClientboundPac
import com.viaversion.viaversion.protocols.protocol1_19_4to1_19_3.Protocol1_19_4To1_19_3;
import com.viaversion.viaversion.protocols.protocol1_19_4to1_19_3.ServerboundPackets1_19_4;
import com.viaversion.viaversion.rewriter.CommandRewriter;
import com.viaversion.viaversion.rewriter.StatisticsRewriter;
import com.viaversion.viaversion.rewriter.TagRewriter;
import java.nio.charset.StandardCharsets;
import java.util.Base64;
@@ -98,6 +99,8 @@ public final class Protocol1_19_3To1_19_4 extends BackwardsProtocol<ClientboundP
tagRewriter.removeTags("minecraft:damage_type");
tagRewriter.registerGeneric(ClientboundPackets1_19_4.TAGS);
new StatisticsRewriter<>(this).register(ClientboundPackets1_19_4.STATISTICS);
registerClientbound(ClientboundPackets1_19_4.SERVER_DATA, wrapper -> {
final JsonElement element = wrapper.read(Type.COMPONENT);
wrapper.write(Type.OPTIONAL_COMPONENT, element);
@@ -1,5 +1,5 @@
/*
* This file is part of ViaVersion - https://github.com/ViaVersion/ViaVersion
* 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
@@ -27,11 +27,8 @@ 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_3;
import com.viaversion.viaversion.api.type.types.version.Types1_19_4;
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.gson.JsonElement;
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;
@@ -71,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"));
}
});
@@ -86,7 +83,7 @@ public final class EntityPackets1_19_4 extends EntityRewriter<ClientboundPackets
map(Type.DOUBLE); // Z
map(Type.FLOAT); // Yaw
map(Type.FLOAT); // Pitch
map(Type.UNSIGNED_BYTE); // Relative arguments
map(Type.BYTE); // Relative arguments
map(Type.VAR_INT); // Id
create(Type.BOOLEAN, false); // Dismount vehicle
}
@@ -142,18 +139,29 @@ public final class EntityPackets1_19_4 extends EntityRewriter<ClientboundPackets
meta.setMetaType(Types1_19_3.META_TYPES.byId(id));
});
registerMetaTypeHandler(Types1_19_3.META_TYPES.itemType, Types1_19_3.META_TYPES.blockStateType, Types1_19_3.META_TYPES.particleType, Types1_19_3.META_TYPES.optionalComponentType);
registerMetaTypeHandler(Types1_19_3.META_TYPES.itemType, Types1_19_3.META_TYPES.blockStateType, null, Types1_19_3.META_TYPES.particleType,
Types1_19_3.META_TYPES.componentType, Types1_19_3.META_TYPES.optionalComponentType);
filter().filterFamily(Entity1_19_4Types.MINECART_ABSTRACT).index(11).handler((event, meta) -> {
final int blockState = meta.value();
meta.setValue(protocol.getMappingData().getNewBlockStateId(blockState));
});
filter().filterFamily(Entity1_19_4Types.BOAT).index(11).handler((event, meta) -> {
final int boatType = meta.value();
if (boatType > 4) { // Cherry
meta.setValue(boatType - 1);
}
});
filter().type(Entity1_19_4Types.TEXT_DISPLAY).index(22).handler(((event, meta) -> {
// Send as custom display name
event.setIndex(2);
meta.setMetaType(Types1_19_3.META_TYPES.optionalComponentType);
event.createExtraMeta(new Metadata(3, Types1_19_3.META_TYPES.booleanType, true)); // Show custom name
final JsonElement element = meta.value();
protocol.getTranslatableRewriter().processText(element);
}));
filter().filterFamily(Entity1_19_4Types.DISPLAY).handler((event, meta) -> {
// TODO Maybe spawn an extra entity to ride the armor stand for blocks and items
@@ -0,0 +1,117 @@
/*
* 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;
import com.viaversion.viabackwards.api.BackwardsProtocol;
import com.viaversion.viabackwards.api.rewriters.SoundRewriter;
import com.viaversion.viabackwards.api.rewriters.TranslatableRewriter;
import com.viaversion.viabackwards.protocol.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.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();
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);
public Protocol1_19_4To1_20() {
super(ClientboundPackets1_19_4.class, ClientboundPackets1_19_4.class, ServerboundPackets1_19_4.class, ServerboundPackets1_19_4.class);
}
@Override
protected void registerPackets() {
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);
soundRewriter.registerStopSound(ClientboundPackets1_19_4.STOP_SOUND);
soundRewriter.register1_19_3Sound(ClientboundPackets1_19_4.SOUND);
soundRewriter.registerSound(ClientboundPackets1_19_4.ENTITY_SOUND);
new StatisticsRewriter<>(this).register(ClientboundPackets1_19_4.STATISTICS);
//TODO open window
translatableRewriter.registerComponentPacket(ClientboundPackets1_19_4.ACTIONBAR);
translatableRewriter.registerComponentPacket(ClientboundPackets1_19_4.TITLE_TEXT);
translatableRewriter.registerComponentPacket(ClientboundPackets1_19_4.TITLE_SUBTITLE);
translatableRewriter.registerBossBar(ClientboundPackets1_19_4.BOSSBAR);
translatableRewriter.registerDisconnect(ClientboundPackets1_19_4.DISCONNECT);
translatableRewriter.registerTabList(ClientboundPackets1_19_4.TAB_LIST);
translatableRewriter.registerComponentPacket(ClientboundPackets1_19_4.SYSTEM_CHAT);
translatableRewriter.registerComponentPacket(ClientboundPackets1_19_4.DISGUISED_CHAT);
translatableRewriter.registerPing();
registerClientbound(ClientboundPackets1_19_4.UPDATE_ENABLED_FEATURES, wrapper -> {
String[] enabledFeatures = wrapper.read(Type.STRING_ARRAY);
final int length = enabledFeatures.length;
enabledFeatures = Arrays.copyOf(enabledFeatures, length + 1);
enabledFeatures[length] = "minecraft:update_1_20";
wrapper.write(Type.STRING_ARRAY, enabledFeatures);
});
registerClientbound(ClientboundPackets1_19_4.COMBAT_END, wrapper -> {
wrapper.passthrough(Type.VAR_INT); // Duration
wrapper.write(Type.INT, -1); // Killer ID - unused (who knows for how long?)
});
registerClientbound(ClientboundPackets1_19_4.COMBAT_KILL, wrapper -> {
wrapper.passthrough(Type.VAR_INT); // Duration
wrapper.write(Type.INT, -1); // Killer ID - unused (who knows for how long?)
translatableRewriter.processText(wrapper.passthrough(Type.COMPONENT));
});
}
@Override
public void init(final UserConnection user) {
addEntityTracker(user, new EntityTrackerBase(user, Entity1_19_4Types.PLAYER));
}
@Override
public BackwardsMappings getMappingData() {
return MAPPINGS;
}
@Override
public EntityPackets1_20 getEntityRewriter() {
return entityRewriter;
}
@Override
public BlockItemPackets1_20 getItemRewriter() {
return itemRewriter;
}
@Override
public TranslatableRewriter<ClientboundPackets1_19_4> getTranslatableRewriter() {
return translatableRewriter;
}
}
@@ -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;
}
}
@@ -0,0 +1,230 @@
/*
* 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.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.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);
}
@Override
public void registerPackets() {
final BlockRewriter<ClientboundPackets1_19_4> blockRewriter = new BlockRewriter<>(protocol, Type.POSITION1_14);
blockRewriter.registerBlockAction(ClientboundPackets1_19_4.BLOCK_ACTION);
blockRewriter.registerBlockChange(ClientboundPackets1_19_4.BLOCK_CHANGE);
blockRewriter.registerEffect(ClientboundPackets1_19_4.EFFECT, 1010, 2001);
blockRewriter.registerBlockEntityData(ClientboundPackets1_19_4.BLOCK_ENTITY_DATA, this::handleBlockEntity);
protocol.registerClientbound(ClientboundPackets1_19_4.CHUNK_DATA, new PacketHandlers() {
@Override
protected void register() {
handler(blockRewriter.chunkDataHandler1_19(Chunk1_18Type::new, BlockItemPackets1_20.this::handleBlockEntity));
create(Type.BOOLEAN, true); // Trust edges
}
});
protocol.registerClientbound(ClientboundPackets1_19_4.UPDATE_LIGHT, wrapper -> {
wrapper.passthrough(Type.VAR_INT); // X
wrapper.passthrough(Type.VAR_INT); // Y
wrapper.write(Type.BOOLEAN, true); // Trust edges
});
protocol.registerClientbound(ClientboundPackets1_19_4.MULTI_BLOCK_CHANGE, new PacketHandlers() {
@Override
public void register() {
map(Type.LONG); // Chunk position
create(Type.BOOLEAN, false); // Suppress light updates
handler(wrapper -> {
for (final BlockChangeRecord record : wrapper.passthrough(Type.VAR_LONG_BLOCK_CHANGE_RECORD_ARRAY)) {
record.setBlockId(protocol.getMappingData().getNewBlockStateId(record.getBlockId()));
}
});
}
});
registerOpenWindow(ClientboundPackets1_19_4.OPEN_WINDOW);
registerSetCooldown(ClientboundPackets1_19_4.COOLDOWN);
registerWindowItems1_17_1(ClientboundPackets1_19_4.WINDOW_ITEMS);
registerSetSlot1_17_1(ClientboundPackets1_19_4.SET_SLOT);
registerEntityEquipmentArray(ClientboundPackets1_19_4.ENTITY_EQUIPMENT);
registerClickWindow1_17_1(ServerboundPackets1_19_4.CLICK_WINDOW);
registerTradeList1_19(ClientboundPackets1_19_4.TRADE_LIST);
registerCreativeInvAction(ServerboundPackets1_19_4.CREATIVE_INVENTORY_ACTION, Type.FLAT_VAR_INT_ITEM);
registerWindowPropertyEnchantmentHandler(ClientboundPackets1_19_4.WINDOW_PROPERTY);
registerSpawnParticle1_19(ClientboundPackets1_19_4.SPAWN_PARTICLE);
protocol.registerClientbound(ClientboundPackets1_19_4.ADVANCEMENTS, wrapper -> {
wrapper.passthrough(Type.BOOLEAN); // Reset/clear
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
handleItemToClient(wrapper.passthrough(Type.FLAT_VAR_INT_ITEM)); // Icon
wrapper.passthrough(Type.VAR_INT); // Frame type
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.passthrough(Type.STRING_ARRAY); // Criteria
int arrayLength = wrapper.passthrough(Type.VAR_INT);
for (int array = 0; array < arrayLength; array++) {
wrapper.passthrough(Type.STRING_ARRAY); // String array
}
wrapper.read(Type.BOOLEAN); // Sends telemetry
}
});
protocol.registerClientbound(ClientboundPackets1_19_4.OPEN_SIGN_EDITOR, wrapper -> {
final Position position = wrapper.passthrough(Type.POSITION1_14);
final boolean frontSide = wrapper.read(Type.BOOLEAN);
if (frontSide) {
wrapper.user().remove(BackSignEditStorage.class);
} else {
wrapper.user().put(new BackSignEditStorage(position));
}
});
protocol.registerServerbound(ServerboundPackets1_19_4.UPDATE_SIGN, wrapper -> {
final Position position = wrapper.passthrough(Type.POSITION1_14);
final BackSignEditStorage backSignEditStorage = wrapper.user().remove(BackSignEditStorage.class);
final boolean frontSide = backSignEditStorage == null || !backSignEditStorage.position().equals(position);
wrapper.write(Type.BOOLEAN, frontSide);
});
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) {
return;
}
final CompoundTag tag = blockEntity.tag();
final CompoundTag frontText = tag.remove("front_text");
tag.remove("back_text");
if (frontText != null) {
writeMessages(frontText, tag, false);
writeMessages(frontText, tag, true);
final Tag color = frontText.remove("color");
if (color != null) {
tag.put("Color", color);
}
final Tag glowing = frontText.remove("has_glowing_text");
if (glowing != null) {
tag.put("GlowingText", glowing);
}
}
}
private void writeMessages(final CompoundTag frontText, final CompoundTag tag, final boolean filtered) {
final ListTag messages = frontText.get(filtered ? "filtered_messages" : "messages");
if (messages == null) {
return;
}
int i = 0;
for (final Tag message : messages) {
tag.put((filtered ? "FilteredText" : "Text") + ++i, message);
}
}
}
@@ -0,0 +1,158 @@
/*
* 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.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;
import com.viaversion.viaversion.api.type.types.version.Types1_20;
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_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);
}
@Override
public void registerPackets() {
registerTrackerWithData1_19(ClientboundPackets1_19_4.SPAWN_ENTITY, Entity1_19_4Types.FALLING_BLOCK);
registerMetadataRewriter(ClientboundPackets1_19_4.ENTITY_METADATA, Types1_20.METADATA_LIST, Types1_19_4.METADATA_LIST);
registerRemoveEntities(ClientboundPackets1_19_4.REMOVE_ENTITIES);
protocol.registerClientbound(ClientboundPackets1_19_4.JOIN_GAME, new PacketHandlers() {
@Override
public void register() {
map(Type.INT); // Entity id
map(Type.BOOLEAN); // Hardcore
map(Type.UNSIGNED_BYTE); // Gamemode
map(Type.BYTE); // Previous Gamemode
map(Type.STRING_ARRAY); // World List
map(Type.NBT); // Dimension registry
map(Type.STRING); // Dimension key
map(Type.STRING); // World
map(Type.LONG); // Seed
map(Type.VAR_INT); // Max players
map(Type.VAR_INT); // Chunk radius
map(Type.VAR_INT); // Simulation distance
map(Type.BOOLEAN); // Reduced debug info
map(Type.BOOLEAN); // Show death screen
map(Type.BOOLEAN); // Debug
map(Type.BOOLEAN); // Flat
map(Type.OPTIONAL_GLOBAL_POSITION); // Last death location
read(Type.VAR_INT); // Portal cooldown
handler(dimensionDataHandler()); // Caches dimensions to access data like height later
handler(biomeSizeTracker()); // Tracks the amount of biomes sent for chunk data
handler(worldDataTrackerHandlerByKey()); // Tracks world height and name for chunk data and entity (un)tracking
handler(wrapper -> {
final CompoundTag registry = wrapper.get(Type.NBT, 0);
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");
if (newTrimPatterns.contains(Key.stripMinecraftNamespace(templateItem.getValue()))) {
templateItem.setValue("minecraft:spire_armor_trim_smithing_template");
}
}
});
}
});
protocol.registerClientbound(ClientboundPackets1_19_4.RESPAWN, new PacketHandlers() {
@Override
public void register() {
map(Type.STRING); // Dimension
map(Type.STRING); // World
map(Type.LONG); // Seed
map(Type.UNSIGNED_BYTE); // Gamemode
map(Type.BYTE); // Previous gamemode
map(Type.BOOLEAN); // Debug
map(Type.BOOLEAN); // Flat
map(Type.BYTE); // Data to keep
map(Type.OPTIONAL_GLOBAL_POSITION); // Last death location
read(Type.VAR_INT); // Portal cooldown
handler(worldDataTrackerHandlerByKey()); // Tracks world height and name for chunk data and entity (un)tracking
}
});
}
@Override
protected void registerRewrites() {
filter().handler((event, meta) -> meta.setMetaType(Types1_19_4.META_TYPES.byId(meta.metaType().typeId())));
registerMetaTypeHandler(Types1_19_4.META_TYPES.itemType, Types1_19_4.META_TYPES.blockStateType, Types1_19_4.META_TYPES.optionalBlockStateType,
Types1_19_4.META_TYPES.particleType, Types1_19_4.META_TYPES.componentType, Types1_19_4.META_TYPES.optionalComponentType);
filter().filterFamily(Entity1_19_4Types.MINECART_ABSTRACT).index(11).handler((event, meta) -> {
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,34 @@
/*
* 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.storage;
import com.viaversion.viaversion.api.connection.StorableObject;
import com.viaversion.viaversion.api.minecraft.Position;
public final class BackSignEditStorage implements StorableObject {
private final Position position;
public BackSignEditStorage(final Position position) {
this.position = position;
}
public Position position() {
return position;
}
}
@@ -0,0 +1,181 @@
/*
* 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 -> {
final ServerboundLoginPackets ackPacket = ServerboundLoginPackets.LOGIN_ACKNOWLEDGED;
wrapper.create(ackPacket).sendToServer(Protocol1_20To1_20_2.class);
// We can't set the internal state to configuration here as protocols down the line will expect the state to be play
wrapper.user().put(new ConfigurationPacketStorage());
});
registerClientbound(State.CONFIGURATION, ClientboundConfigurationPackets1_20_2.FINISH_CONFIGURATION.getId(), ClientboundConfigurationPackets1_20_2.FINISH_CONFIGURATION.getId(), wrapper -> {
wrapper.cancel();
wrapper.create(ServerboundConfigurationPackets1_20_2.FINISH_CONFIGURATION).sendToServer(Protocol1_20To1_20_2.class);
wrapper.user().get(ConfigurationPacketStorage.class).setFinished(true);
});
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();
// 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().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
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,410 @@
/*
* 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.fastutil.objects.Object2IntMap;
import com.viaversion.viaversion.libs.fastutil.objects.Object2IntOpenHashMap;
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.rewriter.BlockRewriter;
import com.viaversion.viaversion.util.Key;
import com.viaversion.viaversion.util.MathUtil;
import java.util.Arrays;
import java.util.List;
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> {
private final Object2IntMap<String> effects = new Object2IntOpenHashMap<>();
public BlockItemPacketRewriter1_20_2(final Protocol1_20To1_20_2 protocol) {
super(protocol, Type.ITEM1_20_2, Type.ITEM1_20_2_VAR_INT_ARRAY);
final List<String> effects = Arrays.asList(
"speed",
"slowness",
"haste",
"mining_fatigue",
"strength",
"instant_health",
"instant_damage",
"jump_boost",
"nausea",
"regeneration",
"resistance",
"fire_resistance",
"water_breathing",
"invisibility",
"blindness",
"night_vision",
"hunger",
"weakness",
"poison",
"wither",
"health_boost",
"absorption",
"saturation",
"glowing",
"levitation",
"luck",
"unluck",
"slow_falling",
"conduit_power",
"dolphins_grace",
"bad_omen",
"hero_of_the_village",
"darkness"
);
for (int i = 0; i < effects.size(); i++) {
final String effect = effects.get(i);
this.effects.put(effect, i + 1); // Effects start at 1 before 1.20.2
}
}
@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 -> {
if (wrapper.passthrough(Type.BOOLEAN)) {
// Effects start at 1 before 1.20.2
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 -> {
wrapper.write(Type.FLAT_VAR_INT_ITEM_ARRAY_VAR_INT, wrapper.read(Type.ITEM1_20_2_VAR_INT_ARRAY)); // Items
wrapper.write(Type.FLAT_VAR_INT_ITEM, 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
map(Type.ITEM1_20_2, Type.FLAT_VAR_INT_ITEM); // Item
}
});
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, 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, 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, wrapper.read(Type.FLAT_VAR_INT_ITEM));
}
// Carried item
wrapper.write(Type.ITEM1_20_2, wrapper.read(Type.FLAT_VAR_INT_ITEM));
});
}
});
protocol.registerClientbound(ClientboundPackets1_20_2.TRADE_LIST, wrapper -> {
wrapper.cancel();
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, wrapper.read(Type.ITEM1_20_2)); // Input
wrapper.write(Type.FLAT_VAR_INT_ITEM, wrapper.read(Type.ITEM1_20_2)); // Output
wrapper.write(Type.FLAT_VAR_INT_ITEM, 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
map(Type.FLAT_VAR_INT_ITEM, Type.ITEM1_20_2); // 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, 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);
}
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(effects.getInt(effectKey)));
}
final StringTag secondaryEffect = tag.remove("secondary_effect");
if (secondaryEffect != null) {
final String effectKey = Key.stripMinecraftNamespace(secondaryEffect.getValue());
tag.put("Secondary", new IntTag(effects.getInt(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_20_2.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
@@ -1,4 +1,157 @@
{
"1.20": {
"advancements.adventure.craft_decorated_pot_using_only_sherds.description": "Make a Decorated Pot out of 4 Pottery Sherds",
"advancements.adventure.craft_decorated_pot_using_only_sherds.title": "Careful Restoration",
"advancements.adventure.read_power_from_chiseled_bookshelf.description": "Read the power signal of a Chiseled Bookshelf using a Comparator",
"advancements.adventure.read_power_from_chiseled_bookshelf.title": "The Power of Books",
"advancements.adventure.salvage_sherd.description": "Brush a Suspicious block to obtain a Pottery Sherd",
"advancements.adventure.salvage_sherd.title": "Respecting the Remnants",
"advancements.adventure.trim_with_all_exclusive_armor_patterns.description": "Apply these smithing templates at least once: Spire, Snout, Rib, Ward, Silence, Vex, Tide, Wayfinder",
"advancements.adventure.trim_with_all_exclusive_armor_patterns.title": "Smithing with Style",
"advancements.adventure.trim_with_any_armor_pattern.description": "Craft a trimmed armor at a Smithing Table",
"advancements.adventure.trim_with_any_armor_pattern.title": "Crafting a New Look",
"advancements.husbandry.feed_snifflet.description": "Feed a Snifflet",
"advancements.husbandry.feed_snifflet.title": "Little Sniffs",
"advancements.husbandry.obtain_sniffer_egg.description": "Obtain a Sniffer Egg",
"advancements.husbandry.obtain_sniffer_egg.title": "Smells Interesting",
"advancements.husbandry.plant_any_sniffer_seed.description": "Plant any Sniffer seed",
"advancements.husbandry.plant_any_sniffer_seed.title": "Planting the Past",
"block.minecraft.calibrated_sculk_sensor": "Calibrated Sculk Sensor",
"block.minecraft.pitcher_crop": "Pitcher Crop",
"block.minecraft.pitcher_plant": "Pitcher Plant",
"block.minecraft.sniffer_egg": "Sniffer Egg",
"block.minecraft.suspicious_gravel": "Suspicious Gravel",
"commands.data.modify.invalid_substring": "Invalid substring indices: %s to %s",
"commands.function.success.multiple.result": "Executed %s functions",
"commands.function.success.single.result": "Function '%2$s' returned %1$s",
"death.attack.genericKill": "%1$s was killed",
"death.attack.genericKill.player": "%1$s was killed whilst fighting %2$s",
"death.attack.outsideBorder": "%1$s left the confines of this world",
"death.attack.outsideBorder.player": "%1$s left the confines of this world whilst fighting %2$s",
"disconnect.ignoring_status_request": "Ignoring status request",
"gui.toRealms": "Back to Realms List",
"gui.toWorld": "Back to World List",
"item.minecraft.angler_pottery_shard": "Angler Pottery Shard",
"item.minecraft.angler_pottery_sherd": "Angler Pottery Sherd",
"item.minecraft.archer_pottery_shard": "Archer Pottery Shard",
"item.minecraft.archer_pottery_sherd": "Archer Pottery Sherd",
"item.minecraft.arms_up_pottery_shard": "Arms Up Pottery Shard",
"item.minecraft.arms_up_pottery_sherd": "Arms Up Pottery Sherd",
"item.minecraft.blade_pottery_shard": "Blade Pottery Shard",
"item.minecraft.blade_pottery_sherd": "Blade Pottery Sherd",
"item.minecraft.brewer_pottery_shard": "Brewer Pottery Shard",
"item.minecraft.brewer_pottery_sherd": "Brewer Pottery Sherd",
"item.minecraft.burn_pottery_shard": "Burn Pottery Shard",
"item.minecraft.burn_pottery_sherd": "Burn Pottery Sherd",
"item.minecraft.danger_pottery_shard": "Danger Pottery Shard",
"item.minecraft.danger_pottery_sherd": "Danger Pottery Sherd",
"item.minecraft.explorer_pottery_shard": "Explorer Pottery Shard",
"item.minecraft.explorer_pottery_sherd": "Explorer Pottery Sherd",
"item.minecraft.friend_pottery_shard": "Friend Pottery Shard",
"item.minecraft.friend_pottery_sherd": "Friend Pottery Sherd",
"item.minecraft.heart_pottery_shard": "Heart Pottery Shard",
"item.minecraft.heart_pottery_sherd": "Heart Pottery Sherd",
"item.minecraft.heartbreak_pottery_shard": "Heartbreak Pottery Shard",
"item.minecraft.heartbreak_pottery_sherd": "Heartbreak Pottery Sherd",
"item.minecraft.howl_pottery_shard": "Howl Pottery Shard",
"item.minecraft.howl_pottery_sherd": "Howl Pottery Sherd",
"item.minecraft.miner_pottery_shard": "Miner Pottery Shard",
"item.minecraft.miner_pottery_sherd": "Miner Pottery Sherd",
"item.minecraft.mourner_pottery_shard": "Mourner Pottery Shard",
"item.minecraft.mourner_pottery_sherd": "Mourner Pottery Sherd",
"item.minecraft.music_disc_relic": "Music Disc",
"item.minecraft.music_disc_relic.desc": "Aaron Cherof - Relic",
"item.minecraft.pitcher_plant": "Pitcher Plant",
"item.minecraft.pitcher_pod": "Pitcher Pod",
"item.minecraft.plenty_pottery_shard": "Plenty Pottery Shard",
"item.minecraft.plenty_pottery_sherd": "Plenty Pottery Sherd",
"item.minecraft.prize_pottery_shard": "Prize Pottery Shard",
"item.minecraft.prize_pottery_sherd": "Prize Pottery Sherd",
"item.minecraft.sheaf_pottery_shard": "Sheaf Pottery Shard",
"item.minecraft.sheaf_pottery_sherd": "Sheaf Pottery Sherd",
"item.minecraft.shelter_pottery_shard": "Shelter Pottery Shard",
"item.minecraft.shelter_pottery_sherd": "Shelter Pottery Sherd",
"item.minecraft.skull_pottery_shard": "Skull Pottery Shard",
"item.minecraft.skull_pottery_sherd": "Skull Pottery Sherd",
"item.minecraft.snort_pottery_shard": "Snort Pottery Shard",
"item.minecraft.snort_pottery_sherd": "Snort Pottery Sherd",
"mco.backup.entry": "Backup (%s)",
"mco.backup.entry.description": "Description",
"mco.backup.entry.enabledPack": "Enabled Pack",
"mco.backup.entry.gameDifficulty": "Game Difficulty",
"mco.backup.entry.gameMode": "Game Mode",
"mco.backup.entry.gameServerVersion": "Game Server Version",
"mco.backup.entry.name": "Name",
"mco.backup.entry.seed": "Seed",
"mco.backup.entry.templateName": "Template Name",
"mco.backup.entry.undefined": "Undefined Change",
"mco.backup.entry.uploaded": "Uploaded",
"mco.backup.entry.worldType": "World Type",
"mco.backup.info.title": "Changes from last backup",
"mco.backup.unknown": "UNKNOWN",
"mco.configure.world.invited.number": "Invited (%s)",
"mco.configure.world.minigame": "Current: %s",
"mco.configure.world.subscription.remaining.months.days": "%1$s month(s), %2$s day(s)",
"mco.configure.world.subscription.remaining.months": "%1$s month(s)",
"mco.configure.world.subscription.remaining.days": "%1$s day(s)",
"mco.configure.world.uninvite.player": "Are you sure that you want to uninvite '%s'?",
"mco.download.percent": "%s %%",
"mco.download.resourcePack.fail": "Failed to download resource pack!",
"mco.download.speed": "(%s/s)",
"mco.errorMessage.6005": "World locked",
"mco.errorMessage.6006": "World is out of date",
"mco.errorMessage.6007": "User in too many Realms",
"mco.errorMessage.6008": "Invalid Realm name",
"mco.errorMessage.6009": "Invalid Realm description",
"mco.errorMessage.generic": "An error occurred: ",
"mco.errorMessage.realmsService": "An error occurred (%s):",
"mco.errorMessage.realmsService.realmsError": "Realms (%s):",
"mco.info": "Info!",
"mco.question": "Question",
"mco.upload.entry.id": "%1$s (%2$s)",
"mco.upload.entry.cheats": "%1$s, %2$s",
"mco.time.now": "right now",
"mco.time.secondsAgo": "%1$s second(s) ago",
"mco.time.minutesAgo": "%1$s minute(s) ago",
"mco.time.hoursAgo": "%1$s hour(s) ago",
"mco.time.daysAgo": "%1$s day(s) ago",
"mco.warning": "Warning!",
"mco.worldSlot.minigame": "Minigame",
"multiplayer.disconnect.invalid_public_key_signature.new": "Invalid signature for profile public key.\nTry restarting your game.",
"quickplay.error.invalid_identifier": "Could not find world with the provided identifier",
"quickplay.error.realm_connect": "Could not connect to Realm",
"quickplay.error.realm_permission": "Lacking permission to connect to this Realm",
"quickplay.error.title": "Failed to Quick Play",
"subtitles.block.amethyst_block.resonate": "Amethyst resonates",
"subtitles.block.sign.waxed_interact_fail": "Sign wobbles",
"subtitles.block.sniffer_egg.crack": "Sniffer Egg cracks",
"subtitles.block.sniffer_egg.hatch": "Sniffer Egg hatches",
"subtitles.block.sniffer_egg.plop": "Sniffer plops",
"subtitles.entity.sniffer.egg_crack": "Sniffer Egg cracks",
"subtitles.entity.sniffer.egg_hatch": "Sniffer Egg hatches",
"subtitles.item.brush.brushing.generic": "Brushing",
"subtitles.item.brush.brushing.gravel": "Brushing Gravel",
"subtitles.item.brush.brushing.gravel.complete": "Brushing Gravel completed",
"subtitles.item.brush.brushing.sand": "Brushing Sand",
"subtitles.item.brush.brushing.sand.complete": "Brushing Sand completed",
"telemetry.event.advancement_made.description": "Understanding the context behind receiving an advancement can help us better understand and improve the progression of the game.",
"telemetry.event.advancement_made.title": "Advancement Made",
"telemetry.event.game_load_times.description": "This event can help us figure out where startup performance improvements are needed by measuring the execution times of the startup phases.",
"telemetry.event.game_load_times.title": "Game Load Times",
"telemetry.property.advancement_game_time.title": "Game Time (Ticks)",
"telemetry.property.advancement_id.title": "Advancement ID",
"telemetry.property.launcher_name.title": "Launcher Name",
"telemetry.property.load_time_bootstrap_ms.title": "Bootstrap Time (Milliseconds)",
"telemetry.property.load_time_loading_overlay_ms.title": "Time in Loading Screen (Milliseconds)",
"telemetry.property.load_time_pre_window_ms.title": "Time Before Window Opens (Milliseconds)",
"telemetry.property.load_time_total_time_ms.title": "Total Load Time (Milliseconds)",
"telemetry.property.realms_map_content.title": "Realms Map Content (Minigame Name)",
"trim_pattern.minecraft.host": "Host Armor Trim",
"trim_pattern.minecraft.raiser": "Raiser Armor Trim",
"trim_pattern.minecraft.shaper": "Shaper Armor Trim",
"trim_pattern.minecraft.silence": "Silence Armor Trim",
"trim_pattern.minecraft.wayfinder": "Wayfinder Armor Trim"
},
"1.19.4": {
"accessibility.onboarding.screen.narrator": "Press enter to enable the narrator",
"accessibility.onboarding.screen.title": "Welcome to Minecraft!\n\nWould you like to enable the Narrator or visit the Accessibility Settings?",
Binary file not shown.

After

Width:  |  Height:  |  Size: 20 KiB

@@ -10,6 +10,7 @@
"issues": "https://github.com/ViaVersion/ViaBackwards/issues",
"sources": "https://github.com/ViaVersion/ViaBackwards"
},
"icon": "assets/viabackwards/textures/squarelogo.png",
"environment": "*",
"authors": [
"Matsv",
+7
View File
@@ -0,0 +1,7 @@
projectVersion=4.8.0
# 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.6.0-1.19.4-pre4-SNAPSHOT"
viaver = "4.8.0-1.20.2-pre1-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.0.2-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
+10 -5
View File
@@ -83,10 +83,8 @@ done
# This is normally unused
# shellcheck disable=SC2034
APP_BASE_NAME=${0##*/}
APP_HOME=$( cd "${APP_HOME:-./}" && pwd -P ) || exit
# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"'
# 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
@@ -133,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.
@@ -197,6 +198,10 @@ if "$cygwin" || "$msys" ; then
done
fi
# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"'
# Collect all arguments for the java command;
# * $DEFAULT_JVM_OPTS, $JAVA_OPTS, and $GRADLE_OPTS can contain fragments of
# shell script including quotes and variable substitutions, so put them in
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
+3 -2
View File
@@ -15,8 +15,9 @@ dependencyResolutionManagement {
pluginManagement {
plugins {
id("net.kyori.blossom") version "1.2.0"
id("com.github.johnrengelman.shadow") version "8.1.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"
}
}
+83
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,83 @@ tasks {
}
publishShadowJar()
val branch = rootProject.branchName()
val baseVersion = project.version as String
val isRelease = !baseVersion.contains('-')
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()}"
}
val isMainBranch = branch == "master"
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)
}
}
}
}
}
}